Hi Simon,
On Sat, Jan 31, 2015 at 12:34 AM, Simon Glass <[email protected]> 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 <[email protected]> > --- 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 <[email protected]> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <errno.h> > +#include <usb.h> > +#include <dm/device-internal.h> > + > +static bool usb_started; /* flag for the started/stopped USB status */ > +static bool asynch_allowed; > + > +int usb_disable_asynch(int disable) > +{ > + int old_value = asynch_allowed; > + > + asynch_allowed = !disable; > + return old_value; > +} > + > +int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, > + int length, int interval) > +{ > + struct udevice *dev = udev->controller_dev; > + struct dm_usb_ops *ops = usb_get_ops(dev); > + > + if (!ops->control) > + return -ENOSYS; > + > + return ops->interrupt(dev, udev, pipe, buffer, length, interval); > +} > + > +int submit_control_msg(struct usb_device *udev, unsigned long pipe, > + void *buffer, int length, struct devrequest *setup) > +{ > + struct udevice *dev = udev->controller_dev; > + struct dm_usb_ops *ops = usb_get_ops(dev); > + > + if (!ops->control) > + return -ENOSYS; > + > + return ops->control(dev, udev, pipe, buffer, length, setup); > +} > + > +int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void > *buffer, > + int length) > +{ > + struct udevice *dev = udev->controller_dev; > + struct dm_usb_ops *ops = usb_get_ops(dev); > + > + if (!ops->control) > + return -ENOSYS; > + > + return ops->bulk(dev, udev, pipe, buffer, length); > +} > + > +int usb_alloc_device(struct usb_device *udev) > +{ > + struct udevice *dev = udev->controller_dev; > + struct dm_usb_ops *ops = usb_get_ops(dev); > + > + if (!ops->alloc_device) > + return -ENOSYS; > + > + return ops->alloc_device(dev, udev); > +} > + > +int usb_stop(void) > +{ > + return 0; > +} > + > +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 > [email protected] > http://lists.denx.de/mailman/listinfo/u-boot -- Best Regards Vivek Gautam Samsung R&D Institute, Bangalore India _______________________________________________ U-Boot mailing list [email protected] http://lists.denx.de/mailman/listinfo/u-boot

