diff options
author | Tom Rini | 2019-04-21 19:00:04 -0400 |
---|---|---|
committer | Tom Rini | 2019-04-21 19:00:04 -0400 |
commit | 6c5f8dd540d7a8eff244d4c27a09451ca12c8d20 (patch) | |
tree | 9eaba554d99f15aa5dfc302c338f59895f9b43e4 | |
parent | b4fde1633e67bb618fd33aad6e6322b7cecf1154 (diff) | |
parent | 7fd9f31c6bd13609da61b985cf8f5f65ebebd913 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-usb
- Various fastboot, dwc2/stm32 updates
39 files changed, 680 insertions, 251 deletions
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi index c0698754861..0aae69b0a04 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 = <STM32_PINMUX('I', 11, ANALOG)>; + bias-pull-up; + }; + }; + uart4_pins_a: uart4-0 { pins1 { pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */ diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index af7acfa0375..0f32a38dc94 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; + 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 0882765d0c9..e36773dde91 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>; @@ -249,11 +267,25 @@ status = "okay"; }; +&usbotg_hs { + dr_mode = "peripheral"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + status = "okay"; +}; + &usbphyc { - vdd3v3-supply = <&vdd_usb>; 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-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts index 2664c9ce904..0366782fda9 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-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi index 8b92b1fa2ee..5b19e44d2fb 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 7eb4bee31cf..94634336a5e 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"; @@ -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/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 24d299ac33b..76917b022ed 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,7 +7,9 @@ #include <config.h> #include <clk.h> #include <dm.h> +#include <g_dnl.h> #include <generic-phy.h> +#include <i2c.h> #include <led.h> #include <misc.h> #include <phy.h> @@ -58,11 +60,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 +152,75 @@ 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; +/* STMicroelectronics STUSB1600 Type-C controller */ +#define STUSB1600_CC_CONNECTION_STATUS 0x0E -int board_usb_init(int index, enum usb_init_type init) +/* STUSB1600_CC_CONNECTION_STATUS bitfields */ +#define STUSB1600_CC_ATTACH BIT(0) + +static int stusb1600_init(struct udevice **dev_stusb1600) { - 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; + ofnode node; + struct udevice *dev, *bus; int ret; + u32 chip_addr; - /* 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; - } + *dev_stusb1600 = NULL; - if (!fdtdec_get_is_enabled(blob, node)) { - debug("stm32 usbotg is disabled in the device tree\n"); + /* if node stusb1600 is present, means DK1 or DK2 board */ + node = ofnode_by_compatible(ofnode_null(), "st,stusb1600"); + if (!ofnode_valid(node)) 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); + ret = ofnode_read_u32(node, "reg", &chip_addr); if (ret) - return ret; + return -EINVAL; - 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); + ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node), + &bus); if (ret) { - debug("usbotg has no resets defined in the device tree\n"); - goto clk_err; + printf("bus for stusb1600 not found\n"); + return -ENODEV; } - 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 = dm_i2c_probe(bus, chip_addr, 0, &dev); + if (!ret) + *dev_stusb1600 = dev; - ret = generic_phy_init(&phy); - if (ret) { - debug("failed to init usb phy\n"); - goto phy_power_err; - } - } + return ret; +} - /* 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; - } +static int stusb1600_cable_connected(struct udevice *dev) +{ + u8 status; - 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); + if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1)) + return 0; - return dwc2_udc_probe(&stm32mp_otg_data); + return status & STUSB1600_CC_ATTACH; +} -phy_init_err: - generic_phy_exit(&phy); +#include <usb/dwc2_udc.h> +int g_dnl_board_usb_cable_connected(void) +{ + struct udevice *stusb1600; + struct udevice *dwc2_udc_otg; + int ret; -phy_power_err: - generic_phy_power_off(&phy); + if (!stusb1600_init(&stusb1600)) + return stusb1600_cable_connected(stusb1600); -clk_err: - clk_disable(&clk); + 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"); - 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 +361,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/cmd/dfu.c b/cmd/dfu.c index c9ba0621970..91a750a4fca 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 "<USB_controller> <interface> <dev> [list]\n" " - device firmware upgrade via <USB_controller>\n" diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c index 753ae4f42a7..570cf3aa508 100644 --- a/cmd/usb_mass_storage.c +++ b/cmd/usb_mass_storage.c @@ -14,6 +14,7 @@ #include <part.h> #include <usb.h> #include <usb_mass_storage.h> +#include <watchdog.h> 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: diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig index 6afda724537..ffe013fa2df 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 a396a393105..105ff01d14d 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 1746df90f41..a37966bc6dc 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 d2d6f2fb6e4..ff131eb6017 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 6b0d0242f2e..63cb240ea89 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 4578f74a620..57cd54bac26 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 739b0786f34..31ba5158b58 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 a6c36eda503..944dd0db3c8 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/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 6781adb81e7..fd164fa596d 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -69,9 +69,9 @@ 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_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 a050cee6918..f82b770bc87 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -60,9 +60,9 @@ 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_DWC2=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 diff --git a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt index 725ae71ae65..da98407403d 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/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt new file mode 100644 index 00000000000..61493f7cb0c --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -0,0 +1,58 @@ +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. +- 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 + +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/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index 4d264c985d7..4268628f5ef 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); @@ -56,13 +57,16 @@ static const struct { .variable = "product", .dispatch = getvar_product }, { + .variable = "platform", + .dispatch = getvar_platform + }, { .variable = "current-slot", .dispatch = getvar_current_slot }, { .variable = "slot-suffixes", .dispatch = getvar_slot_suffixes }, { - .variable = "has_slot", + .variable = "has-slot", .dispatch = getvar_has_slot #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) }, { @@ -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 */ diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index 4c1c7fd2cd8..90ca81da9b5 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, @@ -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; } diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 8e98b4b627b..6f1119036d7 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 */ @@ -51,17 +52,17 @@ 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; - int index; bool init; bool powered; } 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; @@ -154,6 +155,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); @@ -165,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; @@ -184,6 +194,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; @@ -203,6 +214,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; } @@ -213,17 +236,6 @@ 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 (ret) - return ret; - } - - if (usbphyc_phy->vdda1v8) { - ret = regulator_set_enable(usbphyc_phy->vdda1v8, true); - if (ret) - return ret; - } if (usbphyc_phy->vdd) { ret = regulator_set_enable(usbphyc_phy->vdd, true); if (ret) @@ -247,18 +259,6 @@ 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 (ret) - return ret; - } - - if (usbphyc_phy->vdda1v8) { - ret = regulator_set_enable(usbphyc_phy->vdda1v8, false); - if (ret) - return ret; - } - if (usbphyc_phy->vdd) { ret = regulator_set_enable(usbphyc_phy->vdd, false); if (ret) @@ -298,19 +298,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; } @@ -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 @@ -359,7 +375,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", @@ -367,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); } diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3c7ad033e3f..494ab533cca 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -18,11 +18,17 @@ */ #undef DEBUG #include <common.h> +#include <clk.h> +#include <dm.h> +#include <generic-phy.h> +#include <malloc.h> +#include <reset.h> + #include <linux/errno.h> #include <linux/list.h> -#include <malloc.h> #include <linux/usb/ch9.h> +#include <linux/usb/otg.h> #include <linux/usb/gadget.h> #include <asm/byteorder.h> @@ -31,6 +37,8 @@ #include <asm/mach-types.h> +#include <power/regulator.h> + #include "dwc2_udc_otg_regs.h" #include "dwc2_udc_otg_priv.h" @@ -140,7 +148,6 @@ static struct usb_ep_ops dwc2_ep_ops = { /***********************************************************/ -void __iomem *regs_otg; struct dwc2_usbotg_reg *reg; bool dfu_usb_get_reset(void) @@ -223,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. */ @@ -297,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 @@ -400,6 +456,8 @@ 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; + int pdata_hw_ep; debug("Reseting OTG controller\n"); @@ -482,10 +540,23 @@ 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; + 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]; + 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) @@ -731,6 +802,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 = { @@ -818,8 +893,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; @@ -844,12 +917,311 @@ 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; + struct udevice *usb33d_supply; +}; + +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); + 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"); + 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); + + platdata->force_b_session_valid = + dev_read_bool(dev, "u-boot,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**/ + + 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, + struct reset_ctl_bulk *resets) +{ + int ret; + + ret = reset_get_bulk(dev, resets); + if (ret == -ENOTSUPP) + return 0; + + if (ret) + return ret; + + ret = reset_assert_bulk(resets); + + if (!ret) { + udelay(2); + 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); + struct dwc2_usbotg_reg *usbotg_reg = + (struct dwc2_usbotg_reg *)platdata->regs_otg; + 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; + + 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, + A_VALOEN | A_VALOVAL | B_VALOEN | B_VALOVAL); + + 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" }, + { .compatible = "st,stm32mp1-hsotg", + .data = (ulong)dwc2_set_stm32mp1_hsotg_params }, + {}, +}; + +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), +}; + +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/drivers/usb/gadget/dwc2_udc_otg_priv.h b/drivers/usb/gadget/dwc2_udc_otg_priv.h index aaa90187fb7..e72b22ac61e 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 a1829b3fd12..434db5ba39a 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,22 +60,26 @@ 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 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 */ - 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]; }; @@ -83,8 +87,15 @@ 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_GOTINT */ +#define GOTGINT_SES_END_DET (1<<2) /* DWC2_UDC_OTG_GAHBCFG */ #define PTXFE_HALF (0<<8) @@ -118,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) @@ -246,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\ @@ -269,4 +281,13 @@ 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 + +/* 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/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index a75af4987f8..7eb632d3b14 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); + } + } + + if (intr_status & INT_OTG) { + gotgint = readl(®->gotgint); + debug_cond(DEBUG_ISR, + "\tOTG interrupt: (GOTGINT):0x%x\n", gotgint); - /* HACK to let gadget detect disconnected state */ + 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) { diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index f8f2205a62d..75005ccdd1b 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 @@ -54,6 +55,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 0834ff50219..7721907d8f0 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 ccbdc0a3356..98ec0d626ea 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 fb9c2a6d04d..3d4d08aa70e 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 ae9b75bb87a..84c801d10a9 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 601b30dffd5..7309e7d4831 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 4372280d2bb..db990fcb2b4 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 48f1f7baccb..a535d0c2f2d 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 f44a4280f43..1170f24748d 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/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 4068de045dc..a6c12212a9b 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,8 +23,14 @@ 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; + bool activate_stm_id_vb_detection; }; int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata); +int dwc2_udc_B_session_valid(struct udevice *dev); + #endif /* __DWC2_USB_GADGET */ diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 5092c3fb4ce..421362d9532 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 |