xhci-omap.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * OMAP USB HOST xHCI Controller
  3. *
  4. * (C) Copyright 2013
  5. * Texas Instruments, <www.ti.com>
  6. *
  7. * Author: Dan Murphy <dmurphy@ti.com>
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <common.h>
  12. #include <usb.h>
  13. #include <asm-generic/errno.h>
  14. #include <asm/omap_common.h>
  15. #include <asm/arch/cpu.h>
  16. #include <asm/arch/sys_proto.h>
  17. #include <linux/compat.h>
  18. #include <linux/usb/dwc3.h>
  19. #include <linux/usb/xhci-omap.h>
  20. #include "xhci.h"
  21. /* Declare global data pointer */
  22. DECLARE_GLOBAL_DATA_PTR;
  23. static struct omap_xhci omap;
  24. inline int __board_usb_init(int index, enum usb_init_type init)
  25. {
  26. return 0;
  27. }
  28. int board_usb_init(int index, enum usb_init_type init)
  29. __attribute__((weak, alias("__board_usb_init")));
  30. static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode)
  31. {
  32. clrsetbits_le32(&dwc3_reg->g_ctl,
  33. DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG),
  34. DWC3_GCTL_PRTCAPDIR(mode));
  35. }
  36. static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg)
  37. {
  38. /* Before Resetting PHY, put Core in Reset */
  39. setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET);
  40. omap_reset_usb_phy(dwc3_reg);
  41. /* After PHYs are stable we can take Core out of reset state */
  42. clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET);
  43. }
  44. static int dwc3_core_init(struct dwc3 *dwc3_reg)
  45. {
  46. u32 reg;
  47. u32 revision;
  48. unsigned int dwc3_hwparams1;
  49. revision = readl(&dwc3_reg->g_snpsid);
  50. /* This should read as U3 followed by revision number */
  51. if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) {
  52. puts("this is not a DesignWare USB3 DRD Core\n");
  53. return -1;
  54. }
  55. dwc3_core_soft_reset(dwc3_reg);
  56. dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1);
  57. reg = readl(&dwc3_reg->g_ctl);
  58. reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
  59. reg &= ~DWC3_GCTL_DISSCRAMBLE;
  60. switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) {
  61. case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
  62. reg &= ~DWC3_GCTL_DSBLCLKGTNG;
  63. break;
  64. default:
  65. debug("No power optimization available\n");
  66. }
  67. /*
  68. * WORKAROUND: DWC3 revisions <1.90a have a bug
  69. * where the device can fail to connect at SuperSpeed
  70. * and falls back to high-speed mode which causes
  71. * the device to enter a Connect/Disconnect loop
  72. */
  73. if ((revision & DWC3_REVISION_MASK) < 0x190a)
  74. reg |= DWC3_GCTL_U2RSTECN;
  75. writel(reg, &dwc3_reg->g_ctl);
  76. return 0;
  77. }
  78. static int omap_xhci_core_init(struct omap_xhci *omap)
  79. {
  80. int ret = 0;
  81. usb_phy_power(1);
  82. omap_enable_phy(omap);
  83. ret = dwc3_core_init(omap->dwc3_reg);
  84. if (ret) {
  85. debug("%s:failed to initialize core\n", __func__);
  86. return ret;
  87. }
  88. /* We are hard-coding DWC3 core to Host Mode */
  89. dwc3_set_mode(omap->dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
  90. return ret;
  91. }
  92. static void omap_xhci_core_exit(struct omap_xhci *omap)
  93. {
  94. usb_phy_power(0);
  95. }
  96. int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
  97. {
  98. struct omap_xhci *ctx = &omap;
  99. int ret = 0;
  100. ctx->hcd = (struct xhci_hccr *)OMAP_XHCI_BASE;
  101. ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET);
  102. ctx->usb3_phy = (struct omap_usb3_phy *)OMAP_OCP1_SCP_BASE;
  103. ctx->otg_wrapper = (struct omap_dwc_wrapper *)OMAP_OTG_WRAPPER_BASE;
  104. ret = board_usb_init(index, USB_INIT_HOST);
  105. if (ret != 0) {
  106. puts("Failed to initialize board for USB\n");
  107. return ret;
  108. }
  109. ret = omap_xhci_core_init(ctx);
  110. if (ret < 0) {
  111. puts("Failed to initialize xhci\n");
  112. return ret;
  113. }
  114. *hccr = (struct xhci_hccr *)(OMAP_XHCI_BASE);
  115. *hcor = (struct xhci_hcor *)((uint32_t) *hccr
  116. + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
  117. debug("omap-xhci: init hccr %x and hcor %x hc_length %d\n",
  118. (uint32_t)*hccr, (uint32_t)*hcor,
  119. (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
  120. return ret;
  121. }
  122. void xhci_hcd_stop(int index)
  123. {
  124. struct omap_xhci *ctx = &omap;
  125. omap_xhci_core_exit(ctx);
  126. }