dwc3-uniphier.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * UniPhier Specific Glue Layer for DWC3
  4. *
  5. * Copyright (C) 2016-2017 Socionext Inc.
  6. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  7. */
  8. #include <dm.h>
  9. #include <linux/bitops.h>
  10. #include <linux/errno.h>
  11. #include <linux/io.h>
  12. #include <linux/sizes.h>
  13. #define UNIPHIER_PRO4_DWC3_RESET 0x40
  14. #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5)
  15. #define UNIPHIER_PRO4_DWC3_RESET_XLINK BIT(4)
  16. #define UNIPHIER_PRO4_DWC3_RESET_PHY_SS BIT(2)
  17. #define UNIPHIER_PRO5_DWC3_RESET 0x00
  18. #define UNIPHIER_PRO5_DWC3_RESET_PHY_S1 BIT(17)
  19. #define UNIPHIER_PRO5_DWC3_RESET_PHY_S0 BIT(16)
  20. #define UNIPHIER_PRO5_DWC3_RESET_XLINK BIT(15)
  21. #define UNIPHIER_PRO5_DWC3_RESET_XIOMMU BIT(14)
  22. #define UNIPHIER_PXS2_DWC3_RESET 0x00
  23. #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15)
  24. static int uniphier_pro4_dwc3_init(void __iomem *regs)
  25. {
  26. u32 tmp;
  27. tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET);
  28. tmp &= ~UNIPHIER_PRO4_DWC3_RESET_PHY_SS;
  29. tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK;
  30. writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET);
  31. return 0;
  32. }
  33. static int uniphier_pro5_dwc3_init(void __iomem *regs)
  34. {
  35. u32 tmp;
  36. tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET);
  37. tmp &= ~(UNIPHIER_PRO5_DWC3_RESET_PHY_S1 |
  38. UNIPHIER_PRO5_DWC3_RESET_PHY_S0);
  39. tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU;
  40. writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET);
  41. return 0;
  42. }
  43. static int uniphier_pxs2_dwc3_init(void __iomem *regs)
  44. {
  45. u32 tmp;
  46. tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET);
  47. tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK;
  48. writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET);
  49. return 0;
  50. }
  51. static int uniphier_dwc3_probe(struct udevice *dev)
  52. {
  53. fdt_addr_t base;
  54. void __iomem *regs;
  55. int (*init)(void __iomem *regs);
  56. int ret;
  57. base = devfdt_get_addr(dev);
  58. if (base == FDT_ADDR_T_NONE)
  59. return -EINVAL;
  60. regs = ioremap(base, SZ_32K);
  61. if (!regs)
  62. return -ENOMEM;
  63. init = (typeof(init))dev_get_driver_data(dev);
  64. ret = init(regs);
  65. if (ret)
  66. dev_err(dev, "failed to init glue layer\n");
  67. iounmap(regs);
  68. return ret;
  69. }
  70. static const struct udevice_id uniphier_dwc3_match[] = {
  71. {
  72. .compatible = "socionext,uniphier-pro4-dwc3",
  73. .data = (ulong)uniphier_pro4_dwc3_init,
  74. },
  75. {
  76. .compatible = "socionext,uniphier-pro5-dwc3",
  77. .data = (ulong)uniphier_pro5_dwc3_init,
  78. },
  79. {
  80. .compatible = "socionext,uniphier-pxs2-dwc3",
  81. .data = (ulong)uniphier_pxs2_dwc3_init,
  82. },
  83. {
  84. .compatible = "socionext,uniphier-ld20-dwc3",
  85. .data = (ulong)uniphier_pxs2_dwc3_init,
  86. },
  87. {
  88. .compatible = "socionext,uniphier-pxs3-dwc3",
  89. .data = (ulong)uniphier_pxs2_dwc3_init,
  90. },
  91. { /* sentinel */ }
  92. };
  93. U_BOOT_DRIVER(usb_xhci) = {
  94. .name = "uniphier-dwc3",
  95. .id = UCLASS_SIMPLE_BUS,
  96. .of_match = uniphier_dwc3_match,
  97. .probe = uniphier_dwc3_probe,
  98. };