ulpi.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * ulpi.c - DesignWare USB3 Controller's ULPI PHY interface
  4. *
  5. * Copyright (C) 2015 Intel Corporation
  6. *
  7. * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
  8. */
  9. #include <linux/delay.h>
  10. #include <linux/time64.h>
  11. #include <linux/ulpi/regs.h>
  12. #include "core.h"
  13. #include "io.h"
  14. #define DWC3_ULPI_ADDR(a) \
  15. ((a >= ULPI_EXT_VENDOR_SPECIFIC) ? \
  16. DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \
  17. DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a))
  18. #define DWC3_ULPI_BASE_DELAY DIV_ROUND_UP(NSEC_PER_SEC, 60000000L)
  19. static int dwc3_ulpi_busyloop(struct dwc3 *dwc, u8 addr, bool read)
  20. {
  21. unsigned long ns = 5L * DWC3_ULPI_BASE_DELAY;
  22. unsigned int count = 10000;
  23. u32 reg;
  24. if (addr >= ULPI_EXT_VENDOR_SPECIFIC)
  25. ns += DWC3_ULPI_BASE_DELAY;
  26. if (read)
  27. ns += DWC3_ULPI_BASE_DELAY;
  28. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
  29. if (reg & DWC3_GUSB2PHYCFG_SUSPHY)
  30. usleep_range(1000, 1200);
  31. while (count--) {
  32. ndelay(ns);
  33. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
  34. if (reg & DWC3_GUSB2PHYACC_DONE)
  35. return 0;
  36. cpu_relax();
  37. }
  38. return -ETIMEDOUT;
  39. }
  40. static int dwc3_ulpi_read(struct device *dev, u8 addr)
  41. {
  42. struct dwc3 *dwc = dev_get_drvdata(dev);
  43. u32 reg;
  44. int ret;
  45. reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
  46. dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
  47. ret = dwc3_ulpi_busyloop(dwc, addr, true);
  48. if (ret)
  49. return ret;
  50. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
  51. return DWC3_GUSB2PHYACC_DATA(reg);
  52. }
  53. static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
  54. {
  55. struct dwc3 *dwc = dev_get_drvdata(dev);
  56. u32 reg;
  57. reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
  58. reg |= DWC3_GUSB2PHYACC_WRITE | val;
  59. dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
  60. return dwc3_ulpi_busyloop(dwc, addr, false);
  61. }
  62. static const struct ulpi_ops dwc3_ulpi_ops = {
  63. .read = dwc3_ulpi_read,
  64. .write = dwc3_ulpi_write,
  65. };
  66. int dwc3_ulpi_init(struct dwc3 *dwc)
  67. {
  68. /* Register the interface */
  69. dwc->ulpi = ulpi_register_interface(dwc->dev, &dwc3_ulpi_ops);
  70. if (IS_ERR(dwc->ulpi)) {
  71. dev_err(dwc->dev, "failed to register ULPI interface");
  72. return PTR_ERR(dwc->ulpi);
  73. }
  74. return 0;
  75. }
  76. void dwc3_ulpi_exit(struct dwc3 *dwc)
  77. {
  78. if (dwc->ulpi) {
  79. ulpi_unregister_interface(dwc->ulpi);
  80. dwc->ulpi = NULL;
  81. }
  82. }