dwc3-uniphier.c 2.8 KB

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