dm: Add USB support
Subsystems (11)
v2 cover dm: Add USB support
This series adds 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.
With the RFC series, only USB controllers had a real driver model device. USB devices (including the hub in the controller) were not modelled as driver model devices.
While this was expedient, and produced much fewer patches, it is not a long-term solution. Also, since then, driver model Ethernet support (which USB can use) has been merged to u-boot-dm/next. It seems better to bite the bullet and do a full conversion.
Unfortunately this results in a very large series. It includes:
- USB uclass
- USB hub uclass
- Adjustments to make USB keyboard, Ethernet and storage continue to work
- Sandbox USB emulation support
- Sandbox USB emulations for flash and hub devices
- A reasonable set of tests
- EHCI and XHCI support (not OHCI)
- Conversion of Tegra and Exynos drivers to driver model
- Adjustments to make the 'usb' command operate as expected
- README describing how USB works with driver model
Both EHCI and XHCI needed a little bit of refactoring before they are converted to driver model - e.g. removal of weak fuctions and splitting up the init code.
This series includes patches to remove the non-driver-model code for Exynos and Tegra, to be applied once everything is stable. For now it is convenient to be able to compare the two options.
This series does not change how USB is started up. The 'usb start' command scans the buses as before, and takes just as long. Once it has started you can use 'dm tree' to see the tree structure of the USB bus, although 'usb tree' provides a better view. It is unclear how we could implement lazy init for USB given the long time it takes to probe the bus.
A README is provided to describe how USB works under driver model.
This series is available at u-boot-dm/usb-working.
Changes in v2:
- Rewrite and expand series to support driver model fully
Simon Glass (80):
linker_lists: Add a function to access a linker list entry
sandbox: Fix comment for os_open()
dm: test: bus: Use a local variable to simplify code
dm: exynos: snow: Move the keyboard to I2C
dm: core: Support allocating driver-private data for DMA
dm: core: Convert driver_bind() to use const
dm: core: Rename driver data function to dev_get_driver_data()
dm: core: Mark device as active before calling uclass probe() methods
dm: core: Add device children and sibling functions
dm: gpio: Add an implementation for gpio_get_number()
dm: usb: Add a uclass for USB controllers
dm: usb: Adjust usb command to prepare for driver model
dm: usb: Adjust usb_alloc_new_device() to return an error
dm: usb: Convert 'usb' command to support driver model
dm: usb: Drop the legacy USB init sequence
dm: usb: Refactor port resets
dm: usb: Move descriptor setup code into its own function
dm: usb: Split out more code from usb_new_device()
dm: usb: Complete the splitting up of usb_new_device()
dm: usb: Convert core usb.c file to support driver model
dm: usb: Split hub detection into its own function
dm: usb: Add driver model support for hubs
dm: usb: Move USB storage definitions to usb_defs.h
dm: usb: Fix type problems in usb_stor_get_info()
dm: usb: Simply device finding code in usb_storage
dm: usb: Adjust usb_storage to work with sandbox
dm: usb: Move storage device scanning into its own function
dm: usb: Convert usb_storage to driver model
dm: usb: Move all the EHCI weak functions together and declare them
dm: usb: Pass EHCI controller pointer to ehci_get_port_speed()
dm: usb: Allow ECHI to hold private data for the controller
dm: usb: tegra: Store the controller type explicitly
dm: usb: Pass EHCI controller pointer to ehci_powerup_fixup()
dm: usb: tegra: Drop use of global controller variable
dm: usb: Pass EHCI controller pointer to ehci_set_usbmode()
dm: usb: Pass EHCI controller pointer to ehci_get_portsc_register()
dm: usb: ehci: Use a function to find the controller from struct
udevice
dm: usb: Refactor EHCI init
dm: usb: Drop the EHCI weak functions
dm: usb: Change ehci_reset() to use a pointer
dm: usb: Add driver model support to EHCI
dm: usb: Allow USB drivers to be declared and auto-probed
dm: usb: Bind generic USB devices when there is no driver
dm: usb: Allow setting up a USB controller as a device/gadget
dm: usb: Split out the keyboard probe into its own function
dm: usb: Support driver model with USB keyboards
dm: usb: tegra: Add vbus GPIOs for nyan
dm: usb: Move struct usb_string to a common place
dm: usb: sandbox: Add a uclass for USB device emulation
dm: usb: sandbox: Reset emulation devices in usb stop()
dm: usb: sandbox: Add an emulator for USB flash devices
dm: usb: sandbox: Add an emulator for USB hub emulation
dm: usb: sandbox: Add a driver for sandbox
dm: usb: dts: sandbox: Add some sample USB devices to sandbox
dm: usb: Add support for USB ethernet devices with driver model
dm: usb: exynos: Add driver model support to exynos EHCI
dm: usb: tegra: Remove the port_addr_clear_csc variable
dm: usb: tegra: Tidy up error handling and a static function
dm: usb: tegra: Move most of init/uninit into a function
dm: usb: tegra: Add driver model support to tegra EHCI
dm: usb: xhci: Use a function to get xhci_ctrl
dm: usb: xhci: Use explicit parameters for xhci_alloc_virt_device()
dm: usb: xhci: Use explicit parameters for
xhci_setup_addressable_virt_dev()
dm: usb: xhci: Factor out common init/uninit
dm: usb: Support driver model in XHCI
dm: usb: Rename the XHCI HCD to U-Boot
dm: usb: exynos: Adjust XHCI driver to support driver model
dm: usb: exynos: Use driver model for USB
dm: usb: exynos: Enable both USB ports on snow
dm: usb: exynos: Enable both EHCI and XHCI on snow
dm: usb: tegra: Move to driver model for USB
dm: usb: Add a generic descriptor struct
dm: usb: Tidy up pipe value decoding
dm: usb: sandbox: Enable USB
dm: test: Correct printf() output nit in 'dm uclass'
dm: test: Allow 'dm test' to select a particular test to run
dm: usb: Add tests for the USB uclass
dm: usb: tegra: Drop legacy USB code
dm: usb: exynos: Drop legacy USB code
dm: usb: Add a README for driver model
Makefile | 1 + arch/arm/cpu/armv7/exynos/Kconfig | 3 + arch/arm/dts/exynos5250-snow.dts | 5 +- arch/arm/dts/tegra124-nyan-big.dts | 2 + arch/arm/mach-tegra/Kconfig | 3 + arch/sandbox/dts/sandbox.dts | 40 ++ board/genesi/mx51_efikamx/efikamx-usb.c | 4 +- board/nvidia/common/board.c | 1 - common/cmd_usb.c | 198 ++++++++-- common/usb.c | 277 ++++++++------ common/usb_hub.c | 194 ++++++++-- common/usb_kbd.c | 119 ++++-- common/usb_storage.c | 249 ++++++------ configs/sandbox_defconfig | 4 + doc/driver-model/usb-info.txt | 415 ++++++++++++++++++++ drivers/core/device-remove.c | 4 +- drivers/core/device.c | 66 +++- drivers/core/lists.c | 2 +- drivers/gpio/gpio-uclass.c | 12 + drivers/i2c/s3c24x0_i2c.c | 2 +- drivers/i2c/tegra_i2c.c | 6 +- drivers/usb/Kconfig | 16 + drivers/usb/emul/Kconfig | 8 + drivers/usb/emul/Makefile | 10 + drivers/usb/emul/sandbox_flash.c | 423 +++++++++++++++++++++ drivers/usb/emul/sandbox_hub.c | 303 +++++++++++++++ drivers/usb/emul/usb-emul-uclass.c | 263 +++++++++++++ drivers/usb/eth/usb_ether.c | 52 ++- drivers/usb/gadget/ci_udc.c | 4 + drivers/usb/host/Makefile | 5 + drivers/usb/host/ehci-exynos.c | 127 +++---- drivers/usb/host/ehci-faraday.c | 112 +++--- drivers/usb/host/ehci-hcd.c | 379 ++++++++++++++----- drivers/usb/host/ehci-mx5.c | 12 + drivers/usb/host/ehci-tegra.c | 288 +++++++------- drivers/usb/host/ehci.h | 47 +++ drivers/usb/host/usb-sandbox.c | 117 ++++++ drivers/usb/host/usb-uclass.c | 645 ++++++++++++++++++++++++++++++++ drivers/usb/host/xhci-exynos5.c | 106 +++--- drivers/usb/host/xhci-mem.c | 24 +- drivers/usb/host/xhci-ring.c | 8 +- drivers/usb/host/xhci.c | 312 ++++++++++++--- drivers/usb/host/xhci.h | 31 +- drivers/usb/musb-new/musb_uboot.c | 4 +- include/configs/sandbox.h | 2 + include/configs/snow.h | 2 + include/dm/device-internal.h | 2 +- include/dm/device.h | 51 ++- include/dm/test.h | 7 +- include/dm/uclass-id.h | 5 + include/fdtdec.h | 5 - include/linker_lists.h | 10 + include/linux/usb/ch9.h | 18 + include/linux/usb/gadget.h | 13 - include/os.h | 2 +- include/usb.h | 494 +++++++++++++++++++++++- include/usb_defs.h | 68 +++- lib/fdtdec.c | 5 - test/dm/Makefile | 1 + test/dm/bus.c | 16 +- test/dm/cmd_dm.c | 13 +- test/dm/test-dm.sh | 3 + test/dm/test-main.c | 7 +- test/dm/test-uclass.c | 3 +- test/dm/test.dts | 41 ++ test/dm/usb.c | 50 +++ 66 files changed, 4807 insertions(+), 914 deletions(-) create mode 100644 doc/driver-model/usb-info.txt create mode 100644 drivers/usb/emul/Kconfig create mode 100644 drivers/usb/emul/Makefile create mode 100644 drivers/usb/emul/sandbox_flash.c create mode 100644 drivers/usb/emul/sandbox_hub.c create mode 100644 drivers/usb/emul/usb-emul-uclass.c create mode 100644 drivers/usb/host/usb-sandbox.c create mode 100644 drivers/usb/host/usb-uclass.c create mode 100644 test/dm/usb.c
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 1/80 linker_lists: Add a function to access a linker list entry
Once declared, you cannot access a linker_list entry since you do not have a symbol name for it. Add llsym() macro to provide this. This avoids searching for the symbol at run-time based on name.
An example usage is to declare a driver with U_BOOT_DRIVER(), then obtain a pointer to that driver later.
---
Changes in v2: None
include/linker_lists.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
include/linker_lists.h +10 -0
@@ -103,6 +103,16 @@*/ /** +* ll_sym() - Access a linker-generated array entry +* @_type: Data type of the entry +* @_name: Name of the entry +* @_list: name of the list. Should contain only characters allowed +* in a C variable name! +*/ +#define llsym (_type, _name, _list) \ + ((_type *)&_u_boot_list_2_##_list##_2_##_name) + +/** * ll_entry_declare() - Declare linker-generated array entry * @_type: Data type of the entry * @_name: Name of the entry
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 1/80 linker_lists: Add a function to access a linker list entry
Quoted 7 lines · Simon Glass
Once declared, you cannot access a
linker_listentry since you do not have a symbol name for it. Addllsym()macro to provide this. This avoids searching for the symbol at run-time based on name.An example usage is to declare a driver with
U_BOOT_DRIVER(), then obtain a pointer to that driver later.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/linker_lists.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 2/80 sandbox: Fix comment for os_open()
In reply to Simon GlassThis has the wrong #define in the function comment. Fix it.
---
Changes in v2: None
include/os.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/os.h +1 -1
@@ -64,7 +64,7 @@ off_t os_lseek(int fd, off_t offset, int whence);* Access to the OS open() system call * * \param pathname Pathname of file to open -* \param flags Flags, like O_RDONLY, O_RDWR +* \param flags Flags, like OS_O_RDONLY, OS_O_RDWR * \return file descriptor, or -1 on error */ int os_open (const char *pathname,int flags);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 2/80 sandbox: Fix comment for os_open()
Quoted 9 lines · Simon Glass
This has the wrong #define in the function comment. Fix it.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/os.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 3/80 dm: test: bus: Use a local variable to simplify code
In reply to Simon GlassAdjust this test to avoid repeating the same code too often.
---
Changes in v2: None
test/dm/bus.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
test/dm/bus.c +10 -6
@@ -273,20 +273,22 @@ DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);/* As above but the size is controlled by the uclass */ static int dm_test_bus_parent_data_uclass (struct dm_test_state *dms) { +struct driver *drv;struct udevice *bus;int size;int ret;/* Set the driver size to 0 so that the uclass size is used */ ut_assertok (uclass_find_device (UCLASS_TEST_BUS ,0 , &bus)); - size = bus->driver->per_child_auto_alloc_size; + drv = (struct driver *)bus->driver; + size = drv->per_child_auto_alloc_size; bus->uclass->uc_drv->per_child_auto_alloc_size = size; - bus->driver->per_child_auto_alloc_size =0 ; + drv->per_child_auto_alloc_size =0 ; ret =test_bus_parent_data (dms);if (ret)return ret; bus->uclass->uc_drv->per_child_auto_alloc_size =0 ; - bus->driver->per_child_auto_alloc_size = size; + drv->per_child_auto_alloc_size = size;return 0 ; }
@@ -414,19 +416,21 @@ DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);static int dm_test_bus_parent_platdata_uclass (struct dm_test_state *dms) {struct udevice *bus; +struct driver *drv;int size;int ret;/* Set the driver size to 0 so that the uclass size is used */ ut_assertok (uclass_find_device (UCLASS_TEST_BUS ,0 , &bus)); - size = bus->driver->per_child_platdata_auto_alloc_size; + drv = (struct driver *)bus->driver; + size = drv->per_child_platdata_auto_alloc_size; bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size; - bus->driver->per_child_platdata_auto_alloc_size =0 ; + drv->per_child_platdata_auto_alloc_size =0 ; ret =test_bus_parent_platdata (dms);if (ret)return ret; bus->uclass->uc_drv->per_child_platdata_auto_alloc_size =0 ; - bus->driver->per_child_platdata_auto_alloc_size = size; + drv->per_child_platdata_auto_alloc_size = size;return 0 ; }
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 3/80 dm: test: bus: Use a local variable to simplify code
Quoted 9 lines · Simon Glass
Adjust this test to avoid repeating the same code too often.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
test/dm/bus.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 4/80 dm: exynos: snow: Move the keyboard to I2C
In reply to Simon GlassThe snow keyboard on shipping devices is actually on I2C not SPI. Move the label to indicate this.
---
Changes in v2: None
arch/arm/dts/exynos5250-snow.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/dts/exynos5250-snow.dts +2 -2
@@ -40,7 +40,7 @@ }; i2c4: i2c at 12ca0000 { - cros-ec at 1e { + cros_ec: cros-ec at 1e { reg = <0x1e>; compatible = "google,cros-ec"; i2c-max-frequency = <100000>;
@@ -65,7 +65,7 @@ spi at 131b0000 { spi-max-frequency = <1000000>; spi-deactivate-delay = <100>; - cros_ec: cros-ec at 0 { + cros-ec at 0 { reg = <0>; compatible = "google,cros-ec"; spi-max-frequency = <5000000>;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 4/80 dm: exynos: snow: Move the keyboard to I2C
Hi,
Quoted 10 lines · Simon Glass
The snow keyboard on shipping devices is actually on I2C not SPI. Move the label to indicate this.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
arch/arm/dts/exynos5250-snow.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
This patch is not needed now, so I'm dropping it. Commit c9b53f8d solved this problem.
Regards,
Simon
PATCH v2 5/80 dm: core: Support allocating driver-private data for DMA
In reply to Simon GlassSome driver want to put DMA buffers in their private data. Add a flag to tell driver model to align driver-private data to a cache boundary so that DMA will work correctly in this case.
---
Changes in v2: None
drivers/core/device.c | 19 +++++++++++++++++-- include/dm/device.h | 3 +++ 2 files changed, 20 insertions(+), 2 deletions(-)
drivers/core/device.c +17 -2
@@ -164,6 +164,21 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, -1, devp); } +static void *alloc_priv (int size,uint flags) +{ +void *priv; + +if (flags &DM_FLAG_ALLOC_PRIV_DMA ) { + priv =memalign (ARCH_DMA_MINALIGN , size); +if (priv) +memset (priv,'\0' , size); + }else { + priv =calloc (1 , size); + } + +return priv; +} +int device_probe_child (struct udevice *dev,void *parent_priv) {struct driver *drv;
@@ -182,7 +197,7 @@ int device_probe_child(struct udevice *dev, void *parent_priv)/* Allocate private data if requested */ if (drv->priv_auto_alloc_size) { - dev->priv =calloc (1 , drv->priv_auto_alloc_size); + dev->priv =alloc_priv (drv->priv_auto_alloc_size, drv->flags);if (!dev->priv) { ret = -ENOMEM ; goto fail;
@@ -206,7 +221,7 @@ int device_probe_child(struct udevice *dev, void *parent_priv) per_child_auto_alloc_size; }if (size) { - dev->parent_priv =calloc (1 , size); + dev->parent_priv =alloc_priv (size, drv->flags);if (!dev->parent_priv) { ret = -ENOMEM ; goto fail;
include/dm/device.h +3 -0
@@ -30,6 +30,9 @@ struct driver_info;/* DM is responsible for allocating and freeing parent_platdata */ #define DM_FLAG_ALLOC_PARENT_PDATA (1 << 3) +/* Allocate driver private data on a DMA boundary */ +#define DM_FLAG_ALLOC_PRIV_DMA (1 << 4) +/** * struct udevice - An instance of a driver *
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 5/80 dm: core: Support allocating driver-private data for DMA
Quoted 4 lines · Simon Glass
Some driver want to put DMA buffers in their private data. Add a flag to tell driver model to align driver-private data to a cache boundary so that DMA will work correctly in this case.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/core/device.c | 19 +++++++++++++++++-- include/dm/device.h | 3 +++ 2 files changed, 20 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 6/80 dm: core: Convert driver_bind() to use const
In reply to Simon GlassThe driver is not modified by driver model, so update driver_bind() to recognise that.
---
Changes in v2: None
drivers/core/device-remove.c | 4 ++-- drivers/core/device.c | 7 ++++--- include/dm/device-internal.h | 2 +- include/dm/device.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-)
drivers/core/device-remove.c +2 -2
@@ -66,7 +66,7 @@ static int device_chld_remove(struct udevice *dev)int device_unbind (struct udevice *dev) { -struct driver *drv; +const struct driver *drv;int ret;if (!dev)
@@ -139,7 +139,7 @@ void device_free(struct udevice *dev)int device_remove (struct udevice *dev) { -struct driver *drv; +const struct driver *drv;int ret;if (!dev)
drivers/core/device.c +4 -3
@@ -24,8 +24,9 @@DECLARE_GLOBAL_DATA_PTR ; -int device_bind (struct udevice *parent,struct driver *drv,const char *name, -void *platdata,int of_offset,struct udevice **devp) +int device_bind (struct udevice *parent,const struct driver *drv, +const char *name,void *platdata,int of_offset, +struct udevice **devp) {struct udevice *dev;struct uclass *uc;
@@ -181,7 +182,7 @@ static void *alloc_priv(int size, uint flags)int device_probe_child (struct udevice *dev,void *parent_priv) { -struct driver *drv; +const struct driver *drv;int size =0 ;int ret;int seq;
include/dm/device-internal.h +1 -1
@@ -34,7 +34,7 @@ struct udevice;* @devp: Returns a pointer to the bound device * @return 0 if OK, -ve on error */ -int device_bind (struct udevice *parent,struct driver *drv, +int device_bind (struct udevice *parent,const struct driver *drv,const char *name,void *platdata,int of_offset,struct udevice **devp);
include/dm/device.h +1 -1
@@ -70,7 +70,7 @@ struct driver_info;* when the device is probed and will be unique within the device's uclass. */ struct udevice { -struct driver *driver; +const struct driver *driver;const char *name;void *platdata;void *parent_platdata;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 6/80 dm: core: Convert driver_bind() to use const
Quoted 6 lines · Simon Glass
The driver is not modified by driver model, so update
driver_bind()to recognise that.Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
drivers/core/device-remove.c | 4 ++-- drivers/core/device.c | 7 ++++--- include/dm/device-internal.h | 2 +- include/dm/device.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 7/80 dm: core: Rename driver data function to dev_get_driver_data()
In reply to Simon GlassThe existing get_get_of_data() function provides access to both the driver's compatible string and its driver data. However only the latter is actually useful. Update the interface to reflect this and fix up existing users.
---
Changes in v2: None
drivers/core/device.c | 4 ++-- drivers/core/lists.c | 2 +- drivers/i2c/s3c24x0_i2c.c | 2 +- drivers/i2c/tegra_i2c.c | 6 +++--- include/dm/device.h | 16 +++++++++++----- 5 files changed, 18 insertions(+), 12 deletions(-)
drivers/core/device.c +2 -2
@@ -467,9 +467,9 @@ struct udevice *dev_get_parent(struct udevice *child)return child->parent; } -ulong dev_get_of_data (struct udevice *dev) +ulong dev_get_driver_data (struct udevice *dev) { -return dev->of_id->data; +return dev->driver_data; }enum uclass_id device_get_uclass_id (struct udevice *dev)
drivers/core/lists.c +1 -1
@@ -168,7 +168,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,dm_warn ("Error binding driver '%s'\n" , entry->name);return ret; }else { - dev->of_id = id; + dev->driver_data = id->data; found = true;if (devp) *devp = dev;
drivers/i2c/s3c24x0_i2c.c +1 -1
@@ -1348,7 +1348,7 @@ static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)struct s3c24x0_i2c_bus *i2c_bus =dev_get_priv (dev);int node, flags; - i2c_bus->is_highspeed = dev->of_id->data; + i2c_bus->is_highspeed =dev_get_driver_data (dev); node = dev->of_offset;if (i2c_bus->is_highspeed) {
drivers/i2c/tegra_i2c.c +3 -3
@@ -338,7 +338,7 @@ static int tegra_i2c_probe(struct udevice *dev)bool is_dvc; i2c_bus->id = dev->seq; - i2c_bus->type =dev_get_of_data (dev); + i2c_bus->type =dev_get_driver_data (dev); i2c_bus->regs = (struct i2c_ctlr *)fdtdec_get_addr (blob, node,"reg" );/*
@@ -360,7 +360,7 @@ static int tegra_i2c_probe(struct udevice *dev)if (i2c_bus->periph_id ==-1 )return -EINVAL ; - is_dvc =dev_get_of_data (dev) ==TYPE_DVC ; + is_dvc =dev_get_driver_data (dev) ==TYPE_DVC ;if (is_dvc) { i2c_bus->control = &((struct dvc_ctlr *)i2c_bus->regs)->control;
@@ -469,7 +469,7 @@ int tegra_i2c_get_dvc_bus(struct udevice **busp)for (uclass_first_device (UCLASS_I2C , &bus); bus;uclass_next_device (&bus)) { -if (dev_get_of_data (bus) ==TYPE_DVC ) { +if (dev_get_driver_data (bus) ==TYPE_DVC ) { *busp = bus;return 0 ; }
include/dm/device.h +11 -5
@@ -55,7 +55,8 @@ struct driver_info;* @platdata: Configuration data for this device * @parent_platdata: The parent bus's configuration data for this device * @of_offset: Device tree node offset for this device (- for none) -* @of_id: Pointer to the udevice_id structure which created the device +* @driver_data: Driver data word for the entry that matched this device with +* its driver * @parent: Parent of this device, or NULL for the top level device * @priv: Private data for this device * @uclass: Pointer to uclass for this device
@@ -75,7 +76,7 @@ struct udevice {void *platdata;void *parent_platdata;int of_offset; -const struct udevice_id *of_id; +ulong driver_data;struct udevice *parent;void *priv;struct uclass *uclass;
@@ -251,13 +252,18 @@ struct udevice *dev_get_parent(struct udevice *child);void *dev_get_uclass_priv (struct udevice *dev);/** -* dev_get_of_data() - get the device tree data used to bind a device +* dev_get_driver_data() - get the driver data used to bind a device * * When a device is bound using a device tree node, it matches a * particular compatible string as in struct udevice_id. This function -* returns the associated data value for that compatible string +* returns the associated data value for that compatible string. This is +* the 'data' field in struct udevice_id. +* +* For USB devices, this is the driver_info field in struct usb_device_id. +* +* @dev: Device to check */ -ulong dev_get_of_data (struct udevice *dev); +ulong dev_get_driver_data (struct udevice *dev);/* * device_get_uclass_id() - return the uclass ID of a device
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 7/80 dm: core: Rename driver data function to dev_get_driver_data()
Quoted 7 lines · Simon Glass
The existing
get_get_of_data()function provides access to both the driver's compatible string and its driver data. However only the latter is actually useful. Update the interface to reflect this and fix up existing users.Signed-off-by Simon Glass <[email protected]>---
Quoted 8 lines
Changes in v2: None
drivers/core/device.c | 4 ++-- drivers/core/lists.c | 2 +- drivers/i2c/s3c24x0_i2c.c | 2 +- drivers/i2c/tegra_i2c.c | 6 +++--- include/dm/device.h | 16 +++++++++++----- 5 files changed, 18 insertions(+), 12 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 8/80 dm: core: Mark device as active before calling uclass probe() methods
In reply to Simon GlassThe uclass pre-probe functions may end up calling back into the device in some circumstances. This can fail if recursion takes place. Adjust the ordering so that we mark the device as active early, then retract this later if needed.
---
Changes in v2: None
drivers/core/device.c | 8 +++++--- test/dm/test-uclass.c | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-)
drivers/core/device.c +5 -3
@@ -243,6 +243,8 @@ int device_probe_child(struct udevice *dev, void *parent_priv) } dev->seq = seq; + dev->flags |=DM_FLAG_ACTIVATED ; + ret =uclass_pre_probe_device (dev);if (ret) goto fail;
@@ -269,10 +271,8 @@ int device_probe_child(struct udevice *dev, void *parent_priv) } ret =uclass_post_probe_device (dev); -if (ret) { - dev->flags &= ~DM_FLAG_ACTIVATED ; +if (ret) goto fail_uclass; - }return 0 ; fail_uclass:
@@ -281,6 +281,8 @@ fail_uclass: __func__, dev->name); } fail: + dev->flags &= ~DM_FLAG_ACTIVATED ; + dev->seq =-1 ;device_free (dev);
test/dm/test-uclass.c +2 -1
@@ -31,6 +31,7 @@ int test_ping(struct udevice *dev, int pingval, int *pingret)static int test_post_bind (struct udevice *dev) { dm_testdrv_op_count[DM_TEST_OP_POST_BIND ]++; +ut_assert (!device_active (dev));return 0 ; }
@@ -48,7 +49,7 @@ static int test_pre_probe(struct udevice *dev) dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE ]++;ut_assert (priv); -ut_assert (!device_active (dev)); +ut_assert (device_active (dev));return 0 ; }
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 8/80 dm: core: Mark device as active before calling uclass probe() methods
Quoted 5 lines · Simon Glass
The uclass pre-probe functions may end up calling back into the device in some circumstances. This can fail if recursion takes place. Adjust the ordering so that we mark the device as active early, then retract this later if needed.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/core/device.c | 8 +++++--- test/dm/test-uclass.c | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 9/80 dm: core: Add device children and sibling functions
In reply to Simon GlassAdd some utility functions to check for children and for the last sibling in a device's parent.
---
Changes in v2: None
drivers/core/device.c | 28 ++++++++++++++++++++++++++++ include/dm/device.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+)
drivers/core/device.c +28 -0
@@ -490,3 +490,31 @@ fdt_addr_t dev_get_addr(struct udevice *dev) return FDT_ADDR_T_NONE; }#endif + +bool device_has_children (struct udevice *dev) +{ +return !list_empty (&dev->child_head); +} + +bool device_has_active_children (struct udevice *dev) +{ +struct udevice *child; + +for (device_find_first_child (dev, &child); + child; +device_find_next_child (&child)) { +if (device_active (child)) +return true; + } + +return false; +} + +bool device_is_last_sibling (struct udevice *dev) +{ +struct udevice *parent = dev->parent; + +if (!parent) +return false; +return list_is_last (&dev->sibling_node, &parent->child_head); +}
include/dm/device.h +30 -0
@@ -380,4 +380,34 @@ int device_find_next_child(struct udevice **devp);*/ fdt_addr_t dev_get_addr (struct udevice *dev); +/** +* device_has_children() - check if a device has any children +* +* @dev: Device to check +* @return true if the device has one or more children +*/ +bool device_has_children (struct udevice *dev); + +/** +* device_has_active_children() - check if a device has any active children +* +* @dev: Device to check +* @return true if the device has one or more children and at least one of +* them is active (probed). +*/ +bool device_has_active_children (struct udevice *dev); + +/** +* device_is_last_sibling() - check if a device is the last sibling +* +* This function can be useful for display purposes, when special action needs +* to be taken when displaying the last sibling. This can happen when a tree +* view of devices is being displayed. +* +* @dev: Device to check +* @return true if there are no more siblings after this one - i.e. is it +* last in the list. +*/ +bool device_is_last_sibling (struct udevice *dev); +#endif
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 9/80 dm: core: Add device children and sibling functions
Quoted 11 lines · Simon Glass
Add some utility functions to check for children and for the last sibling in a device's parent.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/core/device.c | 28 ++++++++++++++++++++++++++++ include/dm/device.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 10/80 dm: gpio: Add an implementation for gpio_get_number()
In reply to Simon GlassThis has a prototype but no implementation. It returns the global GPIO number given a gpio_desc. It is useful for debugging in some cases.
---
Changes in v2: None
drivers/gpio/gpio-uclass.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/gpio/gpio-uclass.c +12 -0
@@ -689,6 +689,18 @@ static int gpio_renumber(struct udevice *removed_dev)return 0 ; } +int gpio_get_number (struct gpio_desc *desc) +{ +struct udevice *dev = desc->dev; +struct gpio_dev_priv *uc_priv; + +if (!dev) +return -1 ; + uc_priv = dev->uclass_priv; + +return uc_priv->gpio_base + desc->offset; +} +static int gpio_post_probe (struct udevice *dev) {struct gpio_dev_priv *uc_priv =dev_get_uclass_priv (dev);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 10/80 dm: gpio: Add an implementation for gpio_get_number()
Quoted 10 lines · Simon Glass
This has a prototype but no implementation. It returns the global GPIO number given a
gpio_desc. It is useful for debugging in some cases.Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/gpio/gpio-uclass.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 11/80 dm: usb: Add a uclass for USB controllers
In reply to Simon GlassAdd a uclass that can represent a USB controller. For now we do not create devices for things attached to the controller. This will be added later.
---
Changes in v2: None
drivers/usb/Kconfig | 14 ++ drivers/usb/host/Makefile | 4 + drivers/usb/host/usb-uclass.c | 392 ++++++++++++++++++++++++++++++++++++++ drivers/usb/musb-new/musb_uboot.c | 4 +- include/dm/uclass-id.h | 1 + include/usb.h | 285 ++++++++++++++++++++++++++- 6 files changed, 694 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/host/usb-uclass.c
drivers/usb/Kconfig +14 -0
@@ -35,6 +35,20 @@ config USB if USB +config DM_USB + bool "Enable driver model for USB" + depends on USB && DM + help + Enable driver model for USB. The USB interface is then implemented + by the USB uclass. Multiple USB controllers of different types + (XHCI, EHCI) can be attached and used. The 'usb' command works as + normal. OCHI is not supported at present. + + Much of the code is shared but with this option enabled the USB + uclass takes care of device enumeration. USB devices can be + declared with the USB_DEVICE() macro and will be automatically + probed when found on the bus. + source "drivers/usb/host/Kconfig" config USB_STORAGE
drivers/usb/host/Makefile +4 -0
@@ -5,6 +5,10 @@ # SPDX-License-Identifier: GPL-2.0+ # +ifdef CONFIG_DM_USB +obj-$(CONFIG_CMD_USB) += usb-uclass.o +endif + # ohci obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o obj-$(CONFIG_USB_ATMEL) += ohci-at91.o
drivers/usb/host/usb-uclass.c new file +392 -0
392 lines not on this page · raw message
drivers/usb/musb-new/musb_uboot.c +3 -1
@@ -177,7 +177,7 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)return NULL ;/* URB still pending */ } -void usb_reset_root_port (void ) +int usb_reset_root_port (void ) {void *mbase = host->mregs;u8 power;
@@ -194,6 +194,8 @@ void usb_reset_root_port(void) (musb_readb (mbase,MUSB_DEVCTL ) &MUSB_DEVCTL_FSDEV ) ?USB_SPEED_FULL :USB_SPEED_LOW ;mdelay ((host_speed ==USB_SPEED_LOW ) ?200 :50 ); + +return 0 ; }int usb_lowlevel_init (int index,enum usb_init_type init,void **controller)
include/dm/uclass-id.h +1 -0
@@ -39,6 +39,7 @@ enum uclass_id {UCLASS_PCI_GENERIC ,/* Generic PCI bus device */ UCLASS_PCH ,/* x86 platform controller hub */ UCLASS_ETH ,/* Ethernet device */ +UCLASS_USB ,/* USB bus */ UCLASS_COUNT , UCLASS_INVALID = -1,
include/usb.h +280 -5
332 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 11/80 dm: usb: Add a uclass for USB controllers
Quoted 8 lines · Simon Glass
Add a uclass that can represent a USB controller. For now we do not create devices for things attached to the controller. This will be added later.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
Quoted 8 lines
drivers/usb/Kconfig | 14 ++ drivers/usb/host/Makefile | 4 + drivers/usb/host/usb-uclass.c | 392 ++++++++++++++++++++++++++++++++++++++ drivers/usb/musb-new/musb_uboot.c | 4 +- include/dm/uclass-id.h | 1 + include/usb.h | 285 ++++++++++++++++++++++++++- 6 files changed, 694 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/host/usb-uclass.c
Applied to u-boot-dm/next.
PATCH v2 12/80 dm: usb: Adjust usb command to prepare for driver model
In reply to Simon GlassUse 'udev' instead of 'dev' in a few places, reserving 'dev' for driver model's struct udevice. Also adjust the code in a few minor ways to make it easier to plumb in driver model.
---
Changes in v2: None
common/cmd_usb.c | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-)
common/cmd_usb.c +25 -26
@@ -254,15 +254,15 @@ static void usb_display_config(struct usb_device *dev)static struct usb_device *usb_find_device (int devnum) { -struct usb_device *dev; +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; }return NULL ;
@@ -305,8 +305,8 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) has_child =1 ; }/* check if we are the last one */ - last_child =1 ; -if (dev->parent !=NULL ) { + last_child = (dev->parent !=NULL ); +if (last_child) {for (i =0 ; i < dev->parent->maxchild; i++) {/* search for children */ if (dev->parent->children[i] == dev) {
@@ -324,7 +324,7 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) }/* for all children of the parent */ printf ("\b+-" );/* correct last child */ -if (last_child) +if (last_child && index) pre[index-1 ] =' ' ; }/* if not root hub */ else
@@ -355,7 +355,7 @@ static void usb_show_tree(struct usb_device *dev) {char preamble[32 ]; -memset (preamble,0 ,32 ); +memset (preamble,'\0' ,sizeof (preamble));usb_show_tree_graph (dev, &preamble[0 ]); }
@@ -466,9 +466,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;
@@ -509,11 +508,11 @@ 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" );for (i =0 ; i <USB_MAX_DEVICE ; i++) { - dev =usb_get_dev_index (i); -if (dev ==NULL ) + udev =usb_get_dev_index (i); +if (udev ==NULL )break ; -if (dev->parent ==NULL ) -usb_show_tree (dev); +if (udev->parent ==NULL ) +usb_show_tree (udev); }return 0 ; }
@@ -521,23 +520,23 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])int d;if (argc ==2 ) {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); }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 +545,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 )
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 12/80 dm: usb: Adjust usb command to prepare for driver model
Quoted 11 lines · Simon Glass
Use 'udev' instead of 'dev' in a few places, reserving 'dev' for driver model's struct udevice. Also adjust the code in a few minor ways to make it easier to plumb in driver model.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/cmd_usb.c | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 13/80 dm: usb: Adjust usb_alloc_new_device() to return an error
In reply to Simon GlassThis function returns NULL on error at present. Adjust it so that we can return a real error, as is needed with driver model. Also improve the error handling in its caller, usb_hub_port_connect_change(), and adjust the code order to prepare for driver model.
---
Changes in v2: None
common/usb.c | 17 ++++++++--------- common/usb_hub.c | 41 ++++++++++++++++++++++++++--------------- include/usb.h | 20 ++++++++++++++++++-- 3 files changed, 52 insertions(+), 26 deletions(-)
common/usb.c +8 -9
@@ -94,12 +94,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)
@@ -827,16 +827,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 (struct udevice *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 +843,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 +853,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 (struct udevice *controller) { dev_index--;debug ("Freeing device node: %d\n" , dev_index);
common/usb_hub.c +26 -15
95 lines not on this page · raw message
include/usb.h +18 -2
@@ -703,10 +703,26 @@ 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); +/** +* usb_alloc_new_device() - Allocate a new device +* +* @devp: returns a pointer of a new device structure. With driver model this +* is a device pointer, but with legacy USB this pointer is +* driver-specific. +* @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); + +/** +* usb_free_device() - Free a partially-inited device +* +* This is an internal function. It is used to reverse the action of +* usb_alloc_new_device() when we hit a problem during init. +*/ +void usb_free_device (struct udevice *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_ */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 13/80 dm: usb: Adjust usb_alloc_new_device() to return an error
Quoted 6 lines · Simon Glass
This function returns NULL on error at present. Adjust it so that we can return a real error, as is needed with driver model. Also improve the error handling in its caller,
usb_hub_port_connect_change(), and adjust the code order to prepare for driver model.Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
common/usb.c | 17 ++++++++--------- common/usb_hub.c | 41 ++++++++++++++++++++++++++--------------- include/usb.h | 20 ++++++++++++++++++-- 3 files changed, 52 insertions(+), 26 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 14/80 dm: usb: Convert 'usb' command to support driver model
In reply to Simon GlassAdjust this command to work with the new driver model uclass. It needs to iterate through multiple independent controllers to find hubs, and work through their children recursively in a different way. Otherwise the functionality is much the same.
---
Changes in v2: None
common/cmd_usb.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 2 deletions(-)
common/cmd_usb.c +145 -2
@@ -2,6 +2,9 @@* (C) Copyright 2001 * Denis Peter, MPL AG Switzerland * +* Adapted for U-Boot driver model +* (C) Copyright 2015 Google, Inc +* * Most of this source has been derived from the Linux USB * project. *
@@ -10,6 +13,7 @@#include <common.h> #include <command.h> +#include <dm.h> #include <asm/byteorder.h> #include <asm/unaligned.h> #include <part.h>
@@ -252,8 +256,46 @@ static void usb_display_config(struct usb_device *dev)printf ("\n" ); } +/* +* With driver model this isn't right since we can have multiple controllers +* and the device numbering starts at 1 on each bus. +* TODO(sjg at chromium.org): Add a way to specify the controller/bus. +*/ static struct usb_device *usb_find_device (int devnum) { +#ifdef CONFIG_DM_USB +struct usb_device *udev; +struct udevice *hub; +struct uclass *uc; +int ret; + +/* Device addresses start at 1 */ + devnum++; + ret =uclass_get (UCLASS_USB_HUB , &uc); +if (ret) +return NULL ; + + uclass_foreach_dev(hub, uc) { +struct udevice *dev; + +if (!device_active (hub)) +continue ; + udev =dev_get_parentdata (hub); +if (udev->devnum == devnum) +return udev; + +for (device_find_first_child (hub, &dev); + dev; +device_find_next_child (&dev)) { +if (!device_active (hub)) +continue ; + + udev =dev_get_parentdata (dev); +if (udev->devnum == devnum) +return udev; + } + } +#else struct usb_device *udev;int d;
@@ -264,6 +306,7 @@ static struct usb_device *usb_find_device(int devnum)if (udev->devnum == devnum) return udev; } +#endif return NULL ; }
@@ -293,20 +336,31 @@ static inline char *portspeed(int speed)/* shows the device tree recursively */ static void usb_show_tree_graph (struct usb_device *dev,char *pre) { -int i, index; +int index;int has_child, last_child; index =strlen (pre);printf (" %s" , pre); +#ifdef CONFIG_DM_USB + has_child =device_has_active_children (dev->dev); +#else /* check if the device has connected children */ +int i; + has_child =0 ;for (i =0 ; i < dev->maxchild; i++) {if (dev->children[i] !=NULL ) has_child =1 ; } +#endif /* check if we are the last one */ +#ifdef CONFIG_DM_USB + last_child =device_is_last_sibling (dev->dev); +#else last_child = (dev->parent !=NULL ); +#endif if (last_child) { +#ifndef CONFIG_DM_USB for (i =0 ; i < dev->parent->maxchild; i++) {/* search for children */ if (dev->parent->children[i] == dev) {
@@ -322,6 +376,7 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) } /* while */ }/* device found */ }/* for all children of the parent */ +#endif printf ("\b+-" );/* correct last child */ if (last_child && index)
@@ -340,6 +395,26 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre)if (strlen (dev->mf) ||strlen (dev->prod) ||strlen (dev->serial))printf (" %s %s %s %s\n" , pre, dev->mf, dev->prod, dev->serial);printf (" %s\n" , pre); +#ifdef CONFIG_DM_USB +struct udevice *child; + +for (device_find_first_child (dev->dev, &child); + child; +device_find_next_child (&child)) { +struct usb_device *udev; + +if (!device_active (child)) +continue ; + + udev =dev_get_parentdata (child); + +/* Ignore emulators, we only want real devices */ +if (device_get_uclass_id (child) !=UCLASS_USB_EMUL ) { +usb_show_tree_graph (udev, pre); + pre[index] =0 ; + } + } +#else if (dev->maxchild >0 ) {for (i =0 ; i < dev->maxchild; i++) {if (dev->children[i] !=NULL ) {
@@ -348,6 +423,7 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) } } } +#endif }/* main routine for the tree command */
@@ -448,10 +524,13 @@ static void do_usb_start(void)if (usb_init () <0 )return ; +/* Driver model will probe the devices as they are found */ +#ifndef CONFIG_DM_USB #ifdef CONFIG_USB_STORAGE /* try to recognize storage devices immediately */ usb_stor_curr_dev =usb_stor_scan (1 );#endif +#endif #ifdef CONFIG_USB_HOST_ETHER /* try to recognize ethernet devices immediately */ usb_ether_curr_dev =usb_host_eth_scan (1 );
@@ -461,6 +540,43 @@ static void do_usb_start(void)#endif } +#ifdef CONFIG_DM_USB +static void show_info (struct udevice *dev) +{ +struct udevice *child; +struct usb_device *udev; + + udev =dev_get_parentdata (dev); +usb_display_desc (udev); +usb_display_config (udev); +for (device_find_first_child (dev, &child); + child; +device_find_next_child (&child)) { +if (device_active (child)) +show_info (child); + } +} + +static int usb_device_info (void ) +{ +struct udevice *bus; + +for (uclass_first_device (UCLASS_USB , &bus); + bus; +uclass_next_device (&bus)) { +struct udevice *hub; + +device_find_first_child (bus, &hub); +if (device_get_uclass_id (hub) ==UCLASS_USB_HUB && +device_active (hub)) { +show_info (hub); + } + } + +return 0 ; +} +#endif +/****************************************************************************** * usb command intepreter */
@@ -507,6 +623,23 @@ 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 *bus; + +for (uclass_first_device (UCLASS_USB , &bus); + bus; +uclass_next_device (&bus)) { +struct usb_device *udev; +struct udevice *hub; + +device_find_first_child (bus, &hub); +if (device_get_uclass_id (hub) ==UCLASS_USB_HUB && +device_active (hub)) { + udev =dev_get_parentdata (hub); +usb_show_tree (udev); + } + } +#else for (i =0 ; i <USB_MAX_DEVICE ; i++) { udev =usb_get_dev_index (i);if (udev ==NULL )
@@ -514,11 +647,15 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (udev->parent ==NULL )usb_show_tree (udev); } +#endif return 0 ; }if (strncmp (argv[1 ],"inf" ,3 ) ==0 ) { -int d;if (argc ==2 ) { +#ifdef CONFIG_DM_USB +usb_device_info (); +#else +int d;for (d =0 ; d <USB_MAX_DEVICE ; d++) { udev =usb_get_dev_index (d);if (udev ==NULL )
@@ -526,8 +663,14 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])usb_display_desc (udev); usb_display_config(udev); } +#endif return 0 ; }else { +/* +* With driver model this isn't right since we can +* have multiple controllers and the device numbering +* starts@1 on each bus. +*/ i =simple_strtoul (argv[2 ],NULL ,10 );printf ("config for device %d\n" , i); udev =usb_find_device (i);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 14/80 dm: usb: Convert 'usb' command to support driver model
Quoted 5 lines · Simon Glass
Adjust this command to work with the new driver model uclass. It needs to iterate through multiple independent controllers to find hubs, and work through their children recursively in a different way. Otherwise the functionality is much the same.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/cmd_usb.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 15/80 dm: usb: Drop the legacy USB init sequence
In reply to Simon GlassThis CONFIG is not used anywhere in U-Boot, so drop it.
---
Changes in v2: None
common/usb.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-)
common/usb.c +4 -22
@@ -899,26 +899,8 @@ int usb_new_device(struct usb_device *dev) addr = dev->devnum; dev->devnum =0 ; -#ifdef CONFIG_LEGACY_USB_INIT_SEQ -/* this is the old and known way of initializing devices, it is -* different than what Windows and Linux are doing. Windows and Linux -* both retrieve 64 bytes while reading the device descriptor -* Several USB stick devices report ERR: CTL_TIMEOUT, caused by an -* invalid header while reading 8 bytes as device descriptor. */ - dev->descriptor.bMaxPacketSize0 =8 ;/* Start off at 8 bytes */ - dev->maxpacketsize =PACKET_SIZE_8 ; - dev->epmaxpacketin[0 ] =8 ; - dev->epmaxpacketout[0 ] =8 ; - - err =usb_get_descriptor (dev,USB_DT_DEVICE ,0 , tmpbuf,8 ); -if (err <8 ) { -printf ("\n USB device not responding, " \ -"giving up (status=%lX)\n" , dev->status); -return 1 ; - } -memcpy (&dev->descriptor, tmpbuf,8 ); -#else -/* This is a Windows scheme of initialization sequence, with double +/* +* This is a Windows scheme of initialization sequence, with double * reset of the device (Linux uses the same sequence) * Some equipment is said to work only with such init sequence; this * patch is based on the work by Alan Stern:
@@ -929,7 +911,8 @@ int usb_new_device(struct usb_device *dev)struct usb_device *parent = dev->parent;unsigned short portstatus; -/* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is +/* +* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is * only 18 bytes long, this will terminate with a short packet. But if * the maxpacket size is 8 or 16 the device may be waiting to transmit * some more, or keeps on retransmitting the 8 byte header. */
@@ -972,7 +955,6 @@ int usb_new_device(struct usb_device *dev) }else {usb_reset_root_port (); } -#endif dev->epmaxpacketin[0 ] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0 ] = dev->descriptor.bMaxPacketSize0;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 15/80 dm: usb: Drop the legacy USB init sequence
Quoted 3 lines · Simon Glass
This CONFIG is not used anywhere in U-Boot, so drop it.
Signed-off-by Simon Glass <[email protected]>
Best regards,
Marek Vasut
PATCH v2 15/80 dm: usb: Drop the legacy USB init sequence
Quoted 6 lines · Marek Vasut
Quoted 3 lines · Simon Glass
This CONFIG is not used anywhere in U-Boot, so drop it.
Signed-off-by Simon Glass <[email protected]>Acked-by Marek Vasut <[email protected]>
Applied to u-boot-dm/next.
PATCH v2 16/80 dm: usb: Refactor port resets
In reply to Simon GlassMove the port reset code into its own function. Rename usb_hub_reset() to indicate that is is now a legacy function.
---
Changes in v2: None
common/usb.c | 40 ++++++++++++++++++++++++++-------------- common/usb_hub.c | 4 ++-- include/usb.h | 18 +++++++++++++++++- 3 files changed, 45 insertions(+), 17 deletions(-)
common/usb.c +26 -14
@@ -871,6 +871,26 @@ __weak int usb_alloc_device(struct usb_device *udev) {return 0 ; } + +int usb_legacy_port_reset (struct usb_device *hub,int portnr) +{ +if (hub) { +unsigned short portstatus; +int err; + +/* reset the port for the second time */ + err =legacy_hub_port_reset (hub, portnr -1 , &portstatus); +if (err <0 ) { +printf ("\n Couldn't reset port %i\n" , portnr); +return err; + } + }else { +usb_reset_root_port (); + } + +return 0 ; +} +/* * 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
@@ -907,9 +927,6 @@ int usb_new_device(struct usb_device *dev)* http://sourceforge.net/mailarchive/forum.php? * thread_id=5729457&forum_id=5398 */ -__maybe_unused struct usb_device_descriptor *desc; -struct usb_device *parent = dev->parent; -unsigned short portstatus;/* * send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is
@@ -917,7 +934,6 @@ int usb_new_device(struct usb_device *dev)* the maxpacket size is 8 or 16 the device may be waiting to transmit * some more, or keeps on retransmitting the 8 byte header. */ - desc = (struct usb_device_descriptor *)tmpbuf; dev->descriptor.bMaxPacketSize0 =64 ;/* Start off at 64 bytes */ /* Default to 64 byte max packet size */ dev->maxpacketsize =PACKET_SIZE_64 ;
@@ -931,6 +947,9 @@ int usb_new_device(struct usb_device *dev)* of that is done for XHCI unlike EHCI. */ #ifndef CONFIG_USB_XHCI +struct usb_device_descriptor *desc; + + desc = (struct usb_device_descriptor *)tmpbuf; err =usb_get_descriptor (dev,USB_DT_DEVICE ,0 , desc,64 );if (err <0 ) {debug ("usb_new_device: usb_get_descriptor() failed\n" );
@@ -945,16 +964,9 @@ int usb_new_device(struct usb_device *dev) dev->descriptor.bDeviceClass = desc->bDeviceClass;#endif -if (parent) { -/* reset the port for the second time */ - err =hub_port_reset (dev->parent, dev->portnr -1 , &portstatus); -if (err <0 ) { -printf ("\n Couldn't reset port %i\n" , dev->portnr); -return 1 ; - } - }else { -usb_reset_root_port (); - } + err =usb_legacy_port_reset (dev->parent, dev->portnr); +if (err) +return err; dev->epmaxpacketin[0 ] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0 ] = dev->descriptor.bMaxPacketSize0;
common/usb_hub.c +2 -2
@@ -141,7 +141,7 @@ static inline char *portspeed(int portstatus)return speed_str; } -int hub_port_reset (struct usb_device *dev,int port, +int legacy_hub_port_reset (struct usb_device *dev,int port,unsigned short *portstat) {int tries;
@@ -241,7 +241,7 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port)mdelay (200 );/* Reset the port */ - ret =hub_port_reset (dev, port, &portstatus); + ret =legacy_hub_port_reset (dev, port, &portstatus);if (ret <0 ) {printf ("cannot reset port %i!?\n" , port +1 );return ret;
include/usb.h +17 -1
@@ -700,9 +700,25 @@ bool usb_device_has_child_on_port(struct usb_device *parent, int port);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, + +/** +* legacy_hub_port_reset() - reset a port given its usb_device pointer +* +* Reset a hub port and see if a device is present on that port, providing +* sufficient time for it to show itself. The port status is returned. +* +* With driver model this moves to hub_port_reset() and is passed a struct +* udevice. +* +* @dev: USB device to reset +* @port: Port number to reset (note ports are numbered from 0 here) +* @portstat: Returns port status +*/ +int legacy_hub_port_reset (struct usb_device *dev,int port,unsigned short *portstat); +int hub_port_reset (struct udevice *dev,int port,unsigned short *portstat); +/** * usb_alloc_new_device() - Allocate a new device *
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 16/80 dm: usb: Refactor port resets
Quoted 4 lines · Simon Glass
Move the port reset code into its own function. Rename
usb_hub_reset()to indicate that is is now a legacy function.Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
common/usb.c | 40 ++++++++++++++++++++++++++-------------- common/usb_hub.c | 4 ++-- include/usb.h | 18 +++++++++++++++++- 3 files changed, 45 insertions(+), 17 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 17/80 dm: usb: Move descriptor setup code into its own function
In reply to Simon Glassusb_new_device() is far too long and does far too much. As a first step, move the code that does initial setup and reads a descriptor into its own function called usb_setup_descriptor().
For XHCI the init order is different - we set up the device but don't actually read the descriptor until after we set an address. Support this option as a parameter to usb_setup_descriptor().
Avoid changing this torturous code more than necessary to make it easy to review.
---
Changes in v2: None
common/usb.c | 117 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 50 deletions(-)
common/usb.c +67 -50
@@ -891,35 +891,12 @@ int usb_legacy_port_reset(struct usb_device *hub, int portnr)return 0 ; } -/* -* 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 -* get the ball rolling.. -* -* Returns 0 for success, != 0 for error. -*/ -int usb_new_device (struct usb_device *dev) +static int usb_setup_descriptor (struct usb_device *dev,bool do_read) { -int addr, err; -int tmp; +__maybe_unused struct usb_device_descriptor *desc; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);/* -* Allocate usb 3.0 device context. -* USB 3.0 (xHCI) protocol tries to allocate device slot -* and related data structures first. This call does that. -* Refer to sec 4.3.2 in xHCI spec rev1.0 -*/ -if (usb_alloc_device (dev)) { -printf ("Cannot allocate device context to get SLOT_ID\n" ); -return -1 ; - } - -/* We still haven't set the Address yet */ - addr = dev->devnum; - dev->devnum =0 ; - -/* * This is a Windows scheme of initialization sequence, with double * reset of the device (Linux uses the same sequence) * Some equipment is said to work only with such init sequence; this
@@ -934,40 +911,31 @@ int usb_new_device(struct usb_device *dev)* the maxpacket size is 8 or 16 the device may be waiting to transmit * some more, or keeps on retransmitting the 8 byte header. */ + desc = (struct usb_device_descriptor *)tmpbuf; dev->descriptor.bMaxPacketSize0 =64 ;/* Start off at 64 bytes */ /* Default to 64 byte max packet size */ dev->maxpacketsize =PACKET_SIZE_64 ; dev->epmaxpacketin[0 ] =64 ; dev->epmaxpacketout[0 ] =64 ; -/* -* XHCI needs to issue a Address device command to setup -* proper device context structures, before it can interact -* with the device. So a get_descriptor will fail before any -* of that is done for XHCI unlike EHCI. -*/ -#ifndef CONFIG_USB_XHCI -struct usb_device_descriptor *desc; +if (do_read) { +int err; - desc = (struct usb_device_descriptor *)tmpbuf; - err =usb_get_descriptor (dev,USB_DT_DEVICE ,0 , desc,64 ); -if (err <0 ) { -debug ("usb_new_device: usb_get_descriptor() failed\n" ); -return 1 ; + err =usb_get_descriptor (dev,USB_DT_DEVICE ,0 , desc,64 ); +if (err <sizeof (dev->descriptor)) { +if (err <0 ) { +printf ("unable to get device descriptor (error=%d)\n" , + err); +return err; + }else { +printf ("USB device descriptor short read (expected %i, got %i)\n" , + (int )sizeof (dev->descriptor), err); +return -EIO ; + } + } +memcpy (&dev->descriptor, tmpbuf,sizeof (dev->descriptor)); } - dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; -/* -* Fetch the device class, driver can use this info -* to differentiate between HUB and DEVICE. -*/ - dev->descriptor.bDeviceClass = desc->bDeviceClass; -#endif - - err =usb_legacy_port_reset (dev->parent, dev->portnr); -if (err) -return err; - dev->epmaxpacketin[0 ] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0 ] = dev->descriptor.bMaxPacketSize0;switch (dev->descriptor.bMaxPacketSize0) {
@@ -984,6 +952,55 @@ int usb_new_device(struct usb_device *dev) dev->maxpacketsize =PACKET_SIZE_64 ;break ; } + +return 0 ; +} + +/* +* 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 +* get the ball rolling.. +* +* Returns 0 for success, != 0 for error. +*/ +int usb_new_device (struct usb_device *dev) +{ +bool do_read = true; +int addr, err; +int tmp; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + +/* +* Allocate usb 3.0 device context. +* USB 3.0 (xHCI) protocol tries to allocate device slot +* and related data structures first. This call does that. +* Refer to sec 4.3.2 in xHCI spec rev1.0 +*/ +if (usb_alloc_device (dev)) { +printf ("Cannot allocate device context to get SLOT_ID\n" ); +return -1 ; + } + +/* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum =0 ; + +/* +* XHCI needs to issue a Address device command to setup +* proper device context structures, before it can interact +* with the device. So a get_descriptor will fail before any +* of that is done for XHCI unlike EHCI. +*/ +#ifndef CONFIG_USB_XHCI + do_read = false; +#endif + err =usb_setup_descriptor (dev, do_read); +if (err) +return err; + err =usb_legacy_port_reset (dev->parent, dev->portnr); +if (err) +return err; + dev->devnum = addr; err =usb_set_address (dev);/* set address */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 17/80 dm: usb: Move descriptor setup code into its own function
Quoted 11 lines · Simon Glass
usb_new_device()is far too long and does far too much. As a first step, move the code that does initial setup and reads a descriptor into its own function calledusb_setup_descriptor().For XHCI the init order is different - we set up the device but don't actually read the descriptor until after we set an address. Support this option as a parameter to
usb_setup_descriptor().Avoid changing this torturous code more than necessary to make it easy to review.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb.c | 117 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 50 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 18/80 dm: usb: Split out more code from usb_new_device()
In reply to Simon GlassMove the code that sets up the device with a new address into its own function, usb_prepare_device().
---
Changes in v2: None
common/usb.c | 72 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 30 deletions(-)
common/usb.c +42 -30
@@ -956,19 +956,10 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read)return 0 ; } -/* -* 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 -* get the ball rolling.. -* -* Returns 0 for success, != 0 for error. -*/ -int usb_new_device (struct usb_device *dev) +static int usb_prepare_device (struct usb_device *dev,int addr,bool do_read, +struct usb_device *parent,int portnr) { -bool do_read = true; -int addr, err; -int tmp; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); +int err;/* * Allocate usb 3.0 device context.
@@ -976,28 +967,15 @@ int usb_new_device(struct usb_device *dev)* and related data structures first. This call does that. * Refer to sec 4.3.2 in xHCI spec rev1.0 */ -if (usb_alloc_device (dev)) { + err =usb_alloc_device (dev); +if (err) {printf ("Cannot allocate device context to get SLOT_ID\n" ); -return -1 ; +return err; } - -/* We still haven't set the Address yet */ - addr = dev->devnum; - dev->devnum =0 ; - -/* -* XHCI needs to issue a Address device command to setup -* proper device context structures, before it can interact -* with the device. So a get_descriptor will fail before any -* of that is done for XHCI unlike EHCI. -*/ -#ifndef CONFIG_USB_XHCI - do_read = false; -#endif err =usb_setup_descriptor (dev, do_read);if (err)return err; - err =usb_legacy_port_reset (dev->parent, dev->portnr); + err =usb_legacy_port_reset (parent, portnr);if (err)return err;
@@ -1008,11 +986,45 @@ int usb_new_device(struct usb_device *dev)if (err <0 ) {printf ("\n USB device not accepting new address " \"(error=%lX)\n" , dev->status); -return 1 ; +return err; }mdelay (10 );/* Let the SET_ADDRESS settle */ +return 0 ; +} + +/* +* 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 +* get the ball rolling.. +* +* Returns 0 for success, != 0 for error. +*/ +int usb_new_device (struct usb_device *dev) +{ +bool do_read = true; +int addr, err; +int tmp, ret; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + +/* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum =0 ; + +/* +* XHCI needs to issue a Address device command to setup +* proper device context structures, before it can interact +* with the device. So a get_descriptor will fail before any +* of that is done for XHCI unlike EHCI. +*/ +#ifndef CONFIG_USB_XHCI + do_read = false; +#endif + ret =usb_prepare_device (dev, addr, do_read, dev->parent, dev->portnr); +if (ret) +return ret; + tmp =sizeof (dev->descriptor); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 18/80 dm: usb: Split out more code from usb_new_device()
Quoted 10 lines · Simon Glass
Move the code that sets up the device with a new address into its own function,
usb_prepare_device().Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb.c | 72 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 30 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 19/80 dm: usb: Complete the splitting up of usb_new_device()
In reply to Simon GlassThis function now calls usb_setup_device() to set up the device and usb_hub_probe() to check if it is a hub. The XHCI special case is now a parameter to usb_setup_device(). The latter will be used by the USB uclass when it is added, since it does not rely on any CONFIGs or legacy data structures.
---
Changes in v2: None
common/usb.c | 114 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 46 deletions(-)
common/usb.c +68 -46
@@ -994,71 +994,40 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,return 0 ; } -/* -* 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 -* get the ball rolling.. -* -* Returns 0 for success, != 0 for error. -*/ -int usb_new_device (struct usb_device *dev) +static int usb_select_config (struct usb_device *dev) { -bool do_read = true; -int addr, err; -int tmp, ret; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); +int err; -/* We still haven't set the Address yet */ - addr = dev->devnum; - dev->devnum =0 ; - -/* -* XHCI needs to issue a Address device command to setup -* proper device context structures, before it can interact -* with the device. So a get_descriptor will fail before any -* of that is done for XHCI unlike EHCI. -*/ -#ifndef CONFIG_USB_XHCI - do_read = false; -#endif - ret =usb_prepare_device (dev, addr, do_read, dev->parent, dev->portnr); -if (ret) -return ret; - - tmp =sizeof (dev->descriptor); + err =usb_setup_descriptor (dev, true); +if (err) +return err; - err =usb_get_descriptor (dev,USB_DT_DEVICE ,0 , - tmpbuf,sizeof (dev->descriptor)); -if (err < tmp) { -if (err <0 ) -printf ("unable to get device descriptor (error=%d)\n" , - err); -else -printf ("USB device descriptor short read " \ -"(expected %i, got %i)\n" , tmp, err); -return 1 ; - } -memcpy (&dev->descriptor, tmpbuf,sizeof (dev->descriptor));/* correct le values */ le16_to_cpus (&dev->descriptor.bcdUSB);le16_to_cpus (&dev->descriptor.idVendor);le16_to_cpus (&dev->descriptor.idProduct);le16_to_cpus (&dev->descriptor.bcdDevice); +/* only support for one config for now */ err =usb_get_configuration_no (dev, tmpbuf,0 );if (err <0 ) {printf ("usb_new_device: Cannot read configuration, " \"skipping device %04x:%04x\n" , dev->descriptor.idVendor, dev->descriptor.idProduct); -return -1 ; +return -err; }usb_parse_config (dev, tmpbuf,0 );usb_set_maxpacket (dev); -/* we set the default configuration here */ +/* +* we set the default configuration here +* This seems premature. If the driver wants a different configuration +* it will need to select itself. +*/ if (usb_set_configuration (dev, dev->config.desc.bConfigurationValue)) {printf ("failed to set default configuration " \"len %d, status %lX\n" , dev->act_len, dev->status); -return -1 ; +return -err; } debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", dev->descriptor.iManufacturer, dev->descriptor.iProduct,
@@ -1078,11 +1047,64 @@ int usb_new_device(struct usb_device *dev)debug ("Manufacturer %s\n" , dev->mf);debug ("Product %s\n" , dev->prod);debug ("SerialNumber %s\n" , dev->serial); -/* now prode if the device is a hub */ -usb_hub_probe (dev,0 ); +return 0 ; } +static int usb_setup_device (struct usb_device *dev,bool do_read, +struct usb_device *parent,int portnr) +{ +int addr; +int ret; + +/* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum =0 ; + + ret =usb_prepare_device (dev, addr, do_read, parent, portnr); +if (ret) +return ret; + ret =usb_select_config (dev); + +return ret; +} + +/* +* 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 +* get the ball rolling.. +* +* Returns 0 for success, != 0 for error. +*/ +int usb_new_device (struct usb_device *dev) +{ +bool do_read = true; +int count; +int err; + +/* +* XHCI needs to issue a Address device command to setup +* proper device context structures, before it can interact +* with the device. So a get_descriptor will fail before any +* of that is done for XHCI unlike EHCI. +*/ +#ifndef CONFIG_USB_XHCI + do_read = false; +#endif + err =usb_setup_device (dev, do_read, dev->parent, dev->portnr); +if (err) +return err; + + count =1 ; +/* now prode if the device is a hub */ + err =usb_hub_probe (dev,0 ); +if (err <0 ) +return err; + count += err; + +return count; +} +__weak int board_usb_init (int index,enum usb_init_type init) {
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 19/80 dm: usb: Complete the splitting up of usb_new_device()
Quoted 6 lines · Simon Glass
This function now calls
usb_setup_device()to set up the device andusb_hub_probe()to check if it is a hub. The XHCI special case is now a parameter tousb_setup_device(). The latter will be used by the USB uclass when it is added, since it does not rely on any CONFIGs or legacy data structures.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb.c | 114 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 46 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 20/80 dm: usb: Convert core usb.c file to support driver model
In reply to Simon GlassAdd the required #ifdefs and remove unwanted data structures so that the USB uclass will be able to use this file.
---
Changes in v2: None
common/usb.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
common/usb.c +25 -6
@@ -28,6 +28,7 @@*/ #include <common.h> #include <command.h> +#include <dm.h> #include <asm/processor.h> #include <linux/compiler.h> #include <linux/ctype.h>
@@ -41,12 +42,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
@@ -152,6 +154,7 @@ int usb_disable_asynch(int disable) asynch_allowed = !disable; return old_value; } +#endif /* !CONFIG_DM_USB */ /*-------------------------------------------------------------------
@@ -815,6 +818,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
@@ -871,7 +875,9 @@ __weak int usb_alloc_device(struct usb_device *udev) {return 0 ; } +#endif /* !CONFIG_DM_USB */ +#ifndef CONFIG_DM_USB int usb_legacy_port_reset (struct usb_device *hub,int portnr) {if (hub) {
@@ -890,6 +896,7 @@ int usb_legacy_port_reset(struct usb_device *hub, int portnr) return 0; } +#endif static int usb_setup_descriptor (struct usb_device *dev,bool do_read) {
@@ -994,7 +1001,7 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,return 0 ; } -static int usb_select_config (struct usb_device *dev) +int usb_select_config (struct usb_device *dev) { ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);int err;
@@ -1051,8 +1058,8 @@ static int usb_select_config(struct usb_device *dev)return 0 ; } -static int usb_setup_device (struct usb_device *dev,bool do_read, -struct usb_device *parent,int portnr) +int usb_setup_device (struct usb_device *dev,bool do_read, +struct usb_device *parent,int portnr) {int addr;int ret;
@@ -1069,6 +1076,7 @@ static int usb_setup_device(struct usb_device *dev, bool do_read,return ret; } +#ifndef 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
@@ -1104,10 +1112,21 @@ int usb_new_device(struct usb_device *dev) return count; } +#endif __weak int board_usb_init (int index,enum usb_init_type init) {return 0 ; } + +bool usb_device_has_child_on_port (struct usb_device *parent,int port) +{ +#ifdef CONFIG_DM_USB +return false; +#else +return parent->children[port] !=NULL ; +#endif +} +/* EOF */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 20/80 dm: usb: Convert core usb.c file to support driver model
Quoted 10 lines · Simon Glass
Add the required #ifdefs and remove unwanted data structures so that the USB uclass will be able to use this file.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 21/80 dm: usb: Split hub detection into its own function
In reply to Simon GlassSplit out the hub detection logic so it can be used by driver model. Also adjust the code to return errors correctly.
---
Changes in v2: None
common/usb_hub.c | 57 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 16 deletions(-)
common/usb_hub.c +41 -16
@@ -297,27 +297,30 @@ static int usb_hub_configure(struct usb_device *dev)struct usb_hub_descriptor *descriptor;struct usb_hub_device *hub;__maybe_unused struct usb_hub_status *hubsts; +int ret;/* "allocate" Hub device */ hub =usb_hub_allocate ();if (hub ==NULL ) -return -1 ; +return -ENOMEM ; hub->pusb_dev = dev;/* Get the the hub descriptor */ -if (usb_get_hub_descriptor (dev, buffer,4 ) <0 ) { + ret =usb_get_hub_descriptor (dev, buffer,4 ); +if (ret <0 ) {debug ("usb_hub_configure: failed to get hub " \"descriptor, giving up %lX\n" , dev->status); -return -1 ; +return ret; } descriptor = (struct usb_hub_descriptor *)buffer; length =min_t (int, descriptor->bLength,sizeof (struct usb_hub_descriptor )); -if (usb_get_hub_descriptor (dev, buffer, length) <0 ) { + ret =usb_get_hub_descriptor (dev, buffer, length); +if (ret <0 ) {debug ("usb_hub_configure: failed to get hub " \"descriptor 2nd giving up %lX\n" , dev->status); -return -1 ; +return ret; }memcpy ((unsigned char *)&hub->desc, buffer, length);/* adjust 16bit values */
@@ -385,13 +388,14 @@ static int usb_hub_configure(struct usb_device *dev)if (sizeof (struct usb_hub_status ) >USB_BUFSIZ ) {debug ("usb_hub_configure: failed to get Status - " \"too long: %d\n" , descriptor->bLength); -return -1 ; +return -EFBIG ; } -if (usb_get_hub_status (dev, buffer) <0 ) { + ret =usb_get_hub_status (dev, buffer); +if (ret <0 ) {debug ("usb_hub_configure: failed to get Status %lX\n" , dev->status); -return -1 ; +return ret; }#ifdef DEBUG
@@ -423,6 +427,7 @@ static int usb_hub_configure(struct usb_device *dev)int ret;ulong start =get_timer (0 ); +debug ("\n\nScanning port %d\n" , i +1 );/* * Wait for (whichever finishes first) * - A maximum of 10 seconds
@@ -503,33 +508,53 @@ static int usb_hub_configure(struct usb_device *dev)return 0 ; } -int usb_hub_probe (struct usb_device *dev,int ifnum) +static int usb_hub_check (struct usb_device *dev,int ifnum) {struct usb_interface *iface; -struct usb_endpoint_descriptor *ep; -int ret; +struct usb_endpoint_descriptor *ep =NULL ; iface = &dev->config.if_desc[ifnum];/* Is it a hub? */ if (iface->desc.bInterfaceClass !=USB_CLASS_HUB ) -return 0 ; + goto err;/* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((iface->desc.bInterfaceSubClass !=0 ) && (iface->desc.bInterfaceSubClass !=1 )) -return 0 ; + goto err;/* Multiple endpoints? What kind of mutant ninja-hub is this? */ if (iface->desc.bNumEndpoints !=1 ) -return 0 ; + goto err; ep = &iface->ep_desc[0 ];/* Output endpoint? Curiousier and curiousier.. */ if (!(ep->bEndpointAddress &USB_DIR_IN )) -return 0 ; + goto err;/* If it's not an interrupt endpoint, we'd better punt! */ if ((ep->bmAttributes &3 ) !=3 ) -return 0 ; + goto err;/* We found a hub */ debug ("USB hub found\n" ); +return 0 ; + +err: +debug ("USB hub not found: bInterfaceClass=%d, bInterfaceSubClass=%d, bNumEndpoints=%d\n" , + iface->desc.bInterfaceClass, iface->desc.bInterfaceSubClass, + iface->desc.bNumEndpoints); +if (ep) { +debug (" bEndpointAddress=%#x, bmAttributes=%d" , + ep->bEndpointAddress, ep->bmAttributes); + } + +return -ENOENT ; +} + +int usb_hub_probe (struct usb_device *dev,int ifnum) +{ +int ret; + + ret =usb_hub_check (dev, ifnum); +if (ret) +return 0 ; ret =usb_hub_configure (dev);return ret; }
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 21/80 dm: usb: Split hub detection into its own function
Quoted 10 lines · Simon Glass
Split out the hub detection logic so it can be used by driver model. Also adjust the code to return errors correctly.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_hub.c | 57 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 16 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 22/80 dm: usb: Add driver model support for hubs
In reply to Simon GlassAdjust the existing hub code to support driver model, and add a USB driver for hubs.
---
Changes in v2: None
common/usb_hub.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++--- include/dm/uclass-id.h | 1 + 2 files changed, 91 insertions(+), 4 deletions(-)
common/usb_hub.c +90 -4
@@ -24,12 +24,16 @@#include <common.h> #include <command.h> +#include <dm.h> #include <errno.h> #include <asm/processor.h> #include <asm/unaligned.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <asm/unaligned.h> +#include <dm/root.h> + +DECLARE_GLOBAL_DATA_PTR ;#include <usb.h> #ifdef CONFIG_4xx
@@ -38,6 +42,7 @@#define USB_BUFSIZ 512 +/* TODO(sjg at chromium.org): Remove this when CONFIG_DM_USB is defined */ static struct usb_hub_device hub_dev[USB_MAX_HUB ];static int usb_hub_index;
@@ -148,7 +153,12 @@ int legacy_hub_port_reset(struct usb_device *dev, int port, ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);unsigned short portstatus, portchange; -debug ("hub_port_reset: resetting port %d...\n" , port); +#ifdef CONFIG_DM_USB +debug ("%s: resetting '%s' port %d...\n" , __func__, dev->dev->name, + port +1 ); +#else +debug ("%s: resetting port %d...\n" , __func__, port +1 ); +#endif for (tries =0 ; tries <MAX_TRIES ; tries++) {usb_set_port_feature (dev, port +1 ,USB_PORT_FEAT_RESET );
@@ -206,10 +216,17 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,return 0 ; } +#ifdef CONFIG_DM_USB +int hub_port_reset (struct udevice *dev,int port,unsigned short *portstat) +{ +struct usb_device *udev =dev_get_parentdata (dev); + +return legacy_hub_port_reset (udev, port, portstat); +} +#endif int 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, speed;
@@ -232,7 +249,8 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port)/* Disconnect any existing devices under this port */ if (((!(portstatus &USB_PORT_STAT_CONNECTION )) && - (!(portstatus &USB_PORT_STAT_ENABLE ))) || (dev->children[port])) { + (!(portstatus &USB_PORT_STAT_ENABLE ))) || +usb_device_has_child_on_port (dev, port)) {debug ("usb_disconnect(&hub->children[port]);\n" );/* Return now if nothing is connected */ if (!(portstatus &USB_PORT_STAT_CONNECTION ))
@@ -264,6 +282,13 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port)break ; } +#ifdef CONFIG_DM_USB +struct udevice *child; + + ret =usb_scan_device (dev->dev, port +1 , speed, &child); +#else +struct usb_device *usb; + ret =usb_alloc_new_device (dev->controller, &usb);if (ret) {printf ("cannot create new device: ret=%d" , ret);
@@ -280,6 +305,9 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port)/* Woops, disable the port */ usb_free_device (dev->controller); dev->children[port] = NULL; + } +#endif +if (ret <0 ) {debug ("hub: disabling port %d\n" , port +1 );usb_clear_port_feature (dev, port +1 ,USB_PORT_FEAT_ENABLE ); }
@@ -427,7 +455,11 @@ static int usb_hub_configure(struct usb_device *dev)int ret;ulong start =get_timer (0 ); +#ifdef CONFIG_DM_USB +debug ("\n\nScanning '%s' port %d\n" , dev->dev->name, i +1 ); +#else debug ("\n\nScanning port %d\n" , i +1 ); +#endif /* * Wait for (whichever finishes first) * - A maximum of 10 seconds
@@ -477,7 +509,7 @@ static int usb_hub_configure(struct usb_device *dev)* them again. Works at least with mouse driver */ if (!(portstatus &USB_PORT_STAT_ENABLE ) && (portstatus &USB_PORT_STAT_CONNECTION ) && - ((dev->children[i]))) { +usb_device_has_child_on_port (dev, i)) {debug ("already running port %i " \"disabled by hub (EMI?), " \"re-enabling...\n" , i +1 );
@@ -558,3 +590,57 @@ int usb_hub_probe(struct usb_device *dev, int ifnum) ret =usb_hub_configure (dev);return ret; } + +#ifdef CONFIG_DM_USB +int usb_hub_scan (struct udevice *hub) +{ +struct usb_device *udev =dev_get_parentdata (hub); + +return usb_hub_configure (udev); +} + +static int usb_hub_post_bind (struct udevice *dev) +{ +/* Scan the bus for devices */ +return dm_scan_fdt_node (dev, gd->fdt_blob, dev->of_offset, false); +} + +static int usb_hub_post_probe (struct udevice *dev) +{ +debug ("%s\n" , __func__); +return usb_hub_scan (dev); +} + +static const struct udevice_id usb_hub_ids[] = { + { .compatible ="usb-hub" }, + { } +}; + +U_BOOT_DRIVER (usb_generic_hub) = { + .name ="usb_hub" , + .id =UCLASS_USB_HUB , + .of_match = usb_hub_ids, + .flags =DM_FLAG_ALLOC_PRIV_DMA , +}; + +UCLASS_DRIVER (usb_hub) = { + .id =UCLASS_USB_HUB , + .name ="usb_hub" , + .post_bind = usb_hub_post_bind, + .post_probe = usb_hub_post_probe, + .child_pre_probe = usb_child_pre_probe, + .per_child_auto_alloc_size =sizeof (struct usb_device ), + .per_child_platdata_auto_alloc_size =sizeof (struct usb_dev_platdata ), +}; + +static const struct usb_device_id hub_id_table[] = { + { + .match_flags =USB_DEVICE_ID_MATCH_DEV_CLASS , + .bDeviceClass =USB_CLASS_HUB + }, + { }/* Terminating entry */ +}; + +USB_DEVICE (usb_generic_hub, hub_id_table); + +#endif
include/dm/uclass-id.h +1 -0
@@ -40,6 +40,7 @@ enum uclass_id {UCLASS_PCH ,/* x86 platform controller hub */ UCLASS_ETH ,/* Ethernet device */ UCLASS_USB ,/* USB bus */ +UCLASS_USB_HUB ,/* USB hub */ UCLASS_COUNT , UCLASS_INVALID = -1,
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 22/80 dm: usb: Add driver model support for hubs
Quoted 11 lines · Simon Glass
Adjust the existing hub code to support driver model, and add a USB driver for hubs.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_hub.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++--- include/dm/uclass-id.h | 1 + 2 files changed, 91 insertions(+), 4 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 23/80 dm: usb: Move USB storage definitions to usb_defs.h
In reply to Simon GlassThese are better off in a header file so they can be used by other code (e.g. the sandbox USB storage emulator).
---
Changes in v2: None
common/usb_storage.c | 45 ++------------------------------------------- include/usb_defs.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 43 deletions(-)
common/usb_storage.c +2 -43
@@ -56,49 +56,8 @@ static const unsigned char us_direction[256/8] = {#define US_DIRECTION (x) ((us_direction[x>>3] >> (x & 7)) & 1) static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN))); - -/* -* CBI style -*/ - -#define US_CBI_ADSC 0 - -/* -* BULK only -*/ -#define US_BBB_RESET 0xff -#define US_BBB_GET_MAX_LUN 0xfe - -/* Command Block Wrapper */ -typedef struct { -__u32 dCBWSignature; -# define CBWSIGNATURE 0x43425355 -__u32 dCBWTag; -__u32 dCBWDataTransferLength; -__u8 bCBWFlags; -# define CBWFLAGS_OUT 0x00 -# define CBWFLAGS_IN 0x80 -__u8 bCBWLUN; -__u8 bCDBLength; -# define CBWCDBLENGTH 16 -__u8 CBWCDB[CBWCDBLENGTH ]; -}umass_bbb_cbw_t ; -#define UMASS_BBB_CBW_SIZE 31static __u32 CBWTag; -/* Command Status Wrapper */ -typedef struct { -__u32 dCSWSignature; -# define CSWSIGNATURE 0x53425355 -__u32 dCSWTag; -__u32 dCSWDataResidue; -__u8 bCSWStatus; -# define CSWSTATUS_GOOD 0x0 -# define CSWSTATUS_FAILED 0x1 -# define CSWSTATUS_PHASE 0x2 -}umass_bbb_csw_t ; -#define UMASS_BBB_CSW_SIZE 13 -#define USB_MAX_STOR_DEV 5static int usb_max_devs;/* number of highest available usb device */
@@ -483,7 +442,7 @@ static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)int actlen;int dir_in;unsigned int pipe; -ALLOC_CACHE_ALIGN_BUFFER (umass_bbb_cbw_t, cbw,1 ); + ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1); dir_in =US_DIRECTION (srb->cmd[0 ]);
@@ -658,7 +617,7 @@ static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)int dir_in;int actlen, data_actlen;unsigned int pipe, pipein, pipeout; -ALLOC_CACHE_ALIGN_BUFFER (umass_bbb_csw_t, csw,1 ); + ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);#ifdef BBB_XPORT_TRACE unsigned char *ptr;int index;
include/usb_defs.h +42 -0
46 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 23/80 dm: usb: Move USB storage definitions to usb_defs.h
Quoted 11 lines · Simon Glass
These are better off in a header file so they can be used by other code (e.g. the sandbox USB storage emulator).
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_storage.c | 45 ++------------------------------------------- include/usb_defs.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 43 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 24/80 dm: usb: Fix type problems in usb_stor_get_info()
In reply to Simon GlassThis function assumes that unsigned long is 32-bits wide, but it is not on 64-bit machines. Use the correct type, and add a few debug() lines also.
---
Changes in v2: None
common/usb_storage.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
common/usb_storage.c +11 -7
@@ -1178,6 +1178,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE || iface->desc.bInterfaceSubClass < US_SC_MIN || iface->desc.bInterfaceSubClass > US_SC_MAX) { +debug ("Not mass storage\n" );/* if it's not a mass storage, we go no further */ return 0 ; }
@@ -1293,9 +1294,9 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, block_dev_desc_t *dev_desc) {unsigned char perq, modi; - ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2); +ALLOC_CACHE_ALIGN_BUFFER (uint32_t, cap,2 ); ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36); -unsigned long *capacity, *blksz; +uint32_t *capacity, *blksz;ccb *pccb = &usb_ccb; pccb->pdata = usb_stor_buf;
@@ -1304,8 +1305,10 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, pccb->lun = dev_desc->lun;debug (" address %d\n" , dev_desc->target); -if (usb_inquiry (pccb, ss)) +if (usb_inquiry (pccb, ss)) { +debug ("%s: usb_inquiry() failed\n" , __func__);return -1 ; + } perq = usb_stor_buf[0 ]; modi = usb_stor_buf[1 ];
@@ -1315,6 +1318,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,* they would not respond to test_unit_ready . */ if (((perq &0x1f ) ==0x1f ) || ((perq &0x1f ) ==0x0d )) { +debug ("%s: unknown/unsupported device\n" , __func__);return 0 ; }if ((modi&0x80 ) ==0x80 ) {
@@ -1352,19 +1356,19 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, cap[1 ] =0x200 ; } ss->flags &= ~USB_READY ; -debug ("Read Capacity returns: 0x%lx, 0x%lx\n" , cap[0 ], cap[1 ]); +debug ("Read Capacity returns: 0x%x, 0x%x\n" , cap[0 ], cap[1 ]);#if 0 if (cap[0 ] > (0x200000 *10 ))/* greater than 10 GByte */ cap[0 ] >>=16 ;#endif - cap[0 ] =cpu_to_be32 (cap[0 ]); - cap[1 ] =cpu_to_be32 (cap[1 ]); + cap[0 ] =be32_to_cpu (cap[0 ]); + cap[1 ] =be32_to_cpu (cap[1 ]);/* this assumes bigendian! */ cap[0 ] +=1 ; capacity = &cap[0 ]; blksz = &cap[1 ]; -debug ("Capacity = 0x%lx, blocksz = 0x%lx\n" , *capacity, *blksz); +debug ("Capacity = 0x%x, blocksz = 0x%x\n" , *capacity, *blksz); dev_desc->lba = *capacity; dev_desc->blksz = *blksz; dev_desc->log2blksz =LOG2 (dev_desc->blksz);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 24/80 dm: usb: Fix type problems in usb_stor_get_info()
Quoted 10 lines · Simon Glass
This function assumes that unsigned long is 32-bits wide, but it is not on 64-bit machines. Use the correct type, and add a few
debug()lines also.Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_storage.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 25/80 dm: usb: Simply device finding code in usb_storage
In reply to Simon GlassThe for() loop is not needed since the value is immediately accessible. Use this instead to simplify the code.
---
Changes in v2: None
common/usb_storage.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-)
common/usb_storage.c +11 -19
@@ -1005,7 +1005,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 )
@@ -1013,14 +1013,11 @@ 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) { +debug ("%s: No device\n" , __func__); +return 0 ; } ss = (struct us_data *)dev->privptr;
@@ -1078,7 +1075,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 )
@@ -1086,15 +1083,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 */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 25/80 dm: usb: Simply device finding code in usb_storage
Quoted 10 lines · Simon Glass
The
for()loop is not needed since the value is immediately accessible. Use this instead to simplify the code.Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_storage.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 26/80 dm: usb: Adjust usb_storage to work with sandbox
In reply to Simon GlassWith a few tweaks we can compile this code with sandbox and enable testing of the USB storage layer.
---
Changes in v2: None
common/usb_storage.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
common/usb_storage.c +5 -3
@@ -34,6 +34,7 @@#include <common.h> #include <command.h> #include <inttypes.h> +#include <mapmem.h> #include <asm/byteorder.h> #include <asm/processor.h>
@@ -295,8 +296,9 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)/* set up the transfer loop */ do { /* transfer the data */ - debug("Bulk xfer 0x%x(%d) try #%d\n", - (unsigned int)buf, this_xfer, 11 - maxtry); + debug("Bulk xfer 0x%lx(%d) try #%d\n", + (ulong)map_to_sysmem(buf), this_xfer, + 11 - maxtry); result = usb_bulk_msg(us->pusb_dev, pipe, buf, this_xfer, &partial, USB_CNTL_TIMEOUT * 5);
@@ -562,7 +564,7 @@ static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us) (void *) &us->ip_data, us->irqmaxp, us->irqinterval); timeout =1000 ;while (timeout--) { -if ((volatile int *) us->ip_wanted ==NULL ) +if (*(volatile int *)&us->ip_wanted ==0 )break ;mdelay (10 ); }
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 26/80 dm: usb: Adjust usb_storage to work with sandbox
Quoted 10 lines · Simon Glass
With a few tweaks we can compile this code with sandbox and enable testing of the USB storage layer.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_storage.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 27/80 dm: usb: Move storage device scanning into its own function
In reply to Simon GlassThe usb_stor_scan() function is quite long, so split out the code that scans each device into its own function. Also, rather than setting up the block device list once at the start, set it up as each device is scanned. This makes it possible to use this code from driver model.
---
Changes in v2: None
common/usb_storage.c | 97 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 38 deletions(-)
common/usb_storage.c +59 -38
@@ -33,6 +33,7 @@#include <common.h> #include <command.h> +#include <errno.h> #include <inttypes.h> #include <mapmem.h> #include <asm/byteorder.h>
@@ -168,6 +169,60 @@ 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 */ + +debug ("\n\nProbing for storage\n" ); +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]; +memset (blkdev,'\0' ,sizeof (block_dev_desc_t)); + blkdev->if_type =IF_TYPE_USB ; + blkdev->dev = usb_max_devs; + 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; + blkdev->lun = lun; + blkdev->priv = dev; + +if (usb_stor_get_info (dev, &usb_stor[start], + &usb_dev_desc[usb_max_devs]) == +1 ) { + usb_max_devs++; +debug ("%s: Found device %p\n" , __func__, dev); + } + } + } + +/* 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 ; +} + +void usb_stor_reset (void ) +{ + usb_max_devs =0 ; +} +/******************************************************************************* * scan the usb and reports device info * to the user if mode = 1
@@ -176,54 +231,20 @@ static unsigned int usb_get_max_lun(struct us_data *us)int usb_stor_scan (int mode) {unsigned char i; -struct usb_device *dev;if (mode ==1 )printf (" scanning usb for storage devices... " );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; - } - - usb_max_devs =0 ; +usb_stor_reset ();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 */ usb_disable_asynch (0 );/* asynch transfer allowed */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 27/80 dm: usb: Move storage device scanning into its own function
Quoted 5 lines · Simon Glass
The
usb_stor_scan()function is quite long, so split out the code that scans each device into its own function. Also, rather than setting up the block device list once at the start, set it up as each device is scanned. This makes it possible to use this code from driver model.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_storage.c | 97 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 38 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 28/80 dm: usb: Convert usb_storage to driver model
In reply to Simon GlassAdd support for scanning USB storage devices with driver model. This mostly involves adding a USB device ID for storage devices.
---
Changes in v2: None
common/usb_storage.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
common/usb_storage.c +49 -2
@@ -9,6 +9,8 @@* * Adapted for U-Boot: * (C) Copyright 2001 Denis Peter, MPL AG Switzerland +* Driver model conversion: +* (C) Copyright 2015 Google, Inc * * For BBB support (C) Copyright 2003 * Gary Jennejohn, DENX Software Engineering <[email protected]>
@@ -33,11 +35,13 @@#include <common.h> #include <command.h> +#include <dm.h> #include <errno.h> #include <inttypes.h> #include <mapmem.h> #include <asm/byteorder.h> #include <asm/processor.h> +#include <dm/device-internal.h> #include <part.h> #include <usb.h>
@@ -106,7 +110,6 @@ struct us_data {static struct us_data usb_stor[USB_MAX_STOR_DEV ]; -#define USB_STOR_TRANSPORT_GOOD 0#define USB_STOR_TRANSPORT_FAILED -1#define USB_STOR_TRANSPORT_ERROR -2
@@ -119,7 +122,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
@@ -223,6 +225,7 @@ void usb_stor_reset(void) usb_max_devs =0 ; } +#ifndef CONFIG_DM_USB /******************************************************************************* * scan the usb and reports device info * to the user if mode = 1
@@ -253,6 +256,7 @@ int usb_stor_scan(int mode)return 0 ; return -1; } +#endif static int usb_stor_irq (struct usb_device *dev) {
@@ -1396,3 +1400,46 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,debug ("partype: %d\n" , dev_desc->part_type);return 1 ; } + +#ifdef CONFIG_DM_USB + +static int usb_mass_storage_probe (struct udevice *dev) +{ +struct usb_device *udev =dev_get_parentdata (dev); +int ret; + +usb_disable_asynch (1 );/* asynch transfer not allowed */ + ret =usb_stor_probe_device (udev); +usb_disable_asynch (0 );/* asynch transfer allowed */ + +return ret; +} + +static const struct udevice_id usb_mass_storage_ids[] = { + { .compatible ="usb-mass-storage" }, + { } +}; + +U_BOOT_DRIVER (usb_mass_storage) = { + .name ="usb_mass_storage" , + .id =UCLASS_MASS_STORAGE , + .of_match = usb_mass_storage_ids, + .probe = usb_mass_storage_probe, +}; + +UCLASS_DRIVER (usb_mass_storage) = { + .id =UCLASS_MASS_STORAGE , + .name ="usb_mass_storage" , +}; + +static const struct usb_device_id mass_storage_id_table[] = { + { + .match_flags =USB_DEVICE_ID_MATCH_INT_CLASS , + .bInterfaceClass =USB_CLASS_MASS_STORAGE + }, + { }/* Terminating entry */ +}; + +USB_DEVICE (usb_mass_storage, mass_storage_id_table); + +#endif
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 28/80 dm: usb: Convert usb_storage to driver model
Quoted 10 lines · Simon Glass
Add support for scanning USB storage devices with driver model. This mostly involves adding a USB device ID for storage devices.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_storage.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 29/80 dm: usb: Move all the EHCI weak functions together and declare them
In reply to Simon GlassPut these at the top of the file so they are in one place. Also add function prototypes to the header file to avoid call site mismatches.
---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 22 +++++++++++----------- drivers/usb/host/ehci.h | 6 ++++++ 2 files changed, 17 insertions(+), 11 deletions(-)
drivers/usb/host/ehci-hcd.c +11 -11
@@ -143,6 +143,17 @@ __weak void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)mdelay (50 ); } +__weak uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port) +{ +if (port <0 || port >=CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS ) { +/* Printing the message would cause a scan failure! */ +debug ("The request port(%u) is not configured\n" , port); +return NULL ; + } + +return (uint32_t *)&hcor->or_portsc[port]; +} +static int handshake (uint32_t *ptr,uint32_t mask,uint32_t done,int usec) {uint32_t result;
@@ -649,17 +660,6 @@ fail:return -1 ; } -__weak uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port) -{ -if (port <0 || port >=CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS ) { -/* Printing the message would cause a scan failure! */ -debug ("The request port(%u) is not configured\n" , port); -return NULL ; - } - -return (uint32_t *)&hcor->or_portsc[port]; -} -int ehci_submit_root (struct usb_device *dev,unsigned long pipe,void *buffer,int length,struct devrequest *req)
drivers/usb/host/ehci.h +6 -0
@@ -250,6 +250,12 @@ struct ehci_ctrl {int ntds; }; +/* Weak functions that drivers can override */ +int ehci_get_port_speed (struct ehci_hcor *hcor,uint32_t reg); +void ehci_set_usbmode (int index); +void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg); +uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port); +/* Low level init functions */ int ehci_hcd_init (int index,enum usb_init_type init,struct ehci_hccr **hccr,struct ehci_hcor **hcor);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 29/80 dm: usb: Move all the EHCI weak functions together and declare them
Quoted 11 lines · Simon Glass
Put these at the top of the file so they are in one place. Also add function prototypes to the header file to avoid call site mismatches.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 22 +++++++++++----------- drivers/usb/host/ehci.h | 6 ++++++ 2 files changed, 17 insertions(+), 11 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 30/80 dm: usb: Pass EHCI controller pointer to ehci_get_port_speed()
In reply to Simon GlassAdjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller.
---
Changes in v2: None
drivers/usb/host/ehci-faraday.c | 5 +++-- drivers/usb/host/ehci-hcd.c | 4 ++-- drivers/usb/host/ehci-tegra.c | 5 +++-- drivers/usb/host/ehci.h | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-)
drivers/usb/host/ehci-faraday.c +3 -2
@@ -101,11 +101,12 @@ void ehci_set_usbmode(int index)* This ehci_get_port_speed() overrides the weak function * in "ehci-hcd.c". */ -int ehci_get_port_speed (struct ehci_hcor *hcor,uint32_t reg) +int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) {int spd, ret =PORTSC_PSPD_HS ; -union ehci_faraday_regs *regs = (void __iomem *)((ulong )hcor -0x10 ); +union ehci_faraday_regs *regs; + ret = (void __iomem *)((ulong )ctrl->hcor -0x10 );if (ehci_is_fotg2xx (regs)) spd =OTGCSR_SPD (readl (®s->otg.otgcsr));else
drivers/usb/host/ehci-hcd.c +2 -2
@@ -119,7 +119,7 @@ static struct descriptor {#define ehci_is_TDI () (0)#endif -__weak int ehci_get_port_speed (struct ehci_hcor *hcor,uint32_t reg) +__weak int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) {return PORTSC_PSPD (reg); }
@@ -781,7 +781,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[1 ] |=USB_PORT_STAT_POWER >>8 ;if (ehci_is_TDI ()) { -switch (ehci_get_port_speed (ctrl->hcor, reg)) { +switch (ehci_get_port_speed (ctrl, reg)) {case PORTSC_PSPD_FS :break ;case PORTSC_PSPD_LS :
drivers/usb/host/ehci-tegra.c +3 -2
@@ -225,13 +225,14 @@ void ehci_set_usbmode(int index)* This ehci_get_port_speed overrides the weak function ehci_get_port_speed * in "ehci-hcd.c". */ -int ehci_get_port_speed (struct ehci_hcor *hcor,uint32_t reg) +int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) {uint32_t tmp;uint32_t *reg_ptr;if (controller->has_hostpc) { - reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd +HOSTPC1_DEVLC ); + reg_ptr = (uint32_t *)((u8 *)&ctrl->hcor->or_usbcmd + +HOSTPC1_DEVLC ); tmp =ehci_readl (reg_ptr);return HOSTPC1_PSPD (tmp); }else
drivers/usb/host/ehci.h +1 -1
@@ -251,7 +251,7 @@ struct ehci_ctrl { };/* Weak functions that drivers can override */ -int ehci_get_port_speed (struct ehci_hcor *hcor,uint32_t reg); +int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg);void ehci_set_usbmode (int index);void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg);uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 30/80 dm: usb: Pass EHCI controller pointer to ehci_get_port_speed()
Quoted 6 lines · Simon Glass
Adjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller.
Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
drivers/usb/host/ehci-faraday.c | 5 +++-- drivers/usb/host/ehci-hcd.c | 4 ++-- drivers/usb/host/ehci-tegra.c | 5 +++-- drivers/usb/host/ehci.h | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 31/80 dm: usb: Allow ECHI to hold private data for the controller
In reply to Simon GlassAdd a private data pointer that clients of EHCI can use to access their private information. This establishes a link between struct ehci_ctrl and its associated controller data structure.
---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 10 ++++++++++ drivers/usb/host/ehci.h | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+)
drivers/usb/host/ehci-hcd.c +10 -0
@@ -930,6 +930,16 @@ unknown:return -1 ; } +void ehci_set_controller_priv (int index,void *priv) +{ + ehcic[index].priv = priv; +} + +void *ehci_get_controller_priv (int index) +{ +return ehcic[index].priv; +} +int usb_lowlevel_stop (int index) {ehci_shutdown (&ehcic[index]);
drivers/usb/host/ehci.h +21 -0
@@ -248,6 +248,7 @@ struct ehci_ctrl {uint32_t *periodic_list;int periodic_schedules;int ntds; +void *priv;/* client's private data */ };/* Weak functions that drivers can override */
@@ -256,6 +257,26 @@ void ehci_set_usbmode(int index);void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg);uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port); +/** +* ehci_set_controller_priv() - Set up private data for the controller +* +* This function can be called in ehci_hcd_init() to tell the EHCI layer +* about the controller's private data pointer. Then in the above functions +* this can be accessed given the struct ehci_ctrl pointer. +* +* @index: Controller number to set +* @priv: Controller pointer +*/ +void ehci_set_controller_priv (int index,void *priv); + +/** +* ehci_get_controller_priv() - Get controller private data +* +* @index Controller number to get +* @return controller pointer for this index +*/ +void *ehci_get_controller_priv (int index); +/* Low level init functions */ int ehci_hcd_init (int index,enum usb_init_type init,struct ehci_hccr **hccr,struct ehci_hcor **hcor);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 31/80 dm: usb: Allow ECHI to hold private data for the controller
Quoted 4 lines · Simon Glass
Add a private data pointer that clients of EHCI can use to access their private information. This establishes a link between struct
ehci_ctrland its associated controller data structure.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 10 ++++++++++ drivers/usb/host/ehci.h | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 32/80 dm: usb: tegra: Store the controller type explicitly
In reply to Simon GlassAt present the tegra driver uses a separate pointer to know which controller type is in use. This works because only one controller type is used at a time.
With driver model we want to make the controller state hermetic in the sense that it is not necessary to look elsewhere to know the controller type. This will permit a controller to implement the EHCI weak functions without reference to global data structures.
To achieve this, define an enum for the controller type and store it with the information on each EHCI controller.
---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-)
drivers/usb/host/ehci-tegra.c +24 -6
@@ -61,6 +61,14 @@ enum dr_mode { DR_MODE_OTG, /* supports both */ }; +enum usb_ctlr_type { +USB_CTLR_T20 , +USB_CTLR_T30 , +USB_CTLR_T114 , + +USB_CTRL_COUNT , +}; +/* Information about a USB port */ struct fdt_usb {struct usb_ctlr *reg;/* address of registers in physical memory */
@@ -69,6 +77,7 @@ struct fdt_usb { unsigned enabled:1; /* 1 to enable, 0 to disable */ unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ unsigned initialized:1; /* has this port already been initialized? */ +enum usb_ctlr_type type;enum usb_init_type init_type;enum dr_mode dr_mode;/* dual role mode */ enum periph_id periph_id;/* peripheral id */
@@ -162,7 +171,7 @@ struct fdt_usb_controller {const unsigned *pll_parameter; }; -static struct fdt_usb_controller fdt_usb_controllers[] = { +static struct fdt_usb_controller fdt_usb_controllers[USB_CTRL_COUNT ] = { { .compat =COMPAT_NVIDIA_TEGRA20_USB , .has_hostpc =0 ,
@@ -284,7 +293,7 @@ void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr)setbits_le32 (&usbctlr->susp_ctrl,UTMIP_PHY_ENB ); } -static const unsigned *get_pll_timing (void ) +static const unsigned *get_pll_timing (struct fdt_usb_controller *controller) {const unsigned *timing;
@@ -331,6 +340,7 @@ static void init_phy_mux(struct fdt_usb *config, uint pts,static int init_utmi_usb_controller (struct fdt_usb *config,enum usb_init_type init) { +struct fdt_usb_controller *controller;u32 b_sess_valid_mask, val;int loop_count;const unsigned *timing;
@@ -363,11 +373,14 @@ static int init_utmi_usb_controller(struct fdt_usb *config,VBUS_SENSE_CTL_MASK , VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); + controller = &fdt_usb_controllers[config->type]; +debug ("controller=%p, type=%d\n" , controller, config->type); +/* * PLL Delay CONFIGURATION settings. The following parameters control * the bring up of the plls. */ - timing =get_pll_timing (); + timing =get_pll_timing (controller);if (!controller->has_hostpc) { val =readl (&usbctlr->utmip_misc_cfg1);
@@ -702,10 +715,12 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)* @blob: fdt blob * @node_list: list of nodes to process (any <=0 are ignored) * @count: number of nodes to process +* @id: controller type (enum usb_ctlr_type) * * Return: 0 - ok, -1 - error */ -static int process_usb_nodes (const void *blob,int node_list[],int count) +static int process_usb_nodes (const void *blob,int node_list[],int count, +enum usb_ctlr_type id) {struct fdt_usb config;int node, i;
@@ -729,9 +744,11 @@ static int process_usb_nodes(const void *blob, int node_list[], int count)return -1 ; }if (!clk_done) { -config_clock (get_pll_timing ()); +config_clock (get_pll_timing ( + &fdt_usb_controllers[id])); clk_done =1 ; } + config.type = id; config.initialized =0 ;/* add new USB port to the list of available ports */
@@ -753,7 +770,7 @@ int usb_process_devicetree(const void *blob) count =fdtdec_find_aliases_for_id (blob,"usb" , controller->compat, node_list,USB_PORTS_MAX );if (count) { - err =process_usb_nodes (blob, node_list, count); + err =process_usb_nodes (blob, node_list, count, i);if (err)printf ("%s: Error processing USB node!\n" , __func__);
@@ -786,6 +803,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,return -1 ; config = &port[index]; +ehci_set_controller_priv (index, config);switch (init) {case USB_INIT_HOST :
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 32/80 dm: usb: tegra: Store the controller type explicitly
Quoted 12 lines · Simon Glass
At present the tegra driver uses a separate pointer to know which controller type is in use. This works because only one controller type is used at a time.
With driver model we want to make the controller state hermetic in the sense that it is not necessary to look elsewhere to know the controller type. This will permit a controller to implement the EHCI weak functions without reference to global data structures.
To achieve this, define an enum for the controller type and store it with the information on each EHCI controller.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 33/80 dm: usb: Pass EHCI controller pointer to ehci_powerup_fixup()
In reply to Simon GlassAdjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller.
---
Changes in v2: None
board/genesi/mx51_efikamx/efikamx-usb.c | 3 ++- drivers/usb/host/ehci-hcd.c | 5 +++-- drivers/usb/host/ehci-tegra.c | 3 ++- drivers/usb/host/ehci.h | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-)
board/genesi/mx51_efikamx/efikamx-usb.c +2 -1
@@ -173,7 +173,8 @@ int board_ehci_hcd_init(int port)return 0 ; } -void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg) +void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg) {uint32_t port =OTG_BASE_ADDR + (0x200 *CONFIG_MXC_USB_PORT );struct usb_ehci *ehci = (struct usb_ehci *)port;
drivers/usb/host/ehci-hcd.c +3 -2
@@ -138,7 +138,8 @@ __weak void ehci_set_usbmode(int index)ehci_writel (reg_ptr, tmp); } -__weak void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg) +__weak void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg) {mdelay (50 ); }
@@ -843,7 +844,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,* usb 2.0 specification say 50 ms resets on * root */ -ehci_powerup_fixup (status_reg, ®); +ehci_powerup_fixup (ctrl, status_reg, ®);ehci_writel (status_reg, reg & ~EHCI_PS_PR );/*
drivers/usb/host/ehci-tegra.c +2 -1
@@ -198,7 +198,8 @@ static struct fdt_usb_controller *controller;* This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup * in "ehci-hcd.c". */ -void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg) +void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg) {mdelay (50 );/* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */
drivers/usb/host/ehci.h +2 -1
@@ -254,7 +254,8 @@ struct ehci_ctrl {/* Weak functions that drivers can override */ int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg);void ehci_set_usbmode (int index); -void ehci_powerup_fixup (uint32_t *status_reg,uint32_t *reg); +void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg);uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port);/**
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 33/80 dm: usb: Pass EHCI controller pointer to ehci_powerup_fixup()
Quoted 6 lines · Simon Glass
Adjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller.
Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
board/genesi/mx51_efikamx/efikamx-usb.c | 3 ++- drivers/usb/host/ehci-hcd.c | 5 +++-- drivers/usb/host/ehci-tegra.c | 3 ++- drivers/usb/host/ehci.h | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 34/80 dm: usb: tegra: Drop use of global controller variable
In reply to Simon GlassWe don't need this anymore, so adjust the code to avoid using it.
---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/usb/host/ehci-tegra.c +9 -7
@@ -189,8 +189,6 @@ static struct fdt_usb_controller fdt_usb_controllers[USB_CTRL_COUNT] = { }, }; -static struct fdt_usb_controller *controller; -/* * A known hardware issue where Connect Status Change bit of PORTSC register * of USB1 controller will be set after Port Reset.
@@ -201,6 +199,10 @@ static struct fdt_usb_controller *controller;void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg,uint32_t *reg) { +struct fdt_usb *config = ctrl->priv; +struct fdt_usb_controller *controller; + + controller = &fdt_usb_controllers[config->type];mdelay (50 );/* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */ if (controller->has_hostpc)
@@ -237,9 +239,12 @@ void ehci_set_usbmode(int index)*/ int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) { +struct fdt_usb *config = ctrl->priv; +struct fdt_usb_controller *controller;uint32_t tmp;uint32_t *reg_ptr; + controller = &fdt_usb_controllers[config->type];if (controller->has_hostpc) { reg_ptr = (uint32_t *)((u8 *)&ctrl->hcor->or_usbcmd +HOSTPC1_DEVLC );
@@ -766,10 +771,9 @@ int usb_process_devicetree(const void *blob)int i;for (i =0 ; i <ARRAY_SIZE (fdt_usb_controllers); i++) { - controller = &fdt_usb_controllers[i]; - count =fdtdec_find_aliases_for_id (blob,"usb" , - controller->compat, node_list,USB_PORTS_MAX ); + fdt_usb_controllers[i].compat, node_list, +USB_PORTS_MAX );if (count) { err =process_usb_nodes (blob, node_list, count, i);if (err)
@@ -778,8 +782,6 @@ int usb_process_devicetree(const void *blob)return err; } } -if (i ==ARRAY_SIZE (fdt_usb_controllers)) - controller =NULL ;return err; }
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 34/80 dm: usb: tegra: Drop use of global controller variable
Quoted 9 lines · Simon Glass
We don't need this anymore, so adjust the code to avoid using it.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 35/80 dm: usb: Pass EHCI controller pointer to ehci_set_usbmode()
In reply to Simon GlassAdjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller. This makes the weak functions use a consistent API.
---
Changes in v2: None
drivers/usb/host/ehci-faraday.c | 2 +- drivers/usb/host/ehci-hcd.c | 6 +++--- drivers/usb/host/ehci-tegra.c | 5 ++--- drivers/usb/host/ehci.h | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-)
drivers/usb/host/ehci-faraday.c +1 -1
@@ -92,7 +92,7 @@ int ehci_hcd_stop(int index)* This ehci_set_usbmode() overrides the weak function * in "ehci-hcd.c". */ -void ehci_set_usbmode (int index) +void ehci_set_usbmode (struct ehci_ctrl *ctrl) {/* nothing needs to be done */ }
drivers/usb/host/ehci-hcd.c +3 -3
@@ -124,12 +124,12 @@ __weak int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)return PORTSC_PSPD (reg); } -__weak void ehci_set_usbmode (int index) +__weak void ehci_set_usbmode (struct ehci_ctrl *ctrl) {uint32_t tmp;uint32_t *reg_ptr; - reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd +USBMODE ); + reg_ptr = (uint32_t *)((u8 *)&ctrl->hcor->or_usbcmd +USBMODE ); tmp =ehci_readl (reg_ptr); tmp |=USBMODE_CM_HC ;#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN )
@@ -187,7 +187,7 @@ static int ehci_reset(int index) }if (ehci_is_TDI ()) -ehci_set_usbmode (index); +ehci_set_usbmode (&ehcic[index]);#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH cmd =ehci_readl (&ehcic[index].hcor->or_txfilltuning);
drivers/usb/host/ehci-tegra.c +2 -3
@@ -219,13 +219,12 @@ void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,* This ehci_set_usbmode overrides the weak function ehci_set_usbmode * in "ehci-hcd.c". */ -void ehci_set_usbmode (int index) +void ehci_set_usbmode (struct ehci_ctrl *ctrl) { -struct fdt_usb *config; +struct fdt_usb *config = ctrl->priv;struct usb_ctlr *usbctlr;uint32_t tmp; - config = &port[index]; usbctlr = config->reg; tmp =ehci_readl (&usbctlr->usb_mode);
drivers/usb/host/ehci.h +1 -1
@@ -253,7 +253,7 @@ struct ehci_ctrl {/* Weak functions that drivers can override */ int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg); -void ehci_set_usbmode (int index); +void ehci_set_usbmode (struct ehci_ctrl *ctrl);void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg,uint32_t *reg);uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 35/80 dm: usb: Pass EHCI controller pointer to ehci_set_usbmode()
Quoted 7 lines · Simon Glass
Adjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller. This makes the weak functions use a consistent API.
Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
drivers/usb/host/ehci-faraday.c | 2 +- drivers/usb/host/ehci-hcd.c | 6 +++--- drivers/usb/host/ehci-tegra.c | 5 ++--- drivers/usb/host/ehci.h | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 36/80 dm: usb: Pass EHCI controller pointer to ehci_get_portsc_register()
In reply to Simon GlassAdjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller. This makes the weak functions use a consistent API.
---
Changes in v2: None
drivers/usb/host/ehci-faraday.c | 4 ++-- drivers/usb/host/ehci-hcd.c | 6 +++--- drivers/usb/host/ehci.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-)
drivers/usb/host/ehci-faraday.c +2 -2
@@ -134,7 +134,7 @@ int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)* This ehci_get_portsc_register() overrides the weak function * in "ehci-hcd.c". */ -uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port) +uint32_t *ehci_get_portsc_register (struct ehci_ctrl *ctrl,int port) {/* Faraday EHCI has one and only one portsc register */ if (port) {
@@ -144,5 +144,5 @@ uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) }/* Faraday EHCI PORTSC register offset is 0x20 from hcor */ -return (uint32_t *)((uint8_t *)hcor +0x20 ); +return (uint32_t *)((uint8_t *)ctrl->hcor +0x20 ); }
drivers/usb/host/ehci-hcd.c +3 -3
@@ -144,7 +144,7 @@ __weak void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,mdelay (50 ); } -__weak uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port) +__weak uint32_t *ehci_get_portsc_register (struct ehci_ctrl *ctrl,int port) {if (port <0 || port >=CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS ) {/* Printing the message would cause a scan failure! */
@@ -152,7 +152,7 @@ __weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port)return NULL ; } -return (uint32_t *)&hcor->or_portsc[port]; +return (uint32_t *)&ctrl->hcor->or_portsc[port]; }static int handshake (uint32_t *ptr,uint32_t mask,uint32_t done,int usec)
@@ -687,7 +687,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,case USB_REQ_GET_STATUS | ((USB_RT_PORT |USB_DIR_IN ) <<8 ):case USB_REQ_SET_FEATURE | ((USB_DIR_OUT |USB_RT_PORT ) <<8 ):case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT |USB_RT_PORT ) <<8 ): - status_reg =ehci_get_portsc_register (ctrl->hcor, port -1 ); + status_reg =ehci_get_portsc_register (ctrl, port -1 );if (!status_reg)return -1 ;break ;
drivers/usb/host/ehci.h +1 -1
@@ -256,7 +256,7 @@ int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg);void ehci_set_usbmode (struct ehci_ctrl *ctrl);void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg,uint32_t *reg); -uint32_t *ehci_get_portsc_register (struct ehci_hcor *hcor,int port); +uint32_t *ehci_get_portsc_register (struct ehci_ctrl *ctrl,int port);/** * ehci_set_controller_priv() - Set up private data for the controller
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 36/80 dm: usb: Pass EHCI controller pointer to ehci_get_portsc_register()
Quoted 5 lines · Simon Glass
Adjust this function so that it is passed an EHCI controller pointer so that implementations can look up their controller. This makes the weak functions use a consistent API.
Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
drivers/usb/host/ehci-faraday.c | 4 ++-- drivers/usb/host/ehci-hcd.c | 6 +++--- drivers/usb/host/ehci.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 37/80 dm: usb: ehci: Use a function to find the controller from struct udevice
In reply to Simon GlassWith driver model we want to remove the controller pointer in struct udevice and use driver model data structures instead. To prepare for this, move access to this field to a function which can provide a different implementation for driver model.
---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 54 +++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 17 deletions(-)
drivers/usb/host/ehci-hcd.c +37 -17
@@ -119,6 +119,11 @@ static struct descriptor {#define ehci_is_TDI () (0)#endif +static struct ehci_ctrl *ehci_get_ctrl (struct usb_device *udev) +{ +return udev->controller; +} +__weak int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) {return PORTSC_PSPD (reg);
@@ -315,7 +320,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,uint32_t cmd;int timeout;int ret =0 ; -struct ehci_ctrl *ctrl = dev->controller; +struct ehci_ctrl *ctrl =ehci_get_ctrl (dev);debug ("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n" , dev, pipe, buffer, length, req);
@@ -661,9 +666,8 @@ fail:return -1 ; } -int -ehci_submit_root (struct usb_device *dev,unsigned long pipe,void *buffer, -int length,struct devrequest *req) +static int ehci_submit_root (struct usb_device *dev,unsigned long pipe, +void *buffer,int length,struct devrequest *req) {uint8_t tmpbuf[4 ];u16 typeReq;
@@ -672,7 +676,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,uint32_t reg;uint32_t *status_reg;int port =le16_to_cpu (req->index) &0xff ; -struct ehci_ctrl *ctrl = dev->controller; +struct ehci_ctrl *ctrl =ehci_get_ctrl (dev); srclen =0 ;
@@ -1075,9 +1079,8 @@ done:return 0 ; } -int -submit_bulk_msg (struct usb_device *dev,unsigned long pipe,void *buffer, -int length) +static int _ehci_submit_bulk_msg (struct usb_device *dev,unsigned long pipe, +void *buffer,int length) {if (usb_pipetype (pipe) !=PIPE_BULK ) {
@@ -1087,11 +1090,11 @@ submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,return ehci_submit_async (dev, pipe, buffer, length,NULL ); } -int -submit_control_msg (struct usb_device *dev,unsigned long pipe,void *buffer, -int length,struct devrequest *setup) +static int _ehci_submit_control_msg (struct usb_device *dev,unsigned long pipe, +void *buffer,int length, +struct devrequest *setup) { -struct ehci_ctrl *ctrl = dev->controller; +struct ehci_ctrl *ctrl =ehci_get_ctrl (dev);if (usb_pipetype (pipe) !=PIPE_CONTROL ) {debug ("non-control pipe (type=%lu)" ,usb_pipetype (pipe));
@@ -1161,7 +1164,7 @@ struct int_queue * create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, int elementsize, void *buffer, int interval) { - struct ehci_ctrl *ctrl = dev->controller; + struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);struct int_queue *result =NULL ;int i;
@@ -1353,7 +1356,7 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)int destroy_int_queue (struct usb_device *dev,struct int_queue *queue) { -struct ehci_ctrl *ctrl = dev->controller; +struct ehci_ctrl *ctrl =ehci_get_ctrl (dev);int result =-1 ;unsigned long timeout;
@@ -1397,9 +1400,8 @@ out:return result; } -int -submit_int_msg (struct usb_device *dev,unsigned long pipe,void *buffer, -int length,int interval) +static int _ehci_submit_int_msg (struct usb_device *dev,unsigned long pipe, +void *buffer,int length,int interval) {void *backbuffer;struct int_queue *queue;
@@ -1434,3 +1436,21 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,/* everything worked out fine */ return result; } + +int submit_bulk_msg (struct usb_device *dev,unsigned long pipe, +void *buffer,int length) +{ +return _ehci_submit_bulk_msg (dev, pipe, buffer, length); +} + +int submit_control_msg (struct usb_device *dev,unsigned long pipe,void *buffer, +int length,struct devrequest *setup) +{ +return _ehci_submit_control_msg (dev, pipe, buffer, length, setup); +} + +int submit_int_msg (struct usb_device *dev,unsigned long pipe, +void *buffer,int length,int interval) +{ +return _ehci_submit_int_msg (dev, pipe, buffer, length, interval); +}
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 37/80 dm: usb: ehci: Use a function to find the controller from struct udevice
Quoted 5 lines · Simon Glass
With driver model we want to remove the controller pointer in struct udevice and use driver model data structures instead. To prepare for this, move access to this field to a function which can provide a different implementation for driver model.
Quoted 7 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 54 +++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 17 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 38/80 dm: usb: Refactor EHCI init
In reply to Simon GlassMove the bulk of the code in usb_lowlevel_init() into a separate function which will also be used by driver model. Keep the CONFIG options out of this function by providing a tweak flag for Faraday. We need to avoid using CONFIG options in driver model code where possible, since it makes it impossible to use multiple controllers in that code where they have different options.
The CONFIG_EHCI_HCD_INIT_AFTER_RESET option is also kept out of the common init function. With driver model the controller will be able to perform this extra init itself after registering with the EHCI layer.
---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 117 +++++++++++++++++++++++++------------------- drivers/usb/host/ehci.h | 6 +++ 2 files changed, 72 insertions(+), 51 deletions(-)
drivers/usb/host/ehci-hcd.c +66 -51
@@ -945,41 +945,19 @@ void *ehci_get_controller_priv(int index)return ehcic[index].priv; } -int usb_lowlevel_stop (int index) -{ -ehci_shutdown (&ehcic[index]); -return ehci_hcd_stop (index); -} - -int usb_lowlevel_init (int index,enum usb_init_type init,void **controller) +static int ehci_common_init (struct ehci_ctrl *ctrl,uint tweaks) { -uint32_t reg; -uint32_t cmd;struct QH *qh_list;struct QH *periodic; +uint32_t reg; +uint32_t cmd;int i; -int rc; - - rc =ehci_hcd_init (index, init, &ehcic[index].hccr, &ehcic[index].hcor); -if (rc) -return rc; -if (init ==USB_INIT_DEVICE ) - goto done; - -/* EHCI spec section 4.1 */ -if (ehci_reset (index)) -return -1 ; -#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET ) - rc =ehci_hcd_init (index, init, &ehcic[index].hccr, &ehcic[index].hcor); -if (rc) -return rc; -#endif /* Set the high address word (aka segment) for 64-bit controller */ -if (ehci_readl (&ehcic[index].hccr->cr_hccparams) &1 ) -ehci_writel (&ehcic[index].hcor->or_ctrldssegment,0 ); +if (ehci_readl (&ctrl->hccr->cr_hccparams) &1 ) +ehci_writel (&ctrl->hcor->or_ctrldssegment,0 ); - qh_list = &ehcic[index].qh_list; + qh_list = &ctrl->qh_list;/* Set head of reclaim list */ memset (qh_list,0 ,sizeof (*qh_list));
@@ -995,14 +973,14 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) ALIGN_END_ADDR(struct QH, qh_list, 1));/* Set async. queue head pointer. */ -ehci_writel (&ehcic[index].hcor->or_asynclistaddr, (uint32_t )qh_list); +ehci_writel (&ctrl->hcor->or_asynclistaddr, (uint32_t )qh_list);/* * Set up periodic list * Step 1: Parent QH for all periodic transfers. */ - ehcic[index].periodic_schedules =0 ; - periodic = &ehcic[index].periodic_queue; + ctrl->periodic_schedules =0 ; + periodic = &ctrl->periodic_queue;memset (periodic,0 ,sizeof (*periodic)); periodic->qh_link =cpu_to_hc32 (QH_LINK_TERMINATE ); periodic->qh_overlay.qt_next =cpu_to_hc32 (QT_NEXT_TERMINATE );
@@ -1020,25 +998,25 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)* Split Transactions will be spread across microframes using * S-mask and C-mask. */ -if (ehcic[index].periodic_list ==NULL ) - ehcic[index].periodic_list =memalign (4096 ,1024 *4 ); +if (ctrl->periodic_list ==NULL ) + ctrl->periodic_list =memalign (4096 ,1024 *4 ); -if (!ehcic[index].periodic_list) +if (!ctrl->periodic_list)return -ENOMEM ;for (i =0 ; i <1024 ; i++) { - ehcic[index].periodic_list[i] =cpu_to_hc32 ((uint32_t )periodic + ctrl->periodic_list[i] =cpu_to_hc32 ((uint32_t )periodic |QH_LINK_TYPE_QH ); } -flush_dcache_range ((uint32_t )ehcic[index].periodic_list, -ALIGN_END_ADDR (uint32_t, ehcic[index].periodic_list, +flush_dcache_range ((uint32_t )ctrl->periodic_list, +ALIGN_END_ADDR (uint32_t, ctrl->periodic_list,1024 ));/* Set periodic list base address */ -ehci_writel (&ehcic[index].hcor->or_periodiclistbase, - (uint32_t )ehcic[index].periodic_list); +ehci_writel (&ctrl->hcor->or_periodiclistbase, + (uint32_t )ctrl->periodic_list); - reg =ehci_readl (&ehcic[index].hccr->cr_hcsparams); + reg =ehci_readl (&ctrl->hccr->cr_hcsparams); descriptor.hub.bNbrPorts =HCS_N_PORTS (reg);debug ("Register %x NbrPorts %d\n" , reg, descriptor.hub.bNbrPorts);/* Port Indicators */
@@ -1051,29 +1029,66 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) | 0x01, &descriptor.hub.wHubCharacteristics);/* Start the host controller. */ - cmd =ehci_readl (&ehcic[index].hcor->or_usbcmd); + cmd =ehci_readl (&ctrl->hcor->or_usbcmd);/* * Philips, Intel, and maybe others need CMD_RUN before the * root hub will detect new devices (why?); NEC doesn't */ cmd &= ~(CMD_LRESET |CMD_IAAD |CMD_PSE |CMD_ASE |CMD_RESET ); cmd |=CMD_RUN ; -ehci_writel (&ehcic[index].hcor->or_usbcmd, cmd); +ehci_writel (&ctrl->hcor->or_usbcmd, cmd); -#ifndef CONFIG_USB_EHCI_FARADAY -/* take control over the ports */ - cmd =ehci_readl (&ehcic[index].hcor->or_configflag); - cmd |=FLAG_CF ; -ehci_writel (&ehcic[index].hcor->or_configflag, cmd); -#endif +if (!(tweaks &EHCI_TWEAK_NO_INIT_CF )) { +/* take control over the ports */ + cmd =ehci_readl (&ctrl->hcor->or_configflag); + cmd |=FLAG_CF ; +ehci_writel (&ctrl->hcor->or_configflag, cmd); + }/* unblock posted write */ - cmd =ehci_readl (&ehcic[index].hcor->or_usbcmd); + cmd =ehci_readl (&ctrl->hcor->or_usbcmd);mdelay (5 ); - reg =HC_VERSION (ehci_readl (&ehcic[index].hccr->cr_capbase)); + reg =HC_VERSION (ehci_readl (&ctrl->hccr->cr_capbase));printf ("USB EHCI %x.%02x\n" , reg >>8 , reg &0xff ); - ehcic[index].rootdev =0 ; +return 0 ; +} + +int usb_lowlevel_stop (int index) +{ +ehci_shutdown (&ehcic[index]); +return ehci_hcd_stop (index); +} + +int usb_lowlevel_init (int index,enum usb_init_type init,void **controller) +{ +struct ehci_ctrl *ctrl = &ehcic[index]; +uint tweaks =0 ; +int rc; + + rc =ehci_hcd_init (index, init, &ctrl->hccr, &ctrl->hcor); +if (rc) +return rc; +if (init ==USB_INIT_DEVICE ) + goto done; + +/* EHCI spec section 4.1 */ +if (ehci_reset (index)) +return -1 ; + +#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET ) + rc =ehci_hcd_init (index, init, &ctrl->hccr, &ctrl->hcor); +if (rc) +return rc; +#endif +#ifdef CONFIG_USB_EHCI_FARADAY + tweaks |=EHCI_TWEAK_NO_INIT_CF ; +#endif + rc =ehci_common_init (ctrl, tweaks); +if (rc) +return rc; + + ctrl->rootdev =0 ; done: *controller = &ehcic[index];return 0 ;
drivers/usb/host/ehci.h +6 -0
@@ -238,6 +238,12 @@ struct QH { }; }; +/* Tweak flags for EHCI, used to control operation */ +enum { +/* don't use or_configflag in init */ +EHCI_TWEAK_NO_INIT_CF =1 <<0 , +}; +struct ehci_ctrl {struct ehci_hccr *hccr;/* R/O registers, not need for volatile */ struct ehci_hcor *hcor;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 38/80 dm: usb: Refactor EHCI init
Quoted 11 lines · Simon Glass
Move the bulk of the code in
usb_lowlevel_init()into a separate function which will also be used by driver model. Keep the CONFIG options out of this function by providing a tweak flag for Faraday. We need to avoid using CONFIG options in driver model code where possible, since it makes it impossible to use multiple controllers in that code where they have different options.The
CONFIG_EHCI_HCD_INIT_AFTER_RESEToption is also kept out of the common init function. With driver model the controller will be able to perform this extra init itself after registering with the EHCI layer.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 117 +++++++++++++++++++++++++------------------- drivers/usb/host/ehci.h | 6 +++ 2 files changed, 72 insertions(+), 51 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 39/80 dm: usb: Drop the EHCI weak functions
In reply to Simon GlassThese are a pain with driver model because we might have different EHCI drivers which want to implement them differently. Now that they use consistent function signatures, we can in good conscience move them to a struct.
---
Changes in v2: None
board/genesi/mx51_efikamx/efikamx-usb.c | 5 +- drivers/usb/host/ehci-faraday.c | 113 +++++++++++++++----------------- drivers/usb/host/ehci-hcd.c | 49 +++++++++++--- drivers/usb/host/ehci-mx5.c | 12 ++++ drivers/usb/host/ehci-tegra.c | 26 ++++---- drivers/usb/host/ehci.h | 27 +++++--- 6 files changed, 136 insertions(+), 96 deletions(-)
board/genesi/mx51_efikamx/efikamx-usb.c +3 -2
@@ -173,8 +173,9 @@ int board_ehci_hcd_init(int port)return 0 ; } -void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, -uint32_t *reg) +/* This overrides a weak function */ +void mx5_ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg) {uint32_t port =OTG_BASE_ADDR + (0x200 *CONFIG_MXC_USB_PORT );struct usb_ehci *ehci = (struct usb_ehci *)port;
drivers/usb/host/ehci-faraday.c +54 -59
128 lines not on this page · raw message
drivers/usb/host/ehci-hcd.c +39 -10
107 lines not on this page · raw message
drivers/usb/host/ehci-mx5.c +12 -0
@@ -218,11 +218,23 @@ void __weak board_ehci_hcd_postinit(struct usb_ehci *ehci, int port) { } +__weak void mx5_ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg) +{ +mdelay (50 ); +} + +static const struct ehci_ops mx5_ehci_ops = { + .powerup_fixup = mx5_ehci_powerup_fixup, +}; +int ehci_hcd_init (int index,enum usb_init_type init,struct ehci_hccr **hccr,struct ehci_hcor **hcor) {struct usb_ehci *ehci; +/* The only user for this is efikamx-usb */ +ehci_set_controller_priv (index,NULL , &mx5_ehci_ops);set_usboh3_clk ();enable_usboh3_clk (true);set_usb_phy_clk ();
drivers/usb/host/ehci-tegra.c +11 -15
@@ -193,11 +193,9 @@ static struct fdt_usb_controller fdt_usb_controllers[USB_CTRL_COUNT] = {* A known hardware issue where Connect Status Change bit of PORTSC register * of USB1 controller will be set after Port Reset. * We have to clear it in order for later device enumeration to proceed. -* This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup -* in "ehci-hcd.c". */ -void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, -uint32_t *reg) +static void tegra_ehci_powerup_fixup (struct ehci_ctrl *ctrl, +uint32_t *status_reg,uint32_t *reg) {struct fdt_usb *config = ctrl->priv;struct fdt_usb_controller *controller;
@@ -215,11 +213,7 @@ void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, *reg |=EHCI_PS_CSC ; } -/* -* This ehci_set_usbmode overrides the weak function ehci_set_usbmode -* in "ehci-hcd.c". -*/ -void ehci_set_usbmode (struct ehci_ctrl *ctrl) +static void tegra_ehci_set_usbmode (struct ehci_ctrl *ctrl) {struct fdt_usb *config = ctrl->priv;struct usb_ctlr *usbctlr;
@@ -232,11 +226,7 @@ void ehci_set_usbmode(struct ehci_ctrl *ctrl)ehci_writel (&usbctlr->usb_mode, tmp); } -/* -* This ehci_get_port_speed overrides the weak function ehci_get_port_speed -* in "ehci-hcd.c". -*/ -int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) +static int tegra_ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg) {struct fdt_usb *config = ctrl->priv;struct fdt_usb_controller *controller;
@@ -714,6 +704,12 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)return 0 ; } +static const struct ehci_ops tegra_ehci_ops = { + .set_usb_mode = tegra_ehci_set_usbmode, + .get_port_speed = tegra_ehci_get_port_speed, + .powerup_fixup = tegra_ehci_powerup_fixup, +}; +/* * process_usb_nodes() - Process a list of USB nodes, adding them to our list * of USB ports.
@@ -805,7 +801,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,return -1 ; config = &port[index]; -ehci_set_controller_priv (index, config); +ehci_set_controller_priv (index, config, &tegra_ehci_ops);switch (init) {case USB_INIT_HOST :
drivers/usb/host/ehci.h +17 -10
@@ -244,6 +244,16 @@ enum { EHCI_TWEAK_NO_INIT_CF = 1 << 0, }; +struct ehci_ctrl ; + +struct ehci_ops { +void (*set_usb_mode)(struct ehci_ctrl *ctrl); +int (*get_port_speed)(struct ehci_ctrl *ctrl,uint32_t reg); +void (*powerup_fixup)(struct ehci_ctrl *ctrl,uint32_t *status_reg, +uint32_t *reg); +uint32_t *(*get_portsc_register)(struct ehci_ctrl *ctrl,int port); +}; +struct ehci_ctrl {struct ehci_hccr *hccr;/* R/O registers, not need for volatile */ struct ehci_hcor *hcor;
@@ -254,27 +264,24 @@ struct ehci_ctrl {uint32_t *periodic_list;int periodic_schedules;int ntds; +struct ehci_ops ops;void *priv;/* client's private data */ }; -/* Weak functions that drivers can override */ -int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg); -void ehci_set_usbmode (struct ehci_ctrl *ctrl); -void ehci_powerup_fixup (struct ehci_ctrl *ctrl,uint32_t *status_reg, -uint32_t *reg); -uint32_t *ehci_get_portsc_register (struct ehci_ctrl *ctrl,int port); -/** -* ehci_set_controller_priv() - Set up private data for the controller +* ehci_set_controller_info() - Set up private data for the controller * * This function can be called in ehci_hcd_init() to tell the EHCI layer * about the controller's private data pointer. Then in the above functions -* this can be accessed given the struct ehci_ctrl pointer. +* this can be accessed given the struct ehci_ctrl pointer. Also special +* EHCI operation methods can be provided if required * * @index: Controller number to set * @priv: Controller pointer +* @ops: Controller operations, or NULL to use default */ -void ehci_set_controller_priv (int index,void *priv); +void ehci_set_controller_priv (int index,void *priv, +const struct ehci_ops *ops);/** * ehci_get_controller_priv() - Get controller private data
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 39/80 dm: usb: Drop the EHCI weak functions
Quoted 10 lines · Simon Glass
These are a pain with driver model because we might have different EHCI drivers which want to implement them differently. Now that they use consistent function signatures, we can in good conscience move them to a struct.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
Quoted 7 lines
board/genesi/mx51_efikamx/efikamx-usb.c | 5 +- drivers/usb/host/ehci-faraday.c | 113 +++++++++++++++----------------- drivers/usb/host/ehci-hcd.c | 49 +++++++++++--- drivers/usb/host/ehci-mx5.c | 12 ++++ drivers/usb/host/ehci-tegra.c | 26 ++++---- drivers/usb/host/ehci.h | 27 +++++--- 6 files changed, 136 insertions(+), 96 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 40/80 dm: usb: Change ehci_reset() to use a pointer
In reply to Simon GlassThe index cannot be used with driver model, and isn't needed anyway. Change the parameter to a pointer.
---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
drivers/usb/host/ehci-hcd.c +8 -9
@@ -176,16 +176,15 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)return -1 ; } -static int ehci_reset (int index) +static int ehci_reset (struct ehci_ctrl *ctrl) { -struct ehci_ctrl *ctrl = &ehcic[index];uint32_t cmd;int ret =0 ; - cmd =ehci_readl (&ehcic[index].hcor->or_usbcmd); + cmd =ehci_readl (&ctrl->hcor->or_usbcmd); cmd = (cmd & ~CMD_RUN ) |CMD_RESET ; -ehci_writel (&ehcic[index].hcor->or_usbcmd, cmd); - ret =handshake ((uint32_t *)&ehcic[index].hcor->or_usbcmd, +ehci_writel (&ctrl->hcor->or_usbcmd, cmd); + ret =handshake ((uint32_t *)&ctrl->hcor->or_usbcmd,CMD_RESET ,0 ,250 *1000 );if (ret <0 ) {printf ("EHCI fail to reset\n" );
@@ -193,13 +192,13 @@ static int ehci_reset(int index) }if (ehci_is_TDI ()) - ctrl->ops.set_usb_mode (&ehcic[index]); + ctrl->ops.set_usb_mode (ctrl);#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH - cmd =ehci_readl (&ehcic[index].hcor->or_txfilltuning); + cmd =ehci_readl (&ctrl->hcor->or_txfilltuning); cmd &= ~TXFIFO_THRESH_MASK ; cmd |=TXFIFO_THRESH (CONFIG_USB_EHCI_TXFIFO_THRESH ); -ehci_writel (&ehcic[index].hcor->or_txfilltuning, cmd); +ehci_writel (&ctrl->hcor->or_txfilltuning, cmd);#endif out:return ret;
@@ -1102,7 +1101,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) goto done;/* EHCI spec section 4.1 */ -if (ehci_reset (index)) +if (ehci_reset (ctrl))return -1 ;#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET )
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 40/80 dm: usb: Change ehci_reset() to use a pointer
Quoted 10 lines · Simon Glass
The index cannot be used with driver model, and isn't needed anyway. Change the parameter to a pointer.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 41/80 dm: usb: Add driver model support to EHCI
In reply to Simon GlassAdd a way for EHCI controller drivers to support driver model. Drivers can call ehci_register() to register themselves in their probe() methods.
---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 125 ++++++++++++++++++++++++++++++++++++++++++-- drivers/usb/host/ehci.h | 6 +++ 2 files changed, 127 insertions(+), 4 deletions(-)
drivers/usb/host/ehci-hcd.c +121 -4
@@ -21,6 +21,7 @@* MA 02111-1307 USA */ #include <common.h> +#include <dm.h> #include <errno.h> #include <asm/byteorder.h> #include <asm/unaligned.h>
@@ -42,7 +43,9 @@*/ #define HCHALT_TIMEOUT (8 * 1000) +#ifndef CONFIG_DM_USB static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT ]; +#endif #define ALIGN_END_ADDR (type, ptr, size) \ ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
@@ -121,7 +124,18 @@ static struct descriptor {static struct ehci_ctrl *ehci_get_ctrl (struct usb_device *udev) { +#ifdef CONFIG_DM_USB +struct udevice *dev; + +/* Find the USB controller */ +for (dev = udev->dev; +device_get_uclass_id (dev) !=UCLASS_USB ; + dev = dev->parent) + ; +return dev_get_priv (dev); +#else return udev->controller; +#endif }static int ehci_get_port_speed (struct ehci_ctrl *ctrl,uint32_t reg)
@@ -281,12 +295,13 @@ static inline u8 ehci_encode_speed(enum usb_device_speed speed)return QH_FULL_SPEED ; } -static void ehci_update_endpt2_dev_n_port (struct usb_device *dev, +static void ehci_update_endpt2_dev_n_port (struct usb_device *udev,struct QH *qh) {struct usb_device *ttdev; +int parent_devnum; -if (dev->speed !=USB_SPEED_LOW && dev->speed !=USB_SPEED_FULL ) +if (udev->speed !=USB_SPEED_LOW && udev->speed !=USB_SPEED_FULL )return ;/*
@@ -294,14 +309,35 @@ static void ehci_update_endpt2_dev_n_port(struct usb_device *dev,* the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs * in the tree before that one! */ - ttdev = dev; +#ifdef CONFIG_DM_USB +struct udevice *parent; + +for (ttdev = udev; ; ) { +struct udevice *dev = ttdev->dev; + +if (dev->parent && +device_get_uclass_id (dev->parent) ==UCLASS_USB_HUB ) + parent = dev->parent; +else + parent =NULL ; +if (!parent) +return ; + ttdev =dev_get_parentdata (parent); +if (!ttdev->speed !=USB_SPEED_HIGH ) +break ; + } + parent_devnum = ttdev->devnum; +#else + ttdev = udev;while (ttdev->parent && ttdev->parent->speed !=USB_SPEED_HIGH ) ttdev = ttdev->parent;if (!ttdev->parent)return ; + parent_devnum = ttdev->parent->devnum; +#endif qh->qh_endpt2 |=cpu_to_hc32 (QH_ENDPT2_PORTNUM (ttdev->portnr) | -QH_ENDPT2_HUBADDR (ttdev->parent->devnum)); +QH_ENDPT2_HUBADDR (parent_devnum)); } static int
@@ -960,6 +996,7 @@ static void ehci_setup_ops(struct ehci_ctrl *ctrl, const struct ehci_ops *ops) } } +#ifndef CONFIG_DM_USB void ehci_set_controller_priv (int index,void *priv,const struct ehci_ops *ops) {struct ehci_ctrl *ctrl = &ehcic[index];
@@ -972,6 +1009,7 @@ void *ehci_get_controller_priv(int index) {return ehcic[index].priv; } +#endif static int ehci_common_init (struct ehci_ctrl *ctrl,uint tweaks) {
@@ -1082,6 +1120,7 @@ static int ehci_common_init(struct ehci_ctrl *ctrl, uint tweaks)return 0 ; } +#ifndef CONFIG_DM_USB int usb_lowlevel_stop (int index) {ehci_shutdown (&ehcic[index]);
@@ -1121,6 +1160,7 @@ done: *controller = &ehcic[index]; return 0; } +#endif static int _ehci_submit_bulk_msg (struct usb_device *dev,unsigned long pipe,void *buffer,int length)
@@ -1480,6 +1520,7 @@ static int _ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe,return result; } +#ifndef CONFIG_DM_USB int submit_bulk_msg (struct usb_device *dev,unsigned long pipe,void *buffer,int length) {
@@ -1497,3 +1538,79 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, {return _ehci_submit_int_msg (dev, pipe, buffer, length, interval); } +#endif + +#ifdef CONFIG_DM_USB +static int ehci_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, udev->dev='%s', portnr=%d\n" , __func__, + dev->name, udev, udev->dev->name, udev->portnr); + +return _ehci_submit_control_msg (udev, pipe, buffer, length, setup); +} + +static int ehci_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 _ehci_submit_bulk_msg (udev, pipe, buffer, length); +} + +static int ehci_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 _ehci_submit_int_msg (udev, pipe, buffer, length, interval); +} + +int ehci_register (struct udevice *dev,struct ehci_hccr *hccr, +struct ehci_hcor *hcor,const struct ehci_ops *ops, +uint tweaks,enum usb_init_type init) +{ +struct ehci_ctrl *ctrl =dev_get_priv (dev); +int ret; + +debug ("%s: dev='%s', ctrl=%p, hccr=%p, hcor=%p, init=%d\n" , __func__, + dev->name, ctrl, hccr, hcor, init); + +ehci_setup_ops (ctrl, ops); + ctrl->hccr = hccr; + ctrl->hcor = hcor; + ctrl->priv = ctrl; + +if (init ==USB_INIT_DEVICE ) + goto done; + ret =ehci_reset (ctrl); +if (ret) + goto err; + + ret =ehci_common_init (ctrl, tweaks); +if (ret) + goto err; +done: +return 0 ; +err: +free (ctrl); +debug ("%s: failed, ret=%d\n" , __func__, ret); +return ret; +} + +int ehci_deregister (struct udevice *dev) +{ +struct ehci_ctrl *ctrl =dev_get_priv (dev); + +ehci_shutdown (ctrl); + +return 0 ; +} + +struct dm_usb_ops ehci_usb_ops = { + .control = ehci_submit_control_msg, + .bulk = ehci_submit_bulk_msg, + .interrupt = ehci_submit_int_msg, +}; + +#endif
drivers/usb/host/ehci.h +6 -0
@@ -296,4 +296,10 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor);int ehci_hcd_stop (int index); +int ehci_register (struct udevice *dev,struct ehci_hccr *hccr, +struct ehci_hcor *hcor,const struct ehci_ops *ops, +uint tweaks,enum usb_init_type init); +int ehci_deregister (struct udevice *dev); +extern struct dm_usb_ops ehci_usb_ops; +#endif /* USB_EHCI_H */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 41/80 dm: usb: Add driver model support to EHCI
Quoted 11 lines · Simon Glass
Add a way for EHCI controller drivers to support driver model. Drivers can call
ehci_register()to register themselves in theirprobe()methods.Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-hcd.c | 125 ++++++++++++++++++++++++++++++++++++++++++-- drivers/usb/host/ehci.h | 6 +++ 2 files changed, 127 insertions(+), 4 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 42/80 dm: usb: Allow USB drivers to be declared and auto-probed
In reply to Simon GlassUSB devices in U-Boot are currently probed only after all devices have been enumerated. Each type of device is probed by custom code, e.g.:
- USB storage
- Keyboard
- Ethernet
With driver model this approach doesn't work very well. We could build a picture of the bus and then go back and add the devices later, but this means that the data structures are incomplete for quite a while. It also does not follow the model of being able to bind a device when we discover it.
We would prefer to have devices automatically be bound as the device is enumerated. This allows us to attach drivers to particular USB classes or product/vendor IDs. This is the method used by Linux.
Add the required #defines from Linux, a way of declaring a USB driver and the logic to locate the correct driver given the USB device's descriptors.
---
Changes in v2: None
drivers/usb/host/usb-uclass.c | 206 +++++++++++++++++++++++++++++++++++++++++- include/usb.h | 107 ++++++++++++++++++++++ 2 files changed, 311 insertions(+), 2 deletions(-)
drivers/usb/host/usb-uclass.c +204 -2
@@ -2,6 +2,8 @@* (C) Copyright 2015 Google, Inc * Written by Simon Glass <[email protected]> * +* usb_match_device() modified from Linux kernel v4.0. +* * SPDX-License-Identifier: GPL-2.0+ */
@@ -247,6 +249,179 @@ int usb_legacy_port_reset(struct usb_device *parent, int portnr)return usb_port_reset (parent, portnr); } +/* returns 0 if no match, 1 if match */ +int usb_match_device (const struct usb_device_descriptor *desc, +const struct usb_device_id *id) +{ +if ((id->match_flags &USB_DEVICE_ID_MATCH_VENDOR ) && + id->idVendor !=le16_to_cpu (desc->idVendor)) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_PRODUCT ) && + id->idProduct !=le16_to_cpu (desc->idProduct)) +return 0 ; + +/* No need to test id->bcdDevice_lo != 0, since 0 is never +greater than any unsigned number. */ +if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_LO ) && + (id->bcdDevice_lo >le16_to_cpu (desc->bcdDevice))) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_HI ) && + (id->bcdDevice_hi <le16_to_cpu (desc->bcdDevice))) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_CLASS ) && + (id->bDeviceClass != desc->bDeviceClass)) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_SUBCLASS ) && + (id->bDeviceSubClass != desc->bDeviceSubClass)) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_PROTOCOL ) && + (id->bDeviceProtocol != desc->bDeviceProtocol)) +return 0 ; + +return 1 ; +} + +/* returns 0 if no match, 1 if match */ +int usb_match_one_id_intf (const struct usb_device_descriptor *desc, +const struct usb_interface_descriptor *int_desc, +const struct usb_device_id *id) +{ +/* The interface class, subclass, protocol and number should never be +* checked for a match if the device class is Vendor Specific, +* unless the match record specifies the Vendor ID. */ +if (desc->bDeviceClass ==USB_CLASS_VENDOR_SPEC && + !(id->match_flags &USB_DEVICE_ID_MATCH_VENDOR ) && + (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS | +USB_DEVICE_ID_MATCH_INT_SUBCLASS | +USB_DEVICE_ID_MATCH_INT_PROTOCOL | +USB_DEVICE_ID_MATCH_INT_NUMBER ))) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_CLASS ) && + (id->bInterfaceClass != int_desc->bInterfaceClass)) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_SUBCLASS ) && + (id->bInterfaceSubClass != int_desc->bInterfaceSubClass)) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_PROTOCOL ) && + (id->bInterfaceProtocol != int_desc->bInterfaceProtocol)) +return 0 ; + +if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_NUMBER ) && + (id->bInterfaceNumber != int_desc->bInterfaceNumber)) +return 0 ; + +return 1 ; +} + +/* returns 0 if no match, 1 if match */ +int usb_match_one_id (struct usb_device_descriptor *desc, +struct usb_interface_descriptor *int_desc, +const struct usb_device_id *id) +{ +if (!usb_match_device (desc, id)) +return 0 ; + +return usb_match_one_id_intf (desc, int_desc, id); +} + +/** +* usb_find_and_bind_driver() - Find and bind the right USB driver +* +* This only looks at certain fields in the descriptor. +*/ +static int usb_find_and_bind_driver (struct udevice *parent, +struct usb_device_descriptor *desc, +struct usb_interface_descriptor *iface, +int bus_seq,int devnum, +struct udevice **devp) +{ +struct usb_driver_entry *start, *entry; +int n_ents; +int ret; +char name[30 ], *str; + + *devp =NULL ; +debug ("%s: Searching for driver\n" , __func__); + start = ll_entry_start(struct usb_driver_entry, usb_driver_entry); + n_ents = ll_entry_count(struct usb_driver_entry, usb_driver_entry); +for (entry = start; entry != start + n_ents; entry++) { +const struct usb_device_id *id; +struct udevice *dev; +const struct driver *drv; +struct usb_dev_platdata *plat; + +for (id = entry->match; id->match_flags; id++) { +if (!usb_match_one_id (desc, iface, id)) +continue ; + + drv = entry->driver; +/* +* We could pass the descriptor to the driver as +* platdata (instead of NULL) and allow its bind() +* method to return -ENOENT if it doesn't support this +* device. That way we could continue the search to +* find another driver. For now this doesn't seem +* necesssary, so just bind the first match. +*/ + ret =device_bind (parent, drv, drv->name,NULL ,-1 , + &dev); +if (ret) + goto error; +debug ("%s: Match found: %s\n" , __func__, drv->name); + dev->driver_data = id->driver_info; + plat =dev_get_parent_platdata (dev); + plat->id = *id; + *devp = dev; +return 0 ; + } + } + + ret = -ENOENT ; +error: +debug ("%s: No match found: %d\n" , __func__, ret); +return ret; +} + +/** +* usb_find_child() - Find an existing device which matches our needs +* +* +*/ +static int usb_find_child (struct udevice *parent, +struct usb_device_descriptor *desc, +struct usb_interface_descriptor *iface, +struct udevice **devp) +{ +struct udevice *dev; + + *devp =NULL ; +for (device_find_first_child (parent, &dev); + dev; +device_find_next_child (&dev)) { +struct usb_dev_platdata *plat =dev_get_parent_platdata (dev); + +/* If this device is already in use, skip it */ +if (device_active (dev)) +continue ; +debug (" %s: name='%s', plat=%d, desc=%d\n" , __func__, + dev->name, plat->id.bDeviceClass, desc->bDeviceClass); +if (usb_match_one_id (desc, iface, &plat->id)) { + *devp = dev; +return 0 ; + } + } + +return -ENOENT ; +} +int usb_scan_device (struct udevice *parent,int port,enum usb_device_speed speed,struct udevice **devp) {
@@ -307,9 +482,36 @@ int usb_scan_device(struct udevice *parent, int port,return ret; ret =usb_find_child (parent, &udev->descriptor, iface, &dev);debug ("** usb_find_child returns %d\n" , ret); +if (ret) { +if (ret != -ENOENT ) +return ret; + ret =usb_find_and_bind_driver (parent, &udev->descriptor, iface, + udev->controller_dev->seq, + udev->devnum, &dev); +if (ret) +return ret; + created = true; + } + plat =dev_get_parent_platdata (dev); +debug ("%s: Probing '%s', plat=%p\n" , __func__, dev->name, plat); + plat->devnum = udev->devnum; + plat->speed = udev->speed; + plat->slot_id = udev->slot_id; + plat->portnr = port; +debug ("** device '%s': stashing slot_id=%d\n" , dev->name, + plat->slot_id); + priv->next_addr++; + ret =device_probe (dev); +if (ret) { +debug ("%s: Device '%s' probe failed\n" , __func__, dev->name); + priv->next_addr--; +if (created) +device_unbind (dev); +return ret; + } + *devp = dev; -/* TODO: Find a suitable driver and create the device */ -return -ENOENT ; +return 0 ; }int usb_child_post_bind (struct udevice *dev)
include/usb.h +107 -0
113 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 42/80 dm: usb: Allow USB drivers to be declared and auto-probed
Quoted 20 lines · Simon Glass
USB devices in U-Boot are currently probed only after all devices have been enumerated. Each type of device is probed by custom code, e.g.:
- USB storage
- Keyboard
- EthernetWith driver model this approach doesn't work very well. We could build a picture of the bus and then go back and add the devices later, but this means that the data structures are incomplete for quite a while. It also does not follow the model of being able to bind a device when we discover it.
We would prefer to have devices automatically be bound as the device is enumerated. This allows us to attach drivers to particular USB classes or product/vendor IDs. This is the method used by Linux.
Add the required #defines from Linux, a way of declaring a USB driver and the logic to locate the correct driver given the USB device's descriptors.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/usb-uclass.c | 206 +++++++++++++++++++++++++++++++++++++++++- include/usb.h | 107 ++++++++++++++++++++++ 2 files changed, 311 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 43/80 dm: usb: Bind generic USB devices when there is no driver
In reply to Simon GlassAt present USB devices with no driver model driver cannot be seen in the device list, and we fail to set them up correctly. This means they cannot be used.
While having real drivers that support driver model for all USB devices is the eventual goal, we are not there yet.
As a stop-gap, add a generic USB driver which is bound when we do not have a real driver. This allows the device to be set up and shown on the bus. It also allows ad-hoc code (such as usb_ether) to find these devices and set them up.
---
Changes in v2: None
drivers/usb/host/usb-uclass.c | 18 +++++++++++++++++- include/dm/uclass-id.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-)
drivers/usb/host/usb-uclass.c +17 -1
@@ -384,7 +384,13 @@ static int usb_find_and_bind_driver(struct udevice *parent, } } - ret = -ENOENT ; +/* Bind a generic driver so that the device can be used */ +snprintf (name,sizeof (name),"generic_bus_%x_dev_%x" , bus_seq, devnum); + str =strdup (name); +if (!str) +return -ENOMEM ; + ret =device_bind_driver (parent,"usb_dev_generic_drv" , str, devp); + error:debug ("%s: No match found: %d\n" , __func__, ret);return ret;
@@ -592,3 +598,13 @@ UCLASS_DRIVER(usb) = { .child_pre_probe = usb_child_pre_probe, .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), }; + +UCLASS_DRIVER (usb_dev_generic) = { + .id =UCLASS_USB_DEV_GENERIC , + .name ="usb_dev_generic" , +}; + +U_BOOT_DRIVER (usb_dev_generic_drv) = { + .id =UCLASS_USB_DEV_GENERIC , + .name ="usb_dev_generic_drv" , +};
include/dm/uclass-id.h +1 -0
@@ -41,6 +41,7 @@ enum uclass_id {UCLASS_ETH ,/* Ethernet device */ UCLASS_USB ,/* USB bus */ UCLASS_USB_HUB ,/* USB hub */ +UCLASS_USB_DEV_GENERIC ,/* USB generic device */ UCLASS_COUNT , UCLASS_INVALID = -1,
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 43/80 dm: usb: Bind generic USB devices when there is no driver
Quoted 12 lines · Simon Glass
At present USB devices with no driver model driver cannot be seen in the device list, and we fail to set them up correctly. This means they cannot be used.
While having real drivers that support driver model for all USB devices is the eventual goal, we are not there yet.
As a stop-gap, add a generic USB driver which is bound when we do not have a real driver. This allows the device to be set up and shown on the bus. It also allows ad-hoc code (such as
usb_ether) to find these devices and set them up.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/usb-uclass.c | 18 +++++++++++++++++- include/dm/uclass-id.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 44/80 dm: usb: Allow setting up a USB controller as a device/gadget
In reply to Simon GlassSome controllers support OTG (on-the-go) where they can operate as either host or device. The gadget layer in U-Boot supports this.
While this layer does not interact with driver model, we can provide a function which sets up the controller in the correct way. This way the code at least builds (although it likely will not work).
---
Changes in v2: None
drivers/usb/gadget/ci_udc.c | 4 ++++ drivers/usb/host/usb-uclass.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+)
drivers/usb/gadget/ci_udc.c +4 -0
@@ -883,7 +883,11 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)if (driver->speed !=USB_SPEED_FULL && driver->speed !=USB_SPEED_HIGH )return -EINVAL ; +#ifdef CONFIG_DM_USB + ret =usb_setup_ehci_gadget (&controller.ctrl); +#else ret =usb_lowlevel_init (0 ,USB_INIT_DEVICE , (void **)&controller.ctrl); +#endif if (ret)return ret;
drivers/usb/host/usb-uclass.c +24 -0
@@ -249,6 +249,30 @@ int usb_legacy_port_reset(struct usb_device *parent, int portnr)return usb_port_reset (parent, portnr); } +int usb_setup_ehci_gadget (struct ehci_ctrl **ctlrp) +{ +struct usb_platdata *plat; +struct udevice *dev; +int ret; + +/* Find the old device and remove it */ + ret =uclass_find_device_by_seq (UCLASS_USB ,0 , true, &dev); +if (ret) +return ret; + ret =device_remove (dev); +if (ret) +return ret; + + plat =dev_get_platdata (dev); + plat->init_type =USB_INIT_DEVICE ; + ret =device_probe (dev); +if (ret) +return ret; + *ctlrp =dev_get_priv (dev); + +return 0 ; +} +/* returns 0 if no match, 1 if match */ int usb_match_device (const struct usb_device_descriptor *desc,const struct usb_device_id *id)
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 44/80 dm: usb: Allow setting up a USB controller as a device/gadget
Quoted 7 lines · Simon Glass
Some controllers support OTG (on-the-go) where they can operate as either host or device. The gadget layer in U-Boot supports this.
While this layer does not interact with driver model, we can provide a function which sets up the controller in the correct way. This way the code at least builds (although it likely will not work).
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/gadget/ci_udc.c | 4 ++++ drivers/usb/host/usb-uclass.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 45/80 dm: usb: Split out the keyboard probe into its own function
In reply to Simon GlassBefore adding driver model support, split out code from this over-long function.
---
Changes in v2: None
common/usb_kbd.c | 89 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 38 deletions(-)
common/usb_kbd.c +51 -38
@@ -471,59 +471,72 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)return 1 ; } +static int probe_usb_keyboard (struct usb_device *dev) +{ +char *stdinname; +struct stdio_dev usb_kbd_dev; +int error; + +/* Try probing the keyboard */ +if (usb_kbd_probe (dev,0 ) !=1 ) +return -ENOENT ; + +/* Register the keyboard */ +debug ("USB KBD: register.\n" ); +memset (&usb_kbd_dev,0 ,sizeof (struct stdio_dev )); +strcpy (usb_kbd_dev.name,DEVNAME ); + usb_kbd_dev.flags =DEV_FLAGS_INPUT |DEV_FLAGS_SYSTEM ; + usb_kbd_dev.getc = usb_kbd_getc; + usb_kbd_dev.tstc = usb_kbd_testc; + usb_kbd_dev.priv = (void *)dev; + error =stdio_register (&usb_kbd_dev); +if (error) +return error; + + stdinname =getenv ("stdin" ); +#ifdef CONFIG_CONSOLE_MUX + error =iomux_doenv (stdin, stdinname); +if (error) +return error; +#else +/* Check if this is the standard input device. */ +if (strcmp (stdinname,DEVNAME )) +return 1 ; + +/* Reassign the console */ +if (overwrite_console ()) +return 1 ; + + error =console_assign (stdin,DEVNAME ); +if (error) +return error; +#endif + +return 0 ; +} +/* Search for keyboard and register it if found. */ int drv_usb_kbd_init (void ) { -struct stdio_dev usb_kbd_dev; -struct usb_device *dev; -char *stdinname =getenv ("stdin" );int error, i; -/* Scan all USB Devices */ +debug ("%s: Probing for keyboard\n" , __func__);/* Scan all USB Devices */ for (i =0 ; i <USB_MAX_DEVICE ; i++) { +struct usb_device *dev; +/* Get USB device. */ dev =usb_get_dev_index (i);if (!dev) -return -1 ; +break ;if (dev->devnum ==-1 )continue ; -/* Try probing the keyboard */ -if (usb_kbd_probe (dev,0 ) !=1 ) -continue ; - -/* Register the keyboard */ -debug ("USB KBD: register.\n" ); -memset (&usb_kbd_dev,0 ,sizeof (struct stdio_dev )); -strcpy (usb_kbd_dev.name,DEVNAME ); - usb_kbd_dev.flags =DEV_FLAGS_INPUT |DEV_FLAGS_SYSTEM ; - usb_kbd_dev.getc = usb_kbd_getc; - usb_kbd_dev.tstc = usb_kbd_testc; - usb_kbd_dev.priv = (void *)dev; - error =stdio_register (&usb_kbd_dev); -if (error) -return error; - -#ifdef CONFIG_CONSOLE_MUX - error =iomux_doenv (stdin, stdinname); -if (error) -return error; -#else -/* Check if this is the standard input device. */ -if (strcmp (stdinname,DEVNAME )) -return 1 ; - -/* Reassign the console */ -if (overwrite_console ()) + error =probe_usb_keyboard (dev); +if (!error)return 1 ; - - error =console_assign (stdin,DEVNAME ); -if (error) +if (error && error != -ENOENT )return error; -#endif - -return 1 ; }/* No USB Keyboard found */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 45/80 dm: usb: Split out the keyboard probe into its own function
Quoted 10 lines · Simon Glass
Before adding driver model support, split out code from this over-long function.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_kbd.c | 89 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 38 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 46/80 dm: usb: Support driver model with USB keyboards
In reply to Simon GlassAllow USB keyboards to work with driver model. The main difference is that we can have multiple buses (each with its own device numbering) and each bus must be scanned.
---
Changes in v2: None
common/usb_kbd.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-)
common/usb_kbd.c +33 -1
@@ -8,6 +8,7 @@* SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <dm.h> #include <errno.h> #include <malloc.h> #include <stdio_dev.h>
@@ -520,7 +521,37 @@ int drv_usb_kbd_init(void) {int error, i; -debug ("%s: Probing for keyboard\n" , __func__);/* Scan all USB Devices */ +debug ("%s: Probing for keyboard\n" , __func__); +#ifdef CONFIG_DM_USB +/* +* TODO: We should add USB_DEVICE() declarations to each USB ethernet +* driver and then most of this file can be removed. +*/ +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, %p\n" , i, dev); +if (!dev) +break ;/* no more devices available */ + + error =probe_usb_keyboard (dev); +if (!error) +return 1 ; +if (error && error != -ENOENT ) +return error; + }/* for */ + } +#else +/* Scan all USB Devices */ for (i =0 ; i <USB_MAX_DEVICE ; i++) {struct usb_device *dev;
@@ -538,6 +569,7 @@ int drv_usb_kbd_init(void)if (error && error != -ENOENT ) return error; } +#endif /* No USB Keyboard found */ return -1 ;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 46/80 dm: usb: Support driver model with USB keyboards
Quoted 11 lines · Simon Glass
Allow USB keyboards to work with driver model. The main difference is that we can have multiple buses (each with its own device numbering) and each bus must be scanned.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
common/usb_kbd.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 47/80 dm: usb: tegra: Add vbus GPIOs for nyan
In reply to Simon GlassThese are needed to enable the USB bus (although not sufficient since it still does not work).
---
Changes in v2: None
arch/arm/dts/tegra124-nyan-big.dts | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/dts/tegra124-nyan-big.dts +2 -0
@@ -230,6 +230,7 @@ usb at 7d000000 { /* Rear external USB port. */ status = "okay"; + nvidia,vbus-gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>; }; usb-phy at 7d000000 {
@@ -246,6 +247,7 @@ usb at 7d008000 { /* Left external USB port. */ status = "okay"; + nvidia,vbus-gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>; }; usb-phy at 7d008000 {
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 47/80 dm: usb: tegra: Add vbus GPIOs for nyan
Quoted 10 lines · Simon Glass
These are needed to enable the USB bus (although not sufficient since it still does not work).
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
arch/arm/dts/tegra124-nyan-big.dts | 2 ++ 1 file changed, 2 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 48/80 dm: usb: Move struct usb_string to a common place
In reply to Simon GlassThis is needed for sandbox USB device emulation, so move it to a place where it can be found by things other than gadgets.
---
Changes in v2: None
include/linux/usb/ch9.h | 13 +++++++++++++ include/linux/usb/gadget.h | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-)
include/linux/usb/ch9.h +13 -0
@@ -1002,4 +1002,17 @@ struct usb_set_sel_req {*/ #define USB_SELF_POWER_VBUS_MAX_DRAW 100 +/** +* struct usb_string - wraps a C string and its USB id +* @id:the (nonzero) ID for this string +* @s:the string, in UTF-8 encoding +* +* If you're using usb_gadget_get_string(), use this to wrap a string +* together with its ID. +*/ +struct usb_string { +u8 id; +const char *s; +}; +#endif /* __LINUX_USB_CH9_H */
include/linux/usb/gadget.h +0 -13
@@ -806,19 +806,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);/* utility to simplify dealing with string descriptors */ /** -* struct usb_string - wraps a C string and its USB id -* @id:the (nonzero) ID for this string -* @s:the string, in UTF-8 encoding -* -* If you're using usb_gadget_get_string(), use this to wrap a string -* together with its ID. -*/ -struct usb_string { -u8 id; -const char *s; -}; - -/** * struct usb_gadget_strings - a set of USB strings in a given language * @language:identifies the strings' language (0x0409 for en-us) * @strings:array of strings with their ids
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 48/80 dm: usb: Move struct usb_string to a common place
Quoted 11 lines · Simon Glass
This is needed for sandbox USB device emulation, so move it to a place where it can be found by things other than gadgets.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/linux/usb/ch9.h | 13 +++++++++++++ include/linux/usb/gadget.h | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 49/80 dm: usb: sandbox: Add a uclass for USB device emulation
In reply to Simon GlassWith sandbox we want to be able to emulate USB devices so that we can test the USB stack. Add a uclass to support this. It implements the same operations as a normal USB device driver, but in this case passes them on to an emulation driver.
---
Changes in v2: None
Makefile | 1 + drivers/usb/Kconfig | 2 + drivers/usb/emul/Kconfig | 8 ++ drivers/usb/emul/Makefile | 8 ++ drivers/usb/emul/usb-emul-uclass.c | 263 +++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/usb.h | 64 ++++++++- 7 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/emul/Kconfig create mode 100644 drivers/usb/emul/Makefile create mode 100644 drivers/usb/emul/usb-emul-uclass.c
Makefile +1 -0
@@ -637,6 +637,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/emul/ libs-y += drivers/usb/eth/ libs-y += drivers/usb/gadget/ libs-y += drivers/usb/host/
drivers/usb/Kconfig +2 -0
@@ -51,6 +51,8 @@ config DM_USB source "drivers/usb/host/Kconfig" +source "drivers/usb/emul/Kconfig" + config USB_STORAGE bool "USB Mass Storage support" ---help---
drivers/usb/emul/Kconfig new file +8 -0
@@ -0,0 +1,8 @@ +config USB_EMUL + bool "Support for USB device emulation" + depends on DM_USB && SANDBOX + help + Since sandbox does not have access to a real USB bus, it is possible + to use device emulators instead. This allows testing of the USB + stack on sandbox without needing a real device, or any host machine + USB resources.
drivers/usb/emul/Makefile new file +8 -0
@@ -0,0 +1,8 @@ +# +# (C) Copyright 2015 Google, Inc +# Written by Simon Glass <[email protected]> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_USB_EMUL) += usb-emul-uclass.o
drivers/usb/emul/usb-emul-uclass.c new file +263 -0
263 lines not on this page · raw message
include/dm/uclass-id.h +1 -0
@@ -21,6 +21,7 @@ enum uclass_id {UCLASS_SPI_EMUL ,/* sandbox SPI device emulator */ UCLASS_I2C_EMUL ,/* sandbox I2C device emulator */ UCLASS_PCI_EMUL ,/* sandbox PCI device emulator */ +UCLASS_USB_EMUL ,/* sandbox USB bus device emulator */ UCLASS_SIMPLE_BUS,/* U-Boot uclasses start here */
include/usb.h +63 -1
74 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 49/80 dm: usb: sandbox: Add a uclass for USB device emulation
Quoted 10 lines · Simon Glass
With sandbox we want to be able to emulate USB devices so that we can test the USB stack. Add a uclass to support this. It implements the same operations as a normal USB device driver, but in this case passes them on to an emulation driver.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
Quoted 11 lines
Makefile | 1 + drivers/usb/Kconfig | 2 + drivers/usb/emul/Kconfig | 8 ++ drivers/usb/emul/Makefile | 8 ++ drivers/usb/emul/usb-emul-uclass.c | 263 +++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/usb.h | 64 ++++++++- 7 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/emul/Kconfig create mode 100644 drivers/usb/emul/Makefile create mode 100644 drivers/usb/emul/usb-emul-uclass.c
Applied to u-boot-dm/next.
PATCH v2 50/80 dm: usb: sandbox: Reset emulation devices in usb stop()
In reply to Simon GlassThese devices must have their addresses removed ready for the next USB bus enumeration. Add this logic to usb_stop().
---
Changes in v2: None
drivers/usb/host/usb-uclass.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/usb/host/usb-uclass.c +11 -0
@@ -93,6 +93,17 @@ int usb_stop(void) err = ret; } +#ifdef CONFIG_SANDBOX +struct udevice *dev; + +/* Reset all enulation devices */ + ret =uclass_get (UCLASS_USB_EMUL , &uc); +if (ret) +return ret; + + uclass_foreach_dev(dev, uc) +usb_emul_reset (dev); +#endif usb_stor_reset ();usb_hub_reset (); usb_started =0 ;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 50/80 dm: usb: sandbox: Reset emulation devices in usb stop()
Quoted 10 lines · Simon Glass
These devices must have their addresses removed ready for the next USB bus enumeration. Add this logic to
usb_stop().Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/usb-uclass.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 51/80 dm: usb: sandbox: Add an emulator for USB flash devices
In reply to Simon GlassThis emulator supports USB enumeration and allows a local file to be provided as the contents of the emulated flash stick. U-Boot can then use the file as it would a normal device, with all access passing through the usb_stor layer and the USB stack.
---
Changes in v2: None
drivers/usb/emul/Makefile | 1 + drivers/usb/emul/sandbox_flash.c | 423 +++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + 3 files changed, 425 insertions(+) create mode 100644 drivers/usb/emul/sandbox_flash.c
drivers/usb/emul/Makefile +1 -0
@@ -5,4 +5,5 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_USB_EMUL) += sandbox_flash.o obj-$(CONFIG_USB_EMUL) += usb-emul-uclass.o
drivers/usb/emul/sandbox_flash.c new file +423 -0
423 lines not on this page · raw message
include/dm/uclass-id.h +1 -0
@@ -43,6 +43,7 @@ enum uclass_id {UCLASS_USB ,/* USB bus */ UCLASS_USB_HUB ,/* USB hub */ UCLASS_USB_DEV_GENERIC ,/* USB generic device */ +UCLASS_MASS_STORAGE ,/* Mass storage device */ UCLASS_COUNT , UCLASS_INVALID = -1,
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 51/80 dm: usb: sandbox: Add an emulator for USB flash devices
Quoted 8 lines · Simon Glass
This emulator supports USB enumeration and allows a local file to be provided as the contents of the emulated flash stick. U-Boot can then use the file as it would a normal device, with all access passing through the
usb_storlayer and the USB stack.Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
drivers/usb/emul/Makefile | 1 + drivers/usb/emul/sandbox_flash.c | 423 +++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + 3 files changed, 425 insertions(+) create mode 100644 drivers/usb/emul/sandbox_flash.c
Applied to u-boot-dm/next.
PATCH v2 52/80 dm: usb: sandbox: Add an emulator for USB hub emulation
In reply to Simon GlassAll USB controllers need a root hub. Add a sandbox emulation for this so that we can add USB devices to sandbox.
---
Changes in v2: None
drivers/usb/emul/Makefile | 1 + drivers/usb/emul/sandbox_hub.c | 303 +++++++++++++++++++++++++++++++++++++++++ include/usb_defs.h | 3 + 3 files changed, 307 insertions(+) create mode 100644 drivers/usb/emul/sandbox_hub.c
drivers/usb/emul/Makefile +1 -0
@@ -6,4 +6,5 @@ # obj-$(CONFIG_USB_EMUL) += sandbox_flash.o +obj-$(CONFIG_USB_EMUL) += sandbox_hub.o obj-$(CONFIG_USB_EMUL) += usb-emul-uclass.o
drivers/usb/emul/sandbox_hub.c new file +303 -0
303 lines not on this page · raw message
include/usb_defs.h +3 -0
@@ -286,6 +286,9 @@#define HUB_CHANGE_LOCAL_POWER 0x0001#define HUB_CHANGE_OVERCURRENT 0x0002 +/* Mask for wIndex in get/set port feature */ +#define USB_HUB_PORT_MASK 0xf +/* * CBI style */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 52/80 dm: usb: sandbox: Add an emulator for USB hub emulation
Quoted 6 lines · Simon Glass
All USB controllers need a root hub. Add a sandbox emulation for this so that we can add USB devices to sandbox.
Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
drivers/usb/emul/Makefile | 1 + drivers/usb/emul/sandbox_hub.c | 303 +++++++++++++++++++++++++++++++++++++++++ include/usb_defs.h | 3 + 3 files changed, 307 insertions(+) create mode 100644 drivers/usb/emul/sandbox_hub.c
Applied to u-boot-dm/next.
PATCH v2 53/80 dm: usb: sandbox: Add a driver for sandbox
In reply to Simon GlassThis driver supports using emulation devices to provide a USB bus within sandbox.
---
Changes in v2: None
drivers/usb/host/Makefile | 1 + drivers/usb/host/usb-sandbox.c | 117 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 drivers/usb/host/usb-sandbox.c
drivers/usb/host/Makefile +1 -0
@@ -7,6 +7,7 @@ ifdef CONFIG_DM_USB obj-$(CONFIG_CMD_USB) += usb-uclass.o +obj-$(CONFIG_SANDBOX) += usb-sandbox.o endif # ohci
drivers/usb/host/usb-sandbox.c new file +117 -0
117 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 53/80 dm: usb: sandbox: Add a driver for sandbox
Quoted 4 lines · Simon Glass
This driver supports using emulation devices to provide a USB bus within sandbox.
Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
drivers/usb/host/Makefile | 1 + drivers/usb/host/usb-sandbox.c | 117 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 drivers/usb/host/usb-sandbox.c
Applied to u-boot-dm/next.
PATCH v2 54/80 dm: usb: dts: sandbox: Add some sample USB devices to sandbox
In reply to Simon GlassThese allow basic testing of the USB functionality within sandbox.
---
Changes in v2: None
arch/sandbox/dts/sandbox.dts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
arch/sandbox/dts/sandbox.dts +40 -0
@@ -1,5 +1,7 @@ /dts-v1/; +#define USB_CLASS_HUB 9 + / { #address-cells = <1>; #size-cells = <1>;
@@ -219,4 +221,42 @@ reg = <0x90000000 0x1000>; host-raw-interface = "lo"; }; + + usb at 0 { + compatible = "sandbox,usb"; + status = "disabled"; + hub { + compatible = "sandbox,usb-hub"; + #address-cells = <1>; + #size-cells = <0>; + flash-stick { + reg = <0>; + compatible = "sandbox,usb-flash"; + }; + }; + }; + + usb at 1 { + compatible = "sandbox,usb"; + hub { + compatible = "usb-hub"; + usb,device-class = <USB_CLASS_HUB>; + hub-emul { + compatible = "sandbox,usb-hub"; + #address-cells = <1>; + #size-cells = <0>; + flash-stick { + reg = <0>; + compatible = "sandbox,usb-flash"; + sandbox,filepath = "flash.bin"; + }; + }; + }; + }; + + usb at 2 { + compatible = "sandbox,usb"; + status = "disabled"; + }; + };
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 54/80 dm: usb: dts: sandbox: Add some sample USB devices to sandbox
Quoted 9 lines · Simon Glass
These allow basic testing of the USB functionality within sandbox.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
arch/sandbox/dts/sandbox.dts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 55/80 dm: usb: Add support for USB ethernet devices with driver model
In reply to Simon GlassAdd support for scanning USB etghernet devices with driver model. This mostly involves scanning all buses since device numbering is not unique across buses.
---
Changes in v2: None
drivers/usb/eth/usb_ether.c | 52 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 8 deletions(-)
drivers/usb/eth/usb_ether.c +44 -8
@@ -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,23 +138,59 @@ int usb_host_eth_scan(int mode) } usb_max_eth_dev =0 ; +#ifdef CONFIG_DM_USB +/* +* TODO: We should add USB_DEVICE() declarations to each USB ethernet +* driver and then most of this file can be removed. +*/ +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, %s\n" , i, dev ? dev->dev->name :"(done)" ); +if (!dev) +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 ) +if (!dev)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 ) { -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 )
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 55/80 dm: usb: Add support for USB ethernet devices with driver model
Quoted 11 lines · Simon Glass
Add support for scanning USB etghernet devices with driver model. This mostly involves scanning all buses since device numbering is not unique across buses.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/eth/usb_ether.c | 52 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 8 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 56/80 dm: usb: exynos: Add driver model support to exynos EHCI
In reply to Simon GlassUpdate this driver with driver model support for USB.
---
Changes in v2: None
drivers/usb/host/ehci-exynos.c | 112 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-)
drivers/usb/host/ehci-exynos.c +111 -1
@@ -8,6 +8,7 @@*/ #include <common.h> +#include <dm.h> #include <fdtdec.h> #include <libfdt.h> #include <malloc.h>
@@ -24,19 +25,73 @@/* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR ; +#ifdef CONFIG_DM_USB +struct exynos_ehci_platdata { +struct usb_platdata usb_plat; +fdt_addr_t hcd_base; +fdt_addr_t phy_base; +struct gpio_desc vbus_gpio; +}; +#endif +/** * Contains pointers to register base addresses * for the usb controller. */ struct exynos_ehci { +struct ehci_ctrl ctrl;struct exynos_usb_phy *usb;struct ehci_hccr *hcd; +#ifndef CONFIG_DM_USB struct gpio_desc vbus_gpio; +#endif }; +#ifndef CONFIG_DM_USB static struct exynos_ehci exynos; +#endif -#ifdef CONFIG_OF_CONTROL +#ifdef CONFIG_DM_USB +static int ehci_usb_ofdata_to_platdata (struct udevice *dev) +{ +struct exynos_ehci_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 =dev_get_addr (dev); +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_EXYNOS_USB_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_usb_parse_dt (const void *blob,struct exynos_ehci *exynos) {fdt_addr_t addr;
@@ -215,6 +270,7 @@ static void reset_usb_phy(struct exynos_usb_phy *usb)set_usbhost_phy_ctrl (POWER_USB_HOST_PHY_CTRL_DISABLE ); } +#ifndef CONFIG_DM_USB /* * EHCI-initialization * Create the appropriate control structures to manage
@@ -268,3 +324,57 @@ int ehci_hcd_stop(int index)return 0 ; } +#endif + +#ifdef CONFIG_DM_USB +static int ehci_usb_probe (struct udevice *dev) +{ +struct exynos_ehci_platdata *plat =dev_get_platdata (dev); +struct exynos_ehci *ctx =dev_get_priv (dev); +struct ehci_hcor *hcor; + + ctx->hcd = (struct ehci_hccr *)plat->hcd_base; + ctx->usb = (struct exynos_usb_phy *)plat->phy_base; + hcor = (struct ehci_hcor *)((uint32_t )ctx->hcd + +HC_LENGTH (ehci_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 ); + +setup_usb_phy (ctx->usb); + +return ehci_register (dev, ctx->hcd, hcor,NULL ,0 ,USB_INIT_HOST ); +} + +static int ehci_usb_remove (struct udevice *dev) +{ +struct exynos_ehci *ctx =dev_get_priv (dev); +int ret; + + ret =ehci_deregister (dev); +if (ret) +return ret; +reset_usb_phy (ctx->usb); + +return 0 ; +} + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible ="samsung,exynos-ehci" }, + { } +}; + +U_BOOT_DRIVER (usb_ehci) = { + .name ="ehci_exynos" , + .id =UCLASS_USB , + .of_match = ehci_usb_ids, + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .probe = ehci_usb_probe, + .remove = ehci_usb_remove, + .ops = &ehci_usb_ops, + .priv_auto_alloc_size =sizeof (struct exynos_ehci ), + .platdata_auto_alloc_size =sizeof (struct exynos_ehci_platdata ), + .flags =DM_FLAG_ALLOC_PRIV_DMA , +}; +#endif
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 56/80 dm: usb: exynos: Add driver model support to exynos EHCI
Quoted 9 lines · Simon Glass
Update this driver with driver model support for USB.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-exynos.c | 112 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 57/80 dm: usb: tegra: Remove the port_addr_clear_csc variable
In reply to Simon GlassThis variable is a bit of a hack. We can obtain the same information from the normal device config. This will fit better with driver model, where global variables are best avoided.
---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/usb/host/ehci-tegra.c +1 -5
@@ -87,8 +87,6 @@ struct fdt_usb {static struct fdt_usb port[USB_PORTS_MAX ];/* List of valid USB ports */ static unsigned port_count;/* Number of available ports */ -/* Port that needs to clear CSC after Port Reset */ -static u32 port_addr_clear_csc;/* * This table has USB timing parameters for each Oscillator frequency we
@@ -206,7 +204,7 @@ static void tegra_ehci_powerup_fixup(struct ehci_ctrl *ctrl,if (controller->has_hostpc) *reg |=EHCI_PS_PE ; -if (((u32 )status_reg &TEGRA_USB_ADDR_MASK ) != port_addr_clear_csc) +if (!config->has_legacy_mode)return ;/* For EHCI_PS_CSC to be cleared in ehci_hcd.c */ if (ehci_readl (status_reg) &EHCI_PS_CSC )
@@ -683,8 +681,6 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) config->enabled =fdtdec_get_is_enabled (blob, node); config->has_legacy_mode =fdtdec_get_bool (blob, node,"nvidia,has-legacy-mode" ); -if (config->has_legacy_mode) - port_addr_clear_csc = (u32 ) config->reg; config->periph_id =clock_decode_periph_id (blob, node);if (config->periph_id ==PERIPH_ID_NONE ) {debug ("%s: Missing/invalid peripheral ID\n" , __func__);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 57/80 dm: usb: tegra: Remove the port_addr_clear_csc variable
Quoted 22 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Simon Glass
Sent: Thursday, March 26, 2015 2:23 AM
To: U-Boot Mailing List
Cc: Marek Vasut; Stephen Warren; Vivek Gautam; Tom Warren
Subject: [U-Boot] [PATCH v2 57/80] dm: usb: tegra: Remove theport_addr_clear_cscvariableThis variable is a bit of a hack. We can obtain the same information from the normal device config. This will fit better with driver model, where global variables > are best avoided.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/usb/host/ehci-tegra.c struct fdt_usb { · line 92
Quoted 7 lines
drivers/usb/host/ehci-tegra.c +0
-1@@ -87,8 +87,6 @@ struct fdt_usb {static struct fdt_usb port[USB_PORTS_MAX ];/* List of valid USB ports */ static unsigned port_count;/* Number of available ports */ -/* Port that needs to clear CSC after Port Reset */ -static u32 port_addr_clear_csc;/* * This table has USB timing parameters for each Oscillator frequency we @@ -206,7 +204,7 @@ static void tegra_ehci_powerup_fixup(struct ehci_ctrl *ctrl,
if (controller->has_hostpc)
drivers/usb/host/ehci-tegra.c static void tegra_ehci_powerup_fixup(struct ehci_ctrl *ctrl, · line 208
Quoted 5 lines
drivers/usb/host/ehci-tegra.c +1
-1*reg |=EHCI_PS_PE ; -if (((u32 )status_reg &TEGRA_USB_ADDR_MASK ) != port_addr_clear_csc) +if (!config->has_legacy_mode)return ;
How do we get config (config->has_legacy_mode) for in this function? If you read ehci_set_usbmode, "config" comes from
"config = &port[index];".
Or "config" is an input argument like set_up_vbus(struct fdt_usb *config, ...) But for ehci_powerup_fixup, I don't see a way for us to get "config".
Quoted 1 line
/* For
EHCI_PS_CSCto be cleared inehci_hcd.c*/
--nvpublic
PATCH v2 57/80 dm: usb: tegra: Remove the port_addr_clear_csc variable
Please ignore my question because it is answered by [PATCH v2 34/80].
Quoted 46 lines · Jim Lin
Quoted 21 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Simon Glass
Sent: Thursday, March 26, 2015 2:23 AM
To: U-Boot Mailing List
Cc: Marek Vasut; Stephen Warren; Vivek Gautam; Tom Warren
Subject: [U-Boot] [PATCH v2 57/80] dm: usb: tegra: Remove theport_addr_clear_cscvariableThis variable is a bit of a hack. We can obtain the same information from the normal device config. This will fit better with driver model, where global variables > are best avoided.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)drivers/usb/host/ehci-tegra.c struct fdt_usb { · line 92
Quoted 7 lines
drivers/usb/host/ehci-tegra.c +0
-1@@ -87,8 +87,6 @@ struct fdt_usb {static struct fdt_usb port[USB_PORTS_MAX ];/* List of valid USB ports */ static unsigned port_count;/* Number of available ports */ -/* Port that needs to clear CSC after Port Reset */ -static u32 port_addr_clear_csc;/* * This table has USB timing parameters for each Oscillator frequency we @@ -206,7 +204,7 @@ static void tegra_ehci_powerup_fixup(struct ehci_ctrl *ctrl, if (
controller->has_hostpc)drivers/usb/host/ehci-tegra.c static void tegra_ehci_powerup_fixup(struct ehci_ctrl *ctrl, · line 208
Quoted 5 lines
drivers/usb/host/ehci-tegra.c +1
-1*reg |=EHCI_PS_PE ; -if (((u32 )status_reg &TEGRA_USB_ADDR_MASK ) != port_addr_clear_csc) +if (!config->has_legacy_mode)return ;How do we get config (
config->has_legacy_mode) for in this function? If you readehci_set_usbmode, "config" comes from
"config = &port[index];".
Or "config" is an input argument likeset_up_vbus(struct fdt_usb *config, ...)But forehci_powerup_fixup, I don't see a way for us to get "config".Quoted 1 line
/* For
EHCI_PS_CSCto be cleared inehci_hcd.c*/--nvpublic
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
PATCH v2 57/80 dm: usb: tegra: Remove the port_addr_clear_csc variable
Quoted 66 lines · Jim Lin
Please ignore my question because it is answered by [PATCH v2 34/80].
Quoted 60 lines · Jim Lin
Quoted 32 lines
-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Simon Glass
Sent: Thursday, March 26, 2015 2:23 AM
To: U-Boot Mailing List
Cc: Marek Vasut; Stephen Warren; Vivek Gautam; Tom Warren
Subject: [U-Boot] [PATCH v2 57/80] dm: usb: tegra: Remove theport_addr_clear_cscvariableThis variable is a bit of a hack. We can obtain the same information from the normal device config. This will fit better with driver model, where global variables > are best avoided.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)(quoted diff) +0
-0
b/drivers/usb/host/ehci-tegra.cindex 38333c7..464f55d 100644drivers/usb/host/ehci-tegra.c +0
-0@@ -87,8 +87,6 @@ struct fdt_usb {static struct fdt_usb port[USB_PORTS_MAX ];/* List of valid USB ports */
static unsignedport_count; /* Number of available
ports */
-/* Port that needs to clear CSC after Port Reset */ -static u32Quoted 5 lines
port_addr_clear_csc; /** This table has USB timing parameters for each Oscillator frequency
we @@ -206,7 +204,7 @@ static void tegra_ehci_powerup_fixup(structehci_ctrl*ctrl,if (controller->has_hostpc)Quoted 6 lines
*reg |= EHCI_PS_PE; - if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != port_addr_clear_csc) + if (!config->has_legacy_mode) return;How do we get config (
config->has_legacy_mode) for in this function? If you readehci_set_usbmode, "config" comes from
"config = &port[index];".
Or "config" is an input argument likeset_up_vbus(struct fdt_usb *config, ...)
But forehci_powerup_fixup, I don't see a way for us to get "config".Quoted 1 line
/* For EHCI_PS_CSC to be cleared in ehci_hcd.c */--nvpublic
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
Applied to u-boot-dm/next.
PATCH v2 58/80 dm: usb: tegra: Tidy up error handling and a static function
In reply to Simon GlassTry to return useful error numbers where possible. Also avoid swallowing an error number when it is returned by a called function.
---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
drivers/usb/host/ehci-tegra.c +11 -8
@@ -266,7 +266,8 @@ static void set_up_vbus(struct fdt_usb *config, enum usb_init_type init) } } -void usbf_reset_controller (struct fdt_usb *config,struct usb_ctlr *usbctlr) +static void usbf_reset_controller (struct fdt_usb *config, +struct usb_ctlr *usbctlr) {/* Reset the USB controller with 2us delay */ reset_periph (config->periph_id,2 );
@@ -524,7 +525,7 @@ static int init_utmi_usb_controller(struct fdt_usb *config,udelay (1 ); }if (!loop_count) -return -1 ; +return -ETIMEDOUT ;/* Disable ICUSB FS/LS transceiver */ clrbits_le32 (&usbctlr->icusb_ctrl,IC_ENB1 );
@@ -567,6 +568,7 @@ static int init_ulpi_usb_controller(struct fdt_usb *config,int loop_count;struct ulpi_viewport ulpi_vp;struct usb_ctlr *usbctlr = config->reg; +int ret;/* set up ULPI reference clock on pllp_out4 */ clock_enable (PERIPH_ID_DEV2_OUT );
@@ -612,9 +614,10 @@ static int init_ulpi_usb_controller(struct fdt_usb *config, ulpi_vp.port_num =0 ; ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; -if (ulpi_init (&ulpi_vp)) { + ret =ulpi_init (&ulpi_vp); +if (ret) {printf ("Tegra ULPI viewport init failed\n" ); -return -1 ; +return ret; }ulpi_set_vbus (&ulpi_vp,1 ,1 );
@@ -631,7 +634,7 @@ static int init_ulpi_usb_controller(struct fdt_usb *config,udelay (1 ); }if (!loop_count) -return -1 ; +return -ETIMEDOUT ;clrbits_le32 (&usbctlr->susp_ctrl,USB_SUSP_CLR );return 0 ;
@@ -642,7 +645,7 @@ static int init_ulpi_usb_controller(struct fdt_usb *config, {printf ("No code to set up ULPI controller, please enable" "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT" ); -return -1 ; +return -ENOSYS ; }#endif
@@ -669,7 +672,7 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)else {debug ("%s: Cannot decode dr_mode '%s'\n" , __func__, mode); -return -FDT_ERR_NOTFOUND ; +return -EINVAL ; } }else { config->dr_mode =DR_MODE_HOST ;
@@ -684,7 +687,7 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) config->periph_id =clock_decode_periph_id (blob, node);if (config->periph_id ==PERIPH_ID_NONE ) {debug ("%s: Missing/invalid peripheral ID\n" , __func__); -return -FDT_ERR_NOTFOUND ; +return -EINVAL ; }gpio_request_by_name_nodev (blob, node,"nvidia,vbus-gpio" ,0 , &config->vbus_gpio,GPIOD_IS_OUT );
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 58/80 dm: usb: tegra: Tidy up error handling and a static function
Quoted 10 lines · Simon Glass
Try to return useful error numbers where possible. Also avoid swallowing an error number when it is returned by a called function.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 59/80 dm: usb: tegra: Move most of init/uninit into a function
In reply to Simon GlassWe want to use mostly the same init and uninit code for driver model, so move the common part into two functions.
---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 143 ++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 62 deletions(-)
drivers/usb/host/ehci-tegra.c +81 -62
@@ -703,6 +703,82 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)return 0 ; } +int usb_common_init (struct fdt_usb *config,enum usb_init_type init) +{ +int ret =0 ; + +switch (init) { +case USB_INIT_HOST : +switch (config->dr_mode) { +case DR_MODE_HOST : +case DR_MODE_OTG : +break ; +default : +printf ("tegrausb: Invalid dr_mode %d for host mode\n" , + config->dr_mode); +return -1 ; + } +break ; +case USB_INIT_DEVICE : +if (config->periph_id !=PERIPH_ID_USBD ) { +printf ("tegrausb: Device mode only supported on first USB controller\n" ); +return -1 ; + } +if (!config->utmi) { +printf ("tegrausb: Device mode only supported with UTMI PHY\n" ); +return -1 ; + } +switch (config->dr_mode) { +case DR_MODE_DEVICE : +case DR_MODE_OTG : +break ; +default : +printf ("tegrausb: Invalid dr_mode %d for device mode\n" , + config->dr_mode); +return -1 ; + } +break ; +default : +printf ("tegrausb: Unknown USB_INIT_* %d\n" , init); +return -1 ; + } + +#ifndef CONFIG_DM_USB +/* skip init, if the port is already initialized */ +if (config->initialized && config->init_type == init) +return 0 ; +#endif + +debug ("%d, %d\n" , config->utmi, config->ulpi); +if (config->utmi) + ret =init_utmi_usb_controller (config, init); +else if (config->ulpi) + ret =init_ulpi_usb_controller (config, init); +if (ret) +return ret; + +set_up_vbus (config, init); + + config->init_type = init; + +return 0 ; +} + +void usb_common_uninit (struct fdt_usb *priv) +{ +struct usb_ctlr *usbctlr; + + usbctlr = priv->reg; + +/* Stop controller */ +writel (0 , &usbctlr->usb_cmd); +udelay (1000 ); + +/* Initiate controller reset */ +writel (2 , &usbctlr->usb_cmd); +udelay (1000 ); +} +static const struct ehci_ops tegra_ehci_ops = { .set_usb_mode = tegra_ehci_set_usbmode, .get_port_speed = tegra_ehci_get_port_speed,
@@ -795,6 +871,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, {struct fdt_usb *config;struct usb_ctlr *usbctlr; +int ret;if (index >= port_count)return -1 ;
@@ -802,62 +879,14 @@ int ehci_hcd_init(int index, enum usb_init_type init, config = &port[index];ehci_set_controller_priv (index, config, &tegra_ehci_ops); -switch (init) { -case USB_INIT_HOST : -switch (config->dr_mode) { -case DR_MODE_HOST : -case DR_MODE_OTG : -break ; -default : -printf ("tegrausb: Invalid dr_mode %d for host mode\n" , - config->dr_mode); -return -1 ; - } -break ; -case USB_INIT_DEVICE : -if (config->periph_id !=PERIPH_ID_USBD ) { -printf ("tegrausb: Device mode only supported on first USB controller\n" ); -return -1 ; - } -if (!config->utmi) { -printf ("tegrausb: Device mode only supported with UTMI PHY\n" ); -return -1 ; - } -switch (config->dr_mode) { -case DR_MODE_DEVICE : -case DR_MODE_OTG : -break ; -default : -printf ("tegrausb: Invalid dr_mode %d for device mode\n" , - config->dr_mode); -return -1 ; - } -break ; -default : -printf ("tegrausb: Unknown USB_INIT_* %d\n" , init); -return -1 ; - } - -/* skip init, if the port is already initialized */ -if (config->initialized && config->init_type == init) - goto success; - -if (config->utmi &&init_utmi_usb_controller (config, init)) { -printf ("tegrausb: Cannot init port %d\n" , index); -return -1 ; - } - -if (config->ulpi &&init_ulpi_usb_controller (config, init)) { + ret =usb_common_init (config, init); +if (ret) {printf ("tegrausb: Cannot init port %d\n" , index); -return -1 ; +return ret; } -set_up_vbus (config, init); - config->initialized =1 ; - config->init_type = init; -success: usbctlr = config->reg; *hccr = (struct ehci_hccr *)&usbctlr->cap_length; *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd;
@@ -870,17 +899,7 @@ success:*/ int ehci_hcd_stop (int index) { -struct usb_ctlr *usbctlr; - - usbctlr = port[index].reg; - -/* Stop controller */ -writel (0 , &usbctlr->usb_cmd); -udelay (1000 ); - -/* Initiate controller reset */ -writel (2 , &usbctlr->usb_cmd); -udelay (1000 ); +usb_common_uninit (&port[index]); port[index].initialized =0 ;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 59/80 dm: usb: tegra: Move most of init/uninit into a function
Quoted 10 lines · Simon Glass
We want to use mostly the same init and uninit code for driver model, so move the common part into two functions.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 143 ++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 62 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 60/80 dm: usb: tegra: Add driver model support to tegra EHCI
In reply to Simon GlassUpdate this driver with driver model support for USB.
---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 83 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
drivers/usb/host/ehci-tegra.c +83 -0
@@ -7,6 +7,7 @@*/ #include <common.h> +#include <dm.h> #include <asm/errno.h> #include <asm/io.h> #include <asm-generic/gpio.h>
@@ -20,6 +21,8 @@#include "ehci.h" +DECLARE_GLOBAL_DATA_PTR ; +#define USB1_ADDR_MASK 0xFFFF0000#define HOSTPC1_DEVLC 0x84
@@ -32,9 +35,11 @@#endif #endif +#ifndef CONFIG_DM_USB enum {USB_PORTS_MAX =3 ,/* Maximum ports we allow */ }; +#endif /* Parameters we need for USB */ enum {
@@ -71,12 +76,15 @@ enum usb_ctlr_type {/* Information about a USB port */ struct fdt_usb { +struct ehci_ctrl ehci;struct usb_ctlr *reg;/* address of registers in physical memory */ unsigned utmi:1 ;/* 1 if port has external tranceiver, else 0 */ unsigned ulpi:1 ;/* 1 if port has external ULPI transceiver */ unsigned enabled:1 ;/* 1 to enable, 0 to disable */ unsigned has_legacy_mode:1 ;/* 1 if this port has legacy mode */ +#ifndef CONFIG_DM_USB unsigned initialized:1 ;/* has this port already been initialized? */ +#endif enum usb_ctlr_type type;enum usb_init_type init_type;enum dr_mode dr_mode;/* dual role mode */
@@ -85,8 +93,10 @@ struct fdt_usb {struct gpio_desc phy_reset_gpio;/* GPIO to reset ULPI phy */ }; +#ifndef CONFIG_DM_USB static struct fdt_usb port[USB_PORTS_MAX ];/* List of valid USB ports */ static unsigned port_count;/* Number of available ports */ +#endif /* * This table has USB timing parameters for each Oscillator frequency we
@@ -163,6 +173,7 @@ static const u8 utmip_elastic_limit = 16;static const u8 utmip_hs_sync_start_delay =9 ;struct fdt_usb_controller { +/* TODO(sjg at chromium.org): Remove when we only use driver model */ int compat;/* flag to determine whether controller supports hostpc register */ u32 has_hostpc:1 ;
@@ -785,6 +796,7 @@ static const struct ehci_ops tegra_ehci_ops = { .powerup_fixup = tegra_ehci_powerup_fixup, }; +#ifndef CONFIG_DM_USB /* * process_usb_nodes() - Process a list of USB nodes, adding them to our list * of USB ports.
@@ -905,3 +917,74 @@ int ehci_hcd_stop(int index)return 0 ; } +#endif /* !CONFIG_DM_USB */ + +#ifdef CONFIG_DM_USB +static int ehci_usb_ofdata_to_platdata (struct udevice *dev) +{ +struct fdt_usb *priv =dev_get_priv (dev); +int ret; + + ret =fdt_decode_usb (gd->fdt_blob, dev->of_offset, priv); +if (ret) +return ret; + + priv->type =dev_get_driver_data (dev); + +return 0 ; +} + +static int ehci_usb_probe (struct udevice *dev) +{ +struct usb_platdata *plat =dev_get_platdata (dev); +struct fdt_usb *priv =dev_get_priv (dev); +struct ehci_hccr *hccr; +struct ehci_hcor *hcor; +static bool clk_done; +int ret; + + ret =usb_common_init (priv, plat->init_type); +if (ret) +return ret; + hccr = (struct ehci_hccr *)&priv->reg->cap_length; + hcor = (struct ehci_hcor *)&priv->reg->usb_cmd; +if (!clk_done) { +config_clock (get_pll_timing (&fdt_usb_controllers[priv->type])); + clk_done = true; + } + +return ehci_register (dev, hccr, hcor, &tegra_ehci_ops,0 , + plat->init_type); +} + +static int ehci_usb_remove (struct udevice *dev) +{ +int ret; + + ret =ehci_deregister (dev); +if (ret) +return ret; + +return 0 ; +} + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible ="nvidia,tegra20-ehci" , .data =USB_CTLR_T20 }, + { .compatible ="nvidia,tegra30-ehci" , .data =USB_CTLR_T30 }, + { .compatible ="nvidia,tegra114-ehci" , .data =USB_CTLR_T114 }, + { } +}; + +U_BOOT_DRIVER (usb_ehci) = { + .name ="ehci_tegra" , + .id =UCLASS_USB , + .of_match = ehci_usb_ids, + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .probe = ehci_usb_probe, + .remove = ehci_usb_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size =sizeof (struct usb_platdata ), + .priv_auto_alloc_size =sizeof (struct fdt_usb ), + .flags =DM_FLAG_ALLOC_PRIV_DMA , +}; +#endif
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 60/80 dm: usb: tegra: Add driver model support to tegra EHCI
Quoted 9 lines · Simon Glass
Update this driver with driver model support for USB.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/ehci-tegra.c | 83 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 61/80 dm: usb: xhci: Use a function to get xhci_ctrl
In reply to Simon GlassRather than getting this directly from struct usb_device, call a function to obtain it. This will make it possible for driver model to provide it another way.
---
Changes in v2: None
drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 19 ++++++++++++------- drivers/usb/host/xhci.h | 2 ++ 3 files changed, 18 insertions(+), 11 deletions(-)
drivers/usb/host/xhci-ring.c +4 -4
@@ -353,7 +353,7 @@ static void giveback_first_trb(struct usb_device *udev, int ep_index,int start_cycle, struct xhci_generic_trb *start_trb) { - struct xhci_ctrl *ctrl = udev->controller; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);/* * Pass all the TRBs to the hardware at once and make sure this write
@@ -477,7 +477,7 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)*/ static void abort_td (struct usb_device *udev,int ep_index) { -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring;union xhci_trb *event;u32 field;
@@ -554,7 +554,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,int start_cycle;u32 field =0 ;u32 length_field =0 ; -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);int slot_id = udev->slot_id;int ep_index;struct xhci_virt_device *virt_dev;
@@ -748,7 +748,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,u32 length_field;u64 buf_64 =0 ;struct xhci_generic_trb *start_trb; -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);int slot_id = udev->slot_id;int ep_index;u32 trb_fields[4 ];
drivers/usb/host/xhci.c +12 -7
@@ -110,6 +110,11 @@ static struct descriptor {static struct xhci_ctrl xhcic[CONFIG_USB_MAX_CONTROLLER_COUNT ]; +struct xhci_ctrl *xhci_get_ctrl (struct usb_device *udev) +{ +return udev->controller; +} +/** * Waits for as per specified amount of time * for the "result" to match with "done"
@@ -250,7 +255,7 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) {struct xhci_container_ctx *in_ctx;struct xhci_virt_device *virt_dev; -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);union xhci_trb *event; virt_dev = ctrl->devs[udev->slot_id];
@@ -298,7 +303,7 @@ static int xhci_set_configuration(struct usb_device *udev)int ep_index;unsigned int dir;unsigned int ep_type; -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);int num_of_ep;int ep_flag =0 ;u64 trb_64 =0 ;
@@ -382,7 +387,7 @@ static int xhci_set_configuration(struct usb_device *udev)static int xhci_address_device (struct usb_device *udev) {int ret =0 ; -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);struct xhci_slot_ctx *slot_ctx;struct xhci_input_control_ctx *ctrl_ctx;struct xhci_virt_device *virt_dev;
@@ -463,8 +468,8 @@ static int xhci_address_device(struct usb_device *udev)*/ int usb_alloc_device (struct usb_device *udev) { +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);union xhci_trb *event; -struct xhci_ctrl *ctrl = udev->controller;int ret;/*
@@ -510,7 +515,7 @@ int usb_alloc_device(struct usb_device *udev)*/ int xhci_check_maxpacket (struct usb_device *udev) { -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);unsigned int slot_id = udev->slot_id;int ep_index =0 ;/* control endpoint */ struct xhci_container_ctx *in_ctx;
@@ -640,7 +645,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe,int len, srclen;uint32_t reg;volatile uint32_t *status_reg; -struct xhci_ctrl *ctrl = udev->controller; +struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);struct xhci_hcor *hcor = ctrl->hcor; if ((req->requesttype & USB_RT_PORT) &&
@@ -904,7 +909,7 @@ int submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, struct devrequest *setup) { - struct xhci_ctrl *ctrl = udev->controller; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);int ret =0 ;if (usb_pipetype (pipe) !=PIPE_CONTROL ) {
drivers/usb/host/xhci.h +2 -0
@@ -1250,4 +1250,6 @@ 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); +struct xhci_ctrl *xhci_get_ctrl (struct usb_device *udev); +#endif /* HOST_XHCI_H_ */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 61/80 dm: usb: xhci: Use a function to get xhci_ctrl
Quoted 5 lines · Simon Glass
Rather than getting this directly from struct
usb_device, call a function to obtain it. This will make it possible for driver model to provide it another way.Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 19 ++++++++++++------- drivers/usb/host/xhci.h | 2 ++ 3 files changed, 18 insertions(+), 11 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 62/80 dm: usb: xhci: Use explicit parameters for xhci_alloc_virt_device()
In reply to Simon GlassThis function should not be delving into struct usb_device. Pass in the parameters it needs directly.
---
Changes in v2: None
drivers/usb/host/xhci-mem.c | 4 +--- drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-)
drivers/usb/host/xhci-mem.c +1 -3
@@ -352,12 +352,10 @@ static struct xhci_container_ctx* @param udev pointer to USB deivce structure * @return 0 on success else -1 on failure */ -int xhci_alloc_virt_device (struct usb_device *udev) +int xhci_alloc_virt_device (struct xhci_ctrl *ctrl,unsigned int slot_id) {u64 byte_64 =0 ; -unsigned int slot_id = udev->slot_id;struct xhci_virt_device *virt_dev; -struct xhci_ctrl *ctrl = udev->controller;/* Slot ID 0 is reserved */ if (ctrl->devs[slot_id]) {
drivers/usb/host/xhci.c +1 -1
@@ -491,7 +491,7 @@ int usb_alloc_device(struct usb_device *udev)xhci_acknowledge_event (ctrl); - ret =xhci_alloc_virt_device (udev); + ret =xhci_alloc_virt_device (ctrl, udev->slot_id);if (ret <0 ) {/* * TODO: Unsuccessful Address Device command shall leave
drivers/usb/host/xhci.h +1 -1
@@ -1246,7 +1246,7 @@ void xhci_flush_cache(uint32_t addr, u32 type_len);void xhci_inval_cache (uint32_t addr,u32 type_len);void xhci_cleanup (struct xhci_ctrl *ctrl);struct xhci_ring *xhci_ring_alloc (unsigned int num_segs,bool link_trbs); -int xhci_alloc_virt_device (struct usb_device *udev); +int xhci_alloc_virt_device (struct xhci_ctrl *ctrl,unsigned int slot_id);int xhci_mem_init (struct xhci_ctrl *ctrl,struct xhci_hccr *hccr,struct xhci_hcor *hcor);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 62/80 dm: usb: xhci: Use explicit parameters for xhci_alloc_virt_device()
Quoted 4 lines · Simon Glass
This function should not be delving into struct
usb_device. Pass in the parameters it needs directly.Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
drivers/usb/host/xhci-mem.c | 4 +--- drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 63/80 dm: usb: xhci: Use explicit parameters for xhci_setup_addressable_virt_dev()
In reply to Simon GlassThis function should not be delving into struct usb_device. Pass in the parameters it needs directly.
---
Changes in v2: None
drivers/usb/host/xhci-mem.c | 19 +++++++------------ drivers/usb/host/xhci.c | 29 ++++++++++++++++++++++------- drivers/usb/host/xhci.h | 3 ++- 3 files changed, 31 insertions(+), 20 deletions(-)
drivers/usb/host/xhci-mem.c +7 -12
@@ -625,17 +625,16 @@ void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *in_ctx,* @param udev pointer to the Device Data Structure * @return returns negative value on failure else 0 on success */ -void xhci_setup_addressable_virt_dev (struct usb_device *udev) +void xhci_setup_addressable_virt_dev (struct xhci_ctrl *ctrl,int slot_id, +int speed,int hop_portnr) { -struct usb_device *hop = udev;struct xhci_virt_device *virt_dev;struct xhci_ep_ctx *ep0_ctx;struct xhci_slot_ctx *slot_ctx;u32 port_num =0 ;u64 trb_64 =0 ; -struct xhci_ctrl *ctrl = udev->controller; - virt_dev = ctrl->devs[udev->slot_id]; + virt_dev = ctrl->devs[slot_id];BUG_ON (!virt_dev);
@@ -646,7 +645,7 @@ void xhci_setup_addressable_virt_dev(struct usb_device *udev)/* Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |=cpu_to_le32 (LAST_CTX (1 ) |0 ); -switch (udev->speed) { +switch (speed) {case USB_SPEED_SUPER : slot_ctx->dev_info |=cpu_to_le32 (SLOT_SPEED_SS );break ;
@@ -664,11 +663,7 @@ void xhci_setup_addressable_virt_dev(struct usb_device *udev)BUG (); } -/* Extract the root hub port number */ -if (hop->parent) -while (hop->parent->parent) - hop = hop->parent; - port_num = hop->portnr; + port_num = hop_portnr;debug ("port_num = %d\n" , port_num); slot_ctx->dev_info2 |=
@@ -678,9 +673,9 @@ void xhci_setup_addressable_virt_dev(struct usb_device *udev)/* Step 4 - ring already allocated */ /* Step 5 */ ep0_ctx->ep_info2 =cpu_to_le32 (CTRL_EP <<EP_TYPE_SHIFT ); -debug ("SPEED = %d\n" , udev->speed); +debug ("SPEED = %d\n" , speed); -switch (udev->speed) { +switch (speed) {case USB_SPEED_SUPER : ep0_ctx->ep_info2 |=cpu_to_le32 (((512 &MAX_PACKET_MASK ) <<MAX_PACKET_SHIFT ));
drivers/usb/host/xhci.c +22 -7
@@ -384,7 +384,7 @@ static int xhci_set_configuration(struct usb_device *udev)* @param udev pointer to the Device Data Structure * @return 0 if successful else error code on failure */ -static int xhci_address_device (struct usb_device *udev) +static int xhci_address_device (struct usb_device *udev,int root_portnr) {int ret =0 ;struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);
@@ -400,8 +400,9 @@ static int xhci_address_device(struct usb_device *udev)* This is the first Set Address since device plug-in * so setting up the slot context. */ -debug ("Setting up addressable devices\n" ); -xhci_setup_addressable_virt_dev (udev); +debug ("Setting up addressable devices %p\n" , ctrl->dcbaa); +xhci_setup_addressable_virt_dev (ctrl, udev->slot_id, udev->speed, + root_portnr); ctrl_ctx =xhci_get_input_control_ctx (virt_dev->in_ctx); ctrl_ctx->add_flags =cpu_to_le32 (SLOT_FLAG |EP0_FLAG );
@@ -903,11 +904,12 @@ submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer,* @param buffer buffer to be read/written based on the request * @param length length of the buffer * @param setup Request type +* @param root_portnr Root port number that this device is on * @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,int root_portnr) {struct xhci_ctrl *ctrl =xhci_get_ctrl (udev);int ret =0 ;
@@ -921,7 +923,7 @@ submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer,return xhci_submit_root (udev, pipe, buffer, setup);if (setup->request ==USB_REQ_SET_ADDRESS ) -return xhci_address_device (udev); +return xhci_address_device (udev, root_portnr);if (setup->request ==USB_REQ_SET_CONFIGURATION ) { ret =xhci_set_configuration (udev);
@@ -1007,6 +1009,19 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)return 0 ; } +int submit_control_msg (struct usb_device *udev,unsigned long pipe, +void *buffer,int length,struct devrequest *setup) +{ +struct usb_device *hop = udev; + +if (hop->parent) +while (hop->parent->parent) + hop = hop->parent; + +return _xhci_submit_control_msg (udev, pipe, buffer, length, setup, + hop->portnr); +} +/** * Stops the XHCI host controller * and cleans up all the related data structures
drivers/usb/host/xhci.h +2 -1
@@ -1232,7 +1232,8 @@ void xhci_endpoint_copy(struct xhci_ctrl *ctrl,void xhci_slot_copy (struct xhci_ctrl *ctrl,struct xhci_container_ctx *in_ctx,struct xhci_container_ctx *out_ctx); -void xhci_setup_addressable_virt_dev (struct usb_device *udev); +void xhci_setup_addressable_virt_dev (struct xhci_ctrl *ctrl,int slot_id, +int speed,int hop_portnr);void xhci_queue_command (struct xhci_ctrl *ctrl,u8 *ptr,u32 slot_id,u32 ep_index,trb_type cmd);void xhci_acknowledge_event (struct xhci_ctrl *ctrl);
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 63/80 dm: usb: xhci: Use explicit parameters for xhci_setup_addressable_virt_dev()
Quoted 4 lines · Simon Glass
This function should not be delving into struct
usb_device. Pass in the parameters it needs directly.Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
drivers/usb/host/xhci-mem.c | 19 +++++++------------ drivers/usb/host/xhci.c | 29 ++++++++++++++++++++++------- drivers/usb/host/xhci.h | 3 ++- 3 files changed, 31 insertions(+), 20 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 64/80 dm: usb: xhci: Factor out common init/uninit
In reply to Simon GlassSince driver model will want to use most of the same code for XHCI init and uninit, put it in a separate function.
---
Changes in v2: None
drivers/usb/host/xhci.c | 85 ++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 33 deletions(-)
drivers/usb/host/xhci.c +52 -33
@@ -936,33 +936,16 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,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.
@@ -1004,7 +987,20 @@ 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 ; }
@@ -1023,6 +1019,38 @@ int submit_control_msg(struct usb_device *udev, unsigned long pipe, }/** +* 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 *
@@ -1032,18 +1060,9 @@ int submit_control_msg(struct usb_device *udev, unsigned long pipe,int usb_lowlevel_stop (int index) {struct xhci_ctrl *ctrl = (xhcic + index); -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)); +xhci_lowlevel_stop (ctrl);xhci_hcd_stop (index); -xhci_cleanup (ctrl);return 0 ;
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 64/80 dm: usb: xhci: Factor out common init/uninit
Quoted 10 lines · Simon Glass
Since driver model will want to use most of the same code for XHCI init and uninit, put it in a separate function.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/xhci.c | 85 ++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 33 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 65/80 dm: usb: Support driver model in XHCI
In reply to Simon GlassAdd driver model support in the XHCI support code so that it can be used by XHCI USB drivers.
---
Changes in v2: None
drivers/usb/host/xhci-mem.c | 1 + drivers/usb/host/xhci.c | 179 ++++++++++++++++++++++++++++++++++++++++++-- drivers/usb/host/xhci.h | 24 ++++++ 3 files changed, 197 insertions(+), 7 deletions(-)
drivers/usb/host/xhci-mem.c +1 -0
@@ -15,6 +15,7 @@*/ #include <common.h> +#include <dm.h> #include <asm/byteorder.h> #include <usb.h> #include <malloc.h>
drivers/usb/host/xhci.c +172 -7
235 lines not on this page · raw message
drivers/usb/host/xhci.h +24 -0
@@ -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;
@@ -1251,6 +1254,27 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id);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; +struct xhci_ctrl *xhci_get_ctrl (struct usb_device *udev);#endif /* HOST_XHCI_H_ */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 65/80 dm: usb: Support driver model in XHCI
Quoted 4 lines · Simon Glass
Add driver model support in the XHCI support code so that it can be used by XHCI USB drivers.
Signed-off-by Simon Glass <[email protected]>
Quoted 8 lines
---
Changes in v2: None
drivers/usb/host/xhci-mem.c | 1 + drivers/usb/host/xhci.c | 179 ++++++++++++++++++++++++++++++++++++++++++-- drivers/usb/host/xhci.h | 24 ++++++ 3 files changed, 197 insertions(+), 7 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 66/80 dm: usb: Rename the XHCI HCD to U-Boot
In reply to Simon GlassThis should be "U-Boot", not "u-boot".
---
Changes in v2: None
drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci.c +1 -1
@@ -704,7 +704,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, srclen =4 ;break ;case 1 :/* Vendor String */ - srcptr ="\16\3u\0-\0b\0o\0o\0t\0" ; + srcptr ="\16\3U\0-\0B\0o\0o\0t\0" ; srclen =14 ;break ;case 2 :/* Product Name */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 66/80 dm: usb: Rename the XHCI HCD to U-Boot
Quoted 9 lines · Simon Glass
This should be "U-Boot", not "u-boot".
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 67/80 dm: usb: exynos: Adjust XHCI driver to support driver model
In reply to Simon GlassSupport driver model in the exynos XHCI driver.
---
Changes in v2: None
drivers/usb/host/xhci-exynos5.c | 120 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-)
drivers/usb/host/xhci-exynos5.c +119 -1
@@ -14,6 +14,7 @@*/ #include <common.h> +#include <dm.h> #include <fdtdec.h> #include <libfdt.h> #include <malloc.h>
@@ -32,20 +33,76 @@/* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR ; +#ifdef CONFIG_DM_USB +struct exynos_xhci_platdata { +fdt_addr_t hcd_base; +fdt_addr_t phy_base; +struct gpio_desc vbus_gpio; +}; +#endif +/** * Contains pointers to register base addresses * for the usb controller. */ struct exynos_xhci { +#ifdef CONFIG_DM_USB +struct usb_platdata usb_plat; +#endif +struct xhci_ctrl ctrl;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;
@@ -283,6 +340,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 +384,63 @@ 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, + .platdata_auto_alloc_size =sizeof (struct exynos_xhci_platdata ), + .priv_auto_alloc_size =sizeof (struct exynos_xhci ), + .flags =DM_FLAG_ALLOC_PRIV_DMA , +}; +#endif
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 67/80 dm: usb: exynos: Adjust XHCI driver to support driver model
Quoted 9 lines · Simon Glass
Support driver model in the exynos XHCI driver.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
drivers/usb/host/xhci-exynos5.c | 120 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 68/80 dm: usb: exynos: Use driver model for USB
In reply to Simon GlassConvert Exynos boards over to use driver model for USB. This does not remove any unnecessary code so far.
---
Changes in v2: None
arch/arm/cpu/armv7/exynos/Kconfig | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/cpu/armv7/exynos/Kconfig +3 -0
@@ -86,6 +86,9 @@ config SYS_MALLOC_F config SYS_MALLOC_F_LEN default 0x400 +config DM_USB + default y + source "board/samsung/smdkv310/Kconfig" source "board/samsung/trats/Kconfig" source "board/samsung/universal_c210/Kconfig"
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 68/80 dm: usb: exynos: Use driver model for USB
Quoted 10 lines · Simon Glass
Convert Exynos boards over to use driver model for USB. This does not remove any unnecessary code so far.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
arch/arm/cpu/armv7/exynos/Kconfig | 3 +++ 1 file changed, 3 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 69/80 dm: usb: exynos: Enable both USB ports on snow
In reply to Simon GlassSwitch snow over to use both EHCI and XHCI at the same time.
---
Changes in v2: None
include/configs/snow.h | 2 ++ 1 file changed, 2 insertions(+)
include/configs/snow.h +2 -0
@@ -26,7 +26,9 @@#define CONFIG_ARCH_EARLY_INIT_R #define CONFIG_USB_XHCI +#define CONFIG_USB_EHCI #define CONFIG_USB_XHCI_EXYNOS +#define CONFIG_USB_EHCI_EXYNOS #define CONFIG_SYS_PROMPT "snow # "#define CONFIG_IDENT_STRING " for snow"
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 69/80 dm: usb: exynos: Enable both USB ports on snow
Quoted 9 lines · Simon Glass
Switch snow over to use both EHCI and XHCI at the same time.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/configs/snow.h | 2 ++ 1 file changed, 2 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 70/80 dm: usb: exynos: Enable both EHCI and XHCI on snow
In reply to Simon GlassSince we can support both controllers now, enable this in the device tree.
---
Changes in v2: None
arch/arm/dts/exynos5250-snow.dts | 1 + 1 file changed, 1 insertion(+)
arch/arm/dts/exynos5250-snow.dts +1 -0
@@ -133,6 +133,7 @@ ehci at 12110000 { samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>; + status = "okay"; }; xhci at 12000000 {
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 70/80 dm: usb: exynos: Enable both EHCI and XHCI on snow
Quoted 9 lines · Simon Glass
Since we can support both controllers now, enable this in the device tree.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
arch/arm/dts/exynos5250-snow.dts | 1 + 1 file changed, 1 insertion(+)
Applied to u-boot-dm/next.
PATCH v2 71/80 dm: usb: tegra: Move to driver model for USB
In reply to Simon GlassMove Tegra boards over to driver model for USB EHCI. There are a few things that are no-longer needed (e.g. in fdtdec.h) but these will be cleaned up in a later patch to be applied one we are confident this change is fully tested.
---
Changes in v2: None
arch/arm/mach-tegra/Kconfig | 3 +++ board/nvidia/common/board.c | 2 ++ 2 files changed, 5 insertions(+)
arch/arm/mach-tegra/Kconfig +3 -0
@@ -47,6 +47,9 @@ config DM_I2C config DM_GPIO default y +config DM_USB + default y + source "arch/arm/mach-tegra/tegra20/Kconfig" source "arch/arm/mach-tegra/tegra30/Kconfig" source "arch/arm/mach-tegra/tegra114/Kconfig"
board/nvidia/common/board.c +2 -0
@@ -128,8 +128,10 @@ int board_init(void)#ifdef CONFIG_USB_EHCI_TEGRA pin_mux_usb (); +#ifndef CONFIG_DM_USB usb_process_devicetree (gd->fdt_blob);#endif +#endif #ifdef CONFIG_LCD tegra_lcd_check_next_stage (gd->fdt_blob,0 );
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 71/80 dm: usb: tegra: Move to driver model for USB
Quoted 5 lines · Simon Glass
Move Tegra boards over to driver model for USB EHCI. There are a few things that are no-longer needed (e.g. in
fdtdec.h) but these will be cleaned up in a later patch to be applied one we are confident this change is fully tested.
Quoted 8 lines
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
arch/arm/mach-tegra/Kconfig | 3 +++ board/nvidia/common/board.c | 2 ++ 2 files changed, 5 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 72/80 dm: usb: Add a generic descriptor struct
In reply to Simon GlassThis is useful for creating lists of descriptors, and is better than using void * for this purpose.
---
Changes in v2: None
include/linux/usb/ch9.h | 5 +++++ 1 file changed, 5 insertions(+)
include/linux/usb/ch9.h +5 -0
@@ -379,6 +379,11 @@ struct usb_endpoint_descriptor {#define USB_DT_ENDPOINT_SIZE 7#define USB_DT_ENDPOINT_AUDIO_SIZE 9/* Audio extension */ +/* Used to access common fields */ +struct usb_generic_descriptor { +__u8 bLength; +__u8 bDescriptorType; +};/* * Endpoints
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 72/80 dm: usb: Add a generic descriptor struct
Quoted 10 lines · Simon Glass
This is useful for creating lists of descriptors, and is better than using void * for this purpose.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/linux/usb/ch9.h | 5 +++++ 1 file changed, 5 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 73/80 dm: usb: Tidy up pipe value decoding
In reply to Simon GlassAdd a few more shifts/masks to make it easier to decode a pipe value (rather than just building it). We need this for USB device emulation.
---
Changes in v2: None
include/usb_defs.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
include/usb_defs.h +17 -6
@@ -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
@@ -178,6 +180,15 @@#define USB_CONTROL 2#define USB_BULK 3 +#define USB_PIPE_TYPE_SHIFT 30 +#define USB_PIPE_TYPE_MASK (3 << USB_PIPE_TYPE_SHIFT) + +#define USB_PIPE_DEV_SHIFT 8 +#define USB_PIPE_DEV_MASK (0x7f << USB_PIPE_DEV_SHIFT) + +#define USB_PIPE_EP_SHIFT 15 +#define USB_PIPE_EP_MASK (0xf << USB_PIPE_EP_SHIFT) +/* USB-status codes: */ #define USB_ST_ACTIVE 0x1/* TD is active */ #define USB_ST_STALLED 0x2/* TD is stalled */
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 73/80 dm: usb: Tidy up pipe value decoding
Quoted 10 lines · Simon Glass
Add a few more shifts/masks to make it easier to decode a pipe value (rather than just building it). We need this for USB device emulation.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/usb_defs.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 74/80 dm: usb: sandbox: Enable USB
In reply to Simon GlassEnable USB emulation and associated features so that USB can be used in sandbox.
---
Changes in v2: None
configs/sandbox_defconfig | 4 ++++ include/configs/sandbox.h | 2 ++ 2 files changed, 6 insertions(+)
configs/sandbox_defconfig +4 -0
@@ -15,3 +15,7 @@ CONFIG_CMD_CROS_EC=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_PCI_SANDBOX=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EMUL=y +CONFIG_USB_STORAGE=y
include/configs/sandbox.h +2 -0
@@ -60,6 +60,7 @@#define CONFIG_CMD_GPT #define CONFIG_PARTITION_UUIDS #define CONFIG_EFI_PARTITION +#define CONFIG_DOS_PARTITION /* * Size of malloc() pool, before and after relocation
@@ -200,5 +201,6 @@#define CONFIG_TPM_TIS_SANDBOX #define CONFIG_CMD_LZMADEC +#define CONFIG_CMD_USB #endif
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 74/80 dm: usb: sandbox: Enable USB
Quoted 11 lines · Simon Glass
Enable USB emulation and associated features so that USB can be used in sandbox.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
configs/sandbox_defconfig | 4 ++++ include/configs/sandbox.h | 2 ++ 2 files changed, 6 insertions(+)
Applied to u-boot-dm/next.
PATCH v2 75/80 dm: test: Correct printf() output nit in 'dm uclass'
In reply to Simon GlassNeither the hyphen nor the equals sign is needed.
---
Changes in v2: None
test/dm/cmd_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
test/dm/cmd_dm.c +1 -1
@@ -79,7 +79,7 @@ static void dm_display_line(struct udevice *dev) dev->flags &DM_FLAG_ACTIVATED ?'*' :' ' , dev->name, (ulong)map_to_sysmem(dev));if (dev->seq !=-1 || dev->req_seq !=-1 ) -printf (", seq-%d, (req=%d)" , dev->seq, dev->req_seq); +printf (", seq %d, (req %d)" , dev->seq, dev->req_seq);puts ("\n" ); }
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 75/80 dm: test: Correct printf() output nit in 'dm uclass'
Quoted 9 lines · Simon Glass
Neither the hyphen nor the equals sign is needed.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
test/dm/cmd_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm/next.
PATCH v2 76/80 dm: test: Allow 'dm test' to select a particular test to run
In reply to Simon GlassAs well as running all tests, it is useful to be able to run a selected test.
---
Changes in v2: None
include/dm/test.h | 7 ++++--- test/dm/cmd_dm.c | 11 ++++++++--- test/dm/test-main.c | 7 +++++-- 3 files changed, 17 insertions(+), 8 deletions(-)
include/dm/test.h +4 -3
@@ -205,12 +205,13 @@ void dm_leak_check_start(struct dm_test_state *dms);/** -* dm_test_main() - Run all the tests +* dm_test_main() - Run all or one of the tests * -* This runs all available driver model tests +* This runs all available driver model tests, or a selected one * +* @test_name: Name of test to run, or NULL for all * @return 0 if OK, -ve on error */ -int dm_test_main (void ); +int dm_test_main (const char *test_name);#endif
test/dm/cmd_dm.c +8 -3
@@ -113,7 +113,12 @@ static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc,static int do_dm_test (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]) { -return dm_test_main (); +const char *test_name =NULL ; + +if (argc >0 ) + test_name = argv[0 ]; + +return dm_test_main (test_name); }#define TEST_HELP "\ndm test Run tests"#else
@@ -133,7 +138,7 @@ static int do_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])cmd_tbl_t *test_cmd;int ret; -if (argc !=2 ) +if (argc <2 )return CMD_RET_USAGE ; test_cmd =find_cmd_tbl (argv[1 ], test_commands,ARRAY_SIZE (test_commands));
@@ -148,7 +153,7 @@ static int do_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }U_BOOT_CMD ( - dm,2 ,1 , do_dm, + dm,3 ,1 , do_dm,"Driver model low level access" ,"tree Dump driver model tree ('*' = activated)\n" "dm uclass Dump list of instances for each uclass"
test/dm/test-main.c +5 -2
@@ -65,7 +65,7 @@ static int dm_test_destroy(struct dm_test_state *dms)return 0 ; } -int dm_test_main (void ) +int dm_test_main (const char *test_name) { struct dm_test *tests = ll_entry_start(struct dm_test, dm_test); const int n_ents = ll_entry_count(struct dm_test, dm_test);
@@ -83,9 +83,12 @@ int dm_test_main(void)ut_assert (gd->fdt_blob); } -printf ("Running %d driver model tests\n" , n_ents); +if (!test_name) +printf ("Running %d driver model tests\n" , n_ents);for (test = tests; test < tests + n_ents; test++) { +if (test_name &&strcmp (test_name, test->name)) +continue ;printf ("Test: %s\n" , test->name);ut_assertok (dm_test_init (dms));
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 76/80 dm: test: Allow 'dm test' to select a particular test to run
Quoted 11 lines · Simon Glass
As well as running all tests, it is useful to be able to run a selected test.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2: None
include/dm/test.h | 7 ++++--- test/dm/cmd_dm.c | 11 ++++++++--- test/dm/test-main.c | 7 +++++-- 3 files changed, 17 insertions(+), 8 deletions(-)
Applied to u-boot-dm/next.
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
In reply to Simon GlassThis adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
---
Changes in v2: None
test/dm/Makefile | 1 + test/dm/test-dm.sh | 3 +++ test/dm/test.dts | 41 +++++++++++++++++++++++++++++++++++++++++ test/dm/usb.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 test/dm/usb.c
test/dm/Makefile +1 -0
@@ -23,4 +23,5 @@ obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_DM_PCI) += pci.o obj-$(CONFIG_DM_SPI_FLASH) += sf.o obj-$(CONFIG_DM_SPI) += spi.o +obj-$(CONFIG_DM_USB) += usb.o endif
test/dm/test-dm.sh +3 -0
@@ -10,5 +10,8 @@ dtc -I dts -O dtb test/dm/test.dts -o test/dm/test.dtb make O=sandbox sandbox_config || die "Cannot configure U-Boot" make O=sandbox -s -j${NUM_CPUS} || die "Cannot build U-Boot" dd if=/dev/zero of=spi.bin bs=1M count=2 +echo -n "this is a test" > testflash.bin +dd if=/dev/zero bs=1M count=4 >>testflash.bin ./sandbox/u-boot -d test/dm/test.dtb -c "dm test" rm spi.bin +rm testflash.bin
test/dm/test.dts +41 -0
51 lines not on this page · raw message
test/dm/usb.c new file +50 -0
50 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Quoted 6 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>---
Quoted 8 lines
Changes in v2: None
test/dm/Makefile | 1 + test/dm/test-dm.sh | 3 +++ test/dm/test.dts | 41 +++++++++++++++++++++++++++++++++++++++++ test/dm/usb.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 test/dm/usb.c
Applied to u-boot-dm/next.
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
In reply to Simon GlassHi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>
I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
U-Boot 2015.04-00280-ge00cb22-dirty (Apr 21 2015 - 00:02:01)
DRAM: 128 MiB
Using default environment
In: serial Out: lcd Err: lcd Net: eth0: eth at 10002000, eth5: eth at 10003000, eth1: eth at 10004000
Running 53 driver model tests
Test: dm_test_autobind
Test: dm_test_autoprobe
Test: dm_test_bus_child_post_bind
Test: dm_test_bus_child_post_bind_uclass
Test: dm_test_bus_child_pre_probe_uclass
Test: dm_test_bus_children
Device 'c-test at 0': seq 0 is in use by 'd-test'
Device 'c-test at 1': seq 1 is in use by 'f-test'
Test: dm_test_bus_children_funcs
Test: dm_test_bus_children_iterators
Test: dm_test_bus_parent_data
Test: dm_test_bus_parent_data_uclass
Test: dm_test_bus_parent_ops
Test: dm_test_bus_parent_platdata
Test: dm_test_bus_parent_platdata_uclass
Test: dm_test_children
Test: dm_test_device_get_uclass_id
Test: dm_test_eth
Using eth at 10002000 device
Using eth at 10003000 device
Using eth at 10004000 device
Test: dm_test_eth_alias
Using eth at 10002000 device
Using eth at 10004000 device
Using eth at 10002000 device
Using eth at 10003000 device
Test: dm_test_eth_prime
Using eth at 10003000 device
Using eth at 10002000 device
Test: dm_test_eth_rotate
Error: eth at 10004000 address not set.
Error: eth at 10004000 address not set.
Using eth at 10002000 device
Error: eth at 10004000 address not set.
Error: eth at 10004000 address not set. Using eth at 10004000 device
Test: dm_test_fdt
Test: dm_test_fdt_offset
Test: dm_test_fdt_pre_reloc
Test: dm_test_fdt_uclass_seq
Test: dm_test_gpio
extra-gpios: get_value: error: gpio b5 not reserved
Test: dm_test_gpio_anon
Test: dm_test_gpio_copy
Test: dm_test_gpio_leak
extra-gpios: get_value: error: gpio b5 not reserved
Program received signal SIGSEGV, Segmentation fault.0x000009ec in ?? ()
(gdb) bt
#0 0x000009ec in ?? ()
#1 0x0806a0aa in uclass_destroy (uc=0xb5abd228) at /home/joe/u-boot/drivers/core/uclass.c:109
#2 0x080a29e1 in dm_leak_check_end (dms=0x8106870) at /home/joe/u-boot/test/dm/core.c:89
#3 0x080a46a6 in dm_test_gpio_leak (dms=0x8106870) at /home/joe/u-boot/test/dm/gpio.c:173
#4 0x080a0ed2 in dm_test_main (test_name=0x0) at /home/joe/u-boot/test/dm/test-main.c:103
#5 0x0809e9fb in do_dm (cmdtp=0x80c0250, flag=0, argc=135022648, argv=0xb5abbd40) at /home/joe/u-boot/test/dm/cmd_dm.c:150
#6 0x08065d6b in cmd_process (flag=0, argc=2, argv=0xb5abbd40, repeatable=0x80c5fc4, ticks=0x0) at /home/joe/u-boot/common/command.c:493
#7 0x0804d6fb in run_list_real (pi=0xb5abbc88) at /home/joe/u-boot/common/cli_hush.c:1656
#8 0x0804dce4 in parse_stream_outer (inp=0xbffff0e8, flag=2) at /home/joe/u-boot/common/cli_hush.c:2003
#9 0x0804df1d in parse_string_outer (s=0xbffff513 "dm test", flag=2) at /home/joe/u-boot/common/cli_hush.c:3248
#10 0x0804a855 in sandbox_main_loop_init () at /home/joe/u-boot/arch/sandbox/cpu/start.c:85
#11 0x0804e65b in run_main_loop () at /home/joe/u-boot/common/board_r.c:682 #12 0x0808f082 in initcall_run_list (init_sequence=0x80c1f68) at /home/joe/u-boot/lib/initcall.c:27
#13 0x0804e798 in board_init_r (new_gd=0xb5ab9f14, dest_addr=0) at /home/joe/u-boot/common/board_r.c:916
#14 0x0804a810 in main (argc=Cannot access memory at address 0x0 ) at /home/joe/u-boot/arch/sandbox/cpu/start.c:276
(gdb) f 1
#1 0x0806a0aa in uclass_destroy (uc=0xb5abd228) at /home/joe/u-boot/drivers/core/uclass.c:109
109 ret = device_unbind(dev);
(gdb) l -
99 int uclass_destroy(struct uclass *uc)
100 {
101 struct uclass_driver *uc_drv; 102 struct udevice *dev, *tmp; 103 int ret;
104
105 list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) {
106 ret = device_remove(dev);
107 if (ret)
108 return ret;
(gdb) l
109 ret = device_unbind(dev);
110 if (ret)
111 return ret;
112 }
113
114 uc_drv = uc->uc_drv;
115 if (uc_drv->destroy)
116 uc_drv->destroy(uc);
117 list_del(&uc->sibling_node);
118 if (uc_drv->priv_auto_alloc_size)
(gdb)
Thoughts?
-Joe
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Joe,
Quoted 135 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
U-Boot 2015.04-00280-ge00cb22-dirty (Apr 21 2015 - 00:02:01)
DRAM: 128 MiB
Using default environmentIn: serial Out: lcd Err: lcd Net: eth0: eth at 10002000, eth5: eth at 10003000, eth1: eth at 10004000Running 53 driver model tests
Test:dm_test_autobind
Test:dm_test_autoprobe
Test:dm_test_bus_child_post_bind
Test:dm_test_bus_child_post_bind_uclass
Test:dm_test_bus_child_pre_probe_uclass
Test:dm_test_bus_children
Device 'c-test at 0': seq 0 is in use by 'd-test'
Device 'c-test at 1': seq 1 is in use by 'f-test'
Test:dm_test_bus_children_funcs
Test:dm_test_bus_children_iterators
Test:dm_test_bus_parent_data
Test:dm_test_bus_parent_data_uclass
Test:dm_test_bus_parent_ops
Test:dm_test_bus_parent_platdata
Test:dm_test_bus_parent_platdata_uclass
Test:dm_test_children
Test:dm_test_device_get_uclass_id
Test:dm_test_eth
Using eth at 10002000 device
Using eth at 10003000 device
Using eth at 10004000 device
Test:dm_test_eth_alias
Using eth at 10002000 device
Using eth at 10004000 device
Using eth at 10002000 device
Using eth at 10003000 device
Test:dm_test_eth_prime
Using eth at 10003000 device
Using eth at 10002000 device
Test:dm_test_eth_rotateError: eth at 10004000 address not set.
Error: eth at 10004000 address not set.
Using eth at 10002000 deviceError: eth at 10004000 address not set.
Error: eth at 10004000 address not set. Using eth at 10004000 device
Test:dm_test_fdt
Test:dm_test_fdt_offset
Test:dm_test_fdt_pre_reloc
Test:dm_test_fdt_uclass_seq
Test:dm_test_gpio
extra-gpios:get_value: error: gpio b5 not reserved
Test:dm_test_gpio_anon
Test:dm_test_gpio_copy
Test:dm_test_gpio_leak
extra-gpios:get_value: error: gpio b5 not reservedProgram received signal SIGSEGV, Segmentation fault.
0x000009ecin ?? ()
(gdb) bt
#00x000009ecin ?? ()
#10x0806a0aainuclass_destroy(uc=0xb5abd228) at/home/joe/u-boot/drivers/core/uclass.c:109
#20x080a29e1indm_leak_check_end(dms=0x8106870) at/home/joe/u-boot/test/dm/core.c:89
#30x080a46a6indm_test_gpio_leak(dms=0x8106870) at/home/joe/u-boot/test/dm/gpio.c:173
#40x080a0ed2indm_test_main(test_name=0x0) at/home/joe/u-boot/test/dm/test-main.c:103
#50x0809e9fbindo_dm(cmdtp=0x80c0250, flag=0, argc=135022648, argv=0xb5abbd40) at/home/joe/u-boot/test/dm/cmd_dm.c:150
#60x08065d6bincmd_process(flag=0, argc=2, argv=0xb5abbd40, repeatable=0x80c5fc4, ticks=0x0) at/home/joe/u-boot/common/command.c:493
#70x0804d6fbinrun_list_real(pi=0xb5abbc88) at/home/joe/u-boot/common/cli_hush.c:1656
#80x0804dce4inparse_stream_outer(inp=0xbffff0e8, flag=2) at/home/joe/u-boot/common/cli_hush.c:2003
#90x0804df1dinparse_string_outer(s=0xbffff513 "dm test", flag=2) at/home/joe/u-boot/common/cli_hush.c:3248
#100x0804a855insandbox_main_loop_init() at/home/joe/u-boot/arch/sandbox/cpu/start.c:85
#110x0804e65binrun_main_loop() at/home/joe/u-boot/common/board_r.c:682#120x0808f082ininitcall_run_list(init_sequence=0x80c1f68) at/home/joe/u-boot/lib/initcall.c:27
#130x0804e798inboard_init_r(new_gd=0xb5ab9f14, dest_addr=0) at/home/joe/u-boot/common/board_r.c:916
#140x0804a810in main (argc=Cannot access memory at address0x0) at/home/joe/u-boot/arch/sandbox/cpu/start.c:276
(gdb) f 1
#10x0806a0aainuclass_destroy(uc=0xb5abd228) at/home/joe/u-boot/drivers/core/uclass.c:109
109 ret =device_unbind(dev);
(gdb) l -
99 intuclass_destroy(struct uclass *uc)
100 {101 struct uclass_driver *uc_drv; 102 struct udevice *dev, *tmp; 103 int ret;104
105list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node){
106 ret =device_remove(dev);
107 if (ret)
108 return ret;
(gdb) l
109 ret =device_unbind(dev);
110 if (ret)
111 return ret;
112 }
113
114uc_drv=uc->uc_drv;
115 if (uc_drv->destroy)
116uc_drv->destroy(uc);
117list_del(&uc->sibling_node);
118 if (uc_drv->priv_auto_alloc_size)
(gdb)
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
Regards,
Simon
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Simon,
Quoted 14 lines · Simon Glass
Hi Joe,
Quoted 11 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
<--snip-->
Quoted 8 lines
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
I tested the series, but I still have a USB test failure...
"""
Test: dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found/home/joe/u-boot/test/dm/usb.c:45, dm_test_usb_flash(): 2 == dev_desc->block_read(dev_desc->dev, 0, 2, cmp): Expected 2, got 0 """
Have you seen that one?
Thanks,
-Joe
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Joe,
Quoted 32 lines · Joe Hershberger
Hi Simon,
Quoted 14 lines · Simon Glass
Hi Joe,
Quoted 11 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
<--snip-->
Quoted 8 lines
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
I tested the series, but I still have a USB test failure...
Quoted 8 lines
"""
Test:dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found/home/joe/u-boot/test/dm/usb.c:45,dm_test_usb_flash(): 2 ==dev_desc->block_read(dev_desc->dev, 0, 2, cmp): Expected 2, got 0 """Have you seen that one?
No I don't see that. It is saying that it was not able to read 2 512-byte blocks from the testflash.bin file. It should be created by the test script. I just tried it again.
BTW I'd like to get a sandbox network device that works in a purely emulated way (i.e. without any reference to real hardware). Then we could use it for ping tests, etc. and they would run instantly. At present the network tests are quite slow. What do you think?
Regards,
Simon
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Simon,
Quoted 42 lines · Simon Glass
Hi Joe,
Quoted 39 lines · Joe Hershberger
Hi Simon,
Quoted 14 lines · Simon Glass
Hi Joe,
Quoted 11 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
<--snip-->
Quoted 8 lines
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
I tested the series, but I still have a USB test failure...
"""
Test:dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found/home/joe/u-boot/test/dm/usb.c:45,dm_test_usb_flash(): 2 ==dev_desc->block_read(dev_desc->dev, 0, 2, cmp): Expected 2, got 0 """
Quoted 5 lines
Quoted 1 line
Have you seen that one?
No I don't see that. It is saying that it was not able to read 2 512-byte blocks from the testflash.bin file. It should be created by the test script. I just tried it again.
That makes sense... I wasn't creating that file. D'oh! Working for me now too.
Quoted 4 lines
BTW I'd like to get a sandbox network device that works in a purely emulated way (i.e. without any reference to real hardware). Then we could use it for ping tests, etc. and they would run instantly. At present the network tests are quite slow. What do you think?
The tests are all using fully emulated Ethernet... the issue is that the ping test ensures that on timeout an error is returned. Even though it is an emulated MAC, the timeout in the network stack is still there.
I'll work on a patch that adds a way to change the ping timeout to make this faster.
Cheers,
-Joe
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Joe,
Quoted 58 lines · Joe Hershberger
Hi Simon,
Quoted 42 lines · Simon Glass
Hi Joe,
Quoted 39 lines · Joe Hershberger
Hi Simon,
Quoted 14 lines · Simon Glass
Hi Joe,
Quoted 11 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
<--snip-->
Quoted 8 lines
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
I tested the series, but I still have a USB test failure...
"""
Test:dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found/home/joe/u-boot/test/dm/usb.c:45,dm_test_usb_flash(): 2 ==dev_desc->block_read(dev_desc->dev, 0, 2, cmp): Expected 2, got 0 """Quoted 5 lines
Quoted 1 line
Have you seen that one?
No I don't see that. It is saying that it was not able to read 2 512-byte blocks from the testflash.bin file. It should be created by the test script. I just tried it again.
That makes sense... I wasn't creating that file. D'oh! Working for me now too.
Quoted 4 lines
BTW I'd like to get a sandbox network device that works in a purely emulated way (i.e. without any reference to real hardware). Then we could use it for ping tests, etc. and they would run instantly. At present the network tests are quite slow. What do you think?
Quoted 7 lines
The tests are all using fully emulated Ethernet... the issue is that the ping test ensures that on timeout an error is returned. Even though it is an emulated MAC, the timeout in the network stack is still there.
I'll work on a patch that adds a way to change the ping timeout to make this faster.
OK thanks for explaining this. Rather than changing the ping timeout, can you look at changing the time? With sandbox it should be possible to adjust the time so that timeouts appear to happen instantly. The arch/sandbox/include/test.h file has some test functions used by various parts of the stack.
Regards,
Simon
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Simon,
Quoted 66 lines · Simon Glass
Hi Joe,
Quoted 63 lines · Joe Hershberger
Hi Simon,
Quoted 42 lines · Simon Glass
Hi Joe,
Quoted 39 lines · Joe Hershberger
Hi Simon,
Quoted 14 lines · Simon Glass
Hi Joe,
Quoted 11 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
<--snip-->
Quoted 8 lines
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
I tested the series, but I still have a USB test failure...
"""
Test:dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found/home/joe/u-boot/test/dm/usb.c:45,dm_test_usb_flash(): 2 ==dev_desc->block_read(dev_desc->dev, 0, 2, cmp): Expected 2, got 0 """Quoted 5 lines
Quoted 1 line
Have you seen that one?
No I don't see that. It is saying that it was not able to read 2 512-byte blocks from the testflash.bin file. It should be created by the test script. I just tried it again.
That makes sense... I wasn't creating that file. D'oh! Working for me now too.
Quoted 4 lines
BTW I'd like to get a sandbox network device that works in a purely emulated way (i.e. without any reference to real hardware). Then we could use it for ping tests, etc. and they would run instantly. At present the network tests are quite slow. What do you think?
The tests are all using fully emulated Ethernet... the issue is that the ping test ensures that on timeout an error is returned. Even though it is an emulated MAC, the timeout in the network stack is still there.
Quoted 8 lines
Quoted 2 lines
I'll work on a patch that adds a way to change the ping timeout to make this faster.
OK thanks for explaining this. Rather than changing the ping timeout, can you look at changing the time? With sandbox it should be possible to adjust the time so that timeouts appear to happen instantly. The
arch/sandbox/include/test.hfile has some test functions used by various parts of the stack.
I posted a series that handles the issue as you recommended and called it "test: Speed up test timeouts by advancing time".
I now notice that the only test that takes any time is the USB Flash test.
"""
Test: dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found
"""
It takes about 3 seconds. Is that a timeout too?
Thanks,
-Joe
PATCH v2 77/80 dm: usb: Add tests for the USB uclass
Hi Joe,
Quoted 72 lines · Joe Hershberger
Hi Simon,
Quoted 69 lines · Simon Glass
Hi Joe,
Quoted 65 lines · Joe Hershberger
Hi Simon,
Quoted 42 lines · Simon Glass
Hi Joe,
Quoted 39 lines · Joe Hershberger
Hi Simon,
Quoted 14 lines · Simon Glass
Hi Joe,
Quoted 11 lines · Joe Hershberger
Hi Simon,
Quoted 4 lines · Simon Glass
This adds a simple test for probing and a functional test using the flash stick emulator, which tests a large chunk of the USB stack.
Signed-off-by Simon Glass <[email protected]>I'm seeing a seg fault when running the dm tests and bisected it to this patch.
I'm not sure why it's related, but it appears to seg fault on a GPIO test...
<--snip-->
Quoted 8 lines
Quoted 1 line
Thoughts?
Yes it is broken. I sent a series to fix this recent ('dm: core: Fix up test failures') starting with this patch:
http://patchwork.ozlabs.org/patch/462556/
If you are able to test it that would be good.
I tested the series, but I still have a USB test failure...
"""
Test:dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found/home/joe/u-boot/test/dm/usb.c:45,dm_test_usb_flash(): 2 ==dev_desc->block_read(dev_desc->dev, 0, 2, cmp): Expected 2, got 0 """Quoted 5 lines
Quoted 1 line
Have you seen that one?
No I don't see that. It is saying that it was not able to read 2 512-byte blocks from the testflash.bin file. It should be created by the test script. I just tried it again.
That makes sense... I wasn't creating that file. D'oh! Working for me now too.
Quoted 4 lines
BTW I'd like to get a sandbox network device that works in a purely emulated way (i.e. without any reference to real hardware). Then we could use it for ping tests, etc. and they would run instantly. At present the network tests are quite slow. What do you think?
The tests are all using fully emulated Ethernet... the issue is that the ping test ensures that on timeout an error is returned. Even though it is an emulated MAC, the timeout in the network stack is still there.
I'll work on a patch that adds a way to change the ping timeout to make this faster.
Quoted 8 lines
Quoted 5 lines
OK thanks for explaining this. Rather than changing the ping timeout, can you look at changing the time? With sandbox it should be possible to adjust the time so that timeouts appear to happen instantly. The
arch/sandbox/include/test.hfile has some test functions used by various parts of the stack.I posted a series that handles the issue as you recommended and called it "test: Speed up test timeouts by advancing time".
I see it. This is great, thank you!
Quoted 9 lines
I now notice that the only test that takes any time is the USB Flash test.
"""
Test:dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found
"""It takes about 3 seconds. Is that a timeout too?
Yes. I'll take a look at how you have advanced time - we should do this for USB too.
Regards,
Simon
PATCH v2 78/80 dm: usb: tegra: Drop legacy USB code
In reply to Simon GlassDrop the code that doesn't use driver model for USB.
---
Changes in v2: None
board/nvidia/common/board.c | 3 - drivers/usb/host/ehci-tegra.c | 150 ------------------------------------------ include/fdtdec.h | 3 - lib/fdtdec.c | 3 - 4 files changed, 159 deletions(-)
board/nvidia/common/board.c +0 -3
@@ -128,9 +128,6 @@ int board_init(void)#ifdef CONFIG_USB_EHCI_TEGRA pin_mux_usb (); -#ifndef CONFIG_DM_USB -usb_process_devicetree (gd->fdt_blob); -#endif #endif #ifdef CONFIG_LCD
drivers/usb/host/ehci-tegra.c +0 -150
203 lines not on this page · raw message
include/fdtdec.h +0 -3
@@ -112,9 +112,6 @@ static inline fdt_size_t fdt_resource_size(const struct fdt_resource *res)*/ enum fdt_compat_id {COMPAT_UNKNOWN , -COMPAT_NVIDIA_TEGRA20_USB ,/* Tegra20 USB port */ -COMPAT_NVIDIA_TEGRA30_USB ,/* Tegra30 USB port */ -COMPAT_NVIDIA_TEGRA114_USB ,/* Tegra114 USB port */ COMPAT_NVIDIA_TEGRA20_EMC ,/* Tegra20 memory controller */ COMPAT_NVIDIA_TEGRA20_EMC_TABLE ,/* Tegra20 memory timing table */ COMPAT_NVIDIA_TEGRA20_KBC ,/* Tegra20 Keyboard */
lib/fdtdec.c +0 -3
@@ -21,9 +21,6 @@ DECLARE_GLOBAL_DATA_PTR;#define COMPAT (id, name) namestatic const char *const compat_names[COMPAT_COUNT ] = {COMPAT (UNKNOWN ,"<none>" ), -COMPAT (NVIDIA_TEGRA20_USB ,"nvidia,tegra20-ehci" ), -COMPAT (NVIDIA_TEGRA30_USB ,"nvidia,tegra30-ehci" ), -COMPAT (NVIDIA_TEGRA114_USB ,"nvidia,tegra114-ehci" ),COMPAT (NVIDIA_TEGRA20_EMC ,"nvidia,tegra20-emc" ),COMPAT (NVIDIA_TEGRA20_EMC_TABLE ,"nvidia,tegra20-emc-table" ),COMPAT (NVIDIA_TEGRA20_KBC ,"nvidia,tegra20-kbc" ),
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 78/80 dm: usb: tegra: Drop legacy USB code
Quoted 5 lines · Simon Glass
Drop the code that doesn't use driver model for USB.
Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
board/nvidia/common/board.c | 3 - drivers/usb/host/ehci-tegra.c | 150 ------------------------------------------ include/fdtdec.h | 3 - lib/fdtdec.c | 3 - 4 files changed, 159 deletions(-)
Applied to u-boot-dm.
PATCH v2 79/80 dm: usb: exynos: Drop legacy USB code
In reply to Simon GlassDrop the code that doesn't use driver model for USB.
---
Changes in v2: None
drivers/usb/host/ehci-exynos.c | 117 ---------------------------------------- drivers/usb/host/xhci-exynos5.c | 108 ------------------------------------- include/fdtdec.h | 2 - lib/fdtdec.c | 2 - 4 files changed, 229 deletions(-)
drivers/usb/host/ehci-exynos.c +0 -117
@@ -25,14 +25,12 @@/* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR ; -#ifdef CONFIG_DM_USB struct exynos_ehci_platdata {struct usb_platdata usb_plat;fdt_addr_t hcd_base;fdt_addr_t phy_base;struct gpio_desc vbus_gpio; }; -#endif /** * Contains pointers to register base addresses
@@ -42,16 +40,8 @@ struct exynos_ehci {struct ehci_ctrl ctrl;struct exynos_usb_phy *usb;struct ehci_hccr *hcd; -#ifndef CONFIG_DM_USB -struct gpio_desc vbus_gpio; -#endif }; -#ifndef CONFIG_DM_USB -static struct exynos_ehci exynos; -#endif - -#ifdef CONFIG_DM_USB static int ehci_usb_ofdata_to_platdata (struct udevice *dev) {struct exynos_ehci_platdata *plat =dev_get_platdata (dev);
@@ -91,55 +81,6 @@ static int ehci_usb_ofdata_to_platdata(struct udevice *dev)return 0 ; } -#else -static int exynos_usb_parse_dt (const void *blob,struct exynos_ehci *exynos) -{ -fdt_addr_t addr; -unsigned int node; -int depth; - - node =fdtdec_next_compatible (blob,0 ,COMPAT_SAMSUNG_EXYNOS_EHCI ); -if (node <=0 ) { -debug ("EHCI: Can't get device node for ehci\n" ); -return -ENODEV ; - } - -/* -* Get the base address for EHCI controller from the device node -*/ - addr =fdtdec_get_addr (blob, node,"reg" ); -if (addr ==FDT_ADDR_T_NONE ) { -debug ("Can't get the EHCI register address\n" ); -return -ENXIO ; - } - - exynos->hcd = (struct ehci_hccr *)addr; - -/* Vbus gpio */ -gpio_request_by_name_nodev (blob, node,"samsung,vbus-gpio" ,0 , - &exynos->vbus_gpio,GPIOD_IS_OUT ); - - depth =0 ; - node =fdtdec_next_compatible_subnode (blob, node, -COMPAT_SAMSUNG_EXYNOS_USB_PHY , &depth); -if (node <=0 ) { -debug ("EHCI: Can't get device node for usb-phy controller\n" ); -return -ENODEV ; - } - -/* -* Get the base address for usbphy from the device node -*/ - exynos->usb = (struct exynos_usb_phy *)fdtdec_get_addr (blob, node, -"reg" ); -if (exynos->usb ==NULL ) { -debug ("Can't get the usbphy register address\n" ); -return -ENXIO ; - } - -return 0 ; -} -#endif static void exynos5_setup_usb_phy (struct exynos_usb_phy *usb) {
@@ -270,63 +211,6 @@ static void reset_usb_phy(struct exynos_usb_phy *usb)set_usbhost_phy_ctrl (POWER_USB_HOST_PHY_CTRL_DISABLE ); } -#ifndef CONFIG_DM_USB -/* -* EHCI-initialization -* Create the appropriate control structures to manage -* a new EHCI host controller. -*/ -int ehci_hcd_init (int index,enum usb_init_type init, -struct ehci_hccr **hccr,struct ehci_hcor **hcor) -{ -struct exynos_ehci *ctx = &exynos; - -#ifdef CONFIG_OF_CONTROL -if (exynos_usb_parse_dt (gd->fdt_blob, ctx)) { -debug ("Unable to parse device tree for ehci-exynos\n" ); -return -ENODEV ; - } -#else - ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy (); - ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci (); -#endif - -#ifdef CONFIG_OF_CONTROL -/* setup the Vbus gpio here */ -if (dm_gpio_is_valid (&ctx->vbus_gpio)) -dm_gpio_set_value (&ctx->vbus_gpio,1 ); -#endif - -setup_usb_phy (ctx->usb); - -board_usb_init (index, init); - - *hccr = ctx->hcd; - *hcor = (struct ehci_hcor *)((uint32_t ) *hccr - +HC_LENGTH (ehci_readl (&(*hccr)->cr_capbase))); - -debug ("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n" , - (uint32_t )*hccr, (uint32_t )*hcor, - (uint32_t )HC_LENGTH (ehci_readl (&(*hccr)->cr_capbase))); - -return 0 ; -} - -/* -* Destroy the appropriate control structures corresponding -* the EHCI host controller. -*/ -int ehci_hcd_stop (int index) -{ -struct exynos_ehci *ctx = &exynos; - -reset_usb_phy (ctx->usb); - -return 0 ; -} -#endif - -#ifdef CONFIG_DM_USB static int ehci_usb_probe (struct udevice *dev) {struct exynos_ehci_platdata *plat =dev_get_platdata (dev);
@@ -377,4 +261,3 @@ U_BOOT_DRIVER(usb_ehci) = { .platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; -#endif
drivers/usb/host/xhci-exynos5.c +0 -108
147 lines not on this page · raw message
include/fdtdec.h +0 -2
@@ -133,8 +133,6 @@ enum fdt_compat_id {COMPAT_WOLFSON_WM8994_CODEC ,/* Wolfson WM8994 Sound Codec */ COMPAT_GOOGLE_CROS_EC ,/* Google CROS_EC Protocol */ COMPAT_GOOGLE_CROS_EC_KEYB ,/* Google CROS_EC Keyboard */ -COMPAT_SAMSUNG_EXYNOS_EHCI ,/* Exynos EHCI controller */ -COMPAT_SAMSUNG_EXYNOS5_XHCI ,/* Exynos5 XHCI controller */ COMPAT_SAMSUNG_EXYNOS_USB_PHY ,/* Exynos phy controller for usb2.0 */ COMPAT_SAMSUNG_EXYNOS5_USB3_PHY ,/* Exynos phy controller for usb3.0 */ COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */
lib/fdtdec.c +0 -2
@@ -41,8 +41,6 @@ static const char * const compat_names[COMPAT_COUNT] = {COMPAT (WOLFSON_WM8994_CODEC ,"wolfson,wm8994-codec" ),COMPAT (GOOGLE_CROS_EC ,"google,cros-ec" ),COMPAT (GOOGLE_CROS_EC_KEYB ,"google,cros-ec-keyb" ), -COMPAT (SAMSUNG_EXYNOS_EHCI ,"samsung,exynos-ehci" ), -COMPAT (SAMSUNG_EXYNOS5_XHCI ,"samsung,exynos5250-xhci" ),COMPAT (SAMSUNG_EXYNOS_USB_PHY ,"samsung,exynos-usb-phy" ),COMPAT (SAMSUNG_EXYNOS5_USB3_PHY ,"samsung,exynos5250-usb3-phy" ), COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 79/80 dm: usb: exynos: Drop legacy USB code
Quoted 5 lines · Simon Glass
Drop the code that doesn't use driver model for USB.
Signed-off-by Simon Glass <[email protected]>---
Quoted 7 lines
Changes in v2: None
drivers/usb/host/ehci-exynos.c | 117 ---------------------------------------- drivers/usb/host/xhci-exynos5.c | 108 ------------------------------------- include/fdtdec.h | 2 - lib/fdtdec.c | 2 - 4 files changed, 229 deletions(-)
Applied to u-boot-dm.
PATCH v2 80/80 dm: usb: Add a README for driver model
In reply to Simon GlassAdd some documentation describing how USB is implemented with USB. This might make things easier for people to understand.
---
Changes in v2:
- Rewrite and expand series to support driver model fully
doc/driver-model/usb-info.txt | 415 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 doc/driver-model/usb-info.txt
doc/driver-model/usb-info.txt new file +415 -0
@@ -0,0 +1,415 @@ +How USB works with driver model +=============================== + +Introduction +------------ + +Driver model USB support makes use of existing features but changes how +drivers are found. This document provides some information intended to help +understand how things work with USB in U-Boot when driver model is enabled. + + +Enabling driver model for USB +----------------------------- + +A new CONFIG_DM_USB option is provided to enable driver model for USB. This +causes the USB uclass to be included, and drops the equivalent code in +usb.c. In particular the usb_init() function is then implemented by the +uclass. + + +Support for ECHI and XCHI +------------------------- + +So far OHCI is not supported. Both EHCI and XHCI drivers should be declared +as drivers in the USB uclass. For example: + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 }, + { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 }, + { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 }, + { } +}; + +U_BOOT_DRIVER(usb_ehci) = { + .name = "ehci_tegra", + .id = UCLASS_USB, + .of_match = ehci_usb_ids, + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .probe = tegra_ehci_usb_probe, + .remove = tegra_ehci_usb_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct fdt_usb), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; + +Here ehci_usb_ids is used to list the controllers that the driver supports. +Each has its own data value. Controllers must be in the UCLASS_USB uclass. + +The ofdata_to_platdata() method allows the controller driver to grab any +necessary settings from the device tree. + +The ops here are ehci_usb_ops. All EHCI drivers will use these same ops in +most cases, since they are all ECHI-compatible. For ECHI there are also some +special operations that can be overriden when calling ehci_register(). + +The driver can use priv_auto_alloc_size to set the size of its private data. +This can hold run-time information needed by the driver for operation. It +exists when the device is probed (not when it is bound) and is removed when +the driver is removed. + +Note that usb_platdata is currently only used to deal with setting up a bus +in USB device mode (OTG operation). It can be omitted if that is not +supported. + +The driver's probe() method should do the basic controller init and then +call ehci_register() to register itself as an EHCI device. It should call +ehci_deregister() in the remove() method. Registering a new EHCI device +does not by itself cause the bus to be scanned. + +The old ehci_hcd_init() function is no-longer used. Nor is it necessary to +set up the USB controllers from board init code. When 'usb start' is used, +each controller will be probed and its bus scanned. + +XHCI works in a similar way. + + +Data structures +--------------- + +The following primary data structures are in use: + +- struct usb_device + This holds information about a device on the bus. All devices have + this structure, even the root hub. The controller itself does not + have this structure. You can access it for a device 'dev' with + dev_get_parentdata(dev). It matches the old structure except that the + parent and child information is not present (since driver model + handles that). Once the device is set up, you can find the device + descriptor and current configuration descriptor in this structure. + +- struct usb_platdata + This holds platform data for a controller. So far this is only used + as a work-around for controllers which can act as USB devices in OTG + mode, since the gadget framework does not use driver model. + +- struct usb_dev_platdata + This holds platform data for a device. You can access it for a + device 'dev' with dev_get_parent_platdata(dev). It holds the device + address and speed - anything that can be determined before the device + driver is actually set up. When probing the bus this structure is + used to provide essential information to the device driver. + +- struct usb_bus_priv + This is private information for each controller, maintained by the + controller uclass. It is mostly used to keep track of the next + device address to use. + +Of these, only struct usb_device was used prior to driver model. + + +USB buses +--------- + +Given a controller, you know the bus - it is the one attached to the +controller. Each controller handles exactly one bus. Every controller has a +root hub attached to it. This hub, which is itself a USB device, can provide +one or more 'ports' to which additional devices can be attached. It is +possible to power up a hub and find out which of its ports have devices +attached. + +Devices are given addresses starting at 1. The root hub is always address 1, +and from there the devices are numbered in sequence. The USB uclass takes +care of this numbering automatically during enumeration. + +USB devices are enumerated by finding a device on a particular hub, and +setting its address to the next available address. The USB bus stretches out +in a tree structure, potentially with multiple hubs each with several ports +and perhaps other hubs. Some hubs will have their own power since otherwise +the 5V 500mA power supplied by the controller will not be sufficient to run +very many devices. + +Enumeration in U-Boot takes a long time since devices are probed one at a +time, and each is given sufficient time to wake up and announce itself. The +timeouts are set for the slowest device. + +Up to 127 devices can be on each bus. USB has four bus speeds: low +(1.5Mbps), full (12Mbps), high (480Mbps) which is only available with USB2 +and newer (EHCI), and super (5Gbps) which is only available with USB3 and +newer (XHCI). If you connect a super-speed device to a high-speed hub, you +will only get high-speed. + + +USB operations +-------------- + +As before driver model, messages can be sent using submit_bulk_msg() and the +like. These are now implemented by the USB uclass and route through the +controller drivers. Note that messages are not sent to the driver of the +device itself - i.e. they don't pass down the stack to the controller. +U-Boot simply finds the controller to which the device is attached, and sends +the message there with an appropriate 'pipe' value so it can be addressed +properly. Having said that, the USB device which should receive the message +is passed in to the driver methods, for use by sandbox. This design decision +is open for review and the code impact of changing it is small since the +methods are typically implemented by the EHCI and XHCI stacks. + +Controller drivers (in UCLASS_USB) themselves provide methods for sending +each message type. For XHCI an additional alloc_device() method is provided +since XHCI needs to allocate a device context before it can even read the +device's descriptor. + +These methods use a 'pipe' which is a collection of bit fields used to +describe the type of message, direction of transfer and the intended +recipient (device number). + + +USB Devices +----------- + +USB devices are found using a simple algorithm which works through the +available hubs in a depth-first search. Devices can be in any uclass, but +are attached to a parent hub (or controller in the case of the root hub) and +so have parent data attached to them (this is struct usb_device). + +By the time the device's probe() method is called, it is enumerated and is +ready to talk to the host. + +The enumeration process needs to work out which driver to attach to each USB +device. It does this by examining the device class, interface class, vendor +ID, product ID, etc. See struct usb_driver_entry for how drivers are matched +with USB devices - you can use the USB_DEVICE() macro to declare a USB +driver. For example, usb_storage.c defines a USB_DEVICE() to handle storage +devices, and it will be used for all USB devices which match. + + + +Technical details on enumeration flow +------------------------------------- + +It is useful to understand precisely how a USB bus is enumerating to avoid +confusion when dealing with USB devices. + +Device initialisation happens roughly like this: + +- At some point the 'usb start' command is run +- This calls usb_init() which works through each controller in turn +- The controller is probed(). This does no enumeration. +- Then usb_scan_bus() is called. This calls usb_scan_device() to scan the +(only) device that is attached to the controller - a root hub +- usb_scan_device() sets up a fake struct usb_device and calls +usb_setup_device(), passing the port number to be scanned, in this case port +0 +- usb_setup_device() first calls usb_prepare_device() to set the device +address, then usb_select_config() to select the first configuration +- at this point the device is enumerated but we do not have a real struct +udevice for it. But we do have the descriptor in struct usb_device so we can +use this to figure out what driver to use +- back in usb_scan_device(), we call usb_find_child() to try to find an +existing device which matches the one we just found on the bus. This can +happen if the device is mentioned in the device tree, or if we previously +scanned the bus and so the device was created before +- if usb_find_child() does not find an existing device, we call +usb_find_and_bind_driver() which tries to bind one +- usb_find_and_bind_driver() searches all available USB drivers (declared +with USB_DEVICE()). If it finds a match it binds that driver to create a new +device. +- If it does not, it binds a generic driver. A generic driver is good enough +to allow access to the device (sending it packets, etc.) but all +functionality will need to be implemented outside the driver model. +- in any case, when usb_find_child() and/or usb_find_and_bind_driver() are +done, we have a device with the correct uclass. At this point we want to +probe the device +- first we store basic information about the new device (address, port, +speed) in its parent platform data. We cannot store it its private data +since that will not exist until the device is probed. +- then we call device_probe() which probes the device +- the first probe step is actually the USB controller's (or USB hubs's) +child_pre_probe() method. This gets called before anything else and is +intended to set up a child device ready to be used with its parent bus. For +USB this calls usb_child_pre_probe() which grabs the information that was +stored in the parent platform data and stores it in the parent private data +(which is struct usb_device, a real one this time). It then calls +usb_select_config() again to make sure that everything about the device is +set up +- note that we have called usb_select_config() twice. This is inefficient +but the alternative is to store additional information in the platform data. +The time taken is minimal and this way is simpler +- at this point the device is set up and ready for use so far as the USB +subsystem is concerned +- the device's probe() method is then called. It can send messages and do +whatever else it wants to make the device work. + +Note that the first device is always a root hub, and this must be scanned to +find any devices. The above steps will have created a hub (UCLASS_USB_HUB), +given it address 1 and set the configuration. + +For hubs, the hub uclass has a post_probe() method. This means that after +any hub is probed, the uclass gets to do some processing. In this case +usb_hub_post_probe() is called, and the following steps take place: + +- usb_hub_post_probe() calls usb_hub_scan() to scan the hub, which in turn +calls usb_hub_configure() +- hub power is enabled +- we loop through each port on the hub, performing the same steps for each +- first, check if there is a device present. This happens in +usb_hub_port_connect_change(). If so, then usb_scan_device() is called to +scan the device, passing the appropriate port number. +- you will recognise usb_scan_device() from the steps above. It sets up the +device ready for use. If it is a hub, it will scan that hub before it +continues here (recursively, depth-first) +- once all hub ports are scanned in this way, the hub is ready for use and +all of its downstream devices also +- additional controllers are scanned in the same way + +The above method has some nice properties: + +- the bus enumeration happens by virtue of driver model's natural device flow +- most logic is in the USB controller and hub uclasses; the actual device +drivers do not need to know they are on a USB bus, at least so far as +enumeration goes +- hub scanning happens automatically after a hub is probed + + +Hubs +---- + +USB hubs are scanned as in the section above. While hubs have their own +uclass, they share some common elements with controllers: + +- they both attach private data to their children (struct usb_device, +accessible for a child with dev_get_parentdata(child)) +- they both use usb_child_pre_probe() to set up their children as proper USB +devices + + +Example - Mass Storage +---------------------- + +As an example of a USB device driver, see usb_storage.c. It uses its own +uclass and declares itself as follows: + +U_BOOT_DRIVER(usb_mass_storage) = { + .name = "usb_mass_storage", + .id = UCLASS_MASS_STORAGE, + .of_match = usb_mass_storage_ids, + .probe = usb_mass_storage_probe, +}; + +static const struct usb_device_id mass_storage_id_table[] = { + { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, + .bInterfaceClass = USB_CLASS_MASS_STORAGE}, + { } /* Terminating entry */ +}; + +USB_DEVICE(usb_mass_storage, mass_storage_id_table); + +The USB_DEVICE() macro attaches the given table of matching information to +the given driver. Note that the driver is declared in U_BOOT_DRIVER() as +'usb_mass_storage' and this must match the first parameter of USB_DEVICE. + +When usb_find_and_bind_driver() is called on a USB device with the +bInterfaceClass value of USB_CLASS_MASS_STORAGE, it will automatically find +this driver and use it. + + +Counter-example: USB Ethernet +----------------------------- + +As an example of the old way of doing things, see usb_ether.c. When the bus +is scanned, all Ethernet devices will be created as generic USB devices (in +uclass UCLASS_USB_DEV_GENERIC). Then, when the scan is completed, +usb_host_eth_scan() will be called. This looks through all the devices on +each bus and manually figures out which are Ethernet devices in the ways of +yore. + +In fact, usb_ether should be moved to driver model. Each USB Ethernet driver +(e.g drivers/usb/eth/asix.c) should include a USB_DEVICE() declaration, so +that it will be found as part of normal USB enumeration. Then, instead of a +generic USB driver, a real (driver-model-aware) driver will be used. Since +Ethernet now supports driver model, this should be fairly easy to achieve, +and then usb_ether.c and the usb_host_eth_scan() will melt away. + + +Sandbox +------- + +All driver model uclasses must have tests and USB is no exception. To +achieve this, a sandbox USB controller is provided. This can make use of +emulation drivers which pretend to be USB devices. Emulations are provided +for a hub and a flash stick. These are enough to create a pretend USB bus +(defined by the sandbox device tree sandbox.dts) which can be scanned and +used. + +Tests in test/dm/usb.c make use of this feature. It allows much of the USB +stack to be tested without real hardware being needed. + +Here is an example device tree fragment: + + usb at 1 { + compatible = "sandbox,usb"; + hub { + compatible = "usb-hub"; + usb,device-class = <USB_CLASS_HUB>; + hub-emul { + compatible = "sandbox,usb-hub"; + #address-cells = <1>; + #size-cells = <0>; + flash-stick { + reg = <0>; + compatible = "sandbox,usb-flash"; + sandbox,filepath = "flash.bin"; + }; + }; + }; + }; + +This defines a single controller, containing a root hub (which is required). +The hub is emulated by a hub emulator, and the emulated hub has a single +flash stick to emulate on one of its ports. + +When 'usb start' is used, the following 'dm tree' output will be available: + + usb [ + ] `-- usb at 1 + usb_hub [ + ] `-- hub + usb_emul [ + ] |-- hub-emul + usb_emul [ + ] | `-- flash-stick + usb_mass_st [ + ] `-- usb_mass_storage + + +This may look a confusing. Most of it mirrors the device tree, but the +'usb_mass_storage' device is not in the device tree. This is created by +usb_find_and_bind_driver() based on the USB_DRIVER in usb_storage.c. While +'flash-stick' is the emulation device, 'usb_mass_storage' is the real U-Boot +USB device driver that talks to it. + + +Future work +----------- + +It is pretty uncommon to have a large USB bus with lots of hubs on an +embedded system. In fact anything other than a root hub is uncommon. Still +it would be possible to speed up enumeration in two ways: + +- breadth-first search would allow devices to be reset and probed in +parallel to some extent +- enumeration could be lazy, in the sense that we could enumerate just the +root hub at first, then only progress to the next 'level' when a device is +used that we cannot find. This could be made easier if the devices were +statically declared in the device tree (which is acceptable for production +boards where the same, known, things are on each bus). + +But in common cases the current algorithm is sufficient. + +Other things that need doing: +- Convert usb_ether to use driver model as described above +- Test that keyboards work (and convert to driver model) +- Move the USB gadget framework to driver model +- Implement OHCI in driver model +- Implement USB PHYs in driver model +- Work out a clever way to provide lazy init for USB devices + +-- +Simon Glass <[email protected]> +23-Mar-15
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH v2 80/80 dm: usb: Add a README for driver model
There are some typos. Please correct them, thanks.
Quoted 30 lines · Simon Glass
Add some documentation describing how USB is implemented with USB. This might make things easier for people to understand.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2:
- Rewrite and expand series to support driver model fullydoc/driver-model/usb-info.txt | 415 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+)create mode 100644
doc/driver-model/usb-info.txtdoc/driver-model/usb-info.txt new file +11
-0@@ -0,0 +1,415 @@ +How USB works with driver model +=============================== + +Introduction +------------ + +Driver model USB support makes use of existing features but changes how +drivers are found. This document provides some information intended to help +understand how things work with USB in U-Boot when driver model is enabled. + +
doc/driver-model/usb-info.txt line 21
Quoted 10 lines
doc/driver-model/usb-info.txt new file +10
-0+Enabling driver model for USB +----------------------------- + +A new CONFIG_DM_USB option is provided to enable driver model for USB. This +causes the USB uclass to be included, and drops the equivalent code in +usb.c. In particular the usb_init() function is then implemented by the +uclass. + + +Support for ECHI and XCHI
EHCI
XHCI
Quoted 23 lines
doc/driver-model/usb-info.txt new file +23
-0+------------------------- + +So far OHCI is not supported. Both EHCI and XHCI drivers should be declared +as drivers in the USB uclass. For example: + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 }, + { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 }, + { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 }, + { } +}; + +U_BOOT_DRIVER(usb_ehci) = { + .name = "ehci_tegra", + .id = UCLASS_USB, + .of_match = ehci_usb_ids, + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .probe = tegra_ehci_usb_probe, + .remove = tegra_ehci_usb_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct fdt_usb), + .flags = DM_FLAG_ALLOC_PRIV_DMA,
doc/driver-model/usb-info.txt line 54
Quoted 10 lines
doc/driver-model/usb-info.txt new file +10
-0+}; + +Here ehci_usb_ids is used to list the controllers that the driver supports. +Each has its own data value. Controllers must be in the UCLASS_USB uclass. + +The ofdata_to_platdata() method allows the controller driver to grab any +necessary settings from the device tree. + +The ops here are ehci_usb_ops. All EHCI drivers will use these same ops in +most cases, since they are all ECHI-compatible. For ECHI there are also some
EHCI-compatible
For EHCI
doc/driver-model/usb-info.txt line 55
Quoted 1 line
doc/driver-model/usb-info.txt new file +1
-0+special operations that can be overriden when calling ehci_register().
overridden
Quoted 4 lines
doc/driver-model/usb-info.txt new file +4
-0+This defines a single controller, containing a root hub (which is required). +The hub is emulated by a hub emulator, and the emulated hub has a single +flash stick to emulate on one of its ports. +
doc/driver-model/usb-info.txt line 381
Quoted 10 lines
doc/driver-model/usb-info.txt new file +10
-0+When 'usb start' is used, the following 'dm tree' output will be available: + + usb [ + ] `-- usb at 1 + usb_hub [ + ] `-- hub + usb_emul [ + ] |-- hub-emul + usb_emul [ + ] | `-- flash-stick + usb_mass_st [ + ] `-- usb_mass_storage + + +This may look a confusing. Most of it mirrors the device tree, but the
may look confusing
--nvpublic
PATCH v2 80/80 dm: usb: Add a README for driver model
Hi Jim,
Quoted 111 lines · Jim Lin
There are some typos. Please correct them, thanks.
Quoted 39 lines · Simon Glass
Add some documentation describing how USB is implemented with USB. This might make things easier for people to understand.
Signed-off-by Simon Glass <[email protected]>---
Changes in v2:
- Rewrite and expand series to support driver model fullydoc/driver-model/usb-info.txt | 415 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+)create mode 100644
doc/driver-model/usb-info.txtdoc/driver-model/usb-info.txt new file +8
-0@@ -0,0 +1,415 @@ +How USB works with driver model +=============================== + +Introduction +------------ + +Driver model USB support makes use of existing features but changes how +drivers are found. This document provides some information intended tohelp
+understand how things work with USB in U-Boot when driver model is enabled.doc/driver-model/usb-info.txt new file +6
-0+ + +Enabling driver model for USB +----------------------------- + +A new CONFIG_DM_USB option is provided to enable driver model for USB.This
doc/driver-model/usb-info.txt line 21
Quoted 6 lines
doc/driver-model/usb-info.txt new file +6
-0+causes the USB uclass to be included, and drops the equivalent code in +usb.c. In particular the usb_init() function is then implemented by the +uclass. + + +Support for ECHI and XCHIEHCI
XHCIQuoted 35 lines
+-------------------------
doc/driver-model/usb-info.txt new file +2
-0+ +So far OHCI is not supported. Both EHCI and XHCI drivers should bedeclared
doc/driver-model/usb-info.txt new file +23
-0+as drivers in the USB uclass. For example: + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 }, + { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 }, + { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 }, + { } +}; + +U_BOOT_DRIVER(usb_ehci) = { + .name = "ehci_tegra", + .id = UCLASS_USB, + .of_match = ehci_usb_ids, + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .probe = tegra_ehci_usb_probe, + .remove = tegra_ehci_usb_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct fdt_usb), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; + +Here ehci_usb_ids is used to list the controllers that the driversupports.
+Each has its own data value. Controllers must be in theUCLASS_USBuclass.doc/driver-model/usb-info.txt new file +5
-0+ +The ofdata_to_platdata() method allows the controller driver to grab any +necessary settings from the device tree. + +The ops here are ehci_usb_ops. All EHCI drivers will use these same opsQuoted 3 lines
in
+most cases, since they are all ECHI-compatible. For ECHI there are also someEHCI-compatible
For EHCIQuoted 2 lines
+special operations that can be overriden when calling
ehci_register().overridden
Quoted 11 lines
+This defines a single controller, containing a root hub (which is required).
doc/driver-model/usb-info.txt new file +4
-0+The hub is emulated by a hub emulator, and the emulated hub has a single +flash stick to emulate on one of its ports. + +When 'usb start' is used, the following 'dm tree' output will beavailable:
++ usb [ + ] `-- usb at 1 + usb_hub [ + ] `-- hub + usb_emul [ + ] |-- hub-emul
Quoted 8 lines
doc/driver-model/usb-info.txt line 381
Quoted 5 lines
+
usb_emul[ + ] | `-- flash-stick
+usb_mass_st[ + ] `--usb_mass_storagedoc/driver-model/usb-info.txt new file +3
-0+ + +This may look a confusing. Most of it mirrors the device tree, but themay look confusing
--nvpublic
Thanks for the corrections, I fixed these.
Applied to u-boot-dm/next.
v2 cover dm: Add USB support
In reply to Simon GlassQuoted 4 lines · Simon Glass
This series adds 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.
Quoted 8 lines
With the RFC series, only USB controllers had a real driver model device. USB devices (including the hub in the controller) were not modelled as driver model devices.
While this was expedient, and produced much fewer patches, it is not a long-term solution. Also, since then, driver model Ethernet support (which USB can use) has been merged to u-boot-dm/next. It seems better to bite the bullet and do a full conversion.
Whew.
Best regards,
Marek Vasut
v2 cover dm: Add USB support
Hi Marek,
Quoted 9 lines · Marek Vasut
Quoted 8 lines · Simon Glass
This series adds 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.
With the RFC series, only USB controllers had a real driver model device. USB devices (including the hub in the controller) were not modelled as driver model devices.
Quoted 8 lines
Quoted 4 lines
While this was expedient, and produced much fewer patches, it is not a long-term solution. Also, since then, driver model Ethernet support (which USB can use) has been merged to u-boot-dm/next. It seems better to bite the bullet and do a full conversion.
Whew.
Reviewed-by Marek Vasut <[email protected]>
Thanks very much for working through these!
Unless there are other comments I plan to apply this to u-boot-dm/next in the next few days. I expect it will need some tweaking as boards are moved over too.
Regards,
Simon
v2 cover dm: Add USB support
Quoted 1 line · Simon Glass
Hi Marek,
Hi Simon,
Quoted 17 lines · Marek Vasut
Quoted 16 lines · Simon Glass
Quoted 4 lines
This series adds 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.
Quoted 8 lines
With the RFC series, only USB controllers had a real driver model device. USB devices (including the hub in the controller) were not modelled as driver model devices.
While this was expedient, and produced much fewer patches, it is not a long-term solution. Also, since then, driver model Ethernet support (which USB can use) has been merged to u-boot-dm/next. It seems better to bite the bullet and do a full conversion.
Whew.
Quoted 7 lines
Quoted 1 line
Reviewed-by Marek Vasut <[email protected]>Thanks very much for working through these!
Unless there are other comments I plan to apply this to u-boot-dm/next in the next few days. I expect it will need some tweaking as boards are moved over too.
Please apply, I'm really looking forward to this.
Thank you very much for putting all the effort into this !
Best regards,
Marek Vasut
v2 cover dm: Add USB support
Hi Marek,
Quoted 26 lines · Marek Vasut
Quoted 1 line · Simon Glass
Hi Marek,
Hi Simon,
Quoted 21 lines · Marek Vasut
Quoted 9 lines · Simon Glass
Quoted 8 lines
This series adds 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.
With the RFC series, only USB controllers had a real driver model device. USB devices (including the hub in the controller) were not modelled as driver model devices.
Quoted 8 lines
Quoted 4 lines
While this was expedient, and produced much fewer patches, it is not a long-term solution. Also, since then, driver model Ethernet support (which USB can use) has been merged to u-boot-dm/next. It seems better to bite the bullet and do a full conversion.
Whew.
Reviewed-by Marek Vasut <[email protected]>Thanks very much for working through these!
Quoted 7 lines
Quoted 3 lines
Unless there are other comments I plan to apply this to u-boot-dm/next in the next few days. I expect it will need some tweaking as boards are moved over too.
Please apply, I'm really looking forward to this.
Thank you very much for putting all the effort into this !
OK, I'll apply to u-boot-dm/next, do a bit more testing, and apply. It will be great to get this moved over.
Regards,
Simon
v2 cover dm: Add USB support
Quoted 1 line · Simon Glass
Hi Marek,
Hi Simon,
Quoted 31 lines · Marek Vasut
Quoted 30 lines · Simon Glass
Quoted 1 line
Hi Marek,
Hi Simon,
Quoted 24 lines · Marek Vasut
Quoted 9 lines · Simon Glass
Quoted 8 lines
This series adds 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.
With the RFC series, only USB controllers had a real driver model device. USB devices (including the hub in the controller) were not modelled as driver model devices.
Quoted 8 lines
Quoted 4 lines
While this was expedient, and produced much fewer patches, it is not a long-term solution. Also, since then, driver model Ethernet support (which USB can use) has been merged to u-boot-dm/next. It seems better to bite the bullet and do a full conversion.
Whew.
Reviewed-by Marek Vasut <[email protected]>Thanks very much for working through these!
Unless there are other comments I plan to apply this to u-boot-dm/next in the next few days. I expect it will need some tweaking as boards are moved over too.
Quoted 6 lines
Quoted 3 lines
Please apply, I'm really looking forward to this.
Thank you very much for putting all the effort into this !
OK, I'll apply to u-boot-dm/next, do a bit more testing, and apply. It will be great to get this moved over.
Thank you!
Best regards,
Marek Vasut