From ad991472e7b112ef6ba96d8a0672e4caa5a07ae4 Mon Sep 17 00:00:00 2001 From: Alex Kiernan Date: Fri, 12 Apr 2019 10:51:05 +0000 Subject: [PATCH 01/25] configs: Migrate USB_MUSB_DISABLE_BULK_COMBINE_SPLIT to Kconfig Migrate support for disable MUSB bulk split/combine to Kconfig Green Travis build: https://travis-ci.org/akiernan/u-boot/builds/519101867 Signed-off-by: Alex Kiernan --- drivers/usb/musb-new/Kconfig | 9 +++++++++ include/configs/am335x_evm.h | 1 - include/configs/baltos.h | 1 - include/configs/bav335x.h | 1 - include/configs/brppt1.h | 3 --- include/configs/brxre1.h | 3 --- include/configs/chiliboard.h | 1 - include/configs/pengwyn.h | 1 - include/configs/siemens-am33x-common.h | 2 -- scripts/config_whitelist.txt | 1 - 10 files changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index f8f2205a62..fdf9ca61da 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -54,6 +54,15 @@ config USB_MUSB_SUNXI Say y here to enable support for the sunxi OTG / DRC USB controller used on almost all sunxi boards. +config USB_MUSB_DISABLE_BULK_COMBINE_SPLIT + bool "Disable MUSB bulk split/combine" + default y + help + On TI AM335x devices, MUSB has bulk split/combine feature enabled + in the ConfigData register, but the current MUSB driver does not + support it yet. Select this option to disable the feature until the + driver adds the support. + endif config USB_MUSB_PIO_ONLY diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index 0834ff5021..7721907d8f 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -240,7 +240,6 @@ * add mass storage support and for gadget we add both RNDIS ethernet * and DFU. */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT #define CONFIG_AM335X_USB0 #define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL #define CONFIG_AM335X_USB1 diff --git a/include/configs/baltos.h b/include/configs/baltos.h index ccbdc0a335..98ec0d626e 100644 --- a/include/configs/baltos.h +++ b/include/configs/baltos.h @@ -251,7 +251,6 @@ * add mass storage support and for gadget we add both RNDIS ethernet * and DFU. */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT #define CONFIG_AM335X_USB0 #define CONFIG_AM335X_USB0_MODE MUSB_HOST #define CONFIG_AM335X_USB1 diff --git a/include/configs/bav335x.h b/include/configs/bav335x.h index fb9c2a6d04..3d4d08aa70 100644 --- a/include/configs/bav335x.h +++ b/include/configs/bav335x.h @@ -387,7 +387,6 @@ DEFAULT_LINUX_BOOT_ENV \ * add mass storage support and for gadget we add both RNDIS ethernet * and DFU. */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT #define CONFIG_AM335X_USB0 #define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL #define CONFIG_AM335X_USB1 diff --git a/include/configs/brppt1.h b/include/configs/brppt1.h index ae9b75bb87..84c801d10a 100644 --- a/include/configs/brppt1.h +++ b/include/configs/brppt1.h @@ -182,9 +182,6 @@ NANDTGTS \ #define CONFIG_NAND_OMAP_GPMC_WSCFG 1 #endif /* CONFIG_NAND */ -/* USB configuration */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT - #if defined(CONFIG_SPI) /* SPI Flash */ #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x40000 diff --git a/include/configs/brxre1.h b/include/configs/brxre1.h index 601b30dffd..7309e7d483 100644 --- a/include/configs/brxre1.h +++ b/include/configs/brxre1.h @@ -68,9 +68,6 @@ BUR_COMMON_ENV \ #define CONFIG_SETUP_MEMORY_TAGS #define CONFIG_INITRD_TAG -/* USB configuration */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT - /* Environment */ #define CONFIG_SYS_MMC_ENV_DEV 1 #define CONFIG_SYS_MMC_ENV_PART 2 diff --git a/include/configs/chiliboard.h b/include/configs/chiliboard.h index 4372280d2b..db990fcb2b 100644 --- a/include/configs/chiliboard.h +++ b/include/configs/chiliboard.h @@ -148,7 +148,6 @@ /* USB configuration */ #define CONFIG_ARCH_MISC_INIT -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT #define CONFIG_AM335X_USB1 #define CONFIG_AM335X_USB1_MODE MUSB_HOST diff --git a/include/configs/pengwyn.h b/include/configs/pengwyn.h index 48f1f7bacc..a535d0c2f2 100644 --- a/include/configs/pengwyn.h +++ b/include/configs/pengwyn.h @@ -157,7 +157,6 @@ * board schematic and physical port wired to each. Then for host we * add mass storage support. */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT #define CONFIG_AM335X_USB0 #define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL #define CONFIG_AM335X_USB1 diff --git a/include/configs/siemens-am33x-common.h b/include/configs/siemens-am33x-common.h index f44a4280f4..1170f24748 100644 --- a/include/configs/siemens-am33x-common.h +++ b/include/configs/siemens-am33x-common.h @@ -150,8 +150,6 @@ /* * USB configuration */ -#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT - #define CONFIG_AM335X_USB0 #define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL #define CONFIG_AM335X_USB1 diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 5092c3fb4c..421362d953 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4537,7 +4537,6 @@ CONFIG_USB_GADGET_SUPERH CONFIG_USB_INVENTRA_DMA CONFIG_USB_ISP1301_I2C_ADDR CONFIG_USB_MAX_CONTROLLER_COUNT -CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT CONFIG_USB_MUSB_TIMEOUT CONFIG_USB_MUSB_TUSB6010 CONFIG_USB_OHCI_EP93XX From 17982a2855b920a855350ea920a965cfdd1863c0 Mon Sep 17 00:00:00 2001 From: Alex Kiernan Date: Thu, 18 Apr 2019 11:10:50 +0000 Subject: [PATCH 02/25] usb: Select USB_MUSB_DSPS with USB_MUSB_TI USB_MUSB_TI requires USB_MUSB_DSPS, failing at link time if it's not selected: drivers/usb/musb-new/built-in.o: In function `ti_musb_host_ofdata_to_platdata': drivers/usb/musb-new/ti-musb.c:193: undefined reference to `musb_dsps_ops' or if OF_CONTROL is not selected: arch/arm/mach-omap2/built-in.o:(.data.usb0+0x24): undefined reference to `musb_dsps_ops' Reviewed-by: Hannes Schmelzer Tested-by: Hannes Schmelzer Signed-off-by: Alex Kiernan --- configs/am335x_boneblack_vboot_defconfig | 1 - configs/am335x_evm_defconfig | 1 - configs/am335x_hs_evm_defconfig | 1 - configs/am335x_hs_evm_uart_defconfig | 1 - configs/brppt1_mmc_defconfig | 1 - configs/brppt1_nand_defconfig | 1 - configs/brppt1_spi_defconfig | 1 - configs/chiliboard_defconfig | 1 - drivers/usb/musb-new/Kconfig | 1 + 9 files changed, 1 insertion(+), 8 deletions(-) diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig index 6afda72453..ffe013fa2d 100644 --- a/configs/am335x_boneblack_vboot_defconfig +++ b/configs/am335x_boneblack_vboot_defconfig @@ -56,7 +56,6 @@ CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" CONFIG_USB_GADGET_VENDOR_NUM=0x0451 diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index a396a39310..105ff01d14 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -64,7 +64,6 @@ CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" CONFIG_USB_GADGET_VENDOR_NUM=0x0451 diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig index 1746df90f4..a37966bc6d 100644 --- a/configs/am335x_hs_evm_defconfig +++ b/configs/am335x_hs_evm_defconfig @@ -60,7 +60,6 @@ CONFIG_DM_USB=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" CONFIG_USB_GADGET_VENDOR_NUM=0x0451 diff --git a/configs/am335x_hs_evm_uart_defconfig b/configs/am335x_hs_evm_uart_defconfig index d2d6f2fb6e..ff131eb601 100644 --- a/configs/am335x_hs_evm_uart_defconfig +++ b/configs/am335x_hs_evm_uart_defconfig @@ -62,7 +62,6 @@ CONFIG_DM_USB=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" CONFIG_USB_GADGET_VENDOR_NUM=0x0451 diff --git a/configs/brppt1_mmc_defconfig b/configs/brppt1_mmc_defconfig index 6b0d0242f2..63cb240ea8 100644 --- a/configs/brppt1_mmc_defconfig +++ b/configs/brppt1_mmc_defconfig @@ -84,7 +84,6 @@ CONFIG_DM_USB=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_FAT_WRITE=y diff --git a/configs/brppt1_nand_defconfig b/configs/brppt1_nand_defconfig index 4578f74a62..57cd54bac2 100644 --- a/configs/brppt1_nand_defconfig +++ b/configs/brppt1_nand_defconfig @@ -88,7 +88,6 @@ CONFIG_DM_USB=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_FAT_WRITE=y diff --git a/configs/brppt1_spi_defconfig b/configs/brppt1_spi_defconfig index 739b0786f3..31ba5158b5 100644 --- a/configs/brppt1_spi_defconfig +++ b/configs/brppt1_spi_defconfig @@ -99,7 +99,6 @@ CONFIG_DM_USB=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_GADGET=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_FAT_WRITE=y diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig index a6c36eda50..944dd0db3c 100644 --- a/configs/chiliboard_defconfig +++ b/configs/chiliboard_defconfig @@ -50,6 +50,5 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_MUSB_HOST=y CONFIG_USB_MUSB_TI=y -CONFIG_USB_MUSB_DSPS=y CONFIG_FAT_WRITE=y CONFIG_LZO=y diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index fdf9ca61da..75005ccdd1 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -21,6 +21,7 @@ config USB_MUSB_GADGET config USB_MUSB_TI bool "Enable TI OTG USB controller" depends on DM_USB + select USB_MUSB_DSPS default n help Say y here to enable support for the dual role high From cbc1081da00923eed4c73bf28b51f9a01ea5d043 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 4 Mar 2019 16:04:44 +0200 Subject: [PATCH 03/25] dfu: Avoid declaring unused variables and absent parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler is not happy when neither USB nor TFTP transport for DFU defined: cmd/dfu.c: In function ‘do_dfu’: cmd/dfu.c:31:8: warning: unused variable ‘devstring’ [-Wunused-variable] char *devstring = argv[3]; ^~~~~~~~~ cmd/dfu.c:30:8: warning: unused variable ‘interface’ [-Wunused-variable] char *interface = argv[2]; ^~~~~~~~~ Surround those variables by #ifdef expression. More serious, that comes under same circumstances, is a compilation error due to absence of macro parameter: In file included from include/image.h:45, from include/common.h:35, from cmd/dfu.c:13: include/command.h:207:24: error: expected expression before ‘,’ token # define _CMD_HELP(x) x, ^ include/command.h:286:18: note: in expansion of macro ‘_CMD_HELP’ _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) } ^~~~~~~~~ include/command.h:290:3: note: in expansion of macro ‘U_BOOT_CMD_MKENT_COMPLETE’ U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ ^~~~~~~~~~~~~~~~~~~~~~~~~ include/command.h:332:2: note: in expansion of macro ‘U_BOOT_CMD_COMPLETE’ U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL) ^~~~~~~~~~~~~~~~~~~ cmd/dfu.c:70:1: note: in expansion of macro ‘U_BOOT_CMD’ U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, ^~~~~~~~~~ make[1]: *** [scripts/Makefile.build:279: cmd/dfu.o] Error 1 make: *** [Makefile:1518: cmd] Error 2 Put empty string unconditionally to have macro parameter present. Fixes: 0f44d33536a5 ("dfu: Fix up the Kconfig mess") Cc: Marek Vasut Signed-off-by: Andy Shevchenko Acked-by: Lukasz Majewski --- cmd/dfu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/dfu.c b/cmd/dfu.c index c9ba062197..91a750a4fc 100644 --- a/cmd/dfu.c +++ b/cmd/dfu.c @@ -27,8 +27,10 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef CONFIG_DFU_OVER_USB char *usb_controller = argv[1]; #endif +#if defined(CONFIG_DFU_OVER_USB) || defined(CONFIG_DFU_OVER_TFTP) char *interface = argv[2]; char *devstring = argv[3]; +#endif int ret = 0; #ifdef CONFIG_DFU_OVER_TFTP @@ -63,6 +65,7 @@ done: U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, "Device Firmware Upgrade", + "" #ifdef CONFIG_DFU_OVER_USB " [list]\n" " - device firmware upgrade via \n" From 4c829466fcc8c0b5303af6bda21366657b959a30 Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Tue, 26 Mar 2019 17:46:14 +0100 Subject: [PATCH 04/25] fastboot: getvar: correct/rename "has_slot" to "has-slot" Since its inception in upstream fastboot android-n-preview-1 [1], "has-slot" option has never taken the form of "has_slot". Amongst the users of "getvar has-slot:" is the upstream bootloadertest.py [2]. Current U-Boot "has_slot" version must be a typo. Fix it. [1] https://android.googlesource.com/platform/system/core/+/a797479bd51c ("Fix fastboot variable name") [2] https://android.googlesource.com/platform/system/extras/+/72de393e118e3 ("Bootloader verification for AndroidThings.") Fixes: f73a7df984a9 ("net: fastboot: Merge AOSP UDP fastboot") Signed-off-by: Eugeniu Rosca Acked-by: Alex Kiernan --- drivers/fastboot/fb_getvar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index 4d264c985d..91a774a345 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -62,7 +62,7 @@ static const struct { .variable = "slot-suffixes", .dispatch = getvar_slot_suffixes }, { - .variable = "has_slot", + .variable = "has-slot", .dispatch = getvar_has_slot #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) }, { From a40297d74105b3949dc72375e0fdc54fe0b170ad Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Thu, 28 Mar 2019 14:31:33 +0100 Subject: [PATCH 05/25] fastboot: Improve error reporting on 'getvar partition-{size, type}' Currently U-Boot reports the same error message in all below cases: [A] host> fastboot getvar partition-type [B] host> fastboot getvar partition-size [C] host> fastboot getvar partition-type: [D] host> fastboot getvar partition-size: [E] host> fastboot getvar partition-type: [F] host> fastboot getvar partition-size: The message looks like: host> fastboot getvar partition-size: getvar:partition-size: FAILED (remote: partition not found) Finished. Total time: 0.003s Be more user friendly and output: - "partition not given" for [A-D] - "partition not found" for [E-F] Fixes: f73a7df984a9 ("net: fastboot: Merge AOSP UDP fastboot") Signed-off-by: Eugeniu Rosca Acked-by: Alex Kiernan --- drivers/fastboot/fb_mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index 4c1c7fd2cd..d04d8a448c 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -308,8 +308,8 @@ int fastboot_mmc_get_part_info(char *part_name, struct blk_desc **dev_desc, fastboot_fail("block device not found", response); return -ENOENT; } - if (!part_name) { - fastboot_fail("partition not found", response); + if (!part_name || !strcmp(part_name, "")) { + fastboot_fail("partition not given", response); return -ENOENT; } From 6841d83cec269d5b926f3bce5d60f840d03ee507 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:09 +0100 Subject: [PATCH 06/25] phy: usbphyc: remove unused variable index Remove unused field index in struct stm32_usbphyc_phy. Signed-off-by: Patrick Delaunay --- drivers/phy/phy-stm32-usbphyc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 8e98b4b627..fc53df25ef 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -55,7 +55,6 @@ struct stm32_usbphyc { struct udevice *vdd; struct udevice *vdda1v1; struct udevice *vdda1v8; - int index; bool init; bool powered; } phys[MAX_PHYS]; @@ -359,7 +358,6 @@ static int stm32_usbphyc_probe(struct udevice *dev) for (i = 0; i < MAX_PHYS; i++) { struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + i; - usbphyc_phy->index = i; usbphyc_phy->init = false; usbphyc_phy->powered = false; ret = stm32_usbphyc_get_regulator(dev, node, "phy-supply", From 1655f2da8449db915fe414e3f88e64ad64f6a77a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:10 +0100 Subject: [PATCH 07/25] phy: usbphyc: update xlate with DT binding Parameter added for port 1, for example: &usbh_ehci { phys = <&usbphyc_port0>; phy-names = "usb"; vbus-supply = <&vbus_sw>; status = "okay"; }; &usbotg_hs { pinctrl-names = "default"; pinctrl-0 = <&usbotg_hs_pins_a>; phys = <&usbphyc_port1 0>; phy-names = "usb2-phy"; status = "okay"; }; Signed-off-by: Patrick Delaunay --- drivers/phy/phy-stm32-usbphyc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index fc53df25ef..ec5b47c8a4 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -297,19 +297,20 @@ static int stm32_usbphyc_get_regulator(struct udevice *dev, ofnode node, static int stm32_usbphyc_of_xlate(struct phy *phy, struct ofnode_phandle_args *args) { - if (args->args_count > 1) { - pr_debug("%s: invalid args_count: %d\n", __func__, - args->args_count); - return -EINVAL; - } + if (args->args_count < 1) + return -ENODEV; if (args->args[0] >= MAX_PHYS) return -ENODEV; - if (args->args_count) - phy->id = args->args[0]; - else - phy->id = 0; + phy->id = args->args[0]; + + if ((phy->id == 0 && args->args_count != 1) || + (phy->id == 1 && args->args_count != 2)) { + dev_err(dev, "invalid number of cells for phy port%ld\n", + phy->id); + return -EINVAL; + } return 0; } From c50151d43f78738d3d9fef4c4f4611e83178dc88 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:11 +0100 Subject: [PATCH 08/25] phy: usbphyc: Binding update of vdda supply Move supply vdda1v1 and vdda1v8 in usbphyc node and no more in port Signed-off-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1.dts | 8 --- arch/arm/dts/stm32mp157c.dtsi | 3 ++ .../phy/phy-stm32-usbphyc.txt | 4 +- drivers/phy/phy-stm32-usbphyc.c | 54 ++++++++++--------- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts index 2664c9ce90..0366782fda 100644 --- a/arch/arm/dts/stm32mp157c-ed1.dts +++ b/arch/arm/dts/stm32mp157c-ed1.dts @@ -382,18 +382,10 @@ status = "okay"; }; -&usbotg_hs { - usb33d-supply = <&usb33>; -}; - &usbphyc_port0 { phy-supply = <&vdd_usb>; - vdda1v1-supply = <®11>; - vdda1v8-supply = <®18>; }; &usbphyc_port1 { phy-supply = <&vdd_usb>; - vdda1v1-supply = <®11>; - vdda1v8-supply = <®18>; }; diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index 7eb4bee31c..472637bb55 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -836,6 +836,7 @@ g-np-tx-fifo-size = <32>; g-tx-fifo-size = <128 128 64 64 64 64 32 32>; dr_mode = "otg"; + usb33d-supply = <&usb33>; status = "disabled"; }; @@ -1161,6 +1162,8 @@ reg = <0x5a006000 0x1000>; clocks = <&rcc USBPHY_K>; resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; status = "disabled"; usbphyc_port0: usb-phy@0 { diff --git a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt index 725ae71ae6..da98407403 100644 --- a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt +++ b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt @@ -23,6 +23,8 @@ Required properties: - compatible: must be "st,stm32mp1-usbphyc" - reg: address and length of the usb phy control register set - clocks: phandle + clock specifier for the PLL phy clock +- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY +- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY - #address-cells: number of address cells for phys sub-nodes, must be <1> - #size-cells: number of size cells for phys sub-nodes, must be <0> @@ -40,8 +42,6 @@ Required properties: - reg: phy port index - phy-supply: phandle to the regulator providing 3V3 power to the PHY, see phy-bindings.txt in the same directory. -- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY -- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY - #phy-cells: see phy-bindings.txt in the same directory, must be <0> for PHY port#1 and must be <1> for PHY port#2, to select USB controller diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index ec5b47c8a4..617c5a0ce0 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -51,10 +51,10 @@ struct pll_params { struct stm32_usbphyc { fdt_addr_t base; struct clk clk; + struct udevice *vdda1v1; + struct udevice *vdda1v8; struct stm32_usbphyc_phy { struct udevice *vdd; - struct udevice *vdda1v1; - struct udevice *vdda1v8; bool init; bool powered; } phys[MAX_PHYS]; @@ -212,19 +212,20 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) int ret; pr_debug("%s phy ID = %lu\n", __func__, phy->id); - if (usbphyc_phy->vdda1v1) { - ret = regulator_set_enable(usbphyc_phy->vdda1v1, true); + if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, true); if (ret) return ret; } - if (usbphyc_phy->vdda1v8) { - ret = regulator_set_enable(usbphyc_phy->vdda1v8, true); + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, true); if (ret) return ret; } - if (usbphyc_phy->vdd) { - ret = regulator_set_enable(usbphyc_phy->vdd, true); + + if (usbphyc->vdd) { + ret = regulator_set_enable(usbphyc->vdd, true); if (ret) return ret; } @@ -246,20 +247,20 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy) if (stm32_usbphyc_is_powered(usbphyc)) return 0; - if (usbphyc_phy->vdda1v1) { - ret = regulator_set_enable(usbphyc_phy->vdda1v1, false); + if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, false); if (ret) return ret; } - if (usbphyc_phy->vdda1v8) { - ret = regulator_set_enable(usbphyc_phy->vdda1v8, false); + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, false); if (ret) return ret; } - if (usbphyc_phy->vdd) { - ret = regulator_set_enable(usbphyc_phy->vdd, false); + if (usbphyc->vdd) { + ret = regulator_set_enable(usbphyc->vdd, false); if (ret) return ret; } @@ -351,6 +352,21 @@ static int stm32_usbphyc_probe(struct udevice *dev) reset_deassert(&reset); } + /* get usbphyc regulator */ + ret = device_get_supply_regulator(dev, "vdda1v1-supply", + &usbphyc->vdda1v1); + if (ret) { + dev_err(dev, "Can't get vdda1v1-supply regulator\n"); + return ret; + } + + ret = device_get_supply_regulator(dev, "vdda1v8-supply", + &usbphyc->vdda1v8); + if (ret) { + dev_err(dev, "Can't get vdda1v8-supply regulator\n"); + return ret; + } + /* * parse all PHY subnodes in order to populate regulator associated * to each PHY port @@ -366,16 +382,6 @@ static int stm32_usbphyc_probe(struct udevice *dev) if (ret) return ret; - ret = stm32_usbphyc_get_regulator(dev, node, "vdda1v1-supply", - &usbphyc_phy->vdda1v1); - if (ret) - return ret; - - ret = stm32_usbphyc_get_regulator(dev, node, "vdda1v8-supply", - &usbphyc_phy->vdda1v8); - if (ret) - return ret; - node = dev_read_next_subnode(node); } From e1904abc1bf90e9b382042a45d645d3dd6fbe8b0 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:12 +0100 Subject: [PATCH 09/25] phy: usbphyc: move vdda1v1 and vdda1v8 in phy_init vdda1v1 and vdda1v8 are used by the PLL. Both need to be enabled before starting the PLL. Signed-off-by: Patrick Delaunay --- drivers/phy/phy-stm32-usbphyc.c | 60 +++++++++++++++++---------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 617c5a0ce0..54363cd165 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -60,7 +60,8 @@ struct stm32_usbphyc { } phys[MAX_PHYS]; }; -void stm32_usbphyc_get_pll_params(u32 clk_rate, struct pll_params *pll_params) +static void stm32_usbphyc_get_pll_params(u32 clk_rate, + struct pll_params *pll_params) { unsigned long long fvco, ndiv, frac; @@ -153,6 +154,18 @@ static int stm32_usbphyc_phy_init(struct phy *phy) if (pllen && stm32_usbphyc_is_init(usbphyc)) goto initialized; + if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, true); + if (ret) + return ret; + } + + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, true); + if (ret) + return ret; + } + if (pllen) { clrbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN); udelay(PLL_PWR_DOWN_TIME_US); @@ -183,6 +196,7 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) { struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; + int ret; pr_debug("%s phy ID = %lu\n", __func__, phy->id); usbphyc_phy->init = false; @@ -202,6 +216,18 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) if (readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN) return -EIO; + if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, false); + if (ret) + return ret; + } + + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, false); + if (ret) + return ret; + } + return 0; } @@ -212,20 +238,8 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) int ret; pr_debug("%s phy ID = %lu\n", __func__, phy->id); - if (usbphyc->vdda1v1) { - ret = regulator_set_enable(usbphyc->vdda1v1, true); - if (ret) - return ret; - } - - if (usbphyc->vdda1v8) { - ret = regulator_set_enable(usbphyc->vdda1v8, true); - if (ret) - return ret; - } - - if (usbphyc->vdd) { - ret = regulator_set_enable(usbphyc->vdd, true); + if (usbphyc_phy->vdd) { + ret = regulator_set_enable(usbphyc_phy->vdd, true); if (ret) return ret; } @@ -247,20 +261,8 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy) if (stm32_usbphyc_is_powered(usbphyc)) return 0; - if (usbphyc->vdda1v1) { - ret = regulator_set_enable(usbphyc->vdda1v1, false); - if (ret) - return ret; - } - - if (usbphyc->vdda1v8) { - ret = regulator_set_enable(usbphyc->vdda1v8, false); - if (ret) - return ret; - } - - if (usbphyc->vdd) { - ret = regulator_set_enable(usbphyc->vdd, false); + if (usbphyc_phy->vdd) { + ret = regulator_set_enable(usbphyc_phy->vdd, false); if (ret) return ret; } From 901f6950a482d11849b7c748eaef7bda010e91dc Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:13 +0100 Subject: [PATCH 10/25] phy: usbphyc: increase PLL wait timeout wait 200us to solve USB init issue on device mode (ums and stm32prog commands) Signed-off-by: Patrick Delaunay --- drivers/phy/phy-stm32-usbphyc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 54363cd165..6f1119036d 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -37,7 +37,8 @@ #define MAX_PHYS 2 -#define PLL_LOCK_TIME_US 100 +/* max 100 us for PLL lock and 100 us for PHY init */ +#define PLL_INIT_TIME_US 200 #define PLL_PWR_DOWN_TIME_US 5 #define PLL_FVCO 2880 /* in MHz */ #define PLL_INFF_MIN_RATE 19200000 /* in Hz */ @@ -177,11 +178,8 @@ static int stm32_usbphyc_phy_init(struct phy *phy) setbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN); - /* - * We must wait PLL_LOCK_TIME_US before checking that PLLEN - * bit is still set - */ - udelay(PLL_LOCK_TIME_US); + /* We must wait PLL_INIT_TIME_US before using PHY */ + udelay(PLL_INIT_TIME_US); if (!(readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN)) return -EIO; From a812d77617749eeaddfa8b9796b9a2eece1ad2f5 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:14 +0100 Subject: [PATCH 11/25] usb: dwc2: remove unused variable regs_otg Remove the global regs_otg variable. Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3c7ad033e3..edca05d009 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -140,7 +140,6 @@ static struct usb_ep_ops dwc2_ep_ops = { /***********************************************************/ -void __iomem *regs_otg; struct dwc2_usbotg_reg *reg; bool dfu_usb_get_reset(void) @@ -818,8 +817,6 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) reg = (struct dwc2_usbotg_reg *)pdata->regs_otg; - /* regs_otg = (void *)pdata->regs_otg; */ - dev->gadget.is_dualspeed = 1; /* Hack only*/ dev->gadget.is_otg = 0; dev->gadget.is_a_peripheral = 0; From c791c8431c34da803fdac4a308999879a6a33834 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:15 +0100 Subject: [PATCH 12/25] usb: dwc2: convert driver to DM_USB_GADGET Minimal conversion to driver model by using the uclass UCLASS_USB_GADGET_GENERIC based on: - reset uclass - clock uclass - generic uclass. Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- doc/device-tree-bindings/usb/dwc2.txt | 54 +++++ drivers/usb/gadget/dwc2_udc_otg.c | 292 +++++++++++++++++++++++++- 2 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt new file mode 100644 index 0000000000..6dc3c4a344 --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -0,0 +1,54 @@ +Platform DesignWare HS OTG USB 2.0 controller +----------------------------------------------------- + +Required properties: +- compatible : One of: + - brcm,bcm2835-usb: The DWC2 USB controller instance in the BCM2835 SoC. + - hisilicon,hi6220-usb: The DWC2 USB controller instance in the hi6220 SoC. + - rockchip,rk3066-usb: The DWC2 USB controller instance in the rk3066 Soc; + - "rockchip,px30-usb", "rockchip,rk3066-usb", "snps,dwc2": for px30 Soc; + - "rockchip,rk3188-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3188 Soc; + - "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc; + - "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs; + - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs; + - "amlogic,meson8-usb": The DWC2 USB controller instance in Amlogic Meson8 SoCs; + - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs; + - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs; + - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs; + - snps,dwc2: A generic DWC2 USB controller with default parameters. + - "st,stm32f4x9-fsotg": The DWC2 USB FS/HS controller instance in STM32F4x9 SoCs + configured in FS mode; + - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs + configured in HS mode; + - "st,stm32f7-hsotg": The DWC2 USB HS controller instance in STM32F7 SoCs + configured in HS mode; +- reg : Should contain 1 register range (address and length) +- interrupts : Should contain 1 interrupt +- clocks: clock provider specifier +- clock-names: shall be "otg" +Refer to clk/clock-bindings.txt for generic clock consumer properties + +Optional properties: +- phys: phy provider specifier +- phy-names: shall be "usb2-phy" +Refer to phy/phy-bindings.txt for generic phy consumer properties +- dr_mode: shall be one of "host", "peripheral" and "otg" + Refer to usb/generic.txt +- g-rx-fifo-size: size of rx fifo size in gadget mode. +- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode. +- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. + +Deprecated properties: +- g-use-dma: gadget DMA mode is automatically detected + +Example: + + usb@101c0000 { + compatible = "ralink,rt3050-usb, snps,dwc2"; + reg = <0x101c0000 40000>; + interrupts = <18>; + clocks = <&usb_otg_ahb_clk>; + clock-names = "otg"; + phys = <&usbphy>; + phy-names = "usb2-phy"; + }; diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index edca05d009..af16fc1ed4 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -18,11 +18,17 @@ */ #undef DEBUG #include +#include +#include +#include +#include +#include + #include #include -#include #include +#include #include #include @@ -31,6 +37,8 @@ #include +#include + #include "dwc2_udc_otg_regs.h" #include "dwc2_udc_otg_priv.h" @@ -222,6 +230,7 @@ static int udc_enable(struct dwc2_udc *dev) return 0; } +#if !CONFIG_IS_ENABLED(DM_USB_GADGET) /* Register entry point for the peripheral controller driver. */ @@ -296,6 +305,54 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_disable(dev); return 0; } +#else /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */ + +static int dwc2_gadget_start(struct usb_gadget *g, + struct usb_gadget_driver *driver) +{ + struct dwc2_udc *dev = the_controller; + + debug_cond(DEBUG_SETUP != 0, "%s: %s\n", __func__, "no name"); + + if (!driver || + (driver->speed != USB_SPEED_FULL && + driver->speed != USB_SPEED_HIGH) || + !driver->bind || !driver->disconnect || !driver->setup) + return -EINVAL; + + if (!dev) + return -ENODEV; + + if (dev->driver) + return -EBUSY; + + /* first hook up the driver ... */ + dev->driver = driver; + + debug_cond(DEBUG_SETUP != 0, + "Registered gadget driver %s\n", dev->gadget.name); + return udc_enable(dev); +} + +static int dwc2_gadget_stop(struct usb_gadget *g) +{ + struct dwc2_udc *dev = the_controller; + + if (!dev) + return -ENODEV; + + if (!dev->driver) + return -EINVAL; + + dev->driver = 0; + stop_activity(dev, dev->driver); + + udc_disable(dev); + + return 0; +} + +#endif /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */ /* * done - retire a request; caller blocked irqs @@ -730,6 +787,10 @@ static void dwc2_fifo_flush(struct usb_ep *_ep) static const struct usb_gadget_ops dwc2_udc_ops = { /* current versions must always be self-powered */ +#if CONFIG_IS_ENABLED(DM_USB_GADGET) + .udc_start = dwc2_gadget_start, + .udc_stop = dwc2_gadget_stop, +#endif }; static struct dwc2_udc memory = { @@ -841,12 +902,239 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) return retval; } -int usb_gadget_handle_interrupts(int index) +int dwc2_udc_handle_interrupt(void) { u32 intr_status = readl(®->gintsts); u32 gintmsk = readl(®->gintmsk); if (intr_status & gintmsk) return dwc2_udc_irq(1, (void *)the_controller); + return 0; } + +#if !CONFIG_IS_ENABLED(DM_USB_GADGET) + +int usb_gadget_handle_interrupts(int index) +{ + return dwc2_udc_handle_interrupt(); +} + +#else /* CONFIG_IS_ENABLED(DM_USB_GADGET) */ + +struct dwc2_priv_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + struct phy *phys; + int num_phys; +}; + +int dm_usb_gadget_handle_interrupts(struct udevice *dev) +{ + return dwc2_udc_handle_interrupt(); +} + +int dwc2_phy_setup(struct udevice *dev, struct phy **array, int *num_phys) +{ + int i, ret, count; + struct phy *usb_phys; + + /* Return if no phy declared */ + if (!dev_read_prop(dev, "phys", NULL)) + return 0; + + count = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); + if (count <= 0) + return count; + + usb_phys = devm_kcalloc(dev, count, sizeof(struct phy), + GFP_KERNEL); + if (!usb_phys) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = generic_phy_get_by_index(dev, i, &usb_phys[i]); + if (ret && ret != -ENOENT) { + dev_err(dev, "Failed to get USB PHY%d for %s\n", + i, dev->name); + return ret; + } + } + + for (i = 0; i < count; i++) { + ret = generic_phy_init(&usb_phys[i]); + if (ret) { + dev_err(dev, "Can't init USB PHY%d for %s\n", + i, dev->name); + goto phys_init_err; + } + } + + for (i = 0; i < count; i++) { + ret = generic_phy_power_on(&usb_phys[i]); + if (ret) { + dev_err(dev, "Can't power USB PHY%d for %s\n", + i, dev->name); + goto phys_poweron_err; + } + } + + *array = usb_phys; + *num_phys = count; + + return 0; + +phys_poweron_err: + for (i = count - 1; i >= 0; i--) + generic_phy_power_off(&usb_phys[i]); + + for (i = 0; i < count; i++) + generic_phy_exit(&usb_phys[i]); + + return ret; + +phys_init_err: + for (; i >= 0; i--) + generic_phy_exit(&usb_phys[i]); + + return ret; +} + +void dwc2_phy_shutdown(struct udevice *dev, struct phy *usb_phys, int num_phys) +{ + int i, ret; + + for (i = 0; i < num_phys; i++) { + if (!generic_phy_valid(&usb_phys[i])) + continue; + + ret = generic_phy_power_off(&usb_phys[i]); + ret |= generic_phy_exit(&usb_phys[i]); + if (ret) { + dev_err(dev, "Can't shutdown USB PHY%d for %s\n", + i, dev->name); + } + } +} + +static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) +{ + struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); + int node = dev_of_offset(dev); + + if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) { + dev_dbg(dev, "Invalid mode\n"); + return -ENODEV; + } + + platdata->regs_otg = dev_read_addr(dev); + + platdata->rx_fifo_sz = dev_read_u32_default(dev, "g-rx-fifo-size", 0); + platdata->np_tx_fifo_sz = dev_read_u32_default(dev, + "g-np-tx-fifo-size", 0); + platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0); + + return 0; +} + +static int dwc2_udc_otg_reset_init(struct udevice *dev, + struct reset_ctl_bulk *resets) +{ + int ret; + + ret = reset_get_bulk(dev, resets); + if (ret == -ENOTSUPP) + return 0; + + if (ret) + return ret; + + ret = reset_deassert_bulk(resets); + if (ret) { + reset_release_bulk(resets); + return ret; + } + + return 0; +} + +static int dwc2_udc_otg_clk_init(struct udevice *dev, + struct clk_bulk *clks) +{ + int ret; + + ret = clk_get_bulk(dev, clks); + if (ret == -ENOSYS) + return 0; + + if (ret) + return ret; + + ret = clk_enable_bulk(clks); + if (ret) { + clk_release_bulk(clks); + return ret; + } + + return 0; +} + +static int dwc2_udc_otg_probe(struct udevice *dev) +{ + struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); + struct dwc2_priv_data *priv = dev_get_priv(dev); + int ret; + + ret = dwc2_udc_otg_clk_init(dev, &priv->clks); + if (ret) + return ret; + + ret = dwc2_udc_otg_reset_init(dev, &priv->resets); + if (ret) + return ret; + + ret = dwc2_phy_setup(dev, &priv->phys, &priv->num_phys); + if (ret) + return ret; + + ret = dwc2_udc_probe(platdata); + if (ret) + return ret; + + the_controller->driver = 0; + + ret = usb_add_gadget_udc((struct device *)dev, &the_controller->gadget); + + return ret; +} + +static int dwc2_udc_otg_remove(struct udevice *dev) +{ + struct dwc2_priv_data *priv = dev_get_priv(dev); + + usb_del_gadget_udc(&the_controller->gadget); + + reset_release_bulk(&priv->resets); + + clk_release_bulk(&priv->clks); + + dwc2_phy_shutdown(dev, priv->phys, priv->num_phys); + + return dm_scan_fdt_dev(dev); +} + +static const struct udevice_id dwc2_udc_otg_ids[] = { + { .compatible = "snps,dwc2" }, +}; + +U_BOOT_DRIVER(dwc2_udc_otg) = { + .name = "dwc2-udc-otg", + .id = UCLASS_USB_GADGET_GENERIC, + .of_match = dwc2_udc_otg_ids, + .ofdata_to_platdata = dwc2_udc_otg_ofdata_to_platdata, + .probe = dwc2_udc_otg_probe, + .remove = dwc2_udc_otg_remove, + .platdata_auto_alloc_size = sizeof(struct dwc2_plat_otg_data), + .priv_auto_alloc_size = sizeof(struct dwc2_priv_data), +}; +#endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */ From c2c74f97afff9351077f2236ab6fa5638de9bd86 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:16 +0100 Subject: [PATCH 13/25] usb: dwc2: force reset assert before to probe the driver Reset the hardware to be sure of the device state. Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index af16fc1ed4..8169fdbb11 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1049,7 +1049,12 @@ static int dwc2_udc_otg_reset_init(struct udevice *dev, if (ret) return ret; - ret = reset_deassert_bulk(resets); + ret = reset_assert_bulk(resets); + + if (!ret) { + udelay(2); + ret = reset_deassert_bulk(resets); + } if (ret) { reset_release_bulk(resets); return ret; From 0fdd0bc621f060fcf60fd4ba48a2a32f338ffeac Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:17 +0100 Subject: [PATCH 14/25] usb: dwc2: Add force-b-session-valid support Handle "force-b-session-valid" property from DT. Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg.c | 9 +++++++++ drivers/usb/gadget/dwc2_udc_otg_regs.h | 8 ++++++-- include/usb/dwc2_udc.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 8169fdbb11..146f11e710 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1034,6 +1034,9 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) "g-np-tx-fifo-size", 0); platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0); + platdata->force_b_session_valid = + dev_read_bool(dev, "force-b-session-valid"); + return 0; } @@ -1088,6 +1091,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev) { struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); struct dwc2_priv_data *priv = dev_get_priv(dev); + struct dwc2_usbotg_reg *usbotg_reg = + (struct dwc2_usbotg_reg *)platdata->regs_otg; int ret; ret = dwc2_udc_otg_clk_init(dev, &priv->clks); @@ -1102,6 +1107,10 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (ret) return ret; + if (platdata->force_b_session_valid) + /* Override B session bits : value and enable */ + setbits_le32(&usbotg_reg->gotgctl, B_VALOEN | B_VALOVAL); + ret = dwc2_udc_probe(platdata); if (ret) return ret; diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a1829b3fd1..0aee4ee929 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -83,8 +83,12 @@ struct dwc2_usbotg_reg { /*definitions related to CSR setting */ /* DWC2_UDC_OTG_GOTGCTL */ -#define B_SESSION_VALID (0x1<<19) -#define A_SESSION_VALID (0x1<<18) +#define B_SESSION_VALID BIT(19) +#define A_SESSION_VALID BIT(18) +#define B_VALOVAL BIT(7) +#define B_VALOEN BIT(6) +#define A_VALOVAL BIT(5) +#define A_VALOEN BIT(4) /* DWC2_UDC_OTG_GAHBCFG */ #define PTXFE_HALF (0<<8) diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 4068de045d..3cf20eab92 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -22,6 +22,7 @@ struct dwc2_plat_otg_data { unsigned int rx_fifo_sz; unsigned int np_tx_fifo_sz; unsigned int tx_fifo_sz; + bool force_b_session_valid; }; int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata); From 2d76160f049c42087011cfa0e6e878aa2ed6b406 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:18 +0100 Subject: [PATCH 15/25] usb: dwc2: Add function for session B check Add a new function to check the session B validity, to be use to check cable connection. Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg.c | 9 +++++++++ include/usb/dwc2_udc.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 146f11e710..b1efad115e 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1151,4 +1151,13 @@ U_BOOT_DRIVER(dwc2_udc_otg) = { .platdata_auto_alloc_size = sizeof(struct dwc2_plat_otg_data), .priv_auto_alloc_size = sizeof(struct dwc2_priv_data), }; + +int dwc2_udc_B_session_valid(struct udevice *dev) +{ + struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); + struct dwc2_usbotg_reg *usbotg_reg = + (struct dwc2_usbotg_reg *)platdata->regs_otg; + + return readl(&usbotg_reg->gotgctl) & B_SESSION_VALID; +} #endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */ diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 3cf20eab92..8a426b631e 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -27,4 +27,6 @@ struct dwc2_plat_otg_data { int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata); +int dwc2_udc_B_session_valid(struct udevice *dev); + #endif /* __DWC2_USB_GADGET */ From 5bd97e80730bdda59656ca927d67d62fb2a4ecb6 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:19 +0100 Subject: [PATCH 16/25] usb: dwc2_udc_otg: Read MAX_HW_ENDPOINT from HWCFG4 register Some DWC2 ip variant doesn't use 16 hardware endpoint as hardcoded in the driver. Bits INEps [29:26] of HWCFG4 register allows to get this information. Signed-off-by: Patrice Chotard Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg.c | 11 ++++++++--- drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 17 ++++++++++++----- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index b1efad115e..5c7d131a5d 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -456,6 +456,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); uint32_t dflt_gusbcfg; uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; + u32 max_hw_ep; debug("Reseting OTG controller\n"); @@ -538,9 +539,13 @@ static void reconfig_usbd(struct dwc2_udc *dev) writel((np_tx_fifo_sz << 16) | rx_fifo_sz, ®->gnptxfsiz); - for (i = 1; i < DWC2_MAX_HW_ENDPOINTS; i++) - writel((rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz*(i-1)) | - tx_fifo_sz << 16, ®->dieptxf[i-1]); + /* retrieve the number of IN Endpoints (excluding ep0) */ + max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK) >> + GHWCFG4_NUM_IN_EPS_SHIFT; + + for (i = 0; i < max_hw_ep; i++) + writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz * i)) | + tx_fifo_sz << 16, ®->dieptxf[i]); /* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl); diff --git a/drivers/usb/gadget/dwc2_udc_otg_priv.h b/drivers/usb/gadget/dwc2_udc_otg_priv.h index aaa90187fb..e72b22ac61 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_priv.h +++ b/drivers/usb/gadget/dwc2_udc_otg_priv.h @@ -23,7 +23,6 @@ #define EP_FIFO_SIZE2 1024 /* ep0-control, ep1in-bulk, ep2out-bulk, ep3in-int */ #define DWC2_MAX_ENDPOINTS 4 -#define DWC2_MAX_HW_ENDPOINTS 16 #define WAIT_FOR_SETUP 0 #define DATA_STATE_XMIT 1 diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index 0aee4ee929..a3899236fc 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,22 +60,25 @@ struct dwc2_usbotg_reg { u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ u32 grxfsiz; /* Receive FIFO Size */ u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */ - u8 res1[216]; + + u8 res1[36]; + u32 ghwcfg4; /* User HW Config4 */ + u8 res2[176]; u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */ - u8 res2[1728]; + u8 res3[1728]; /* Device Configuration */ u32 dcfg; /* Device Configuration Register */ u32 dctl; /* Device Control */ u32 dsts; /* Device Status */ - u8 res3[4]; + u8 res4[4]; u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */ u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */ u32 daint; /* Device All Endpoints Interrupt */ u32 daintmsk; /* Device All Endpoints Interrupt Mask */ - u8 res4[224]; + u8 res5[224]; struct dwc2_dev_in_endp in_endp[16]; struct dwc2_dev_out_endp out_endp[16]; - u8 res5[768]; + u8 res6[768]; struct ep_fifo ep[16]; }; @@ -273,4 +276,8 @@ struct dwc2_usbotg_reg { /* Device ALL Endpoints Interrupt Register (DAINT) */ #define DAINT_IN_EP_INT(x) (x << 0) #define DAINT_OUT_EP_INT(x) (x << 16) + +/* User HW Config4 */ +#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) +#define GHWCFG4_NUM_IN_EPS_SHIFT 26 #endif From 763bb106f66c147b7d0c3046dbba66a07d7a9dd2 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 29 Mar 2019 15:42:20 +0100 Subject: [PATCH 17/25] usb: dwc2_udc_otg: Add tx_fifo_sz array support All TX fifo size can be different, add tx_fifo_sz_array[] into dwc2_plat_otg_data to be able to set them. tx_fifo_sz_array[] is 17 Bytes long and can contains max 16 tx fifo size (synopsys IP supports max 16 IN endpoints). First entry of tx_fifo_sz_array[] is the number of valid fifo size the array contains. In case of tx_fifo_sz_array[] doesn't contains the same number of element than max hardware endpoint, display a warning message. Compatibility with board which doesn't use tx_fifo_sz_array[] (Rockchip rk322x/rk3128/rv1108/rk3288/rk3036) is kept. Signed-off-by: Patrice Chotard Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/dwc2_udc_otg.c | 14 ++++++++++++-- include/usb/dwc2_udc.h | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 5c7d131a5d..106dec5d09 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -457,6 +457,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) uint32_t dflt_gusbcfg; uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; u32 max_hw_ep; + int pdata_hw_ep; debug("Reseting OTG controller\n"); @@ -542,11 +543,20 @@ static void reconfig_usbd(struct dwc2_udc *dev) /* retrieve the number of IN Endpoints (excluding ep0) */ max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT; + pdata_hw_ep = dev->pdata->tx_fifo_sz_nb; + + /* tx_fifo_sz_nb should equal to number of IN Endpoint */ + if (pdata_hw_ep && max_hw_ep != pdata_hw_ep) + pr_warn("Got %d hw endpoint but %d tx-fifo-size in array !!\n", + max_hw_ep, pdata_hw_ep); + + for (i = 0; i < max_hw_ep; i++) { + if (pdata_hw_ep) + tx_fifo_sz = dev->pdata->tx_fifo_sz_array[i]; - for (i = 0; i < max_hw_ep; i++) writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz * i)) | tx_fifo_sz << 16, ®->dieptxf[i]); - + } /* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl); while (readl(®->grstctl) & RX_FIFO_FLUSH) diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 8a426b631e..369f6fbd4a 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -9,6 +9,7 @@ #define __DWC2_USB_GADGET #define PHY0_SLEEP (1 << 5) +#define DWC2_MAX_HW_ENDPOINTS 16 struct dwc2_plat_otg_data { void *priv; @@ -22,6 +23,8 @@ struct dwc2_plat_otg_data { unsigned int rx_fifo_sz; unsigned int np_tx_fifo_sz; unsigned int tx_fifo_sz; + unsigned int tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS]; + unsigned char tx_fifo_sz_nb; bool force_b_session_valid; }; From 931e9d7aa7228867eec7e33fd45718e6018cc96d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:21 +0100 Subject: [PATCH 18/25] usb: dwc2: add support for STM32MP1 Add compatible "st,stm32mp1-hsotg" and associated driver data to manage the usb33d-supply and the ST specific register for VBus sensing. Signed-off-by: Patrick Delaunay # Conflicts: # drivers/usb/gadget/dwc2_udc_otg.c Reviewed-by: Lukasz Majewski --- doc/device-tree-bindings/usb/dwc2.txt | 2 ++ drivers/usb/gadget/dwc2_udc_otg.c | 45 ++++++++++++++++++++++++++ drivers/usb/gadget/dwc2_udc_otg_regs.h | 10 ++++-- include/usb/dwc2_udc.h | 1 + 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt index 6dc3c4a344..eb60ffae58 100644 --- a/doc/device-tree-bindings/usb/dwc2.txt +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -37,6 +37,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties - g-rx-fifo-size: size of rx fifo size in gadget mode. - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode. - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. +- usb33d-supply: external VBUS and ID sensing comparators supply, in order to + perform OTG operation, used on STM32MP1 SoCs. Deprecated properties: - g-use-dma: gadget DMA mode is automatically detected diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 106dec5d09..3fdaa102ba 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -942,6 +942,7 @@ struct dwc2_priv_data { struct reset_ctl_bulk resets; struct phy *phys; int num_phys; + struct udevice *usb33d_supply; }; int dm_usb_gadget_handle_interrupts(struct udevice *dev) @@ -1036,6 +1037,8 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) { struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); int node = dev_of_offset(dev); + ulong drvdata; + void (*set_params)(struct dwc2_plat_otg_data *data); if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) { dev_dbg(dev, "Invalid mode\n"); @@ -1052,9 +1055,28 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) platdata->force_b_session_valid = dev_read_bool(dev, "force-b-session-valid"); + /* force platdata according compatible */ + drvdata = dev_get_driver_data(dev); + if (drvdata) { + set_params = (void *)drvdata; + set_params(platdata); + } + return 0; } +static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) +{ + p->activate_stm_id_vb_detection = true; + p->usb_gusbcfg = + 0 << 15 /* PHY Low Power Clock sel*/ + | 0x9 << 10 /* USB Turnaround time (0x9 for HS phy) */ + | 0 << 9 /* [0:HNP disable,1:HNP enable]*/ + | 0 << 8 /* [0:SRP disable 1:SRP enable]*/ + | 0 << 6 /* 0: high speed utmi+, 1: full speed serial*/ + | 0x7 << 0; /* FS timeout calibration**/ +} + static int dwc2_udc_otg_reset_init(struct udevice *dev, struct reset_ctl_bulk *resets) { @@ -1122,6 +1144,26 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (ret) return ret; + if (CONFIG_IS_ENABLED(DM_REGULATOR) && + platdata->activate_stm_id_vb_detection && + !platdata->force_b_session_valid) { + ret = device_get_supply_regulator(dev, "usb33d-supply", + &priv->usb33d_supply); + if (ret) { + dev_err(dev, "can't get voltage level detector supply\n"); + return ret; + } + ret = regulator_set_enable(priv->usb33d_supply, true); + if (ret) { + dev_err(dev, "can't enable voltage level detector supply\n"); + return ret; + } + /* Enable vbus sensing */ + setbits_le32(&usbotg_reg->ggpio, + GGPIO_STM32_OTG_GCCFG_VBDEN | + GGPIO_STM32_OTG_GCCFG_IDEN); + } + if (platdata->force_b_session_valid) /* Override B session bits : value and enable */ setbits_le32(&usbotg_reg->gotgctl, B_VALOEN | B_VALOVAL); @@ -1154,6 +1196,9 @@ static int dwc2_udc_otg_remove(struct udevice *dev) static const struct udevice_id dwc2_udc_otg_ids[] = { { .compatible = "snps,dwc2" }, + { .compatible = "st,stm32mp1-hsotg", + .data = (ulong)dwc2_set_stm32mp1_hsotg_params }, + {}, }; U_BOOT_DRIVER(dwc2_udc_otg) = { diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a3899236fc..b2a28d7a5d 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,8 +60,9 @@ struct dwc2_usbotg_reg { u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ u32 grxfsiz; /* Receive FIFO Size */ u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */ - - u8 res1[36]; + u8 res0[12]; + u32 ggpio; /* 0x038 */ + u8 res1[20]; u32 ghwcfg4; /* User HW Config4 */ u8 res2[176]; u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */ @@ -280,4 +281,9 @@ struct dwc2_usbotg_reg { /* User HW Config4 */ #define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) #define GHWCFG4_NUM_IN_EPS_SHIFT 26 + +/* OTG general core configuration register (OTG_GCCFG:0x38) for STM32MP1 */ +#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21) +#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22) + #endif diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 369f6fbd4a..a6c12212a9 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -26,6 +26,7 @@ struct dwc2_plat_otg_data { unsigned int tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS]; unsigned char tx_fifo_sz_nb; bool force_b_session_valid; + bool activate_stm_id_vb_detection; }; int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata); From 995d228bce85fde34ef726933fea614837dbc94d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:22 +0100 Subject: [PATCH 19/25] stm32mp1: remove CONFIG_USB_DWC2, HOST support for USBO Remove the HOST support for STM32MP1 USBO device = OTG DWC2. The current DWC2 driver have no dynamic detection of device, So it is dangerous to have start 3V3 when PC is connected to the micro USB connector. => it is preferable to have only DEVICE support CONFIG_USB_GADGET_DWC2_OTG for OTG port See DWC3 driver for clean dual role support... Signed-off-by: Patrick Delaunay --- configs/stm32mp15_basic_defconfig | 1 - configs/stm32mp15_trusted_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 6781adb81e..b6c19724ca 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -71,7 +71,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y -CONFIG_USB_DWC2=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index a050cee691..ed2a2e61c8 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -62,7 +62,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y -CONFIG_USB_DWC2=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 From c31000c534c6d62dd3a3ae58f30eae3ed572d856 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:23 +0100 Subject: [PATCH 20/25] stm32mp1: migrate USBOTG device to driver model Use the DWC2 device driver with DM_USB_GADGET support and cleanup the USB support in STM32MP1 board. Signed-off-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 3 +- arch/arm/dts/stm32mp157a-dk1.dts | 18 ++- arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 1 + arch/arm/dts/stm32mp157c.dtsi | 2 +- board/st/stm32mp1/stm32mp1.c | 165 ++--------------------- configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 7 files changed, 33 insertions(+), 158 deletions(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index af7acfa037..7e2c5d0de3 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -11,6 +11,7 @@ aliases { i2c3 = &i2c4; mmc0 = &sdmmc1; + usb0 = &usbotg_hs; }; config { u-boot,boot-led = "heartbeat"; @@ -190,7 +191,7 @@ }; &usbotg_hs { - usb1600; + force-b-session-valid; hnp-srp-disable; }; diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts index 0882765d0c..b8ef82015b 100644 --- a/arch/arm/dts/stm32mp157a-dk1.dts +++ b/arch/arm/dts/stm32mp157a-dk1.dts @@ -249,11 +249,25 @@ status = "okay"; }; -&usbphyc { - vdd3v3-supply = <&vdd_usb>; +&usbotg_hs { + dr_mode = "peripheral"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; status = "okay"; }; +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; + &vrefbuf { regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2500000>; diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi index 8b92b1fa2e..5b19e44d2f 100644 --- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi @@ -12,6 +12,7 @@ i2c4 = &i2c5; pinctrl2 = &stmfx_pinctrl; spi0 = &qspi; + usb0 = &usbotg_hs; }; }; diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index 472637bb55..94634336a5 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -825,7 +825,7 @@ }; usbotg_hs: usb-otg@49000000 { - compatible = "snps,dwc2"; + compatible = "st,stm32mp1-hsotg", "snps,dwc2"; reg = <0x49000000 0x10000>; clocks = <&rcc USBO_K>; clock-names = "otg"; diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 24d299ac33..b369b7a54b 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,18 +7,17 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include #include -#include /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 @@ -58,11 +57,6 @@ */ DECLARE_GLOBAL_DATA_PTR; -#define STM32MP_GUSBCFG 0x40002407 - -#define STM32MP_GGPIO 0x38 -#define STM32MP_GGPIO_VBUS_SENSING BIT(21) - #define USB_WARNING_LOW_THRESHOLD_UV 660000 #define USB_START_LOW_THRESHOLD_UV 1230000 #define USB_START_HIGH_THRESHOLD_UV 2100000 @@ -155,149 +149,22 @@ static void board_key_check(void) #endif } -static struct dwc2_plat_otg_data stm32mp_otg_data = { - .usb_gusbcfg = STM32MP_GUSBCFG, -}; +#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) -static struct reset_ctl usbotg_reset; - -int board_usb_init(int index, enum usb_init_type init) +int g_dnl_board_usb_cable_connected(void) { - struct fdtdec_phandle_args args; - struct udevice *dev; - const void *blob = gd->fdt_blob; - struct clk clk; - struct phy phy; - int node; - int phy_provider; + struct udevice *dwc2_udc_otg; int ret; - /* find the usb otg node */ - node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); - if (node < 0) { - debug("Not found usb_otg device\n"); - return -ENODEV; - } + ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, + DM_GET_DRIVER(dwc2_udc_otg), + &dwc2_udc_otg); + if (!ret) + debug("dwc2_udc_otg init failed\n"); - if (!fdtdec_get_is_enabled(blob, node)) { - debug("stm32 usbotg is disabled in the device tree\n"); - return -ENODEV; - } - - /* Enable clock */ - ret = fdtdec_parse_phandle_with_args(blob, node, "clocks", - "#clock-cells", 0, 0, &args); - if (ret) { - debug("usbotg has no clocks defined in the device tree\n"); - return ret; - } - - ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev); - if (ret) - return ret; - - if (args.args_count != 1) { - debug("Can't find clock ID in the device tree\n"); - return -ENODATA; - } - - clk.dev = dev; - clk.id = args.args[0]; - - ret = clk_enable(&clk); - if (ret) { - debug("Failed to enable usbotg clock\n"); - return ret; - } - - /* Reset */ - ret = fdtdec_parse_phandle_with_args(blob, node, "resets", - "#reset-cells", 0, 0, &args); - if (ret) { - debug("usbotg has no resets defined in the device tree\n"); - goto clk_err; - } - - ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev); - if (ret || args.args_count != 1) - goto clk_err; - - usbotg_reset.dev = dev; - usbotg_reset.id = args.args[0]; - - reset_assert(&usbotg_reset); - udelay(2); - reset_deassert(&usbotg_reset); - - /* Get USB PHY */ - ret = fdtdec_parse_phandle_with_args(blob, node, "phys", - "#phy-cells", 0, 0, &args); - if (!ret) { - phy_provider = fdt_parent_offset(blob, args.node); - ret = uclass_get_device_by_of_offset(UCLASS_PHY, - phy_provider, &dev); - if (ret) - goto clk_err; - - phy.dev = dev; - phy.id = fdtdec_get_uint(blob, args.node, "reg", -1); - - ret = generic_phy_power_on(&phy); - if (ret) { - debug("unable to power on the phy\n"); - goto clk_err; - } - - ret = generic_phy_init(&phy); - if (ret) { - debug("failed to init usb phy\n"); - goto phy_power_err; - } - } - - /* Parse and store data needed for gadget */ - stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); - if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) { - debug("usbotg: can't get base address\n"); - ret = -ENODATA; - goto phy_init_err; - } - - stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node, - "g-rx-fifo-size", 0); - stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node, - "g-np-tx-fifo-size", 0); - stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node, - "g-tx-fifo-size", 0); - /* Enable voltage level detector */ - if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply", - NULL, 0, 0, &args))) { - if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR, - args.node, &dev)) { - ret = regulator_set_enable(dev, true); - if (ret) { - debug("Failed to enable usb33d\n"); - goto phy_init_err; - } - } - } - /* Enable vbus sensing */ - setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO, - STM32MP_GGPIO_VBUS_SENSING); - - return dwc2_udc_probe(&stm32mp_otg_data); - -phy_init_err: - generic_phy_exit(&phy); - -phy_power_err: - generic_phy_power_off(&phy); - -clk_err: - clk_disable(&clk); - - return ret; + return dwc2_udc_B_session_valid(dwc2_udc_otg); } +#endif /* CONFIG_USB_GADGET */ static int get_led(struct udevice **dev, char *led_string) { @@ -438,16 +305,6 @@ static int board_check_usb_power(void) return 0; } -int board_usb_cleanup(int index, enum usb_init_type init) -{ - /* Reset usbotg */ - reset_assert(&usbotg_reset); - udelay(2); - reset_deassert(&usbotg_reset); - - return 0; -} - static void sysconf_init(void) { #ifndef CONFIG_STM32MP1_TRUSTED diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index b6c19724ca..fd164fa596 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -69,6 +69,7 @@ CONFIG_SERIAL_RX_BUFFER=y CONFIG_STM32_SERIAL=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_GADGET=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index ed2a2e61c8..f82b770bc8 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -60,6 +60,7 @@ CONFIG_SERIAL_RX_BUFFER=y CONFIG_STM32_SERIAL=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_GADGET=y From 6fe7dd3327d552bacf4266d7f1ed074bf98ffb92 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 29 Mar 2019 15:42:24 +0100 Subject: [PATCH 21/25] stm32mp1: add stusb1600 support for DK1 and DK2 board The DK1 and DK2 boards use the USB Type-C controller STUSB1600. This patch updates: - the device tree to add the I2C node in the DT - the board stm32mp1 to probe this I2C device and use this controller to check cable detection. - the DWC2 driver to support a new dt property "u-boot,force-b-session-valid" which forces B session and device mode; it is a workaround because the VBUS sensing and ID detection isn't available with stusb1600. Signed-off-by: Patrick Delaunay Reviewed-by: Lukasz Majewski --- arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 +++ arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 2 +- arch/arm/dts/stm32mp157a-dk1.dts | 18 ++++++++ board/st/stm32mp1/stm32mp1.c | 56 ++++++++++++++++++++++++ doc/device-tree-bindings/usb/dwc2.txt | 2 + drivers/usb/gadget/dwc2_udc_otg.c | 8 +++- 6 files changed, 90 insertions(+), 3 deletions(-) diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi index c069875486..0aae69b0a0 100644 --- a/arch/arm/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi @@ -375,6 +375,13 @@ }; }; + stusb1600_pins_a: stusb1600-0 { + pins { + pinmux = ; + bias-pull-up; + }; + }; + uart4_pins_a: uart4-0 { pins1 { pinmux = ; /* UART4_TX */ diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 7e2c5d0de3..0f32a38dc9 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -191,7 +191,7 @@ }; &usbotg_hs { - force-b-session-valid; + u-boot,force-b-session-valid; hnp-srp-disable; }; diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts index b8ef82015b..e36773dde9 100644 --- a/arch/arm/dts/stm32mp157a-dk1.dts +++ b/arch/arm/dts/stm32mp157a-dk1.dts @@ -67,6 +67,24 @@ /delete-property/dmas; /delete-property/dma-names; + typec: stusb1600@28 { + compatible = "st,stusb1600"; + reg = <0x28>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpioi>; + pinctrl-names = "default"; + pinctrl-0 = <&stusb1600_pins_a>; + + status = "okay"; + + typec_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "sink"; + power-opmode = "default"; + }; + }; + pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index b369b7a54b..76917b022e 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -9,15 +9,18 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include #include +#include /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 @@ -151,11 +154,64 @@ static void board_key_check(void) #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) +/* STMicroelectronics STUSB1600 Type-C controller */ +#define STUSB1600_CC_CONNECTION_STATUS 0x0E + +/* STUSB1600_CC_CONNECTION_STATUS bitfields */ +#define STUSB1600_CC_ATTACH BIT(0) + +static int stusb1600_init(struct udevice **dev_stusb1600) +{ + ofnode node; + struct udevice *dev, *bus; + int ret; + u32 chip_addr; + + *dev_stusb1600 = NULL; + + /* if node stusb1600 is present, means DK1 or DK2 board */ + node = ofnode_by_compatible(ofnode_null(), "st,stusb1600"); + if (!ofnode_valid(node)) + return -ENODEV; + + ret = ofnode_read_u32(node, "reg", &chip_addr); + if (ret) + return -EINVAL; + + ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node), + &bus); + if (ret) { + printf("bus for stusb1600 not found\n"); + return -ENODEV; + } + + ret = dm_i2c_probe(bus, chip_addr, 0, &dev); + if (!ret) + *dev_stusb1600 = dev; + + return ret; +} + +static int stusb1600_cable_connected(struct udevice *dev) +{ + u8 status; + + if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1)) + return 0; + + return status & STUSB1600_CC_ATTACH; +} + +#include int g_dnl_board_usb_cable_connected(void) { + struct udevice *stusb1600; struct udevice *dwc2_udc_otg; int ret; + if (!stusb1600_init(&stusb1600)) + return stusb1600_cable_connected(stusb1600); + ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, DM_GET_DRIVER(dwc2_udc_otg), &dwc2_udc_otg); diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt index eb60ffae58..61493f7cb0 100644 --- a/doc/device-tree-bindings/usb/dwc2.txt +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -39,6 +39,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. - usb33d-supply: external VBUS and ID sensing comparators supply, in order to perform OTG operation, used on STM32MP1 SoCs. +- u-boot,force-b-session-valid: force B-peripheral session instead of relying on + VBUS sensing (only valid when dr_mode = "peripheral" and for u-boot). Deprecated properties: - g-use-dma: gadget DMA mode is automatically detected diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3fdaa102ba..494ab533cc 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1053,7 +1053,7 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0); platdata->force_b_session_valid = - dev_read_bool(dev, "force-b-session-valid"); + dev_read_bool(dev, "u-boot,force-b-session-valid"); /* force platdata according compatible */ drvdata = dev_get_driver_data(dev); @@ -1075,6 +1075,9 @@ static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) | 0 << 8 /* [0:SRP disable 1:SRP enable]*/ | 0 << 6 /* 0: high speed utmi+, 1: full speed serial*/ | 0x7 << 0; /* FS timeout calibration**/ + + if (p->force_b_session_valid) + p->usb_gusbcfg |= 1 << 30; /* FDMOD: Force device mode */ } static int dwc2_udc_otg_reset_init(struct udevice *dev, @@ -1166,7 +1169,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (platdata->force_b_session_valid) /* Override B session bits : value and enable */ - setbits_le32(&usbotg_reg->gotgctl, B_VALOEN | B_VALOVAL); + setbits_le32(&usbotg_reg->gotgctl, + A_VALOEN | A_VALOVAL | B_VALOEN | B_VALOVAL); ret = dwc2_udc_probe(platdata); if (ret) From b762aa126e648fa9bc62fc8997b01a4a73089367 Mon Sep 17 00:00:00 2001 From: Alex Kiernan Date: Tue, 9 Apr 2019 05:30:05 +0000 Subject: [PATCH 22/25] fastboot: Replace literal 32 with PART_NAME_LEN Where we have to compute partition names, rather than using a hardcoded 32 for the partition name length, replace with PART_NAME_LEN. Signed-off-by: Alex Kiernan Reviewed-by: Eugeniu Rosca --- drivers/fastboot/fb_mmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index d04d8a448c..90ca81da9b 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -31,13 +31,13 @@ static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc, ret = part_get_info_by_name(dev_desc, name, info); if (ret < 0) { - /* strlen("fastboot_partition_alias_") + 32(part_name) + 1 */ - char env_alias_name[25 + 32 + 1]; + /* strlen("fastboot_partition_alias_") + PART_NAME_LEN + 1 */ + char env_alias_name[25 + PART_NAME_LEN + 1]; char *aliased_part_name; /* check for alias */ strcpy(env_alias_name, "fastboot_partition_alias_"); - strncat(env_alias_name, name, 32); + strncat(env_alias_name, name, PART_NAME_LEN); aliased_part_name = env_get(env_alias_name); if (aliased_part_name != NULL) ret = part_get_info_by_name(dev_desc, From d73d9fb7e2384b55a6c1866a5d914a621cf8563a Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Tue, 9 Apr 2019 21:11:40 +0200 Subject: [PATCH 23/25] fastboot: add support for 'getvar platform' Our R-Car3 Android userspace relies on the output of 'fastboot getvar platform' and U-Boot currently is not able to handle it: host $> fastboot getvar platform getvar:platform FAILED (remote: Variable not implemented) finished. total time: 0.001s We either have the option of adding 'fastboot.platform' variable to the default/saved environment as a workaround or add proper 'fastboot getvar platform' support in U-Boot via this patch. In the latter case, other platforms can benefit from it too. Note that R-Car3 already exports 'platform' environment variable via v2019.01 commit 00e4b57e9e71c3 ("ARM: rmobile: Set environment variable containing CPU type"). Signed-off-by: Eugeniu Rosca --- drivers/fastboot/fb_getvar.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index 91a774a345..4268628f5e 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -17,6 +17,7 @@ static void getvar_downloadsize(char *var_parameter, char *response); static void getvar_serialno(char *var_parameter, char *response); static void getvar_version_baseband(char *var_parameter, char *response); static void getvar_product(char *var_parameter, char *response); +static void getvar_platform(char *var_parameter, char *response); static void getvar_current_slot(char *var_parameter, char *response); static void getvar_slot_suffixes(char *var_parameter, char *response); static void getvar_has_slot(char *var_parameter, char *response); @@ -55,6 +56,9 @@ static const struct { }, { .variable = "product", .dispatch = getvar_product + }, { + .variable = "platform", + .dispatch = getvar_platform }, { .variable = "current-slot", .dispatch = getvar_current_slot @@ -117,6 +121,16 @@ static void getvar_product(char *var_parameter, char *response) fastboot_fail("Board not set", response); } +static void getvar_platform(char *var_parameter, char *response) +{ + const char *p = env_get("platform"); + + if (p) + fastboot_okay(p, response); + else + fastboot_fail("platform not set", response); +} + static void getvar_current_slot(char *var_parameter, char *response) { /* A/B not implemented, for now always return _a */ From 85d0aec0fda21da28ac886b2bf973f0e1c1b8d41 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 18 Apr 2019 17:18:39 +0200 Subject: [PATCH 24/25] usb: reload watchdog during ums command Reload the watchdog in the mass storage command ums to avoid reboot during the usb waiting loop when the host doesn't send any request. Signed-off-by: Patrick Delaunay --- cmd/usb_mass_storage.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c index 753ae4f42a..570cf3aa50 100644 --- a/cmd/usb_mass_storage.c +++ b/cmd/usb_mass_storage.c @@ -14,6 +14,7 @@ #include #include #include +#include static int ums_read_sector(struct ums *ums_dev, ulong start, lbaint_t blkcnt, void *buf) @@ -226,6 +227,8 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag, rc = CMD_RET_SUCCESS; goto cleanup_register; } + + WATCHDOG_RESET(); } cleanup_register: From 7fd9f31c6bd13609da61b985cf8f5f65ebebd913 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 17 Apr 2019 16:46:13 +0200 Subject: [PATCH 25/25] usb: dwc2: fix gadget disconnect This fixes a disconnect issue detected with fastboot command, when using dwc2 driver. - On u-boot side: uboot>$ fastboot 0 - On USB host PC side, few seconds after PC>$ fastboot reboot # Get stuck, uboot target never reboots By enabling DEBUG_ISR logs, the bus suspend interrupt is seen before the PC command has been issued. When the USB bus suspend occurs, there's a HACK that disables the fastboot (composite driver). Here is the call stack upon USB bus suspend: - dwc2_handle_usb_suspend_intr() - dev->driver->disconnect() - composite_disconnect() - reset_config() - f->disable() - fastboot_disable() - usb_ep_disable(f_fb->out_ep); - usb_ep_disable(f_fb->in_ep); .. other disable calls. When the resume interrupt happens, everything has been disabled, then nothing happens. fastboot command gets stuck on HOST side. Remove original HACK, that disconnects the composite driver upon USB bus suspend. Implement disconnect detection instead: - check GINTSTS OTG interrupt - read GOTGINT register - check GOTGINT, SesEndDet bit (e.g. session end) This is inspired by what is implemented currently in Linux dwc2 driver. Signed-off-by: Fabrice Gasnier Reviewed-by: Marek Vasut --- drivers/usb/gadget/dwc2_udc_otg_regs.h | 6 +++++- drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index b2a28d7a5d..434db5ba39 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -94,6 +94,9 @@ struct dwc2_usbotg_reg { #define A_VALOVAL BIT(5) #define A_VALOEN BIT(4) +/* DWC2_UDC_OTG_GOTINT */ +#define GOTGINT_SES_END_DET (1<<2) + /* DWC2_UDC_OTG_GAHBCFG */ #define PTXFE_HALF (0<<8) #define PTXFE_ZERO (1<<8) @@ -126,6 +129,7 @@ struct dwc2_usbotg_reg { #define INT_NP_TX_FIFO_EMPTY (0x1<<5) #define INT_RX_FIFO_NOT_EMPTY (0x1<<4) #define INT_SOF (0x1<<3) +#define INT_OTG (0x1<<2) #define INT_DEV_MODE (0x0<<0) #define INT_HOST_MODE (0x1<<1) #define INT_GOUTNakEff (0x01<<7) @@ -254,7 +258,7 @@ struct dwc2_usbotg_reg { /* Masks definitions */ #define GINTMSK_INIT (INT_OUT_EP | INT_IN_EP | INT_RESUME | INT_ENUMDONE\ - | INT_RESET | INT_SUSPEND) + | INT_RESET | INT_SUSPEND | INT_OTG) #define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE | AHB_ERROR|TRANSFER_DONE) #define DIEPMSK_INIT (NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE) #define GAHBCFG_INIT (PTXFE_HALF | NPTXFE_HALF | MODE_DMA | BURST_INCR4\ diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index a75af4987f..7eb632d3b1 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -467,7 +467,7 @@ static void process_ep_out_intr(struct dwc2_udc *dev) static int dwc2_udc_irq(int irq, void *_dev) { struct dwc2_udc *dev = _dev; - u32 intr_status; + u32 intr_status, gotgint; u32 usb_status, gintmsk; unsigned long flags = 0; @@ -521,14 +521,24 @@ static int dwc2_udc_irq(int irq, void *_dev) && dev->driver) { if (dev->driver->suspend) dev->driver->suspend(&dev->gadget); + } + } - /* HACK to let gadget detect disconnected state */ + if (intr_status & INT_OTG) { + gotgint = readl(®->gotgint); + debug_cond(DEBUG_ISR, + "\tOTG interrupt: (GOTGINT):0x%x\n", gotgint); + + if (gotgint & GOTGINT_SES_END_DET) { + debug_cond(DEBUG_ISR, "\t\tSession End Detected\n"); + /* Let gadget detect disconnected state */ if (dev->driver->disconnect) { spin_unlock_irqrestore(&dev->lock, flags); dev->driver->disconnect(&dev->gadget); spin_lock_irqsave(&dev->lock, flags); } } + writel(gotgint, ®->gotgint); } if (intr_status & INT_RESUME) {