From 501547cec1f7f0438cae388a104ff60f18576c01 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 24 Jun 2019 19:05:47 +0200 Subject: usb: ehci-mx6: Fix bus enumeration for DM case The EHCI iMX6 driver is only partly converted to DT probing and still uses a tremendous amount of hard-coded addresses. Worse, the driver uses hard-coded SoC-model-specific base addresses, which are derived from values protected by SoC-specific macros, hence the driver is also compiled for a specific SoC model. Even worse, the driver depends on specific sequential indexing of the controllers, from which it derives offsets in the PHY and ANATOP register sets. However, when the driver is probed from DT, the indexing is not correct. In fact, each controller has index 0. This patch derives the index for DT probing case from the controller base addresses, which is not the way this should be done, however it is the least intrusive approach, favorable this close to release. The necessary steps to convert this driver fully to DT probing are described inside the patch, however this should be done in the next release and depends on iMX clock driver patches. Signed-off-by: Marek Vasut Cc: Abel Vesa Cc: Adam Ford Cc: Fabio Estevam Cc: Ludwig Zenz Cc: Lukasz Majewski Cc: Peng Fan Cc: Stefano Babic Cc: Vagrant Cascadian --- drivers/usb/host/ehci-mx6.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 33abfeada0..e9e6ed596d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -503,6 +503,42 @@ static int ehci_usb_ofdata_to_platdata(struct udevice *dev) return 0; } +static int ehci_usb_bind(struct udevice *dev) +{ + /* + * TODO: + * This driver is only partly converted to DT probing and still uses + * a tremendous amount of hard-coded addresses. To make things worse, + * the driver depends on specific sequential indexing of controllers, + * from which it derives offsets in the PHY and ANATOP register sets. + * + * Here we attempt to calculate these indexes from DT information as + * well as we can. The USB controllers on all existing iMX6/iMX7 SoCs + * are placed next to each other, at addresses incremented by 0x200. + * Thus, the index is derived from the multiple of 0x200 offset from + * the first controller address. + * + * However, to complete conversion of this driver to DT probing, the + * following has to be done: + * - DM clock framework support for iMX must be implemented + * - usb_power_config() has to be converted to clock framework + * -> Thus, the ad-hoc "index" variable goes away. + * - USB PHY handling has to be factored out into separate driver + * -> Thus, the ad-hoc "index" variable goes away from the PHY + * code, the PHY driver must parse it's address from DT. This + * USB driver must find the PHY driver via DT phandle. + * -> usb_power_config() shall be moved to PHY driver + * With these changes in place, the ad-hoc indexing goes away and + * the driver is fully converted to DT probing. + */ + fdt_size_t size; + fdt_addr_t addr = devfdt_get_addr_size_index(dev, 0, &size); + + dev->req_seq = (addr - USB_BASE_ADDR) / size; + + return 0; +} + static int ehci_usb_probe(struct udevice *dev) { struct usb_platdata *plat = dev_get_platdata(dev); @@ -564,6 +600,7 @@ U_BOOT_DRIVER(usb_mx6) = { .id = UCLASS_USB, .of_match = mx6_usb_ids, .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .bind = ehci_usb_bind, .probe = ehci_usb_probe, .remove = ehci_deregister, .ops = &ehci_usb_ops, -- cgit v1.2.3 From e445d46651de61fdfecf34cc2cd97d58ca6c5cf3 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Fri, 5 Jul 2019 09:33:56 +0200 Subject: usb: dwc3-generic: remove dm_scan_fdt_dev() from the remove() callback There is simply no reason to do that here. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/dwc3-generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 3e6c494dc6..70431facb3 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -337,7 +337,7 @@ static int dwc3_glue_remove(struct udevice *dev) clk_release_bulk(&glue->clks); - return dm_scan_fdt_dev(dev); + return 0; } static const struct udevice_id dwc3_glue_ids[] = { -- cgit v1.2.3 From 07e33711fec4f1106f36805b5dc830da07c783c5 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Fri, 5 Jul 2019 09:33:57 +0200 Subject: dm: Add a No-op uclass This uclass is intended for devices that do not need any features from the uclass, including binding children. This will typically be used by devices that are used to bind child devices but do not use dm_scan_fdt_dev() to do it. That is for example the case of several USB wrappers that have 2 child devices (1 for device and 1 for host) but bind only one at a any given time. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 12 ++++++++ drivers/core/uclass.c | 5 ++++ include/dm/uclass-id.h | 1 + test/dm/Makefile | 1 + test/dm/nop.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 test/dm/nop.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 8b2d6451c6..c328258901 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -400,6 +400,18 @@ sandbox,silent; /* Don't emit sounds while testing */ }; + nop-test_0 { + compatible = "sandbox,nop_sandbox1"; + nop-test_1 { + compatible = "sandbox,nop_sandbox2"; + bind = "True"; + }; + nop-test_2 { + compatible = "sandbox,nop_sandbox2"; + bind = "False"; + }; + }; + misc-test { compatible = "sandbox,misc_sandbox"; }; diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index fc3157de39..dc9eb62893 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -757,3 +757,8 @@ int uclass_pre_remove_device(struct udevice *dev) return 0; } #endif + +UCLASS_DRIVER(nop) = { + .id = UCLASS_NOP, + .name = "nop", +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 09e0ad5391..418392875c 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -62,6 +62,7 @@ enum uclass_id { UCLASS_MMC, /* SD / MMC card or chip */ UCLASS_MOD_EXP, /* RSA Mod Exp device */ UCLASS_MTD, /* Memory Technology Device (MTD) device */ + UCLASS_NOP, /* No-op devices */ UCLASS_NORTHBRIDGE, /* Intel Northbridge / SDRAM controller */ UCLASS_NVME, /* NVM Express device */ UCLASS_PANEL, /* Display panel, such as an LCD */ diff --git a/test/dm/Makefile b/test/dm/Makefile index 49857c5092..aeb3aa0ca7 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -3,6 +3,7 @@ # Copyright (c) 2013 Google, Inc obj-$(CONFIG_UT_DM) += bus.o +obj-$(CONFIG_UT_DM) += nop.o obj-$(CONFIG_UT_DM) += test-driver.o obj-$(CONFIG_UT_DM) += test-fdt.o obj-$(CONFIG_UT_DM) += test-main.o diff --git a/test/dm/nop.c b/test/dm/nop.c new file mode 100644 index 0000000000..2df29f3d15 --- /dev/null +++ b/test/dm/nop.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for the NOP uclass + * + * (C) Copyright 2019 - Texas Instruments Incorporated - http://www.ti.com/ + * Jean-Jacques Hiblot + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int noptest_bind(struct udevice *parent) +{ + ofnode ofnode = dev_read_first_subnode(parent); + + while (ofnode_valid(ofnode)) { + struct udevice *dev; + const char *bind_flag = ofnode_read_string(ofnode, "bind"); + + if (bind_flag && (strcmp(bind_flag, "True") == 0)) + lists_bind_fdt(parent, ofnode, &dev, false); + ofnode = dev_read_next_subnode(ofnode); + } + + return 0; +} + +static const struct udevice_id noptest1_ids[] = { + { + .compatible = "sandbox,nop_sandbox1", + }, + { } +}; + +U_BOOT_DRIVER(noptest_drv1) = { + .name = "noptest1_drv", + .of_match = noptest1_ids, + .id = UCLASS_NOP, + .bind = noptest_bind, +}; + +static const struct udevice_id noptest2_ids[] = { + { + .compatible = "sandbox,nop_sandbox2", + }, + { } +}; + +U_BOOT_DRIVER(noptest_drv2) = { + .name = "noptest2_drv", + .of_match = noptest2_ids, + .id = UCLASS_NOP, +}; + +static int dm_test_nop(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "nop-test_0", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "nop-test_1", &dev)); + ut_asserteq(-ENODEV, + uclass_get_device_by_name(UCLASS_NOP, "nop-test_2", &dev)); + + return 0; +} + +DM_TEST(dm_test_nop, DM_TESTF_FLAT_TREE | DM_TESTF_SCAN_FDT); -- cgit v1.2.3 From 3b83829ed63fabe460592395571c1d8fd9b861c8 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Fri, 5 Jul 2019 09:33:58 +0200 Subject: usb: dwc3: Use UCLASS_NOP instead of UCLASS_MISC for the DWC3 generic glue dwc3-generic has been broken since MISC uclass has been modified to scan DT sub-nodes after bind. Fixing it by a using the no-op uclass. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- drivers/usb/dwc3/dwc3-generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 70431facb3..406bf0b362 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -350,7 +350,7 @@ static const struct udevice_id dwc3_glue_ids[] = { U_BOOT_DRIVER(dwc3_generic_wrapper) = { .name = "dwc3-generic-wrapper", - .id = UCLASS_MISC, + .id = UCLASS_NOP, .of_match = dwc3_glue_ids, .bind = dwc3_glue_bind, .probe = dwc3_glue_probe, -- cgit v1.2.3