Skip to contentSkip to conversation

RFC: dm: Add USB support

RFC PATCH New Simon Glass 4 participants 21 messages Jan 30, 2015 – Mar 9, 2015

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover RFC: dm: Add USB support

This series adds basic driver model support to USB. The intent is to permit the various subsystems (OHCI, EHCI, XHCI) to co-exist and allow any number of USB ports of different types. So far the absolute limit on the number of USB devices is only slightly relaxed.

Only USB controllers have a real driver model device. USB devices (including the hub in the controller) are not modelled as driver model devices. This is for two reasons:

- it is easier since we don't need to bind a whole lot of devices when scanning
- the two main USB devices (block devices and Ethernet) don't have driver mode support yet anyway, so it would be pointless. However the recent network RFC has encouraged me to send this.

The basic approach is to set up the driver model structures in parallel to what already exists rather than to replace them. This allows both driver model and legacy to be used for USB, although not with the same board.

So far only XHCI is supported. As an example the Exynos XHCI driver is converted to driver model.

I would appreciate comments before going further.

Caveats:
- sandbox code is incomplete and there are no tests
- 'usb stop' does not remove existing devices (I have not yet settled on the best approach)
- the usb.h changes need to be split correctly into the patches once they are final

This series is available at u-boot-dm/usb-working.

Simon Glass (7):
dm: usb: Add a uclass for USB controllers
dm: usb: Support driver model in exynos XHCI
dm: usb: Adjust users of the USB stack to work with driver model
dm: usb: WIP sandbox USB implementation
dm: core: Add a function to get the uclass data for a device
arm: Show relocated PC/LR in the register dump
dm: exynos: Enable driver model for snow XHCI

 Makefile                             |   1 +
 arch/arm/lib/interrupts.c            |  13 +-
 arch/sandbox/dts/sandbox.dts         |  20 +++
 arch/sandbox/include/asm/processor.h |   0
 common/cmd_usb.c                     |  74 ++++++++---
 common/usb.c                         |  28 +++--
 common/usb_hub.c                     |  13 +-
 common/usb_storage.c                 | 148 +++++++++++++---------
 drivers/core/device.c                |  10 ++
 drivers/usb/dev/Makefile             |  10 ++
 drivers/usb/dev/sandbox-flash.c      |  95 +++++++++++++++
 drivers/usb/dev/sandbox-hub.c        | 116 ++++++++++++++++++
 drivers/usb/dev/usb-emul-uclass.c    |  16 +++
 drivers/usb/eth/usb_ether.c          |  46 +++++--
 drivers/usb/host/Makefile            |   5 +
 drivers/usb/host/usb-sandbox.c       | 151 +++++++++++++++++++++++
 drivers/usb/host/usb-uclass.c        | 227 ++++++++++++++++++++++++++++++++++
 drivers/usb/host/xhci-exynos5.c      | 115 +++++++++++++++++-
 drivers/usb/host/xhci.c              | 229 ++++++++++++++++++++++++++++-------
 drivers/usb/host/xhci.h              |  24 ++++
 include/configs/sandbox.h            |   3 +
 include/configs/snow.h               |   1 +
 include/dm/device.h                  |  10 ++
 include/dm/uclass-id.h               |   2 +
 include/usb.h                        |  76 +++++++++++-
 include/usb_defs.h                   |  14 ++-
 26 files changed, 1294 insertions(+), 153 deletions(-)
 create mode 100644 arch/sandbox/include/asm/processor.h
 create mode 100644 drivers/usb/dev/Makefile
 create mode 100644 drivers/usb/dev/sandbox-flash.c
 create mode 100644 drivers/usb/dev/sandbox-hub.c
 create mode 100644 drivers/usb/dev/usb-emul-uclass.c
 create mode 100644 drivers/usb/host/usb-sandbox.c
 create mode 100644 drivers/usb/host/usb-uclass.c
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#1 lore raw

RFC PATCH 1/7 dm: usb: Add a uclass for USB controllers

Add a uclass that can represent a USB controller. For now we do not create devices for things attached to the controller.

---

 drivers/usb/host/Makefile     |   2 +
 drivers/usb/host/usb-uclass.c | 227 ++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h        |   1 +
 3 files changed, 230 insertions(+)
 create mode 100644 drivers/usb/host/usb-uclass.c
drivers/usb/host/Makefile +2 -0
index c11b551..d0b890a 100644
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-$(CONFIG_DM_USB) += usb-uclass.o
+
 # ohci
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
 obj-$(CONFIG_USB_ATMEL) += ohci-at91.o
drivers/usb/host/usb-uclass.c new file +227 -0

227 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index 91bb90d..baab810 100644
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_USB,		/* USB bus */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#2 lore raw

RFC PATCH 1/7 dm: usb: Add a uclass for USB controllers

Quoted 4 lines · Simon Glass

Add a uclass that can represent a USB controller. For now we do not create devices for things attached to the controller.

[...]

drivers/usb/host/usb-uclass.c line 219

Quoted 7 lines
drivers/usb/host/usb-uclass.c new file +7 -0
+UCLASS_DRIVER(usb) = {
+	.id		= UCLASS_USB,
+	.name		= "usb",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+/*
+	.child_pre_probe = usb_child_pre_probe,
+	.post_probe	= i2c_post_probe,

Certainly this is USB, right ? ;-)

Quoted 1 line

+*/

What's the reason for this commented-out stuff please ?

Quoted 12 lines
drivers/usb/host/usb-uclass.c new file +7 -0
+	.per_device_auto_alloc_size = sizeof(struct dm_usb_info),
+/*
+	.per_child_auto_alloc_size = sizeof(struct usb_device),
+	.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.child_post_bind = i2c_child_post_bind,
+*/
+};
include/dm/uclass-id.h +0 -0
index 91bb90d..baab810 100644

include/dm/uclass-id.h enum uclass_id { · line 40

Quoted 7 lines
include/dm/uclass-id.h +1 -0
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_USB,		/* USB bus */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,

Best regards,
Marek Vasut

#3 lore raw

RFC PATCH 1/7 dm: usb: Add a uclass for USB controllers

In reply to Simon Glass

Hi Simon,

Quoted 5 lines · Simon Glass

Add a uclass that can represent a USB controller. For now we do not create devices for things attached to the controller.

---

Please find my comments inline below.

Quoted 102 lines
 drivers/usb/host/Makefile     |   2 +
 drivers/usb/host/usb-uclass.c | 227 ++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h        |   1 +
 3 files changed, 230 insertions(+)
 create mode 100644 drivers/usb/host/usb-uclass.c
drivers/usb/host/Makefile +2 -0
index c11b551..d0b890a 100644
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-$(CONFIG_DM_USB) += usb-uclass.o
+
 # ohci
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
 obj-$(CONFIG_USB_ATMEL) += ohci-at91.o
drivers/usb/host/usb-uclass.c new file +76 -0
new file mode 100644
index 0000000..86564db
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <usb.h>
+#include <dm/device-internal.h>
+
+static bool usb_started; /* flag for the started/stopped USB status */
+static bool asynch_allowed;
+
+int usb_disable_asynch(int disable)
+{
+       int old_value = asynch_allowed;
+
+       asynch_allowed = !disable;
+       return old_value;
+}
+
+int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+                  int length, int interval)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->control)
+               return -ENOSYS;
+
+       return ops->interrupt(dev, udev, pipe, buffer, length, interval);
+}
+
+int submit_control_msg(struct usb_device *udev, unsigned long pipe,
+                      void *buffer, int length, struct devrequest *setup)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->control)
+               return -ENOSYS;
+
+       return ops->control(dev, udev, pipe, buffer, length, setup);
+}
+
+int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+                   int length)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->control)
+               return -ENOSYS;
+
+       return ops->bulk(dev, udev, pipe, buffer, length);
+}
+
+int usb_alloc_device(struct usb_device *udev)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->alloc_device)
+               return -ENOSYS;
+
+       return ops->alloc_device(dev, udev);
+}
+
+int usb_stop(void)
+{
+       return 0;
+}
+

drivers/usb/host/usb-uclass.c line 86

Quoted 10 lines
drivers/usb/host/usb-uclass.c new file +10 -0
+int usb_init(void)
+{
+       int controllers_initialized = 0;
+       struct usb_device *udev;
+       struct udevice *dev;
+       struct uclass *uc;
+       int count = 0;
+       int ret;
+
+       asynch_allowed = 1;

you may still want to do a usb_hub_reset() like usb_init() in common/usb.c does ?

Also make all devices unknown initially

drivers/usb/host/usb-uclass.c line 89

Quoted 3 lines
drivers/usb/host/usb-uclass.c new file +3 -0
+       ret = uclass_get(UCLASS_USB, &uc);
+       if (ret)
+               return ret;

nit: just add an extra line here.

Quoted 157 lines
drivers/usb/host/usb-uclass.c new file +138 -0
+       uclass_foreach_dev(dev, uc) {
+               struct dm_usb_info *usb;
+
+               /* init low_level USB */
+               count++;
+               printf("USB");
+               ret = device_probe(dev);
+               printf("%d:   ", dev->seq);
+               if (ret == -ENODEV) {   /* No such device. */
+                       puts("Port not available.\n");
+                       controllers_initialized++;
+                       continue;
+               }
+
+               if (ret) {              /* Other error. */
+                       puts("probe failed\n");
+                       continue;
+               }
+               /*
+                * lowlevel init is OK, now scan the bus for devices
+                * i.e. search HUBs and configure them
+                */
+               controllers_initialized++;
+               printf("scanning bus %d for devices... ", dev->seq);
+               ret = usb_alloc_new_device(dev, &udev);
+               /*
+                * device 0 is always present
+                * (root hub, so let it analyze)
+                */
+               if (!ret)
+                       usb_new_device(udev);
+
+               usb = dev_get_uclass_priv(dev);
+               if (!usb->dev_index)
+                       printf("No USB Device found\n");
+               else
+                       printf("%d USB Device(s) found\n", usb->dev_index);
+
+               usb_started = true;
+       }
+
+       debug("scan end\n");
+       /* if we were not able to find at least one working bus, bail out */
+       if (!count)
+               printf("No controllers found\n");
+       else if (controllers_initialized == 0)
+               printf("USB error: all controllers failed lowlevel init\n");
+
+       return usb_started ? 0 : -1;
+}
+
+#ifdef CONFIG_MUSB_HOST
+int usb_reset_root_port(void)
+{
+       return -ENOSYS;
+}
+#endif
+
+int usb_alloc_new_device(struct udevice *controller,
+                        struct usb_device **devp)
+{
+       struct dm_usb_info *usb = dev_get_uclass_priv(controller);
+       struct usb_device *udev;
+
+       int i;
+
+       debug("New Device %d\n", usb->dev_index);
+       if (usb->dev_index == USB_MAX_DEVICE) {
+               printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
+               return -ENOSPC;
+       }
+       /* default Address is 0, real addresses start with 1 */
+       udev = &usb->usb_dev[usb->dev_index++];
+       udev->devnum = usb->dev_index;
+       udev->maxchild = 0;
+       for (i = 0; i < USB_MAXCHILDREN; i++)
+               udev->children[i] = NULL;
+       udev->parent = NULL;
+       udev->controller_dev = controller;
+       udev->controller = usb->controller;
+       debug("%s: udev=%p\n", __func__, udev);
+
+       *devp = udev;
+       return 0;
+}
+
+struct usb_device *usb_get_dev_index(struct udevice *controller, int index)
+{
+       struct dm_usb_info *usb = dev_get_uclass_priv(controller);
+       struct usb_device *udev;
+
+       if (index < 0 || index >= USB_MAX_DEVICE)
+               return NULL;
+       udev = &usb->usb_dev[index];
+
+       return udev->controller ? udev : NULL;
+}
+
+/*
+static int usb_child_pre_probe(struct udevice *dev)
+{
+       struct usb_device *udev = dev_get_parentdata(dev);
+
+       udev->controller = dev;
+
+       return 0;
+}
+*/
+/*
+ * Free the newly created device node.
+ * Called in error cases where configuring a newly attached
+ * device fails for some reason.
+ */
+void usb_free_device(struct udevice *controller)
+{
+       struct dm_usb_info *usb = dev_get_uclass_priv(controller);
+
+       usb->dev_index--;
+       debug("Freeing device node: %d\n", usb->dev_index);
+       memset(&usb->usb_dev[usb->dev_index], '\0', sizeof(struct usb_device));
+       usb->usb_dev[usb->dev_index].devnum = -1;
+}
+
+UCLASS_DRIVER(usb) = {
+       .id             = UCLASS_USB,
+       .name           = "usb",
+       .flags          = DM_UC_FLAG_SEQ_ALIAS,
+/*
+       .child_pre_probe = usb_child_pre_probe,
+       .post_probe     = i2c_post_probe,
+*/
+       .per_device_auto_alloc_size = sizeof(struct dm_usb_info),
+/*
+       .per_child_auto_alloc_size = sizeof(struct usb_device),
+       .per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .child_post_bind = i2c_child_post_bind,
+*/
+};
include/dm/uclass-id.h +1 -1
index 91bb90d..baab810 100644
@@ -34,6 +34,7 @@ enum uclass_id {
        UCLASS_I2C_GENERIC,     /* Generic I2C device */
        UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
        UCLASS_MOD_EXP,         /* RSA Mod Exp device */
+       UCLASS_USB,             /* USB bus */
 
        UCLASS_COUNT,
        UCLASS_INVALID = -1,
--

2.2.0.rc0.207.ga3a616c

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Signature · 4 lines
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India
#4 lore raw

RFC PATCH 1/7 dm: usb: Add a uclass for USB controllers

Hi,

On Mon, Mar 9, 2015 at 11:50 AM, Vivek Gautam <[email protected]> wrote:

Sorry i was in the middle of adding comment and the message just got sent. I will add other comments here.

Quoted 103 lines

Hi Simon,

Quoted 5 lines · Simon Glass

Add a uclass that can represent a USB controller. For now we do not create devices for things attached to the controller.

---

Please find my comments inline below.

Quoted 91 lines
 drivers/usb/host/Makefile     |   2 +
 drivers/usb/host/usb-uclass.c | 227 ++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h        |   1 +
 3 files changed, 230 insertions(+)
 create mode 100644 drivers/usb/host/usb-uclass.c
drivers/usb/host/Makefile +2 -0
index c11b551..d0b890a 100644
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-$(CONFIG_DM_USB) += usb-uclass.o
+
 # ohci
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
 obj-$(CONFIG_USB_ATMEL) += ohci-at91.o
drivers/usb/host/usb-uclass.c new file +65 -0
new file mode 100644
index 0000000..86564db
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <usb.h>
+#include <dm/device-internal.h>
+
+static bool usb_started; /* flag for the started/stopped USB status */
+static bool asynch_allowed;
+
+int usb_disable_asynch(int disable)
+{
+       int old_value = asynch_allowed;
+
+       asynch_allowed = !disable;
+       return old_value;
+}
+
+int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+                  int length, int interval)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->control)
+               return -ENOSYS;
+
+       return ops->interrupt(dev, udev, pipe, buffer, length, interval);
+}
+
+int submit_control_msg(struct usb_device *udev, unsigned long pipe,
+                      void *buffer, int length, struct devrequest *setup)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->control)
+               return -ENOSYS;
+
+       return ops->control(dev, udev, pipe, buffer, length, setup);
+}
+
+int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+                   int length)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
+       if (!ops->control)
+               return -ENOSYS;
+
+       return ops->bulk(dev, udev, pipe, buffer, length);
+}
+
+int usb_alloc_device(struct usb_device *udev)
+{
+       struct udevice *dev = udev->controller_dev;
+       struct dm_usb_ops *ops = usb_get_ops(dev);
+
Quoted 8 lines

drivers/usb/host/usb-uclass.c line 73

Quoted 8 lines
drivers/usb/host/usb-uclass.c new file +8 -0
+       if (!ops->alloc_device)
+               return -ENOSYS;
+
+       return ops->alloc_device(dev, udev);
+}
+
+int usb_stop(void)
+{

i think you are already planning to add "remove()" call for host controller here,
alongwith freeing the device, usb_free_device().

Quoted 17 lines

drivers/usb/host/usb-uclass.c line 86

Quoted 13 lines
drivers/usb/host/usb-uclass.c new file +13 -0
+       return 0;
+}
+
+int usb_init(void)
+{
+       int controllers_initialized = 0;
+       struct usb_device *udev;
+       struct udevice *dev;
+       struct uclass *uc;
+       int count = 0;
+       int ret;
+
+       asynch_allowed = 1;

you may still want to do a usb_hub_reset() like usb_init() in common/usb.c does ?

Quoted 1 line

Also make all devices unknown initially

i think this may not be required.

Quoted 160 lines

drivers/usb/host/usb-uclass.c line 89

Quoted 4 lines
drivers/usb/host/usb-uclass.c new file +3 -0
+       ret = uclass_get(UCLASS_USB, &uc);
+       if (ret)
+               return ret;

nit: just add an extra line here.

Quoted 153 lines
drivers/usb/host/usb-uclass.c new file +138 -0
+       uclass_foreach_dev(dev, uc) {
+               struct dm_usb_info *usb;
+
+               /* init low_level USB */
+               count++;
+               printf("USB");
+               ret = device_probe(dev);
+               printf("%d:   ", dev->seq);
+               if (ret == -ENODEV) {   /* No such device. */
+                       puts("Port not available.\n");
+                       controllers_initialized++;
+                       continue;
+               }
+
+               if (ret) {              /* Other error. */
+                       puts("probe failed\n");
+                       continue;
+               }
+               /*
+                * lowlevel init is OK, now scan the bus for devices
+                * i.e. search HUBs and configure them
+                */
+               controllers_initialized++;
+               printf("scanning bus %d for devices... ", dev->seq);
+               ret = usb_alloc_new_device(dev, &udev);
+               /*
+                * device 0 is always present
+                * (root hub, so let it analyze)
+                */
+               if (!ret)
+                       usb_new_device(udev);
+
+               usb = dev_get_uclass_priv(dev);
+               if (!usb->dev_index)
+                       printf("No USB Device found\n");
+               else
+                       printf("%d USB Device(s) found\n", usb->dev_index);
+
+               usb_started = true;
+       }
+
+       debug("scan end\n");
+       /* if we were not able to find at least one working bus, bail out */
+       if (!count)
+               printf("No controllers found\n");
+       else if (controllers_initialized == 0)
+               printf("USB error: all controllers failed lowlevel init\n");
+
+       return usb_started ? 0 : -1;
+}
+
+#ifdef CONFIG_MUSB_HOST
+int usb_reset_root_port(void)
+{
+       return -ENOSYS;
+}
+#endif
+
+int usb_alloc_new_device(struct udevice *controller,
+                        struct usb_device **devp)
+{
+       struct dm_usb_info *usb = dev_get_uclass_priv(controller);
+       struct usb_device *udev;
+
+       int i;
+
+       debug("New Device %d\n", usb->dev_index);
+       if (usb->dev_index == USB_MAX_DEVICE) {
+               printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
+               return -ENOSPC;
+       }
+       /* default Address is 0, real addresses start with 1 */
+       udev = &usb->usb_dev[usb->dev_index++];
+       udev->devnum = usb->dev_index;
+       udev->maxchild = 0;
+       for (i = 0; i < USB_MAXCHILDREN; i++)
+               udev->children[i] = NULL;
+       udev->parent = NULL;
+       udev->controller_dev = controller;
+       udev->controller = usb->controller;
+       debug("%s: udev=%p\n", __func__, udev);
+
+       *devp = udev;
+       return 0;
+}
+
+struct usb_device *usb_get_dev_index(struct udevice *controller, int index)
+{
+       struct dm_usb_info *usb = dev_get_uclass_priv(controller);
+       struct usb_device *udev;
+
+       if (index < 0 || index >= USB_MAX_DEVICE)
+               return NULL;
+       udev = &usb->usb_dev[index];
+
+       return udev->controller ? udev : NULL;
+}
+
+/*
+static int usb_child_pre_probe(struct udevice *dev)
+{
+       struct usb_device *udev = dev_get_parentdata(dev);
+
+       udev->controller = dev;
+
+       return 0;
+}
+*/
+/*
+ * Free the newly created device node.
+ * Called in error cases where configuring a newly attached
+ * device fails for some reason.
+ */
+void usb_free_device(struct udevice *controller)
+{
+       struct dm_usb_info *usb = dev_get_uclass_priv(controller);
+
+       usb->dev_index--;
+       debug("Freeing device node: %d\n", usb->dev_index);
+       memset(&usb->usb_dev[usb->dev_index], '\0', sizeof(struct usb_device));
+       usb->usb_dev[usb->dev_index].devnum = -1;
+}
+
+UCLASS_DRIVER(usb) = {
+       .id             = UCLASS_USB,
+       .name           = "usb",
+       .flags          = DM_UC_FLAG_SEQ_ALIAS,
+/*
+       .child_pre_probe = usb_child_pre_probe,
+       .post_probe     = i2c_post_probe,
+*/
+       .per_device_auto_alloc_size = sizeof(struct dm_usb_info),
+/*
+       .per_child_auto_alloc_size = sizeof(struct usb_device),
+       .per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .child_post_bind = i2c_child_post_bind,
+*/
+};
include/dm/uclass-id.h +1 -1
index 91bb90d..baab810 100644
@@ -34,6 +34,7 @@ enum uclass_id {
        UCLASS_I2C_GENERIC,     /* Generic I2C device */
        UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
        UCLASS_MOD_EXP,         /* RSA Mod Exp device */
+       UCLASS_USB,             /* USB bus */
 
        UCLASS_COUNT,
        UCLASS_INVALID = -1,
--

2.2.0.rc0.207.ga3a616c

Quoted 4 lines
Quoted 4 lines

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Rest looks fine to me.

Signature · 4 lines
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India
#5 lore raw

RFC PATCH 2/7 dm: usb: Support driver model in exynos XHCI

In reply to Simon Glass

(This patch will be split for submission)

Add driver model support to the XHCI framework, and move exynos over to use it.

---

 drivers/usb/host/xhci-exynos5.c | 115 +++++++++++++++++++-
 drivers/usb/host/xhci.c         | 229 ++++++++++++++++++++++++++++++++--------
 drivers/usb/host/xhci.h         |  24 +++++
 3 files changed, 324 insertions(+), 44 deletions(-)
drivers/usb/host/xhci-exynos5.c +113 -2
index a77c8bc..e61f39e 100644
@@ -14,6 +14,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fdtdec.h>
 #include <libfdt.h>
 #include <malloc.h>
@@ -32,6 +33,12 @@
 /* Declare global data pointer */
 DECLARE_GLOBAL_DATA_PTR;
 
+struct exynos_xhci_platdata {
+	fdt_addr_t hcd_base;
+	fdt_addr_t phy_base;
+	struct gpio_desc vbus_gpio;
+};
+
 /**
  * Contains pointers to register base addresses
  * for the usb controller.
@@ -40,12 +47,56 @@ struct exynos_xhci {
 	struct exynos_usb3_phy *usb3_phy;
 	struct xhci_hccr *hcd;
 	struct dwc3 *dwc3_reg;
+#ifndef CONFIG_DM_USB
 	struct gpio_desc vbus_gpio;
+#endif
 };
 
+#ifndef CONFIG_DM_USB
 static struct exynos_xhci exynos;
+#endif
 
-#ifdef CONFIG_OF_CONTROL
+#ifdef CONFIG_DM_USB
+static int xhci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct exynos_xhci_platdata *plat = dev_get_platdata(dev);
+	const void *blob = gd->fdt_blob;
+	unsigned int node;
+	int depth;
+
+	/*
+	 * Get the base address for XHCI controller from the device node
+	 */
+	plat->hcd_base = fdtdec_get_addr(blob, dev->of_offset, "reg");
+	if (plat->hcd_base == FDT_ADDR_T_NONE) {
+		debug("Can't get the XHCI register base address\n");
+		return -ENXIO;
+	}
+
+	depth = 0;
+	node = fdtdec_next_compatible_subnode(blob, dev->of_offset,
+				COMPAT_SAMSUNG_EXYNOS5_USB3_PHY, &depth);
+	if (node <= 0) {
+		debug("XHCI: Can't get device node for usb3-phy controller\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Get the base address for usbphy from the device node
+	 */
+	plat->phy_base = fdtdec_get_addr(blob, node, "reg");
+	if (plat->phy_base == FDT_ADDR_T_NONE) {
+		debug("Can't get the usbphy register address\n");
+		return -ENXIO;
+	}
+
+	/* Vbus gpio */
+	gpio_request_by_name(dev, "samsung,vbus-gpio", 0,
+			     &plat->vbus_gpio, GPIOD_IS_OUT);
+
+	return 0;
+}
+#else
 static int exynos_usb3_parse_dt(const void *blob, struct exynos_xhci *exynos)
 {
 	fdt_addr_t addr;
@@ -182,7 +233,7 @@ static void exynos5_usb3_phy_exit(struct exynos_usb3_phy *phy)
 	set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_DISABLE);
 }
 
-void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode)
+static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode)
 {
 	clrsetbits_le32(&dwc3_reg->g_ctl,
 			DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG),
@@ -283,6 +334,7 @@ static void exynos_xhci_core_exit(struct exynos_xhci *exynos)
 	exynos5_usb3_phy_exit(exynos->usb3_phy);
 }
 
+#ifndef CONFIG_DM_USB
 int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
 {
 	struct exynos_xhci *ctx = &exynos;
@@ -326,3 +378,62 @@ void xhci_hcd_stop(int index)
 
 	exynos_xhci_core_exit(ctx);
 }
+#endif
+
+#ifdef CONFIG_DM_USB
+static int xhci_usb_probe(struct udevice *dev)
+{
+	struct exynos_xhci_platdata *plat = dev_get_platdata(dev);
+	struct exynos_xhci *ctx = dev_get_priv(dev);
+	struct xhci_hcor *hcor;
+	int ret;
+
+	ctx->hcd = (struct xhci_hccr *)plat->hcd_base;
+	ctx->usb3_phy = (struct exynos_usb3_phy *)plat->phy_base;
+	ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET);
+	hcor = (struct xhci_hcor *)((uint32_t)ctx->hcd +
+			HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase)));
+
+	/* setup the Vbus gpio here */
+	if (dm_gpio_is_valid(&plat->vbus_gpio))
+		dm_gpio_set_value(&plat->vbus_gpio, 1);
+
+	ret = exynos_xhci_core_init(ctx);
+	if (ret) {
+		puts("XHCI: failed to initialize controller\n");
+		return -EINVAL;
+	}
+
+	return xhci_register(dev, ctx->hcd, hcor);
+}
+
+static int xhci_usb_remove(struct udevice *dev)
+{
+	struct exynos_xhci *ctx = dev_get_priv(dev);
+	int ret;
+
+	ret = xhci_deregister(dev);
+	if (ret)
+		return ret;
+	exynos_xhci_core_exit(ctx);
+
+	return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+	{ .compatible = "samsung,exynos5250-xhci" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+	.name	= "xhci_exynos",
+	.id	= UCLASS_USB,
+	.of_match = xhci_usb_ids,
+	.ofdata_to_platdata = xhci_usb_ofdata_to_platdata,
+	.probe = xhci_usb_probe,
+	.remove = xhci_usb_remove,
+	.ops	= &xhci_usb_ops,
+	.priv_auto_alloc_size = sizeof(struct exynos_xhci),
+	.platdata_auto_alloc_size = sizeof(struct exynos_xhci_platdata),
+};
+#endif
drivers/usb/host/xhci.c +187 -42

306 lines not on this page · raw message

drivers/usb/host/xhci.h +24 -0
index 6685ed2..f9fd99e 100644
@@ -1200,6 +1200,9 @@ void xhci_hcd_stop(int index);
 #define XHCI_STS_CNR		(1 << 11)
 
 struct xhci_ctrl {
+#ifdef CONFIG_DM_USB
+	struct udevice *dev;
+#endif
 	struct xhci_hccr *hccr;	/* R/O registers, not need for volatile */
 	struct xhci_hcor *hcor;
 	struct xhci_doorbell_array *dba;
@@ -1250,4 +1253,25 @@ int xhci_alloc_virt_device(struct usb_device *udev);
 int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
 		  struct xhci_hcor *hcor);
 
+/**
+ * xhci_deregister() - Unregister an XHCI controller
+ *
+ * @dev:	Controller device
+ * @return 0 if registered, -ve on error
+ */
+int xhci_deregister(struct udevice *dev);
+
+/**
+ * xhci_register() - Register a new XHCI controller
+ *
+ * @dev:	Controller device
+ * @hccr:	Host controller control registers
+ * @hcor:	Not sure what this means
+ * @return 0 if registered, -ve on error
+ */
+int xhci_register(struct udevice *dev, struct xhci_hccr *hccr,
+		  struct xhci_hcor *hcor);
+
+extern struct dm_usb_ops xhci_usb_ops;
+
 #endif /* HOST_XHCI_H_ */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#6 lore raw

RFC PATCH 3/7 dm: usb: Adjust users of the USB stack to work with driver model

In reply to Simon Glass

While we currently don't have driver model support for block devices and Ethernet, we can still allow this to work when driver model is used for USB.

---

 common/cmd_usb.c            |  74 ++++++++++++++++------
 common/usb.c                |  28 +++++----
 common/usb_hub.c            |  13 +++-
 common/usb_storage.c        | 148 ++++++++++++++++++++++++++++----------------
 drivers/usb/eth/usb_ether.c |  46 +++++++++++---
 include/usb.h               |  76 +++++++++++++++++++++--
 6 files changed, 286 insertions(+), 99 deletions(-)
common/cmd_usb.c +55 -19
index 27813f0..b824634 100644
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 #include <part.h>
@@ -254,16 +255,24 @@ static void usb_display_config(struct usb_device *dev)
 
 static struct usb_device *usb_find_device(int devnum)
 {
-	struct usb_device *dev;
+#ifdef CONFIG_DM_USB
+	struct udevice *dev;
+
+	if (uclass_get_device_by_seq(UCLASS_USB, devnum, &dev))
+		return NULL;
+	return dev_get_uclass_priv(dev);
+#else
+	struct usb_device *udev;
 	int d;
 
 	for (d = 0; d < USB_MAX_DEVICE; d++) {
-		dev = usb_get_dev_index(d);
-		if (dev == NULL)
+		udev = usb_get_dev_index(d);
+		if (udev == NULL)
 			return NULL;
-		if (dev->devnum == devnum)
-			return dev;
+		if (udev->devnum == devnum)
+			return udev;
 	}
+#endif
 
 	return NULL;
 }
@@ -466,9 +475,8 @@ static void do_usb_start(void)
  */
 static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-
+	struct usb_device *udev = NULL;
 	int i;
-	struct usb_device *dev = NULL;
 	extern char usb_started;
 #ifdef CONFIG_USB_STORAGE
 	block_dev_desc_t *stor_dev;
@@ -508,36 +516,64 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	}
 	if (strncmp(argv[1], "tree", 4) == 0) {
 		puts("USB device tree:\n");
+#ifdef CONFIG_DM_USB
+		struct udevice *dev;
+
+		for (uclass_first_device(UCLASS_USB, &dev);
+		     dev;
+		     uclass_next_device(&dev)) {
+			struct usb_device *udev = dev_get_uclass_priv(dev);
+
+			usb_show_tree(udev);
+		}
+#else
 		for (i = 0; i < USB_MAX_DEVICE; i++) {
+			struct usb_device *dev;
+
 			dev = usb_get_dev_index(i);
 			if (dev == NULL)
 				break;
 			if (dev->parent == NULL)
 				usb_show_tree(dev);
 		}
+#endif
 		return 0;
 	}
 	if (strncmp(argv[1], "inf", 3) == 0) {
-		int d;
 		if (argc == 2) {
+#ifdef CONFIG_DM_USB
+			struct udevice *dev;
+
+			for (uclass_first_device(UCLASS_USB, &dev);
+			dev;
+			uclass_next_device(&dev)) {
+				struct usb_device *udev;
+
+				udev = dev_get_uclass_priv(dev);
+				usb_display_desc(udev);
+				usb_display_config(udev);
+			}
+#else
+			int d;
 			for (d = 0; d < USB_MAX_DEVICE; d++) {
-				dev = usb_get_dev_index(d);
-				if (dev == NULL)
+				udev = usb_get_dev_index(d);
+				if (udev == NULL)
 					break;
-				usb_display_desc(dev);
-				usb_display_config(dev);
+				usb_display_desc(udev);
+				usb_display_config(udev);
 			}
+#endif
 			return 0;
 		} else {
 			i = simple_strtoul(argv[2], NULL, 10);
 			printf("config for device %d\n", i);
-			dev = usb_find_device(i);
-			if (dev == NULL) {
+			udev = usb_find_device(i);
+			if (udev == NULL) {
 				printf("*** No device available ***\n");
 				return 0;
 			} else {
-				usb_display_desc(dev);
-				usb_display_config(dev);
+				usb_display_desc(udev);
+				usb_display_config(udev);
 			}
 		}
 		return 0;
@@ -546,13 +582,13 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		if (argc < 5)
 			return CMD_RET_USAGE;
 		i = simple_strtoul(argv[2], NULL, 10);
-		dev = usb_find_device(i);
-		if (dev == NULL) {
+		udev = usb_find_device(i);
+		if (udev == NULL) {
 			printf("Device %d does not exist.\n", i);
 			return 1;
 		}
 		i = simple_strtoul(argv[3], NULL, 10);
-		return usb_test(dev, i, argv[4]);
+		return usb_test(udev, i, argv[4]);
 	}
 #ifdef CONFIG_USB_STORAGE
 	if (strncmp(argv[1], "stor", 4) == 0)
common/usb.c +16 -12
index 32e15cd..3ccf8a7 100644
@@ -41,12 +41,13 @@
 
 #define USB_BUFSIZ	512
 
-static struct usb_device usb_dev[USB_MAX_DEVICE];
-static int dev_index;
 static int asynch_allowed;
-
 char usb_started; /* flag for the started/stopped USB status */
 
+#ifndef CONFIG_DM_USB
+static struct usb_device usb_dev[USB_MAX_DEVICE];
+static int dev_index;
+
 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 #endif
@@ -94,12 +95,12 @@ int usb_init(void)
 		controllers_initialized++;
 		start_index = dev_index;
 		printf("scanning bus %d for devices... ", i);
-		dev = usb_alloc_new_device(ctrl);
+		ret = usb_alloc_new_device(ctrl, &dev);
 		/*
 		 * device 0 is always present
 		 * (root hub, so let it analyze)
 		 */
-		if (dev)
+		if (!ret)
 			usb_new_device(dev);
 
 		if (start_index == dev_index)
@@ -152,6 +153,7 @@ int usb_disable_asynch(int disable)
 	asynch_allowed = !disable;
 	return old_value;
 }
+#endif /* !CONFIG_DM_USB */
 
 
 /*-------------------------------------------------------------------
@@ -815,6 +817,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
  * the USB device are static allocated [USB_MAX_DEVICE].
  */
 
+#ifndef CONFIG_DM_USB
 
 /* returns a pointer to the device with the index [index].
  * if the device is not assigned (dev->devnum==-1) returns NULL
@@ -827,16 +830,13 @@ struct usb_device *usb_get_dev_index(int index)
 		return &usb_dev[index];
 }
 
-/* returns a pointer of a new device structure or NULL, if
- * no device struct is available
- */
-struct usb_device *usb_alloc_new_device(void *controller)
+int usb_alloc_new_device(void *controller, struct usb_device **devp)
 {
 	int i;
 	debug("New Device %d\n", dev_index);
 	if (dev_index == USB_MAX_DEVICE) {
 		printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
-		return NULL;
+		return -ENOSPC;
 	}
 	/* default Address is 0, real addresses start with 1 */
 	usb_dev[dev_index].devnum = dev_index + 1;
@@ -846,7 +846,9 @@ struct usb_device *usb_alloc_new_device(void *controller)
 	usb_dev[dev_index].parent = NULL;
 	usb_dev[dev_index].controller = controller;
 	dev_index++;
-	return &usb_dev[dev_index - 1];
+	*devp = &usb_dev[dev_index - 1];
+
+	return 0;
 }
 
 /*
@@ -854,7 +856,7 @@ struct usb_device *usb_alloc_new_device(void *controller)
  * Called in error cases where configuring a newly attached
  * device fails for some reason.
  */
-void usb_free_device(void)
+void usb_free_device(void *controller)
 {
 	dev_index--;
 	debug("Freeing device node: %d\n", dev_index);
@@ -872,6 +874,8 @@ __weak int usb_alloc_device(struct usb_device *udev)
 {
 	return 0;
 }
+#endif /* !CONFIG_DM_USB */
+
 /*
  * By the time we get here, the device has gotten a new device ID
  * and is in the default state. We need to identify the thing and
common/usb_hub.c +11 -2
index 66b4a72..ccdf755 100644
@@ -211,6 +211,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 	struct usb_device *usb;
 	ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
 	unsigned short portstatus;
+	int ret;
 
 	/* Check status */
 	if (usb_get_port_status(dev, port + 1, portsts) < 0) {
@@ -246,7 +247,15 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 	mdelay(200);
 
 	/* Allocate a new device struct for it */
-	usb = usb_alloc_new_device(dev->controller);
+#ifdef CONFIG_DM_USB
+	ret = usb_alloc_new_device(dev->controller_dev, &usb);
+#else
+	ret = usb_alloc_new_device(dev->controller, &usb);
+#endif
+	if (ret) {
+		printf("cannot create new device: reg=%d", ret);
+		return;
+	}
 
 	switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
 	case USB_PORT_STAT_SUPER_SPEED:
@@ -269,7 +278,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 	/* Run it through the hoops (find a driver, etc) */
 	if (usb_new_device(usb)) {
 		/* Woops, disable the port */
-		usb_free_device();
+		usb_free_device(dev->controller);
 		dev->children[port] = NULL;
 		debug("hub: disabling port %d\n", port + 1);
 		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
common/usb_storage.c +93 -55

214 lines not on this page · raw message

drivers/usb/eth/usb_ether.c +39 -7

74 lines not on this page · raw message

include/usb.h +72 -4

106 lines not on this page · raw message

Signature · 1 line
2.2.0.rc0.207.ga3a616c
#7 lore raw

RFC PATCH 3/7 dm: usb: Adjust users of the USB stack to work with driver model

Quoted 652 lines · Simon Glass

While we currently don't have driver model support for block devices and Ethernet, we can still allow this to work when driver model is used for USB.

---

 common/cmd_usb.c            |  74 ++++++++++++++++------
 common/usb.c                |  28 +++++----
 common/usb_hub.c            |  13 +++-
 common/usb_storage.c        | 148 ++++++++++++++++++++++++++++----------------
 drivers/usb/eth/usb_ether.c |  46 +++++++++++---
 include/usb.h               |  76 +++++++++++++++++++++--
 6 files changed, 286 insertions(+), 99 deletions(-)
common/cmd_usb.c +55 -19
index 27813f0..b824634 100644
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 #include <part.h>
@@ -254,16 +255,24 @@ static void usb_display_config(struct usb_device *dev)
 
 static struct usb_device *usb_find_device(int devnum)
 {
-       struct usb_device *dev;
+#ifdef CONFIG_DM_USB
+       struct udevice *dev;
+
+       if (uclass_get_device_by_seq(UCLASS_USB, devnum, &dev))
+               return NULL;
+       return dev_get_uclass_priv(dev);
+#else
+       struct usb_device *udev;
        int d;
 
        for (d = 0; d < USB_MAX_DEVICE; d++) {
-               dev = usb_get_dev_index(d);
-               if (dev == NULL)
+               udev = usb_get_dev_index(d);
+               if (udev == NULL)
                        return NULL;
-               if (dev->devnum == devnum)
-                       return dev;
+               if (udev->devnum == devnum)
+                       return udev;
        }
+#endif
 
        return NULL;
 }
@@ -466,9 +475,8 @@ static void do_usb_start(void)
  */
 static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-
+       struct usb_device *udev = NULL;
        int i;
-       struct usb_device *dev = NULL;
        extern char usb_started;
 #ifdef CONFIG_USB_STORAGE
        block_dev_desc_t *stor_dev;
@@ -508,36 +516,64 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        }
        if (strncmp(argv[1], "tree", 4) == 0) {
                puts("USB device tree:\n");
+#ifdef CONFIG_DM_USB
+               struct udevice *dev;
+
+               for (uclass_first_device(UCLASS_USB, &dev);
+                    dev;
+                    uclass_next_device(&dev)) {
+                       struct usb_device *udev = dev_get_uclass_priv(dev);
+
+                       usb_show_tree(udev);
+               }
+#else
                for (i = 0; i < USB_MAX_DEVICE; i++) {
+                       struct usb_device *dev;
+
                        dev = usb_get_dev_index(i);
                        if (dev == NULL)
                                break;
                        if (dev->parent == NULL)
                                usb_show_tree(dev);
                }
+#endif
                return 0;
        }
        if (strncmp(argv[1], "inf", 3) == 0) {
-               int d;
                if (argc == 2) {
+#ifdef CONFIG_DM_USB
+                       struct udevice *dev;
+
+                       for (uclass_first_device(UCLASS_USB, &dev);
+                       dev;
+                       uclass_next_device(&dev)) {
+                               struct usb_device *udev;
+
+                               udev = dev_get_uclass_priv(dev);
+                               usb_display_desc(udev);
+                               usb_display_config(udev);
+                       }
+#else
+                       int d;
                        for (d = 0; d < USB_MAX_DEVICE; d++) {
-                               dev = usb_get_dev_index(d);
-                               if (dev == NULL)
+                               udev = usb_get_dev_index(d);
+                               if (udev == NULL)
                                        break;
-                               usb_display_desc(dev);
-                               usb_display_config(dev);
+                               usb_display_desc(udev);
+                               usb_display_config(udev);
                        }
+#endif
                        return 0;
                } else {
                        i = simple_strtoul(argv[2], NULL, 10);
                        printf("config for device %d\n", i);
-                       dev = usb_find_device(i);
-                       if (dev == NULL) {
+                       udev = usb_find_device(i);
+                       if (udev == NULL) {
                                printf("*** No device available ***\n");
                                return 0;
                        } else {
-                               usb_display_desc(dev);
-                               usb_display_config(dev);
+                               usb_display_desc(udev);
+                               usb_display_config(udev);
                        }
                }
                return 0;
@@ -546,13 +582,13 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                if (argc < 5)
                        return CMD_RET_USAGE;
                i = simple_strtoul(argv[2], NULL, 10);
-               dev = usb_find_device(i);
-               if (dev == NULL) {
+               udev = usb_find_device(i);
+               if (udev == NULL) {
                        printf("Device %d does not exist.\n", i);
                        return 1;
                }
                i = simple_strtoul(argv[3], NULL, 10);
-               return usb_test(dev, i, argv[4]);
+               return usb_test(udev, i, argv[4]);
        }
 #ifdef CONFIG_USB_STORAGE
        if (strncmp(argv[1], "stor", 4) == 0)
common/usb.c +16 -12
index 32e15cd..3ccf8a7 100644
@@ -41,12 +41,13 @@
 
 #define USB_BUFSIZ     512
 
-static struct usb_device usb_dev[USB_MAX_DEVICE];
-static int dev_index;
 static int asynch_allowed;
-
 char usb_started; /* flag for the started/stopped USB status */
 
+#ifndef CONFIG_DM_USB
+static struct usb_device usb_dev[USB_MAX_DEVICE];
+static int dev_index;
+
 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 #endif
@@ -94,12 +95,12 @@ int usb_init(void)
                controllers_initialized++;
                start_index = dev_index;
                printf("scanning bus %d for devices... ", i);
-               dev = usb_alloc_new_device(ctrl);
+               ret = usb_alloc_new_device(ctrl, &dev);
                /*
                 * device 0 is always present
                 * (root hub, so let it analyze)
                 */
-               if (dev)
+               if (!ret)
                        usb_new_device(dev);
 
                if (start_index == dev_index)
@@ -152,6 +153,7 @@ int usb_disable_asynch(int disable)
        asynch_allowed = !disable;
        return old_value;
 }
+#endif /* !CONFIG_DM_USB */
 
 
 /*-------------------------------------------------------------------
@@ -815,6 +817,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
  * the USB device are static allocated [USB_MAX_DEVICE].
  */
 
+#ifndef CONFIG_DM_USB
 
 /* returns a pointer to the device with the index [index].
  * if the device is not assigned (dev->devnum==-1) returns NULL
@@ -827,16 +830,13 @@ struct usb_device *usb_get_dev_index(int index)
                return &usb_dev[index];
 }
 
-/* returns a pointer of a new device structure or NULL, if
- * no device struct is available
- */
-struct usb_device *usb_alloc_new_device(void *controller)
+int usb_alloc_new_device(void *controller, struct usb_device **devp)
 {
        int i;
        debug("New Device %d\n", dev_index);
        if (dev_index == USB_MAX_DEVICE) {
                printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
-               return NULL;
+               return -ENOSPC;
        }
        /* default Address is 0, real addresses start with 1 */
        usb_dev[dev_index].devnum = dev_index + 1;
@@ -846,7 +846,9 @@ struct usb_device *usb_alloc_new_device(void *controller)
        usb_dev[dev_index].parent = NULL;
        usb_dev[dev_index].controller = controller;
        dev_index++;
-       return &usb_dev[dev_index - 1];
+       *devp = &usb_dev[dev_index - 1];
+
+       return 0;
 }
 
 /*
@@ -854,7 +856,7 @@ struct usb_device *usb_alloc_new_device(void *controller)
  * Called in error cases where configuring a newly attached
  * device fails for some reason.
  */
-void usb_free_device(void)
+void usb_free_device(void *controller)
 {
        dev_index--;
        debug("Freeing device node: %d\n", dev_index);
@@ -872,6 +874,8 @@ __weak int usb_alloc_device(struct usb_device *udev)
 {
        return 0;
 }
+#endif /* !CONFIG_DM_USB */
+
 /*
  * By the time we get here, the device has gotten a new device ID
  * and is in the default state. We need to identify the thing and
common/usb_hub.c +11 -2
index 66b4a72..ccdf755 100644
@@ -211,6 +211,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
        struct usb_device *usb;
        ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
        unsigned short portstatus;
+       int ret;
 
        /* Check status */
        if (usb_get_port_status(dev, port + 1, portsts) < 0) {
@@ -246,7 +247,15 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
        mdelay(200);
 
        /* Allocate a new device struct for it */
-       usb = usb_alloc_new_device(dev->controller);
+#ifdef CONFIG_DM_USB
+       ret = usb_alloc_new_device(dev->controller_dev, &usb);
+#else
+       ret = usb_alloc_new_device(dev->controller, &usb);
+#endif
+       if (ret) {
+               printf("cannot create new device: reg=%d", ret);
+               return;
+       }
 
        switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
        case USB_PORT_STAT_SUPER_SPEED:
@@ -269,7 +278,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
        /* Run it through the hoops (find a driver, etc) */
        if (usb_new_device(usb)) {
                /* Woops, disable the port */
-               usb_free_device();
+               usb_free_device(dev->controller);
                dev->children[port] = NULL;
                debug("hub: disabling port %d\n", port + 1);
                usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
common/usb_storage.c +93 -55
index 1411737..8fb2c18 100644
@@ -33,9 +33,12 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
+#include <errno.h>
 #include <inttypes.h>
 #include <asm/byteorder.h>
 #include <asm/processor.h>
+#include <dm/device-internal.h>
 
 #include <part.h>
 #include <usb.h>
@@ -158,7 +161,6 @@ unsigned long usb_stor_read(int device, lbaint_t blknr,
                            lbaint_t blkcnt, void *buffer);
 unsigned long usb_stor_write(int device, lbaint_t blknr,
                             lbaint_t blkcnt, const void *buffer);
-struct usb_device * usb_get_dev_index(int index);
 void uhci_show_temp_int_td(void);
 
 #ifdef CONFIG_PARTITIONS
@@ -208,6 +210,44 @@ static unsigned int usb_get_max_lun(struct us_data *us)
        return (len > 0) ? *result : 0;
 }
 
+static int usb_stor_probe_device(struct usb_device *dev)
+{
+       if (dev == NULL)
+               return -ENOENT; /* no more devices available */
+
+       if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
+               /* OK, it's a storage device.  Iterate over its LUNs
+                       * and populate `usb_dev_desc'.
+                       */
+               int lun, max_lun, start = usb_max_devs;
+
+               max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
+               for (lun = 0;
+                       lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
+                       lun++) {
+                       struct block_dev_desc *blkdev;
+
+                       blkdev = &usb_dev_desc[usb_max_devs];
+
+                       if (usb_stor_get_info(dev, &usb_stor[start],
+                                             &usb_dev_desc[usb_max_devs]) ==
+                                             1) {
+                               blkdev->lun = lun;
+                               blkdev->priv = dev;
+                               usb_max_devs++;
+                       }
+               }
+       }
+
+       /* if storage device */
+       if (usb_max_devs == USB_MAX_STOR_DEV) {
+               printf("max USB Storage Device reached: %d stopping\n",
+                      usb_max_devs);
+               return -ENOSPC;
+       }
+
+       return 0;
+}
 /*******************************************************************************
  * scan the usb and reports device info
  * to the user if mode = 1
@@ -215,8 +255,8 @@ static unsigned int usb_get_max_lun(struct us_data *us)
  */
 int usb_stor_scan(int mode)
 {
+       struct block_dev_desc *blkdev;
        unsigned char i;
-       struct usb_device *dev;
 
        if (mode == 1)
                printf("       scanning usb for storage devices... ");
@@ -224,47 +264,55 @@ int usb_stor_scan(int mode)
        usb_disable_asynch(1); /* asynch transfer not allowed */
 
        for (i = 0; i < USB_MAX_STOR_DEV; i++) {
-               memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
-               usb_dev_desc[i].if_type = IF_TYPE_USB;
-               usb_dev_desc[i].dev = i;
-               usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
-               usb_dev_desc[i].target = 0xff;
-               usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
-               usb_dev_desc[i].block_read = usb_stor_read;
-               usb_dev_desc[i].block_write = usb_stor_write;
+               blkdev = &usb_dev_desc[i];
+               memset(&blkdev, 0, sizeof(block_dev_desc_t));
+               blkdev->if_type = IF_TYPE_USB;
+               blkdev->dev = i;
+               blkdev->part_type = PART_TYPE_UNKNOWN;
+               blkdev->target = 0xff;
+               blkdev->type = DEV_TYPE_UNKNOWN;
+               blkdev->block_read = usb_stor_read;
+               blkdev->block_write = usb_stor_write;
        }
 
        usb_max_devs = 0;
+#ifdef CONFIG_DM_USB
+       struct udevice *bus;
+       struct uclass *uc;
+       int ret;
+
+       ret = uclass_get(UCLASS_USB, &uc);
+       if (ret)
+               return ret;
+       uclass_foreach_dev(bus, uc) {
+               struct udevice *dev;
+
+               for (device_find_first_child(bus, &dev);
+                    dev;
+                    device_find_next_child(&dev)) {
+                       ret = device_probe(dev);
+                       if (!ret) {
+                               struct usb_device *udev;
+
+                               udev = dev_get_parentdata(dev);
+                               ret = usb_stor_probe_device(udev);
+                       }
+                       if (ret) {
+                               printf("Device '%s' probe failed: %d\n",
+                                      dev->name, ret);
+                       }
+               }
+       }
+#else
        for (i = 0; i < USB_MAX_DEVICE; i++) {
+               struct usb_device *dev;
+
                dev = usb_get_dev_index(i); /* get device */
                debug("i=%d\n", i);
-               if (dev == NULL)
-                       break; /* no more devices available */
-
-               if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
-                       /* OK, it's a storage device.  Iterate over its LUNs
-                        * and populate `usb_dev_desc'.
-                        */
-                       int lun, max_lun, start = usb_max_devs;
-
-                       max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
-                       for (lun = 0;
-                            lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
-                            lun++) {
-                               usb_dev_desc[usb_max_devs].lun = lun;
-                               if (usb_stor_get_info(dev, &usb_stor[start],
-                                   &usb_dev_desc[usb_max_devs]) == 1) {
-                                       usb_max_devs++;
-                               }
-                       }
-               }
-               /* if storage device */
-               if (usb_max_devs == USB_MAX_STOR_DEV) {
-                       printf("max USB Storage Device reached: %d stopping\n",
-                               usb_max_devs);
+               if (usb_stor_probe_device(dev))
                        break;
-               }
        } /* for */
+#endif
 
        usb_disable_asynch(0); /* asynch transfer allowed */
        printf("%d Storage Device(s) found\n", usb_max_devs);
@@ -1046,7 +1094,7 @@ unsigned long usb_stor_read(int device, lbaint_t blknr,
        unsigned short smallblks;
        struct usb_device *dev;
        struct us_data *ss;
-       int retry, i;
+       int retry;
        ccb *srb = &usb_ccb;
 
        if (blkcnt == 0)
@@ -1054,15 +1102,10 @@ unsigned long usb_stor_read(int device, lbaint_t blknr,
 
        device &= 0xff;
        /* Setup  device */
-       debug("\nusb_read: dev %d \n", device);
-       dev = NULL;
-       for (i = 0; i < USB_MAX_DEVICE; i++) {
-               dev = usb_get_dev_index(i);
-               if (dev == NULL)
-                       return 0;
-               if (dev->devnum == usb_dev_desc[device].target)
-                       break;
-       }
+       debug("\nusb_read: dev %d\n", device);
+       dev = usb_dev_desc[device].priv;
+       if (!dev)
+               return 0;
        ss = (struct us_data *)dev->privptr;
 
        usb_disable_asynch(1); /* asynch transfer not allowed */
@@ -1119,7 +1162,7 @@ unsigned long usb_stor_write(int device, lbaint_t blknr,
        unsigned short smallblks;
        struct usb_device *dev;
        struct us_data *ss;
-       int retry, i;
+       int retry;
        ccb *srb = &usb_ccb;
 
        if (blkcnt == 0)
@@ -1127,15 +1170,10 @@ unsigned long usb_stor_write(int device, lbaint_t blknr,
 
        device &= 0xff;
        /* Setup  device */
-       debug("\nusb_write: dev %d \n", device);
-       dev = NULL;
-       for (i = 0; i < USB_MAX_DEVICE; i++) {
-               dev = usb_get_dev_index(i);
-               if (dev == NULL)
-                       return 0;
-               if (dev->devnum == usb_dev_desc[device].target)
-                       break;
-       }
+       debug("\nusb_write: dev %d\n", device);
+       dev = usb_dev_desc[device].priv;
+       if (!dev)
+               return 0;
        ss = (struct us_data *)dev->privptr;
 
        usb_disable_asynch(1); /* asynch transfer not allowed */
drivers/usb/eth/usb_ether.c +39 -7
index 7cb96e3..4334d16 100644
@@ -5,7 +5,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <usb.h>
+#include <dm/device-internal.h>
 
 #include "usb_ether.h"
 
@@ -118,8 +120,6 @@ static void probe_valid_drivers(struct usb_device *dev)
 int usb_host_eth_scan(int mode)
 {
        int i, old_async;
-       struct usb_device *dev;
-
 
        if (mode == 1)
                printf("       scanning usb for ethernet devices... ");
@@ -138,7 +138,38 @@ int usb_host_eth_scan(int mode)
        }
 
        usb_max_eth_dev = 0;
+#ifdef CONFIG_DM_USB
+       struct udevice *bus;
+       struct uclass *uc;
+       int ret;
+
+       ret = uclass_get(UCLASS_USB, &uc);
+       if (ret)
+               return ret;
+       uclass_foreach_dev(bus, uc) {
+               for (i = 0; i < USB_MAX_DEVICE; i++) {
+                       struct usb_device *dev;
+
+                       dev = usb_get_dev_index(bus, i); /* get device */
+                       debug("i=%d\n", i);
+                       if (dev == NULL)
+                               break; /* no more devices available */
+
+                       /*
+                        * find valid usb_ether driver for this device,
+                        * if any
+                        */
+                       probe_valid_drivers(dev);
+
+                       /* check limit */
+                       if (usb_max_eth_dev == USB_MAX_ETH_DEV)
+                               break;
+               } /* for */
+       }
+#else
        for (i = 0; i < USB_MAX_DEVICE; i++) {
+               struct usb_device *dev;
+
                dev = usb_get_dev_index(i); /* get device */
                debug("i=%d\n", i);
                if (dev == NULL)
@@ -148,13 +179,14 @@ int usb_host_eth_scan(int mode)
                probe_valid_drivers(dev);
 
                /* check limit */
-               if (usb_max_eth_dev == USB_MAX_ETH_DEV) {
-                       printf("max USB Ethernet Device reached: %d stopping\n",
-                               usb_max_eth_dev);
+               if (usb_max_eth_dev == USB_MAX_ETH_DEV)
                        break;
-               }
        } /* for */
-
+#endif
+       if (usb_max_eth_dev == USB_MAX_ETH_DEV) {
+               printf("max USB Ethernet Device reached: %d stopping\n",
+                      usb_max_eth_dev);
+       }
        usb_disable_asynch(old_async); /* restore asynch value */
        printf("%d Ethernet Device(s) found\n", usb_max_eth_dev);
        if (usb_max_eth_dev > 0)
include/usb.h +16 -1
index a8fee0b..ba80eb8 100644
@@ -9,6 +9,7 @@
 #ifndef _USB_H_
 #define _USB_H_
 
+#include <fdtdec.h>
 #include <usb_defs.h>
 #include <linux/usb/ch9.h>
 #include <asm/cache.h>
@@ -130,6 +131,10 @@ struct usb_device {
        void *controller;               /* hardware controller private data */
        /* slot_id - for xHCI enabled devices */
        unsigned int slot_id;
+#ifdef CONFIG_DM_USB
+       char **strings;
+       struct udevice *controller_dev;
+#endif
 };
 
 struct int_queue;
@@ -245,7 +250,6 @@ int usb_stop(void); /* stop the USB Controller */
 int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
 int usb_set_idle(struct usb_device *dev, int ifnum, int duration,
                        int report_id);
-struct usb_device *usb_get_dev_index(int index);
 int usb_control_msg(struct usb_device *dev, unsigned int pipe,
                        unsigned char request, unsigned char requesttype,
                        unsigned short value, unsigned short index,
@@ -423,15 +427,79 @@ struct usb_hub_device {
        struct usb_hub_descriptor desc;
 };
 
+#ifdef CONFIG_DM_USB
+
+/* This is attached to each controller */
+struct dm_usb_info {
+       struct usb_device usb_dev[USB_MAX_DEVICE];
+       int dev_index;
+       struct udevice *dev;
+       void *controller;       /* struct xhci_ctrl, etc. */
+};
+
+struct dm_usb_ops {

include/usb.h struct usb_hub_device { · line 450

Quoted 10 lines
include/usb.h +10 -0
+       int (*hcd_init)(struct udevice *dev, fdt_addr_t *hccrp,
+                       fdt_addr_t *hcorp);
+       int (*control)(struct udevice *dev, struct usb_device *udev,
+                      unsigned long pipe, void *buffer, int length,
+                      struct devrequest *setup);
+       int (*bulk)(struct udevice *dev, struct usb_device *udev,
+                   unsigned long pipe, void *buffer, int length);
+       int (*interrupt)(struct udevice *dev, struct usb_device *udev,
+                        unsigned long pipe, void *buffer, int length,
+                        interval);

data type required for "interval". It gives build error.

Quoted 65 lines
include/usb.h +46 -4
+       int (*alloc_device)(struct udevice *dev, struct usb_device *udev);
+};
+
+#define usb_get_ops(dev)       ((struct dm_usb_ops *)(dev)->driver->ops)
+#define usb_get_emul_ops(dev)  ((struct dm_usb_ops *)(dev)->driver->ops)
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                  int length, int interval);
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe,
+                      void *buffer, int length, struct devrequest *setup);
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                   int length);
+
+#ifdef CONFIG_MUSB_HOST
+int usb_reset_root_port(void);
+#endif
+
+void usb_free_device(struct udevice *controller);
+/**
+ * usb_alloc_new_device() - Allocate a new device
+ *
+ * @devp: returns a pointer of a new device structure
+ * @return 0 if OK, -ENOSPC if we have found out of room for new devices
+ */
+int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp);
+
+struct usb_device *usb_get_dev_index(struct udevice *controller, int index);
+
+#else
+
+void usb_free_device(void *controller);
+/**
+ * usb_alloc_new_device() - Allocate a new device
+ *
+ * @devp: returns a pointer of a new device structure
+ * @return 0 if OK, -ENOSPC if we have found out of room for new devices
+ */
+int usb_alloc_new_device(void *controller, struct usb_device **devp);
+
+struct usb_device *usb_get_dev_index(int index);
+
+#endif
+
 int usb_hub_probe(struct usb_device *dev, int ifnum);
 void usb_hub_reset(void);
 int hub_port_reset(struct usb_device *dev, int port,
                          unsigned short *portstat);
 
-struct usb_device *usb_alloc_new_device(void *controller);
-
 int usb_new_device(struct usb_device *dev);
-void usb_free_device(void);
+
 int usb_alloc_device(struct usb_device *dev);
 
 #endif /*_USB_H_ */
--

2.2.0.rc0.207.ga3a616c

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Signature · 4 lines
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India
#8 lore raw

RFC PATCH 4/7 dm: usb: WIP sandbox USB implementation

In reply to Simon Glass

This shows the basic approach with a new directory containing sandbox emulations of USB devices for testing. So far hubs are not supported.

---

 Makefile                             |   1 +
 arch/sandbox/dts/sandbox.dts         |  20 +++++
 arch/sandbox/include/asm/processor.h |   0
 drivers/usb/dev/Makefile             |  10 +++
 drivers/usb/dev/sandbox-flash.c      |  95 ++++++++++++++++++++++
 drivers/usb/dev/sandbox-hub.c        | 116 +++++++++++++++++++++++++++
 drivers/usb/dev/usb-emul-uclass.c    |  16 ++++
 drivers/usb/host/Makefile            |   3 +
 drivers/usb/host/usb-sandbox.c       | 151 +++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h            |   3 +
 include/dm/uclass-id.h               |   1 +
 include/usb_defs.h                   |  14 ++--
 12 files changed, 424 insertions(+), 6 deletions(-)
 create mode 100644 arch/sandbox/include/asm/processor.h
 create mode 100644 drivers/usb/dev/Makefile
 create mode 100644 drivers/usb/dev/sandbox-flash.c
 create mode 100644 drivers/usb/dev/sandbox-hub.c
 create mode 100644 drivers/usb/dev/usb-emul-uclass.c
 create mode 100644 drivers/usb/host/usb-sandbox.c
Makefile +1 -0
index 9b406c8..836d93b 100644
@@ -632,6 +632,7 @@ libs-y += drivers/spi/
 libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
 libs-y += drivers/serial/
+libs-y += drivers/usb/dev/
 libs-y += drivers/usb/eth/
 libs-y += drivers/usb/gadget/
 libs-y += drivers/usb/host/
arch/sandbox/dts/sandbox.dts +20 -0
index 9ce31bf..7d22920 100644
@@ -181,4 +181,24 @@
 		};
 	};
 
+	usb at 0 {
+		compatible = "sandbox,usb";
+		status = "disabled";
+		flash-stick {
+			compatible = "sandbox,usb-flash";
+		};
+	};
+
+	usb at 1 {
+		compatible = "sandbox,usb";
+		flash-stick {
+			compatible = "sandbox,usb-hub";
+		};
+	};
+
+	usb at 2 {
+		compatible = "sandbox,usb";
+		status = "disabled";
+	};
+
 };
arch/sandbox/include/asm/processor.h new file +0 -0
new file mode 100644
index 0000000..e69de29
drivers/usb/dev/Makefile new file +10 -0
new file mode 100644
index 0000000..a741f45
@@ -0,0 +1,10 @@
+#
+# (C) Copyright 2015 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_SANDBOX) += sandbox-flash.o
+obj-$(CONFIG_SANDBOX) += sandbox-hub.o
+obj-$(CONFIG_SANDBOX) += usb-emul-uclass.o
drivers/usb/dev/sandbox-flash.c new file +95 -0

95 lines not on this page · raw message

drivers/usb/dev/sandbox-hub.c new file +116 -0

116 lines not on this page · raw message

drivers/usb/dev/usb-emul-uclass.c new file +16 -0
new file mode 100644
index 0000000..4114df0
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+
+UCLASS_DRIVER(usb_emul) = {
+	.id		= UCLASS_USB_EMUL,
+	.name		= "usb_emul",
+	.per_device_auto_alloc_size = sizeof(struct usb_device),
+};
drivers/usb/host/Makefile +3 -0
index d0b890a..de8354a 100644
@@ -6,6 +6,9 @@
 #
 
 obj-$(CONFIG_DM_USB) += usb-uclass.o
+ifdef CONFIG_DM_USB
+obj-$(CONFIG_SANDBOX) += usb-sandbox.o
+endif
 
 # ohci
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
drivers/usb/host/usb-sandbox.c new file +151 -0

151 lines not on this page · raw message

include/configs/sandbox.h +3 -0
index e9d3f32..392a40f 100644
@@ -201,4 +201,7 @@
 
 #define CONFIG_CMD_LZMADEC
 
+#define CONFIG_CMD_USB
+#define CONFIG_DM_USB
+
 #endif
include/dm/uclass-id.h +1 -0
index baab810..1c33fa6 100644
@@ -20,6 +20,7 @@ enum uclass_id {
 	UCLASS_TEST_BUS,
 	UCLASS_SPI_EMUL,	/* sandbox SPI device emulator */
 	UCLASS_I2C_EMUL,	/* sandbox I2C device emulator */
+	UCLASS_USB_EMUL,	/* sandbox USB bus device emulator */
 	UCLASS_SIMPLE_BUS,
 
 	/* U-Boot uclasses start here */
include/usb_defs.h +8 -6
index 236a5ec..b580bf0 100644
@@ -165,12 +165,14 @@
 #define USB_TEST_MODE_FORCE_ENABLE  0x05
 
 
-/* "pipe" definitions */
-
-#define PIPE_ISOCHRONOUS    0
-#define PIPE_INTERRUPT      1
-#define PIPE_CONTROL        2
-#define PIPE_BULK           3
+/*
+ * "pipe" definitions, use unsigned so we can compare reliably, since this
+ * value is shifted up to bits 30/31.
+ */
+#define PIPE_ISOCHRONOUS    0U
+#define PIPE_INTERRUPT      1U
+#define PIPE_CONTROL        2U
+#define PIPE_BULK           3U
 #define PIPE_DEVEP_MASK     0x0007ff00
 
 #define USB_ISOCHRONOUS    0
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#9 lore raw

RFC PATCH 5/7 dm: core: Add a function to get the uclass data for a device

In reply to Simon Glass

This is a convenience function only so far. Eventually it could have some consistency checking added.

---

 drivers/core/device.c | 10 ++++++++++
 include/dm/device.h   | 10 ++++++++++
 2 files changed, 20 insertions(+)
drivers/core/device.c +10 -0
index b73d3b8..fbb377b 100644
@@ -305,6 +305,16 @@ void *dev_get_priv(struct udevice *dev)
 	return dev->priv;
 }
 
+void *dev_get_uclass_priv(struct udevice *dev)
+{
+	if (!dev) {
+		dm_warn("%s: null device\n", __func__);
+		return NULL;
+	}
+
+	return dev->uclass_priv;
+}
+
 void *dev_get_parentdata(struct udevice *dev)
 {
 	if (!dev) {
include/dm/device.h +10 -0
index 81afa8c..511dbd9 100644
@@ -229,6 +229,16 @@ void *dev_get_parentdata(struct udevice *dev);
 void *dev_get_priv(struct udevice *dev);
 
 /**
+ * dev_get_uclass_priv() - Get the private data for a device's class
+ *
+ * This checks that dev is not NULL, but no other checks for now
+ *
+ * @dev		Device to check
+ * @return uclass private data, or NULL if none
+ */
+void *dev_get_uclass_priv(struct udevice *dev);
+
+/**
  * struct dev_get_parent() - Get the parent of a device
  *
  * @child:	Child to check
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#10 lore raw

RFC PATCH 6/7 arm: Show relocated PC/LR in the register dump

In reply to Simon Glass

If we don't know the relocation address, the raw values are not very useful. Show the pre-relocation values as well as these can be looked up in System.map, etc.

---

 arch/arm/lib/interrupts.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/arm/lib/interrupts.c +9 -4
index 4dacfd9..06f4679 100644
@@ -137,10 +137,15 @@ void show_regs (struct pt_regs *regs)
 
 	flags = condition_codes (regs);
 
-	printf ("pc : [<%08lx>]	   lr : [<%08lx>]\n"
-		"sp : %08lx  ip : %08lx	 fp : %08lx\n",
-		instruction_pointer (regs),
-		regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+	printf("pc : [<%08lx>]	   lr : [<%08lx>]\n",
+	       instruction_pointer(regs), regs->ARM_lr);
+	if (gd->flags & GD_FLG_RELOC) {
+		printf("reloc pc : [<%08lx>]	   lr : [<%08lx>]\n",
+		       instruction_pointer(regs) - gd->reloc_off,
+		       regs->ARM_lr - gd->reloc_off);
+	}
+	printf("sp : %08lx  ip : %08lx	 fp : %08lx\n",
+	       regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
 	printf ("r10: %08lx  r9 : %08lx	 r8 : %08lx\n",
 		regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
 	printf ("r7 : %08lx  r6 : %08lx	 r5 : %08lx  r4 : %08lx\n",
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#11 lore raw

RFC PATCH 6/7 arm: Show relocated PC/LR in the register dump

Hello Simon,

Quoted 5 lines · Simon Glass

If we don't know the relocation address, the raw values are not very useful. Show the pre-relocation values as well as these can be looked up in System.map, etc.

Simon, I think this one go straight into the ARM tree despite being an RFC patch in a series -- it's useful, pretty much standalone and it won't prevent any target from booting.

Amicalement,

Signature · 1 line
Albert.
#12 lore raw

RFC PATCH 6/7 arm: Show relocated PC/LR in the register dump

Hi Albert,

Quoted 8 lines · Albert ARIBAUD

Hello Simon,

Quoted 4 lines · Simon Glass

If we don't know the relocation address, the raw values are not very useful. Show the pre-relocation values as well as these can be looked up in System.map, etc.

Quoted 7 lines
Quoted 1 line

Simon, I think this one go straight into the ARM tree despite being an RFC patch in a series -- it's useful, pretty much standalone and it won't prevent any target from booting.

Sure, I think it is safe.

Regards,
Simon

#13 lore raw

RFC PATCH 6/7 arm: Show relocated PC/LR in the register dump

In reply to Simon Glass

Hello Simon,

Quoted 37 lines · Simon Glass

If we don't know the relocation address, the raw values are not very useful. Show the pre-relocation values as well as these can be looked up in System.map, etc.

---

 arch/arm/lib/interrupts.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/arm/lib/interrupts.c +9 -4
index 4dacfd9..06f4679 100644
@@ -137,10 +137,15 @@ void show_regs (struct pt_regs *regs)
 
 	flags = condition_codes (regs);
 
-	printf ("pc : [<%08lx>]	   lr : [<%08lx>]\n"
-		"sp : %08lx  ip : %08lx	 fp : %08lx\n",
-		instruction_pointer (regs),
-		regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+	printf("pc : [<%08lx>]	   lr : [<%08lx>]\n",
+	       instruction_pointer(regs), regs->ARM_lr);
+	if (gd->flags & GD_FLG_RELOC) {
+		printf("reloc pc : [<%08lx>]	   lr : [<%08lx>]\n",
+		       instruction_pointer(regs) - gd->reloc_off,
+		       regs->ARM_lr - gd->reloc_off);
+	}
+	printf("sp : %08lx  ip : %08lx	 fp : %08lx\n",
+	       regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
 	printf ("r10: %08lx  r9 : %08lx	 r8 : %08lx\n",
 		regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
 	printf ("r7 : %08lx  r6 : %08lx	 r5 : %08lx  r4 : %08lx\n",
Signature · 1 line
2.2.0.rc0.207.ga3a616c

Applied as a "bugfix" to u-boot-arm/master, thanks!

Amicalement,

Signature · 1 line
Albert.
#14 lore raw

RFC PATCH 7/7 dm: exynos: Enable driver model for snow XHCI

In reply to Simon Glass

Switch snow over to use driver model for USB.

---

 include/configs/snow.h | 1 +
 1 file changed, 1 insertion(+)
include/configs/snow.h +1 -0
index ce6676e..00bd646 100644
@@ -27,6 +27,7 @@
 #define CONFIG_BOARD_COMMON
 #define CONFIG_ARCH_EARLY_INIT_R
 
+#define CONFIG_DM_USB
 #define CONFIG_USB_XHCI
 #define CONFIG_USB_XHCI_EXYNOS
 
Signature · 1 line
2.2.0.rc0.207.ga3a616c
#15 lore raw

cover RFC: dm: Add USB support

In reply to Simon Glass
Quoted 24 lines · Simon Glass

This series adds basic driver model support to USB. The intent is to permit the various subsystems (OHCI, EHCI, XHCI) to co-exist and allow any number of USB ports of different types. So far the absolute limit on the number of USB devices is only slightly relaxed.

Only USB controllers have a real driver model device. USB devices (including the hub in the controller) are not modelled as driver model devices. This is for two reasons:

- it is easier since we don't need to bind a whole lot of devices when scanning
- the two main USB devices (block devices and Ethernet) don't have driver mode support yet anyway, so it would be pointless. However the recent network RFC has encouraged me to send this.

The basic approach is to set up the driver model structures in parallel to what already exists rather than to replace them. This allows both driver model and legacy to be used for USB, although not with the same board.

So far only XHCI is supported. As an example the Exynos XHCI driver is converted to driver model.

I would appreciate comments before going further.

Quoted 8 lines

Caveats:
- sandbox code is incomplete and there are no tests
- 'usb stop' does not remove existing devices (I have not yet settled on the best approach)
- the usb.h changes need to be split correctly into the patches once they are final

This series is available at u-boot-dm/usb-working.

Hi!

I'll look at this by the end of next week, I will be free by then. It's not possible for me to do it earlier, sorry. Does this still work for you please?

Best regards,
Marek Vasut

#16 lore raw

cover RFC: dm: Add USB support

Hi Marek,

Quoted 33 lines · Marek Vasut
Quoted 31 lines · Simon Glass

This series adds basic driver model support to USB. The intent is to permit the various subsystems (OHCI, EHCI, XHCI) to co-exist and allow any number of USB ports of different types. So far the absolute limit on the number of USB devices is only slightly relaxed.

Only USB controllers have a real driver model device. USB devices (including the hub in the controller) are not modelled as driver model devices. This is for two reasons:

- it is easier since we don't need to bind a whole lot of devices when scanning
- the two main USB devices (block devices and Ethernet) don't have driver mode support yet anyway, so it would be pointless. However the recent network RFC has encouraged me to send this.

The basic approach is to set up the driver model structures in parallel to what already exists rather than to replace them. This allows both driver model and legacy to be used for USB, although not with the same board.

So far only XHCI is supported. As an example the Exynos XHCI driver is converted to driver model.

I would appreciate comments before going further.

Caveats:
- sandbox code is incomplete and there are no tests
- 'usb stop' does not remove existing devices (I have not yet settled on the best approach)
- the usb.h changes need to be split correctly into the patches once they are final

Quoted 7 lines
Quoted 1 line

This series is available at u-boot-dm/usb-working.

Hi!

I'll look at this by the end of next week, I will be free by then. It's not possible for me to do it earlier, sorry. Does this still work for you please?

Definitely, that sounds good. I was planning to leave it a week or two anyway, although I might fiddle more with the sandbox side in the meantime.

Regards,
Simon

#17 lore raw

cover RFC: dm: Add USB support

Quoted 1 line · Simon Glass

Hi Marek,

Hi!

Quoted 44 lines · Marek Vasut
Quoted 43 lines · Simon Glass
Quoted 36 lines

This series adds basic driver model support to USB. The intent is to permit the various subsystems (OHCI, EHCI, XHCI) to co-exist and allow any number of USB ports of different types. So far the absolute limit on the number of USB devices is only slightly relaxed.

Only USB controllers have a real driver model device. USB devices (including the hub in the controller) are not modelled as driver model devices. This is for two reasons:

- it is easier since we don't need to bind a whole lot of devices when

scanning

- the two main USB devices (block devices and Ethernet) don't have driver

mode support yet anyway, so it would be pointless. However the recent network RFC has encouraged me to send this.

The basic approach is to set up the driver model structures in parallel to what already exists rather than to replace them. This allows both driver model and legacy to be used for USB, although not with the same board.

So far only XHCI is supported. As an example the Exynos XHCI driver is converted to driver model.

I would appreciate comments before going further.

Caveats:
- sandbox code is incomplete and there are no tests
- 'usb stop' does not remove existing devices (I have not yet settled on the best approach)
- the usb.h changes need to be split correctly into the patches once they

Quoted 3 lines

are final

This series is available at u-boot-dm/usb-working.

Hi!

Quoted 7 lines
Quoted 3 lines

I'll look at this by the end of next week, I will be free by then. It's not possible for me to do it earlier, sorry. Does this still work for you please?

Definitely, that sounds good. I was planning to leave it a week or two anyway, although I might fiddle more with the sandbox side in the meantime.

I skimmed through the series finally, it looks mostly good for but a few minor coding style things. I would prefer if this went in for the next MW, what do you think please ?

Best regards,
Marek Vasut

#18 lore raw

cover RFC: dm: Add USB support

Hi Marek,

Quoted 53 lines · Marek Vasut
Quoted 1 line · Simon Glass

Hi Marek,

Hi!

Quoted 48 lines · Marek Vasut
Quoted 46 lines · Simon Glass
Quoted 36 lines

This series adds basic driver model support to USB. The intent is to permit the various subsystems (OHCI, EHCI, XHCI) to co-exist and allow any number of USB ports of different types. So far the absolute limit on the number of USB devices is only slightly relaxed.

Only USB controllers have a real driver model device. USB devices (including the hub in the controller) are not modelled as driver model devices. This is for two reasons:

- it is easier since we don't need to bind a whole lot of devices when

scanning

- the two main USB devices (block devices and Ethernet) don't have driver

mode support yet anyway, so it would be pointless. However the recent network RFC has encouraged me to send this.

The basic approach is to set up the driver model structures in parallel to what already exists rather than to replace them. This allows both driver model and legacy to be used for USB, although not with the same board.

So far only XHCI is supported. As an example the Exynos XHCI driver is converted to driver model.

I would appreciate comments before going further.

Caveats:
- sandbox code is incomplete and there are no tests
- 'usb stop' does not remove existing devices (I have not yet settled on the best approach)
- the usb.h changes need to be split correctly into the patches once they

Quoted 3 lines

are final

This series is available at u-boot-dm/usb-working.

Hi!

I'll look at this by the end of next week, I will be free by then. It's not possible for me to do it earlier, sorry. Does this still work for you please?

Quoted 7 lines
Quoted 3 lines

Definitely, that sounds good. I was planning to leave it a week or two anyway, although I might fiddle more with the sandbox side in the meantime.

I skimmed through the series finally, it looks mostly good for but a few minor coding style things. I would prefer if this went in for the next MW, what do you think please ?

Sounds good, hopefully we can bring in wider driver support too. I'd like to get this lot in before thinking too hard about how to deal with actual devices! Maybe we can target getting this series cleaned up and into u-boot-dm/next by end of Feb?

Regards,
Simon

#19 lore raw

cover RFC: dm: Add USB support

Quoted 1 line · Simon Glass

Hi Marek,

Hi!

[...]

Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 5 lines

Hi!

I'll look at this by the end of next week, I will be free by then. It's not possible for me to do it earlier, sorry. Does this still work for you please?

Definitely, that sounds good. I was planning to leave it a week or two anyway, although I might fiddle more with the sandbox side in the meantime.

Quoted 8 lines
Quoted 3 lines

I skimmed through the series finally, it looks mostly good for but a few minor coding style things. I would prefer if this went in for the next MW, what do you think please ?

Sounds good, hopefully we can bring in wider driver support too. I'd like to get this lot in before thinking too hard about how to deal with actual devices! Maybe we can target getting this series cleaned up and into u-boot-dm/next by end of Feb?

I'll be happy to see it there, yes.

Thank you!

Best regards,
Marek Vasut

#20 lore raw

cover RFC: dm: Add USB support

In reply to Simon Glass

Hi Simon,

Quoted 24 lines · Simon Glass

This series adds basic driver model support to USB. The intent is to permit the various subsystems (OHCI, EHCI, XHCI) to co-exist and allow any number of USB ports of different types. So far the absolute limit on the number of USB devices is only slightly relaxed.

Only USB controllers have a real driver model device. USB devices (including the hub in the controller) are not modelled as driver model devices. This is for two reasons:

- it is easier since we don't need to bind a whole lot of devices when scanning
- the two main USB devices (block devices and Ethernet) don't have driver mode support yet anyway, so it would be pointless. However the recent network RFC has encouraged me to send this.

The basic approach is to set up the driver model structures in parallel to what already exists rather than to replace them. This allows both driver model and legacy to be used for USB, although not with the same board.

So far only XHCI is supported. As an example the Exynos XHCI driver is converted to driver model.

I would appreciate comments before going further.

Quoted 8 lines

Caveats:
- sandbox code is incomplete and there are no tests
- 'usb stop' does not remove existing devices (I have not yet settled on the best approach)
- the usb.h changes need to be split correctly into the patches once they are final

This series is available at u-boot-dm/usb-working.

Just ran a quick test on smdk5250. I used Below is what i get :

--------------------------------------------------------------------------------------
SMDK5250 # usb start
starting USB...
USBRegister 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
0: scanning bus 0 for devices... cannot reset port 1!?
1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found
SMDK5250 # usb start
starting USB...
USB0: scanning bus 0 for devices... BUG: failure at
drivers/usb/host/xhci-mem.c:666/xhci_setup_addressable_virt_dev()! BUG!
resetting ...
--------------------------------------------------------------------------------------

The first time when "scanning bus 0 for devices... cannot reset port 1!?" comes. This seems to be smdk issue only which i am looking into currently.

But the second time when i run usb start, the setup itself hits a NULL pointer it seems.
However just tot of u-boot-dm doesn't give this issue. The device gets detected when "usb reset" is used after doing a "usb start" first time.

Even with my patch series, i hit a NULL pointer BUG, when doing a "usb reset"

--------------------------------------------------------------------------------------
SMDK5250 # usb reset
resetting USB...
Host not halted after 16000 microseconds.

BUG: failure at drivers/usb/host/xhci-mem.c:83/xhci_ring_free()!

BUG!
resetting ...
--------------------------------------------------------------------------------------
However i could understand why this is coming, since usb_lowlevel_stop() called in xhci.c; at that time xhci's data structures are not initialized, and we
hit this BUG.

I will check further on snow.

Quoted 53 lines

Simon Glass (7):
dm: usb: Add a uclass for USB controllers
dm: usb: Support driver model in exynos XHCI
dm: usb: Adjust users of the USB stack to work with driver model
dm: usb: WIP sandbox USB implementation
dm: core: Add a function to get the uclass data for a device
arm: Show relocated PC/LR in the register dump
dm: exynos: Enable driver model for snow XHCI

 Makefile                             |   1 +
 arch/arm/lib/interrupts.c            |  13 +-
 arch/sandbox/dts/sandbox.dts         |  20 +++
 arch/sandbox/include/asm/processor.h |   0
 common/cmd_usb.c                     |  74 ++++++++---
 common/usb.c                         |  28 +++--
 common/usb_hub.c                     |  13 +-
 common/usb_storage.c                 | 148 +++++++++++++---------
 drivers/core/device.c                |  10 ++
 drivers/usb/dev/Makefile             |  10 ++
 drivers/usb/dev/sandbox-flash.c      |  95 +++++++++++++++
 drivers/usb/dev/sandbox-hub.c        | 116 ++++++++++++++++++
 drivers/usb/dev/usb-emul-uclass.c    |  16 +++
 drivers/usb/eth/usb_ether.c          |  46 +++++--
 drivers/usb/host/Makefile            |   5 +
 drivers/usb/host/usb-sandbox.c       | 151 +++++++++++++++++++++++
 drivers/usb/host/usb-uclass.c        | 227 ++++++++++++++++++++++++++++++++++
 drivers/usb/host/xhci-exynos5.c      | 115 +++++++++++++++++-
 drivers/usb/host/xhci.c              | 229 ++++++++++++++++++++++++++++-------
 drivers/usb/host/xhci.h              |  24 ++++
 include/configs/sandbox.h            |   3 +
 include/configs/snow.h               |   1 +
 include/dm/device.h                  |  10 ++
 include/dm/uclass-id.h               |   2 +
 include/usb.h                        |  76 +++++++++++-
 include/usb_defs.h                   |  14 ++-
 26 files changed, 1294 insertions(+), 153 deletions(-)
 create mode 100644 arch/sandbox/include/asm/processor.h
 create mode 100644 drivers/usb/dev/Makefile
 create mode 100644 drivers/usb/dev/sandbox-flash.c
 create mode 100644 drivers/usb/dev/sandbox-hub.c
 create mode 100644 drivers/usb/dev/usb-emul-uclass.c
 create mode 100644 drivers/usb/host/usb-sandbox.c
 create mode 100644 drivers/usb/host/usb-uclass.c

--
2.2.0.rc0.207.ga3a616c

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Signature · 4 lines
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India