1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2 /* 3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved 4 */ 5 #include <config.h> 6 #include <common.h> 7 #include <led.h> 8 #include <clk.h> 9 #include <dm.h> 10 #include <generic-phy.h> 11 #include <phy.h> 12 #include <reset.h> 13 #include <usb.h> 14 #include <asm/arch/stm32.h> 15 #include <asm/io.h> 16 #include <power/regulator.h> 17 #include <usb/dwc2_udc.h> 18 19 /* 20 * Get a global data pointer 21 */ 22 DECLARE_GLOBAL_DATA_PTR; 23 24 #define STM32MP_GUSBCFG 0x40002407 25 26 #define STM32MP_GGPIO 0x38 27 #define STM32MP_GGPIO_VBUS_SENSING BIT(21) 28 29 static struct dwc2_plat_otg_data stm32mp_otg_data = { 30 .usb_gusbcfg = STM32MP_GUSBCFG, 31 }; 32 33 static struct reset_ctl usbotg_reset; 34 35 int board_usb_init(int index, enum usb_init_type init) 36 { 37 struct fdtdec_phandle_args args; 38 struct udevice *dev; 39 const void *blob = gd->fdt_blob; 40 struct clk clk; 41 struct phy phy; 42 int node; 43 int phy_provider; 44 int ret; 45 46 /* find the usb otg node */ 47 node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); 48 if (node < 0) { 49 debug("Not found usb_otg device\n"); 50 return -ENODEV; 51 } 52 53 if (!fdtdec_get_is_enabled(blob, node)) { 54 debug("stm32 usbotg is disabled in the device tree\n"); 55 return -ENODEV; 56 } 57 58 /* Enable clock */ 59 ret = fdtdec_parse_phandle_with_args(blob, node, "clocks", 60 "#clock-cells", 0, 0, &args); 61 if (ret) { 62 debug("usbotg has no clocks defined in the device tree\n"); 63 return ret; 64 } 65 66 ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev); 67 if (ret) 68 return ret; 69 70 if (args.args_count != 1) { 71 debug("Can't find clock ID in the device tree\n"); 72 return -ENODATA; 73 } 74 75 clk.dev = dev; 76 clk.id = args.args[0]; 77 78 ret = clk_enable(&clk); 79 if (ret) { 80 debug("Failed to enable usbotg clock\n"); 81 return ret; 82 } 83 84 /* Reset */ 85 ret = fdtdec_parse_phandle_with_args(blob, node, "resets", 86 "#reset-cells", 0, 0, &args); 87 if (ret) { 88 debug("usbotg has no resets defined in the device tree\n"); 89 goto clk_err; 90 } 91 92 ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev); 93 if (ret || args.args_count != 1) 94 goto clk_err; 95 96 usbotg_reset.dev = dev; 97 usbotg_reset.id = args.args[0]; 98 99 reset_assert(&usbotg_reset); 100 udelay(2); 101 reset_deassert(&usbotg_reset); 102 103 /* Get USB PHY */ 104 ret = fdtdec_parse_phandle_with_args(blob, node, "phys", 105 "#phy-cells", 0, 0, &args); 106 if (!ret) { 107 phy_provider = fdt_parent_offset(blob, args.node); 108 ret = uclass_get_device_by_of_offset(UCLASS_PHY, 109 phy_provider, &dev); 110 if (ret) 111 goto clk_err; 112 113 phy.dev = dev; 114 phy.id = fdtdec_get_uint(blob, args.node, "reg", -1); 115 116 ret = generic_phy_power_on(&phy); 117 if (ret) { 118 debug("unable to power on the phy\n"); 119 goto clk_err; 120 } 121 122 ret = generic_phy_init(&phy); 123 if (ret) { 124 debug("failed to init usb phy\n"); 125 goto phy_power_err; 126 } 127 } 128 129 /* Parse and store data needed for gadget */ 130 stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); 131 if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) { 132 debug("usbotg: can't get base address\n"); 133 ret = -ENODATA; 134 goto phy_init_err; 135 } 136 137 stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node, 138 "g-rx-fifo-size", 0); 139 stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node, 140 "g-np-tx-fifo-size", 0); 141 stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node, 142 "g-tx-fifo-size", 0); 143 /* Enable voltage level detector */ 144 if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply", 145 NULL, 0, 0, &args))) { 146 if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR, 147 args.node, &dev)) { 148 ret = regulator_set_enable(dev, true); 149 if (ret) { 150 debug("Failed to enable usb33d\n"); 151 goto phy_init_err; 152 } 153 } 154 } 155 /* Enable vbus sensing */ 156 setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO, 157 STM32MP_GGPIO_VBUS_SENSING); 158 159 return dwc2_udc_probe(&stm32mp_otg_data); 160 161 phy_init_err: 162 generic_phy_exit(&phy); 163 164 phy_power_err: 165 generic_phy_power_off(&phy); 166 167 clk_err: 168 clk_disable(&clk); 169 170 return ret; 171 } 172 173 int board_usb_cleanup(int index, enum usb_init_type init) 174 { 175 /* Reset usbotg */ 176 reset_assert(&usbotg_reset); 177 udelay(2); 178 reset_deassert(&usbotg_reset); 179 180 return 0; 181 } 182 183 int board_late_init(void) 184 { 185 return 0; 186 } 187 188 /* board dependent setup after realloc */ 189 int board_init(void) 190 { 191 /* address of boot parameters */ 192 gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100; 193 194 if (IS_ENABLED(CONFIG_LED)) 195 led_default_state(); 196 197 return 0; 198 } 199