usb_phy.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /*
  2. * Copyright (c) 2019 - 2021, Broadcom
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <platform_usb.h>
  7. #include <usb_phy.h>
  8. #define USB_PHY_ALREADY_STARTED (-2)
  9. #define USB_MAX_DEVICES 2
  10. #define USB3H_USB2DRD_PHY 0
  11. #define USB3_DRD_PHY 1
  12. /* Common bit fields for all the USB2 phy */
  13. #define USB2_PHY_ISO DRDU2_U2PHY_ISO
  14. #define USB2_AFE_PLL_PWRDWNB DRDU2_U2AFE_PLL_PWRDWNB
  15. #define USB2_AFE_BG_PWRDWNB DRDU2_U2AFE_BG_PWRDWNB
  16. #define USB2_AFE_LDO_PWRDWNB DRDU2_U2AFE_LDO_PWRDWNB
  17. #define USB2_CTRL_CORERDY DRDU2_U2CTRL_CORERDY
  18. #define USB2_PHY_PCTL_MASK DRDU2_U2PHY_PCTL_MASK
  19. #define USB2_PHY_PCTL_OFFSET DRDU2_U2PHY_PCTL_OFFSET
  20. #define USB2_PHY_PCTL_VAL U2PHY_PCTL_VAL
  21. #define USB2_PLL_RESETB DRDU2_U2PLL_RESETB
  22. #define USB2_PHY_RESETB DRDU2_U2PHY_RESETB
  23. static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS];
  24. static usb_phy_t usb_phy_info[2U] = {
  25. {DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY},
  26. {0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY}
  27. };
  28. typedef struct {
  29. void *pcd_id;
  30. } usb_platform_dev;
  31. /* index 0: USB3H + USB2 DRD, 1: USB3 DRD */
  32. static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = {
  33. {&usb_phy_info[0U]},
  34. {&usb_phy_info[1U]}
  35. };
  36. static int32_t pll_lock_check(uint32_t address, uint32_t bit)
  37. {
  38. uint32_t retry;
  39. uint32_t data;
  40. retry = PLL_LOCK_RETRY_COUNT;
  41. do {
  42. data = mmio_read_32(address);
  43. if ((data & bit) != 0U) {
  44. return 0;
  45. }
  46. udelay(1);
  47. } while (--retry != 0);
  48. ERROR("%s(): FAIL (0x%08x)\n", __func__, address);
  49. return -1;
  50. }
  51. /*
  52. * USB2 PHY using external FSM bringup sequence
  53. * Total #3 USB2 phys. All phys has the same
  54. * bringup sequence. Register bit fields for
  55. * some of the PHY's are different.
  56. * Bit fields which are different are passed using
  57. * struct u2_phy_ext_fsm with bit-fields and register addr.
  58. */
  59. static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy)
  60. {
  61. mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
  62. /* Delay as per external FSM spec */
  63. udelay(10U);
  64. mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
  65. /* Delay as per external FSM spec */
  66. udelay(10U);
  67. mmio_clrbits_32(u2_phy->phy_ctrl_reg,
  68. (USB2_AFE_BG_PWRDWNB |
  69. USB2_AFE_PLL_PWRDWNB |
  70. USB2_AFE_LDO_PWRDWNB |
  71. USB2_CTRL_CORERDY));
  72. mmio_clrsetbits_32(u2_phy->phy_ctrl_reg,
  73. (USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET),
  74. (USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET));
  75. /* Delay as per external FSM spec */
  76. udelay(160U);
  77. mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY);
  78. /* Delay as per external FSM spec */
  79. udelay(50U);
  80. mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB);
  81. /* Delay as per external FSM spec */
  82. udelay(200U);
  83. mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin);
  84. mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB);
  85. /* Delay as per external FSM spec */
  86. udelay(10U);
  87. mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin);
  88. /* Delay as per external FSM spec */
  89. udelay(10U);
  90. mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB);
  91. /* Delay as per external FSM spec */
  92. udelay(10U);
  93. mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
  94. /* Delay as per external FSM spec */
  95. udelay(10U);
  96. mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
  97. /* Delay as per external FSM spec */
  98. udelay(1U);
  99. mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB);
  100. mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB);
  101. }
  102. static int32_t usb3h_u2_phy_power_on(uint32_t base)
  103. {
  104. int32_t status;
  105. struct u2_phy_ext_fsm u2_phy;
  106. u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL;
  107. u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL;
  108. u2_phy.phy_iddq = USB3H_U2PHY_IDDQ;
  109. u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL;
  110. u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN;
  111. u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN;
  112. u2_phy_ext_fsm_power_on(&u2_phy);
  113. status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK);
  114. if (status != 0) {
  115. /* re-try by toggling the PLL reset */
  116. mmio_clrbits_32(base + USB3H_U2PLL_CTRL,
  117. (uint32_t)USB3H_U2PLL_RESETB);
  118. mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB);
  119. status = pll_lock_check(base + USB3H_U2PLL_CTRL,
  120. USB3H_U2PLL_LOCK);
  121. if (status != 0)
  122. ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
  123. base + USB3H_U2PLL_CTRL);
  124. }
  125. mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL,
  126. (USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET),
  127. (U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET));
  128. return status;
  129. }
  130. static int32_t usb3h_u3_phy_power_on(uint32_t base)
  131. {
  132. int32_t status;
  133. /* Set pctl with mode and soft reset */
  134. mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL,
  135. (USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET),
  136. (U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET));
  137. mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL,
  138. (uint32_t) USB3H_U3SSPLL_SUSPEND_EN);
  139. mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START);
  140. mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB);
  141. /* Time to stabilize the PLL Control */
  142. mdelay(1U);
  143. status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL,
  144. USB3H_U3PLL_SS_LOCK);
  145. return status;
  146. }
  147. static int32_t drdu3_u2_phy_power_on(uint32_t base)
  148. {
  149. int32_t status;
  150. struct u2_phy_ext_fsm u2_phy;
  151. u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL;
  152. u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL;
  153. u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ;
  154. u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL;
  155. u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN;
  156. u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN;
  157. u2_phy_ext_fsm_power_on(&u2_phy);
  158. status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK);
  159. if (status != 0) {
  160. /* re-try by toggling the PLL reset */
  161. mmio_clrbits_32(base + DRDU3_U2PLL_CTRL,
  162. (uint32_t)DRDU2_U2PLL_RESETB);
  163. mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB);
  164. status = pll_lock_check(base + DRDU3_U2PLL_CTRL,
  165. DRDU3_U2PLL_LOCK);
  166. if (status != 0) {
  167. ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
  168. base + DRDU3_U2PLL_CTRL);
  169. }
  170. }
  171. mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL,
  172. (DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET),
  173. (U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET));
  174. return status;
  175. }
  176. static int32_t drdu3_u3_phy_power_on(uint32_t base)
  177. {
  178. int32_t status;
  179. /* Set pctl with mode and soft reset */
  180. mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL,
  181. (DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET),
  182. (U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET));
  183. mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL,
  184. (uint32_t) DRDU3_U3SSPLL_SUSPEND_EN);
  185. mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START);
  186. mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB);
  187. /* Time to stabilize the PLL Control */
  188. mdelay(1U);
  189. status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL,
  190. DRDU3_U3PLL_SS_LOCK);
  191. return status;
  192. }
  193. static int32_t drdu2_u2_phy_power_on(uint32_t base)
  194. {
  195. int32_t status;
  196. struct u2_phy_ext_fsm u2_phy;
  197. u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL;
  198. u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL;
  199. u2_phy.phy_iddq = DRDU2_U2IDDQ;
  200. u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL;
  201. u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I;
  202. u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I;
  203. u2_phy_ext_fsm_power_on(&u2_phy);
  204. status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK);
  205. if (status != 0) {
  206. /* re-try by toggling the PLL reset */
  207. mmio_clrbits_32(base + DRDU2_U2PLL_CTRL,
  208. (uint32_t)DRDU2_U2PLL_RESETB);
  209. mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB);
  210. status = pll_lock_check(base + DRDU2_U2PLL_CTRL,
  211. DRDU2_U2PLL_LOCK);
  212. if (status != 0)
  213. ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
  214. base + DRDU2_U2PLL_CTRL);
  215. }
  216. mmio_clrsetbits_32(base + DRDU2_PHY_CTRL,
  217. (DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET),
  218. (U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET));
  219. return status;
  220. }
  221. void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port)
  222. {
  223. usb_phy_t *phy = phy_port->p;
  224. switch (phy_port->port_id) {
  225. case USB3HS_PORT:
  226. mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
  227. (uint32_t) USB3H_U2CTRL_CORERDY);
  228. mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
  229. USB3H_U2CTRL_CORERDY);
  230. break;
  231. case DRDU2_PORT:
  232. mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
  233. (uint32_t) DRDU2_U2CTRL_CORERDY);
  234. mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
  235. DRDU2_U2CTRL_CORERDY);
  236. break;
  237. }
  238. }
  239. void u3drd_phy_reset(usb_phy_port_t *phy_port)
  240. {
  241. usb_phy_t *phy = phy_port->p;
  242. if (phy_port->port_id == DRD3HS_PORT) {
  243. mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
  244. (uint32_t) DRDU3_U2CTRL_CORERDY);
  245. mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
  246. DRDU3_U2CTRL_CORERDY);
  247. }
  248. }
  249. static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port)
  250. {
  251. usb_phy_t *phy = phy_port->p;
  252. int32_t status;
  253. switch (phy_port->port_id) {
  254. case USB3SS_PORT:
  255. mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
  256. (uint32_t) USB3H_DISABLE_USB30_P0);
  257. status = usb3h_u3_phy_power_on(phy->usb3hreg);
  258. if (status != 0) {
  259. goto err_usb3h_phy_on;
  260. }
  261. break;
  262. case USB3HS_PORT:
  263. mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
  264. (uint32_t) USB3H_DISABLE_EUSB_P1);
  265. mmio_setbits_32(AXI_DEBUG_CTRL,
  266. AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
  267. mmio_setbits_32(USB3H_DEBUG_CTRL,
  268. USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
  269. mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
  270. USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN);
  271. /* Delay as per external FSM spec */
  272. udelay(10U);
  273. mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
  274. USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN);
  275. status = usb3h_u2_phy_power_on(phy->usb3hreg);
  276. if (status != 0) {
  277. goto err_usb3h_phy_on;
  278. }
  279. break;
  280. case DRDU2_PORT:
  281. mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
  282. (uint32_t) USB3H_DISABLE_EUSB_P0);
  283. mmio_setbits_32(AXI_DEBUG_CTRL,
  284. AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
  285. mmio_setbits_32(USB3H_DEBUG_CTRL,
  286. USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
  287. mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
  288. DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I);
  289. /* Delay as per external FSM spec */
  290. udelay(10U);
  291. mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
  292. DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I);
  293. status = drdu2_u2_phy_power_on(phy->drdu2reg);
  294. if (status != 0) {
  295. mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
  296. USB3H_DISABLE_EUSB_P0);
  297. goto err_drdu2_phy_on;
  298. }
  299. break;
  300. }
  301. /* Device Mode */
  302. if (phy_port->port_id == DRDU2_PORT) {
  303. mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL,
  304. DRDU2_BDC_AXI_SOFT_RST_N);
  305. mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
  306. DRDU2_U2SOFT_RST_N);
  307. }
  308. /* Host Mode */
  309. mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL,
  310. USB3H_XHC_AXI_SOFT_RST_N);
  311. mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
  312. return 0U;
  313. err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
  314. (USB3H_DISABLE_EUSB_P1 |
  315. USB3H_DISABLE_USB30_P0));
  316. err_drdu2_phy_on:
  317. return status;
  318. }
  319. static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port)
  320. {
  321. usb_phy_t *phy = phy_port->p;
  322. int32_t status;
  323. switch (phy_port->port_id) {
  324. case DRD3SS_PORT:
  325. mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
  326. (uint32_t) DRDU3_DISABLE_USB30_P0);
  327. status = drdu3_u3_phy_power_on(phy->drdu3reg);
  328. if (status != 0) {
  329. goto err_drdu3_phy_on;
  330. }
  331. break;
  332. case DRD3HS_PORT:
  333. mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
  334. (uint32_t) DRDU3_DISABLE_EUSB_P0);
  335. mmio_setbits_32(AXI_DEBUG_CTRL,
  336. AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
  337. mmio_setbits_32(USB3H_DEBUG_CTRL,
  338. USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
  339. mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
  340. DRDU3_U2PHY_DFE_SWITCH_PWRONIN);
  341. /* Delay as per external FSM spec */
  342. udelay(10U);
  343. mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
  344. DRDU3_U2PHY_DFE_SWITCH_PWROKIN);
  345. status = drdu3_u2_phy_power_on(phy->drdu3reg);
  346. if (status != 0) {
  347. goto err_drdu3_phy_on;
  348. }
  349. /* Host Mode */
  350. mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
  351. DRDU3_XHC_AXI_SOFT_RST_N);
  352. mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
  353. DRDU3_U3XHC_SOFT_RST_N);
  354. /* Device Mode */
  355. mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
  356. DRDU3_BDC_AXI_SOFT_RST_N);
  357. mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
  358. DRDU3_U3BDC_SOFT_RST_N);
  359. break;
  360. }
  361. return 0U;
  362. err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
  363. (DRDU3_DISABLE_EUSB_P0 |
  364. DRDU3_DISABLE_USB30_P0));
  365. return status;
  366. }
  367. static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port)
  368. {
  369. usb_phy_t *p = phy_port->p;
  370. switch (phy_port->port_id) {
  371. case USB3SS_PORT:
  372. mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
  373. USB3H_DISABLE_USB30_P0);
  374. break;
  375. case USB3HS_PORT:
  376. mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
  377. USB3H_DISABLE_EUSB_P1);
  378. break;
  379. case DRDU2_PORT:
  380. mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
  381. USB3H_DISABLE_EUSB_P0);
  382. break;
  383. }
  384. }
  385. static void u3drd_phy_power_off(usb_phy_port_t *phy_port)
  386. {
  387. usb_phy_t *p = phy_port->p;
  388. switch (phy_port->port_id) {
  389. case DRD3SS_PORT:
  390. mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
  391. DRDU3_DISABLE_USB30_P0);
  392. break;
  393. case DRD3HS_PORT:
  394. mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
  395. DRDU3_DISABLE_EUSB_P0);
  396. break;
  397. }
  398. }
  399. int32_t usb_info_fill(usb_phy_t *phy_info)
  400. {
  401. int32_t index;
  402. if (phy_info->initialized != 0U) {
  403. return USB_PHY_ALREADY_STARTED;
  404. }
  405. if (phy_info->phy_id == USB3H_DRDU2_PHY) {
  406. phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U];
  407. phy_info->ports_enabled = 0x7U;
  408. } else {
  409. phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U];
  410. phy_info->ports_enabled = 0x3U;
  411. }
  412. for (index = MAX_NR_PORTS - 1U; index > -1; index--) {
  413. phy_info->phy_port[index].enabled = (phy_info->ports_enabled
  414. >> index) & 0x1U;
  415. phy_info->phy_port[index].p = phy_info;
  416. phy_info->phy_port[index].port_id = index;
  417. }
  418. return 0U;
  419. }
  420. int32_t usb_phy_init(usb_platform_dev *device)
  421. {
  422. int32_t status;
  423. usb_phy_t *phy_info;
  424. uint32_t index;
  425. phy_info = (usb_phy_t *)device->pcd_id;
  426. status = usb_info_fill(phy_info);
  427. if (status != 0) {
  428. return (status == USB_PHY_ALREADY_STARTED) ? 0 : status;
  429. }
  430. for (index = 0U; index < MAX_NR_PORTS; index++) {
  431. if (phy_info->phy_port[index].enabled != 0U) {
  432. switch (phy_info->phy_id) {
  433. case USB3H_DRDU2_PHY:
  434. status =
  435. u3h_u2drd_phy_power_on(&phy_info->
  436. phy_port[index]);
  437. break;
  438. default:
  439. status =
  440. u3drd_phy_power_on(&phy_info->
  441. phy_port[index]);
  442. }
  443. }
  444. }
  445. phy_info->initialized = !status;
  446. return status;
  447. }
  448. void usb_phy_shutdown(usb_platform_dev *device)
  449. {
  450. usb_phy_t *phy_info;
  451. uint32_t index;
  452. phy_info = (usb_phy_t *)device->pcd_id;
  453. phy_info->initialized = 0U;
  454. for (index = 0U; index < MAX_NR_PORTS; index++) {
  455. if (phy_info->phy_port[index].enabled != 0U) {
  456. switch (phy_info->phy_id) {
  457. case USB3H_DRDU2_PHY:
  458. u3h_u2drd_phy_power_off(&phy_info->
  459. phy_port[index]);
  460. break;
  461. case DRDU3_PHY:
  462. u3drd_phy_power_off(&phy_info->phy_port[index]);
  463. break;
  464. default:
  465. INFO("%s: invalid phy id 0x%x\n", __func__,
  466. phy_info->phy_id);
  467. }
  468. }
  469. }
  470. }
  471. int32_t usb_xhci_init(usb_platform_dev *device)
  472. {
  473. int32_t status;
  474. status = usb_phy_init(device);
  475. if (status == USB_PHY_ALREADY_STARTED) {
  476. status = 0U;
  477. }
  478. return status;
  479. }
  480. int32_t usb_device_init(unsigned int usb_func)
  481. {
  482. int32_t status;
  483. int32_t devices_initialized = 0U;
  484. if ((usb_func & USB3H_USB2DRD) != 0U) {
  485. status = usb_xhci_init(
  486. &xhci_devices_configs[USB3H_USB2DRD_PHY]);
  487. if (status == 0) {
  488. devices_initialized++;
  489. } else {
  490. ERROR("%s(): USB3H_USB2DRD init failure\n", __func__);
  491. }
  492. }
  493. if ((usb_func & USB3_DRD) != 0U) {
  494. status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]);
  495. if (status == 0) {
  496. devices_initialized++;
  497. } else {
  498. ERROR("%s(): USB3_DRD init failure\n", __func__);
  499. }
  500. }
  501. return devices_initialized;
  502. }