ulpi.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * ulpi.c - DesignWare USB3 Controller's ULPI PHY interface
  3. *
  4. * Copyright (C) 2015 Intel Corporation
  5. *
  6. * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/ulpi/regs.h>
  13. #include "core.h"
  14. #include "io.h"
  15. #define DWC3_ULPI_ADDR(a) \
  16. ((a >= ULPI_EXT_VENDOR_SPECIFIC) ? \
  17. DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \
  18. DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a))
  19. static int dwc3_ulpi_busyloop(struct dwc3 *dwc)
  20. {
  21. unsigned count = 1000;
  22. u32 reg;
  23. while (count--) {
  24. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
  25. if (!(reg & DWC3_GUSB2PHYACC_BUSY))
  26. return 0;
  27. cpu_relax();
  28. }
  29. return -ETIMEDOUT;
  30. }
  31. static int dwc3_ulpi_read(struct device *dev, u8 addr)
  32. {
  33. struct dwc3 *dwc = dev_get_drvdata(dev);
  34. u32 reg;
  35. int ret;
  36. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
  37. if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
  38. reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
  39. dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
  40. }
  41. reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
  42. dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
  43. ret = dwc3_ulpi_busyloop(dwc);
  44. if (ret)
  45. return ret;
  46. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
  47. return DWC3_GUSB2PHYACC_DATA(reg);
  48. }
  49. static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
  50. {
  51. struct dwc3 *dwc = dev_get_drvdata(dev);
  52. u32 reg;
  53. reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
  54. if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
  55. reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
  56. dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
  57. }
  58. reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
  59. reg |= DWC3_GUSB2PHYACC_WRITE | val;
  60. dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
  61. return dwc3_ulpi_busyloop(dwc);
  62. }
  63. static const struct ulpi_ops dwc3_ulpi_ops = {
  64. .read = dwc3_ulpi_read,
  65. .write = dwc3_ulpi_write,
  66. };
  67. int dwc3_ulpi_init(struct dwc3 *dwc)
  68. {
  69. /* Register the interface */
  70. dwc->ulpi = ulpi_register_interface(dwc->dev, &dwc3_ulpi_ops);
  71. if (IS_ERR(dwc->ulpi)) {
  72. dev_err(dwc->dev, "failed to register ULPI interface");
  73. return PTR_ERR(dwc->ulpi);
  74. }
  75. return 0;
  76. }
  77. void dwc3_ulpi_exit(struct dwc3 *dwc)
  78. {
  79. if (dwc->ulpi) {
  80. ulpi_unregister_interface(dwc->ulpi);
  81. dwc->ulpi = NULL;
  82. }
  83. }