All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
@ 2015-01-30 19:04 Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers Simon Glass
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

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

-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-02-09 20:59   ` Marek Vasut
  2015-03-09  6:20   ` Vivek Gautam
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 2/7] dm: usb: Support driver model in exynos XHCI Simon Glass
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 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

diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c11b551..d0b890a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -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
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
new file mode 100644
index 0000000..86564db
--- /dev/null
+++ b/drivers/usb/host/usb-uclass.c
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * 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;
+}
+
+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;
+	ret = uclass_get(UCLASS_USB, &uc);
+	if (ret)
+		return ret;
+	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,
+*/
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..baab810 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -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

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 2/7] dm: usb: Support driver model in exynos XHCI
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 3/7] dm: usb: Adjust users of the USB stack to work with driver model Simon Glass
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

(This patch will be split for submission)

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 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(-)

diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c
index a77c8bc..e61f39e 100644
--- a/drivers/usb/host/xhci-exynos5.c
+++ b/drivers/usb/host/xhci-exynos5.c
@@ -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
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 87f2972..fa3a5c5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -21,6 +21,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/byteorder.h>
 #include <usb.h>
 #include <malloc.h>
@@ -108,7 +109,9 @@ static struct descriptor {
 	},
 };
 
+#ifndef CONFIG_DM_USB
 static struct xhci_ctrl xhcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
+#endif
 
 /**
  * Waits for as per specified amount of time
@@ -461,10 +464,10 @@ static int xhci_address_device(struct usb_device *udev)
  * @param udev	pointer to the Device Data Structure
  * @return Returns 0 on succes else return error code on failure
  */
-int usb_alloc_device(struct usb_device *udev)
+int _xhci_alloc_device(struct usb_device *udev)
 {
-	union xhci_trb *event;
 	struct xhci_ctrl *ctrl = udev->controller;
+	union xhci_trb *event;
 	int ret;
 
 	/*
@@ -499,6 +502,13 @@ int usb_alloc_device(struct usb_device *udev)
 	return 0;
 }
 
+#ifndef CONFIG_DM_USB
+int usb_alloc_device(struct usb_device *udev)
+{
+	return _xhci_alloc_device(udev);
+}
+#endif
+
 /*
  * Full speed devices may have a max packet size greater than 8 bytes, but the
  * USB core doesn't know that until it reads the first 8 bytes of the
@@ -858,9 +868,8 @@ unknown:
  * @param interval	interval of the interrupt
  * @return 0
  */
-int
-submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
-						int length, int interval)
+static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe,
+				void *buffer, int length, int interval)
 {
 	/*
 	 * TODO: Not addressing any interrupt type transfer requests
@@ -878,9 +887,8 @@ submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
  * @param length	length of the buffer
  * @return returns 0 if successful else -1 on failure
  */
-int
-submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
-								int length)
+static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe,
+				 void *buffer, int length)
 {
 	if (usb_pipetype(pipe) != PIPE_BULK) {
 		printf("non-bulk pipe (type=%lu)", usb_pipetype(pipe));
@@ -900,9 +908,9 @@ submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
  * @param setup		Request type
  * @return returns 0 if successful else -1 on failure
  */
-int
-submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
-					int length, struct devrequest *setup)
+static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
+				    void *buffer, int length,
+				    struct devrequest *setup)
 {
 	struct xhci_ctrl *ctrl = udev->controller;
 	int ret = 0;
@@ -929,33 +937,16 @@ submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
 	return xhci_ctrl_tx(udev, pipe, setup, length, buffer);
 }
 
-/**
- * Intialises the XHCI host controller
- * and allocates the necessary data structures
- *
- * @param index	index to the host controller data structure
- * @return pointer to the intialised controller
- */
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+static int xhci_lowlevel_init(struct xhci_ctrl *ctrl)
 {
+	struct xhci_hccr *hccr;
+	struct xhci_hcor *hcor;
 	uint32_t val;
 	uint32_t val2;
 	uint32_t reg;
-	struct xhci_hccr *hccr;
-	struct xhci_hcor *hcor;
-	struct xhci_ctrl *ctrl;
-
-	if (xhci_hcd_init(index, &hccr, (struct xhci_hcor **)&hcor) != 0)
-		return -ENODEV;
-
-	if (xhci_reset(hcor) != 0)
-		return -ENODEV;
-
-	ctrl = &xhcic[index];
-
-	ctrl->hccr = hccr;
-	ctrl->hcor = hcor;
 
+	hccr = ctrl->hccr;
+	hcor = ctrl->hcor;
 	/*
 	 * Program the Number of Device Slots Enabled field in the CONFIG
 	 * register with the max value of slots the HC can handle.
@@ -997,11 +988,75 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 	reg = HC_VERSION(xhci_readl(&hccr->cr_capbase));
 	printf("USB XHCI %x.%02x\n", reg >> 8, reg & 0xff);
 
-	*controller = &xhcic[index];
+	return 0;
+}
+
+static int xhci_lowlevel_stop(struct xhci_ctrl *ctrl)
+{
+	u32 temp;
+
+	xhci_reset(ctrl->hcor);
+
+	debug("// Disabling event ring interrupts\n");
+	temp = xhci_readl(&ctrl->hcor->or_usbsts);
+	xhci_writel(&ctrl->hcor->or_usbsts, temp & ~STS_EINT);
+	temp = xhci_readl(&ctrl->ir_set->irq_pending);
+	xhci_writel(&ctrl->ir_set->irq_pending, ER_IRQ_DISABLE(temp));
 
 	return 0;
 }
 
+#ifndef CONFIG_DM_USB
+int submit_control_msg(struct usb_device *udev, unsigned long pipe,
+		       void *buffer, int length, struct devrequest *setup)
+{
+	return _xhci_submit_control_msg(udev, pipe, buffer, length, setup);
+}
+
+int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+		    int length)
+{
+	return _xhci_submit_bulk_msg(udev, pipe, buffer, length);
+}
+
+int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer,
+		   int length, int interval)
+{
+	return _xhci_submit_int_msg(udev, pipe, buffer, length, interval);
+}
+
+/**
+ * Intialises the XHCI host controller
+ * and allocates the necessary data structures
+ *
+ * @param index	index to the host controller data structure
+ * @return pointer to the intialised controller
+ */
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+{
+	struct xhci_hccr *hccr;
+	struct xhci_hcor *hcor;
+	struct xhci_ctrl *ctrl;
+	int ret;
+
+	if (xhci_hcd_init(index, &hccr, (struct xhci_hcor **)&hcor) != 0)
+		return -ENODEV;
+
+	if (xhci_reset(hcor) != 0)
+		return -ENODEV;
+
+	ctrl = &xhcic[index];
+
+	ctrl->hccr = hccr;
+	ctrl->hcor = hcor;
+
+	ret = xhci_lowlevel_init(ctrl);
+
+	*controller = &xhcic[index];
+
+	return ret;
+}
+
 /**
  * Stops the XHCI host controller
  * and cleans up all the related data structures
@@ -1012,19 +1067,109 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 int usb_lowlevel_stop(int index)
 {
 	struct xhci_ctrl *ctrl = (xhcic + index);
-	u32 temp;
 
-	xhci_reset(ctrl->hcor);
+	xhci_lowlevel_stop(ctrl);
+	xhci_hcd_stop(index);
+	xhci_cleanup(ctrl);
 
-	debug("// Disabling event ring interrupts\n");
-	temp = xhci_readl(&ctrl->hcor->or_usbsts);
-	xhci_writel(&ctrl->hcor->or_usbsts, temp & ~STS_EINT);
-	temp = xhci_readl(&ctrl->ir_set->irq_pending);
-	xhci_writel(&ctrl->ir_set->irq_pending, ER_IRQ_DISABLE(temp));
+	return 0;
+}
+#endif /* CONFIG_DM_USB */
 
-	xhci_hcd_stop(index);
+#ifdef CONFIG_DM_USB
+/*
+static struct usb_device *get_usb_device(struct udevice *dev)
+{
+	struct usb_device *udev;
 
+	if (device_get_uclass_id(dev) == UCLASS_USB)
+		udev = dev_get_uclass_priv(dev);
+	else
+		udev = dev_get_parentdata(dev);
+
+	return udev;
+}
+*/
+static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev,
+				   unsigned long pipe, void *buffer, int length,
+				   struct devrequest *setup)
+{
+	debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+	return _xhci_submit_control_msg(udev, pipe, buffer, length, setup);
+}
+
+static int xhci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev,
+				unsigned long pipe, void *buffer, int length)
+{
+	debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+	return _xhci_submit_bulk_msg(udev, pipe, buffer, length);
+}
+
+static int xhci_submit_int_msg(struct udevice *dev, struct usb_device *udev,
+			       unsigned long pipe, void *buffer, int length,
+			       int interval)
+{
+	debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+	return _xhci_submit_int_msg(udev, pipe, buffer, length, interval);
+}
+
+static int xhci_alloc_device(struct udevice *dev, struct usb_device *udev)
+{
+	debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+	return _xhci_alloc_device(udev);
+}
+
+int xhci_register(struct udevice *dev, struct xhci_hccr *hccr,
+		  struct xhci_hcor *hcor)
+{
+	struct dm_usb_info *usb = dev_get_uclass_priv(dev);
+	struct xhci_ctrl *ctrl;
+	int ret;
+
+	debug("%s: dev='%s', hccr=%p, hcor=%p\n", __func__, dev->name,
+	      hccr, hcor);
+	ctrl = calloc(1, sizeof(*ctrl));
+	if (!ctrl)
+		return -ENOMEM;
+
+	ctrl->dev = dev;
+	usb->dev = dev;
+	usb->controller = ctrl;
+
+	ret = xhci_reset(hcor);
+	if (ret)
+		goto err;
+
+	ctrl->hccr = hccr;
+	ctrl->hcor = hcor;
+	ret = xhci_lowlevel_init(ctrl);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	free(ctrl);
+	debug("%s: failed, ret=%d\n", __func__, ret);
+	return ret;
+}
+
+int xhci_deregister(struct udevice *dev)
+{
+	struct dm_usb_info *usb = dev_get_uclass_priv(dev);
+	struct xhci_ctrl *ctrl = usb->controller;
+
+	xhci_lowlevel_stop(ctrl);
 	xhci_cleanup(ctrl);
+	free(ctrl);
 
 	return 0;
 }
+
+struct dm_usb_ops xhci_usb_ops = {
+	.control = xhci_submit_control_msg,
+	.bulk = xhci_submit_bulk_msg,
+	.interrupt = xhci_submit_int_msg,
+	.alloc_device = xhci_alloc_device,
+};
+
+#endif
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6685ed2..f9fd99e 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -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_ */
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 3/7] dm: usb: Adjust users of the USB stack to work with driver model
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 2/7] dm: usb: Support driver model in exynos XHCI Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-02-25 14:09   ` Vivek Gautam
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 4/7] dm: usb: WIP sandbox USB implementation Simon Glass
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 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(-)

diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 27813f0..b824634 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -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)
diff --git a/common/usb.c b/common/usb.c
index 32e15cd..3ccf8a7 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -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
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 66b4a72..ccdf755 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -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);
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 1411737..8fb2c18 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -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 */
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 7cb96e3..4334d16 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -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)
diff --git a/include/usb.h b/include/usb.h
index a8fee0b..ba80eb8 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -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 {
+	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);
+	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

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 4/7] dm: usb: WIP sandbox USB implementation
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
                   ` (2 preceding siblings ...)
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 3/7] dm: usb: Adjust users of the USB stack to work with driver model Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 5/7] dm: core: Add a function to get the uclass data for a device Simon Glass
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 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

diff --git a/Makefile b/Makefile
index 9b406c8..836d93b 100644
--- a/Makefile
+++ b/Makefile
@@ -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/
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9ce31bf..7d22920 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -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";
+	};
+
 };
diff --git a/arch/sandbox/include/asm/processor.h b/arch/sandbox/include/asm/processor.h
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/usb/dev/Makefile b/drivers/usb/dev/Makefile
new file mode 100644
index 0000000..a741f45
--- /dev/null
+++ b/drivers/usb/dev/Makefile
@@ -0,0 +1,10 @@
+#
+# (C) Copyright 2015 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# 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
diff --git a/drivers/usb/dev/sandbox-flash.c b/drivers/usb/dev/sandbox-flash.c
new file mode 100644
index 0000000..51aec69
--- /dev/null
+++ b/drivers/usb/dev/sandbox-flash.c
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#define DEBUG
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+
+enum {
+	STRINGID_null,
+	STRINGID_manufacterer,
+	STRINGID_product,
+	STRINGID_serial,
+
+	STRINGID_count,
+};
+
+static char *usb_strings[] = {
+	"",
+	"sandbox",
+	"flash_emulator",
+	"1234",
+	NULL,
+};
+
+static int sandbox_flash_submit_control_msg(struct udevice *dev,
+					    unsigned long pipe,
+					    void *buffer, int length,
+					    struct devrequest *setup)
+{
+	struct usb_device *udev = dev_get_uclass_priv(dev);
+
+	if (pipe == usb_rcvctrlpipe(udev, 0)) {
+		switch (setup->request) {
+		case USB_REQ_GET_DESCRIPTOR:
+			memcpy(buffer, &udev->descriptor, length);
+			udev->status = 0;
+			udev->act_len = length;
+			return 0;
+		default:
+			debug("request=%x\n", setup->request);
+			break;
+		}
+	}
+	debug("pipe=%lx\n", pipe);
+
+	return -EIO;
+}
+
+static int sandbox_flash_probe(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_uclass_priv(dev);
+	struct usb_device_descriptor *desc;
+	struct usb_config_descriptor *cdesc;
+
+	udev->strings = usb_strings;
+	desc = &udev->descriptor;
+	desc->iManufacturer = STRINGID_manufacterer;
+	desc->iProduct = STRINGID_product;
+	desc->iSerialNumber = STRINGID_serial;
+
+	udev->maxpacketsize = PACKET_SIZE_64;
+
+	cdesc = &udev->config.desc;
+	cdesc->bLength = sizeof(*cdesc);
+	cdesc->bDescriptorType = USB_DT_CONFIG;
+	cdesc->wTotalLength = 100;
+	cdesc->bNumInterfaces = 1;
+	cdesc->bConfigurationValue = 1;
+	cdesc->iConfiguration = 0;
+	cdesc->bmAttributes = 1 << 7;
+	cdesc->bMaxPower = 50;
+
+	return 0;
+}
+
+static const struct dm_usb_ops sandbox_usb_flash_ops = {
+	.submit_control_msg	= sandbox_flash_submit_control_msg,
+};
+
+static const struct udevice_id sandbox_usb_flash_ids[] = {
+	{ .compatible = "sandbox,usb-flash" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_sandbox_flash) = {
+	.name	= "usb_sandbox_flash",
+	.id	= UCLASS_USB_EMUL,
+	.of_match = sandbox_usb_flash_ids,
+	.probe = sandbox_flash_probe,
+	.ops	= &sandbox_usb_flash_ops,
+};
diff --git a/drivers/usb/dev/sandbox-hub.c b/drivers/usb/dev/sandbox-hub.c
new file mode 100644
index 0000000..60ef64a
--- /dev/null
+++ b/drivers/usb/dev/sandbox-hub.c
@@ -0,0 +1,116 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#define DEBUG
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+
+enum {
+	STRING_null,
+	STRING_MANUFACTURER,
+	STRING_PRODUCT,
+	STRING_SERIAL,
+
+	STRING_count,
+};
+
+static char *usb_strings[] = {
+	"",
+	"sandbox",
+	"hub",
+	"2345",
+	NULL,
+};
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof(device_desc),
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+
+	.bDeviceClass =		USB_CLASS_HUB,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
+
+	.idVendor =		__constant_cpu_to_le16(0x1234),
+	.idProduct =		__constant_cpu_to_le16(0x5678),
+	.iManufacturer =	STRING_MANUFACTURER,
+	.iProduct =		STRING_PRODUCT,
+	.iSerialNumber =	STRING_SERIAL,
+	.bNumConfigurations =	1,
+};
+
+static const struct usb_descriptor_header hub_desc[] = {
+};
+
+static int sandbox_hub_submit_control_msg(struct udevice *dev,
+					  unsigned long pipe,
+					  void *buffer, int length,
+					  struct devrequest *setup)
+{
+	struct usb_device *udev = dev_get_uclass_priv(dev);
+
+	if (pipe == usb_rcvctrlpipe(udev, 0)) {
+		switch (setup->request) {
+		case USB_REQ_GET_DESCRIPTOR:
+			memcpy(buffer, &udev->descriptor, length);
+			udev->status = 0;
+			udev->act_len = length;
+			return 0;
+		default:
+			debug("request=%x\n", setup->request);
+			break;
+		}
+	}
+	debug("pipe=%lx\n", pipe);
+
+	return -EIO;
+}
+
+static int sandbox_hub_probe(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_uclass_priv(dev);
+	struct usb_device_descriptor *desc;
+	struct usb_config_descriptor *cdesc;
+
+	udev->strings = usb_strings;
+	desc = &udev->descriptor;
+	desc->iManufacturer = STRING_MANUFACTURER;
+	desc->iProduct = STRING_PRODUCT;
+	desc->iSerialNumber = STRING_SERIAL;
+
+	udev->maxpacketsize = PACKET_SIZE_64;
+
+	cdesc = &udev->config.desc;
+	cdesc->bLength = sizeof(*cdesc);
+	cdesc->bDescriptorType = USB_DT_CONFIG;
+	cdesc->wTotalLength = 100;
+	cdesc->bNumInterfaces = 1;
+	cdesc->bConfigurationValue = 1;
+	cdesc->iConfiguration = 0;
+	cdesc->bmAttributes = 1 << 7;
+	cdesc->bMaxPower = 50;
+
+	return 0;
+}
+
+static const struct dm_usb_ops sandbox_usb_hub_ops = {
+	.submit_control_msg	= sandbox_hub_submit_control_msg,
+};
+
+static const struct udevice_id sandbox_usb_hub_ids[] = {
+	{ .compatible = "sandbox,usb-hub" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_sandbox_hub) = {
+	.name	= "usb_sandbox_hub",
+	.id	= UCLASS_USB_EMUL,
+	.of_match = sandbox_usb_hub_ids,
+	.probe = sandbox_hub_probe,
+	.ops	= &sandbox_usb_hub_ops,
+};
diff --git a/drivers/usb/dev/usb-emul-uclass.c b/drivers/usb/dev/usb-emul-uclass.c
new file mode 100644
index 0000000..4114df0
--- /dev/null
+++ b/drivers/usb/dev/usb-emul-uclass.c
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * 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),
+};
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index d0b890a..de8354a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -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
diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c
new file mode 100644
index 0000000..34bf06d
--- /dev/null
+++ b/drivers/usb/host/usb-sandbox.c
@@ -0,0 +1,151 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#define DEBUG
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int copy_to_unicode(char *buff, int length, const char *str)
+{
+	int ptr;
+	int i;
+
+	if (length < 2)
+		return 0;
+	buff[1] = USB_DT_STRING;
+	for (ptr = 2, i = 0; ptr + 1 < length && *str; i++, ptr += 2) {
+		buff[ptr] = str[i];
+		buff[ptr + 1] = 0;
+	}
+	buff[0] = ptr;
+
+	return ptr;
+}
+
+static int sandbox_submit_control_msg(struct udevice *dev, unsigned long pipe,
+				      void *buffer, int length,
+				      struct devrequest *setup)
+{
+	struct usb_device *udev = dev_get_uclass_priv(dev);
+	struct usb_device *emul_udev;
+	struct udevice *emul;
+	int ret;
+
+	debug("ctrl %s: pipe=%lx, buffer=%p, length=%x, setup=%p\n",
+	      dev->name, pipe, buffer, length, setup);
+	ret = device_get_child(dev, 0, &emul);
+	if (ret)
+		return ret;
+	emul_udev = dev_get_uclass_priv(emul);
+	if (pipe == usb_rcvctrlpipe(udev, 0)) {
+		switch (setup->request) {
+		case USB_REQ_GET_DESCRIPTOR: {
+			int type = setup->value >> 8;
+			int index = setup->value & 0xff;
+
+			if (type == USB_DT_DEVICE && index == 0) {
+				memcpy(buffer, &emul_udev->descriptor, length);
+				udev->status = 0;
+				udev->act_len = length;
+				return 0;
+			} else if (type == USB_DT_CONFIG && index == 0) {
+				memcpy(buffer, &emul_udev->config.desc, length);
+				udev->status = 0;
+				udev->act_len = length;
+				return 0;
+			} else if (type == USB_DT_STRING) {
+				if (index == 0) {
+					char *desc = buffer;
+
+					desc[0] = 4;
+					desc[1] = USB_DT_STRING;
+					desc[2] = 0x09;
+					desc[3] = 0x14;
+					udev->status = 0;
+					udev->act_len = 4;
+					return 0;
+				} else {
+					char **ptr = emul_udev->strings;
+					int i;
+
+					for (i = 0; i < index; i++) {
+						if (!ptr[i])
+							break;
+					}
+					if (ptr[i]) {
+						udev->act_len = copy_to_unicode(
+							buffer, length, ptr[i]);
+						udev->status = 0;
+						return 0;
+					}
+				}
+			}
+			break;
+		}
+		default:
+			debug("requestrcv =%x\n", setup->request);
+			break;
+		}
+	} else if (pipe == usb_snddefctrl(udev)) {
+		switch (setup->request) {
+		case USB_REQ_SET_ADDRESS:
+			emul_udev->devnum = setup->value;
+			udev->status = 0;
+			udev->act_len = 0;
+			return 0;
+		default:
+			debug("requestsend =%x\n", setup->request);
+			break;
+		}
+	} else if (pipe == usb_sndctrlpipe(udev, 0)) {
+		switch (setup->request) {
+		case USB_REQ_SET_CONFIGURATION:
+			emul_udev->configno = setup->value;
+			udev->status = 0;
+			udev->act_len = 0;
+			return 0;
+		default:
+			debug("sndctrlpipe req=%x\n", setup->request);
+			break;
+		}
+	}
+	debug("pipe=%lx\n", pipe);
+
+	return -EIO;
+}
+
+static int sandbox_usb_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sandbox_usb_bind(struct udevice *dev)
+{
+	/* Scan the bus for devices */
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+static const struct dm_usb_ops sandbox_usb_ops = {
+	.submit_control_msg	= sandbox_submit_control_msg,
+};
+
+static const struct udevice_id sandbox_usb_ids[] = {
+	{ .compatible = "sandbox,usb" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_sandbox) = {
+	.name	= "usb_sandbox",
+	.id	= UCLASS_USB,
+	.of_match = sandbox_usb_ids,
+	.probe = sandbox_usb_probe,
+	.bind = sandbox_usb_bind,
+	.ops	= &sandbox_usb_ops,
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e9d3f32..392a40f 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -201,4 +201,7 @@
 
 #define CONFIG_CMD_LZMADEC
 
+#define CONFIG_CMD_USB
+#define CONFIG_DM_USB
+
 #endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index baab810..1c33fa6 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -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 */
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 236a5ec..b580bf0 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -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
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 5/7] dm: core: Add a function to get the uclass data for a device
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
                   ` (3 preceding siblings ...)
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 4/7] dm: usb: WIP sandbox USB implementation Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump Simon Glass
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/device.c | 10 ++++++++++
 include/dm/device.h   | 10 ++++++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index b73d3b8..fbb377b 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -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) {
diff --git a/include/dm/device.h b/include/dm/device.h
index 81afa8c..511dbd9 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -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
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
                   ` (4 preceding siblings ...)
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 5/7] dm: core: Add a function to get the uclass data for a device Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-02-01  8:45   ` Albert ARIBAUD
  2015-02-03 19:20   ` Albert ARIBAUD
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 7/7] dm: exynos: Enable driver model for snow XHCI Simon Glass
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/lib/interrupts.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index 4dacfd9..06f4679 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -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",
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 7/7] dm: exynos: Enable driver model for snow XHCI
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
                   ` (5 preceding siblings ...)
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump Simon Glass
@ 2015-01-30 19:04 ` Simon Glass
  2015-01-30 22:16 ` [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Marek Vasut
  2015-02-25 14:07 ` Vivek Gautam
  8 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-01-30 19:04 UTC (permalink / raw)
  To: u-boot

Switch snow over to use driver model for USB.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/configs/snow.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/configs/snow.h b/include/configs/snow.h
index ce6676e..00bd646 100644
--- a/include/configs/snow.h
+++ b/include/configs/snow.h
@@ -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
 
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
                   ` (6 preceding siblings ...)
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 7/7] dm: exynos: Enable driver model for snow XHCI Simon Glass
@ 2015-01-30 22:16 ` Marek Vasut
  2015-01-30 22:41   ` Simon Glass
  2015-02-25 14:07 ` Vivek Gautam
  8 siblings, 1 reply; 21+ messages in thread
From: Marek Vasut @ 2015-01-30 22:16 UTC (permalink / raw)
  To: u-boot

On Friday, January 30, 2015 at 08:04:50 PM, Simon Glass wrote:
> 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.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
  2015-01-30 22:16 ` [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Marek Vasut
@ 2015-01-30 22:41   ` Simon Glass
  2015-02-09 21:02     ` Marek Vasut
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2015-01-30 22:41 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 30 January 2015 at 15:16, Marek Vasut <marex@denx.de> wrote:
>
> On Friday, January 30, 2015 at 08:04:50 PM, Simon Glass wrote:
> > 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.
>
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump Simon Glass
@ 2015-02-01  8:45   ` Albert ARIBAUD
  2015-02-02 16:42     ` Simon Glass
  2015-02-03 19:20   ` Albert ARIBAUD
  1 sibling, 1 reply; 21+ messages in thread
From: Albert ARIBAUD @ 2015-02-01  8:45 UTC (permalink / raw)
  To: u-boot

Hello Simon,

On Fri, 30 Jan 2015 12:04:56 -0700, Simon Glass <sjg@chromium.org>
wrote:
> 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.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>

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,
-- 
Albert.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump
  2015-02-01  8:45   ` Albert ARIBAUD
@ 2015-02-02 16:42     ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2015-02-02 16:42 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On 1 February 2015 at 01:45, Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:
> Hello Simon,
>
> On Fri, 30 Jan 2015 12:04:56 -0700, Simon Glass <sjg@chromium.org>
> wrote:
>> 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.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
>
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump Simon Glass
  2015-02-01  8:45   ` Albert ARIBAUD
@ 2015-02-03 19:20   ` Albert ARIBAUD
  1 sibling, 0 replies; 21+ messages in thread
From: Albert ARIBAUD @ 2015-02-03 19:20 UTC (permalink / raw)
  To: u-boot

Hello Simon,

On Fri, 30 Jan 2015 12:04:56 -0700, Simon Glass <sjg@chromium.org> wrote:
> 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.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
>  arch/arm/lib/interrupts.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
> index 4dacfd9..06f4679 100644
> --- a/arch/arm/lib/interrupts.c
> +++ b/arch/arm/lib/interrupts.c
> @@ -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",
> -- 
> 2.2.0.rc0.207.ga3a616c
> 

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

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers Simon Glass
@ 2015-02-09 20:59   ` Marek Vasut
  2015-03-09  6:20   ` Vivek Gautam
  1 sibling, 0 replies; 21+ messages in thread
From: Marek Vasut @ 2015-02-09 20:59 UTC (permalink / raw)
  To: u-boot

On Friday, January 30, 2015 at 08:04:51 PM, Simon Glass wrote:
> Add a uclass that can represent a USB controller. For now we do not create
> devices for things attached to the controller.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

[...]

> +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 ? ;-)

> +*/

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

> +	.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,
> +*/
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 91bb90d..baab810 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
  2015-01-30 22:41   ` Simon Glass
@ 2015-02-09 21:02     ` Marek Vasut
  2015-02-10  5:28       ` Simon Glass
  0 siblings, 1 reply; 21+ messages in thread
From: Marek Vasut @ 2015-02-09 21:02 UTC (permalink / raw)
  To: u-boot

On Friday, January 30, 2015 at 11:41:33 PM, Simon Glass wrote:
> Hi Marek,

Hi!

> On 30 January 2015 at 15:16, Marek Vasut <marex@denx.de> wrote:
> > On Friday, January 30, 2015 at 08:04:50 PM, Simon Glass wrote:
> > > 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.
> > 
> > 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.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
  2015-02-09 21:02     ` Marek Vasut
@ 2015-02-10  5:28       ` Simon Glass
  2015-02-10 18:52         ` Marek Vasut
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2015-02-10  5:28 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 9 February 2015 at 14:02, Marek Vasut <marex@denx.de> wrote:
> On Friday, January 30, 2015 at 11:41:33 PM, Simon Glass wrote:
>> Hi Marek,
>
> Hi!
>
>> On 30 January 2015 at 15:16, Marek Vasut <marex@denx.de> wrote:
>> > On Friday, January 30, 2015 at 08:04:50 PM, Simon Glass wrote:
>> > > 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.
>> >
>> > 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.
>
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
  2015-02-10  5:28       ` Simon Glass
@ 2015-02-10 18:52         ` Marek Vasut
  0 siblings, 0 replies; 21+ messages in thread
From: Marek Vasut @ 2015-02-10 18:52 UTC (permalink / raw)
  To: u-boot

On Tuesday, February 10, 2015 at 06:28:30 AM, Simon Glass wrote:
> Hi Marek,

Hi!

[...]

> >> > 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.
> > 
> > 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support
  2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
                   ` (7 preceding siblings ...)
  2015-01-30 22:16 ` [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Marek Vasut
@ 2015-02-25 14:07 ` Vivek Gautam
  8 siblings, 0 replies; 21+ messages in thread
From: Vivek Gautam @ 2015-02-25 14:07 UTC (permalink / raw)
  To: u-boot

Hi Simon,


On Sat, Jan 31, 2015 at 12:34 AM, Simon Glass <sjg@chromium.org> wrote:
> 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.

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.

>
>
> 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



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 3/7] dm: usb: Adjust users of the USB stack to work with driver model
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 3/7] dm: usb: Adjust users of the USB stack to work with driver model Simon Glass
@ 2015-02-25 14:09   ` Vivek Gautam
  0 siblings, 0 replies; 21+ messages in thread
From: Vivek Gautam @ 2015-02-25 14:09 UTC (permalink / raw)
  To: u-boot

On Sat, Jan 31, 2015 at 12:34 AM, Simon Glass <sjg@chromium.org> wrote:
> 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.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>  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(-)
>
> diff --git a/common/cmd_usb.c b/common/cmd_usb.c
> index 27813f0..b824634 100644
> --- a/common/cmd_usb.c
> +++ b/common/cmd_usb.c
> @@ -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)
> diff --git a/common/usb.c b/common/usb.c
> index 32e15cd..3ccf8a7 100644
> --- a/common/usb.c
> +++ b/common/usb.c
> @@ -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
> diff --git a/common/usb_hub.c b/common/usb_hub.c
> index 66b4a72..ccdf755 100644
> --- a/common/usb_hub.c
> +++ b/common/usb_hub.c
> @@ -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);
> diff --git a/common/usb_storage.c b/common/usb_storage.c
> index 1411737..8fb2c18 100644
> --- a/common/usb_storage.c
> +++ b/common/usb_storage.c
> @@ -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 */
> diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
> index 7cb96e3..4334d16 100644
> --- a/drivers/usb/eth/usb_ether.c
> +++ b/drivers/usb/eth/usb_ether.c
> @@ -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)
> diff --git a/include/usb.h b/include/usb.h
> index a8fee0b..ba80eb8 100644
> --- a/include/usb.h
> +++ b/include/usb.h
> @@ -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 {
> +       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.

> +       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



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers
  2015-01-30 19:04 ` [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers Simon Glass
  2015-02-09 20:59   ` Marek Vasut
@ 2015-03-09  6:20   ` Vivek Gautam
  2015-03-09  6:32     ` Vivek Gautam
  1 sibling, 1 reply; 21+ messages in thread
From: Vivek Gautam @ 2015-03-09  6:20 UTC (permalink / raw)
  To: u-boot

Hi Simon,


On Sat, Jan 31, 2015 at 12:34 AM, Simon Glass <sjg@chromium.org> wrote:
> Add a uclass that can represent a USB controller. For now we do not create
> devices for things attached to the controller.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---

Please find my comments inline below.

>
>  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
>
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index c11b551..d0b890a 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -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
> diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
> new file mode 100644
> index 0000000..86564db
> --- /dev/null
> +++ b/drivers/usb/host/usb-uclass.c
> @@ -0,0 +1,227 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + * Written by Simon Glass <sjg@chromium.org>
> + *
> + * 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;
> +}
> +
> +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

> +       ret = uclass_get(UCLASS_USB, &uc);
> +       if (ret)
> +               return ret;

nit: just add an extra line here.

> +       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,
> +*/
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 91bb90d..baab810 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -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



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers
  2015-03-09  6:20   ` Vivek Gautam
@ 2015-03-09  6:32     ` Vivek Gautam
  0 siblings, 0 replies; 21+ messages in thread
From: Vivek Gautam @ 2015-03-09  6:32 UTC (permalink / raw)
  To: u-boot

Hi,


On Mon, Mar 9, 2015 at 11:50 AM, Vivek Gautam <gautamvivek1987@gmail.com> wrote:

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

> Hi Simon,
>
>
> On Sat, Jan 31, 2015 at 12:34 AM, Simon Glass <sjg@chromium.org> wrote:
>> Add a uclass that can represent a USB controller. For now we do not create
>> devices for things attached to the controller.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>
> Please find my comments inline below.
>
>>
>>  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
>>
>> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
>> index c11b551..d0b890a 100644
>> --- a/drivers/usb/host/Makefile
>> +++ b/drivers/usb/host/Makefile
>> @@ -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
>> diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
>> new file mode 100644
>> index 0000000..86564db
>> --- /dev/null
>> +++ b/drivers/usb/host/usb-uclass.c
>> @@ -0,0 +1,227 @@
>> +/*
>> + * (C) Copyright 2015 Google, Inc
>> + * Written by Simon Glass <sjg@chromium.org>
>> + *
>> + * 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)
>> +{

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

>> +       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 ?
>
> Also make all devices unknown initially
i think this may not be required.

>
>> +       ret = uclass_get(UCLASS_USB, &uc);
>> +       if (ret)
>> +               return ret;
>
> nit: just add an extra line here.
>
>> +       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,
>> +*/
>> +};
>> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>> index 91bb90d..baab810 100644
>> --- a/include/dm/uclass-id.h
>> +++ b/include/dm/uclass-id.h
>> @@ -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

Rest looks fine to me.



-- 
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2015-03-09  6:32 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-30 19:04 [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Simon Glass
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 1/7] dm: usb: Add a uclass for USB controllers Simon Glass
2015-02-09 20:59   ` Marek Vasut
2015-03-09  6:20   ` Vivek Gautam
2015-03-09  6:32     ` Vivek Gautam
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 2/7] dm: usb: Support driver model in exynos XHCI Simon Glass
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 3/7] dm: usb: Adjust users of the USB stack to work with driver model Simon Glass
2015-02-25 14:09   ` Vivek Gautam
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 4/7] dm: usb: WIP sandbox USB implementation Simon Glass
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 5/7] dm: core: Add a function to get the uclass data for a device Simon Glass
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 6/7] arm: Show relocated PC/LR in the register dump Simon Glass
2015-02-01  8:45   ` Albert ARIBAUD
2015-02-02 16:42     ` Simon Glass
2015-02-03 19:20   ` Albert ARIBAUD
2015-01-30 19:04 ` [U-Boot] [RFC PATCH 7/7] dm: exynos: Enable driver model for snow XHCI Simon Glass
2015-01-30 22:16 ` [U-Boot] [RFC PATCH 0/7] RFC: dm: Add USB support Marek Vasut
2015-01-30 22:41   ` Simon Glass
2015-02-09 21:02     ` Marek Vasut
2015-02-10  5:28       ` Simon Glass
2015-02-10 18:52         ` Marek Vasut
2015-02-25 14:07 ` Vivek Gautam

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.