ulpi.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * Copyright (c) 2016 Linaro Ltd.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/device.h>
  14. #include <linux/usb/chipidea.h>
  15. #include <linux/ulpi/interface.h>
  16. #include "ci.h"
  17. #define ULPI_WAKEUP BIT(31)
  18. #define ULPI_RUN BIT(30)
  19. #define ULPI_WRITE BIT(29)
  20. #define ULPI_SYNC_STATE BIT(27)
  21. #define ULPI_ADDR(n) ((n) << 16)
  22. #define ULPI_DATA(n) (n)
  23. static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask)
  24. {
  25. unsigned long usec = 10000;
  26. while (usec--) {
  27. if (!hw_read(ci, OP_ULPI_VIEWPORT, mask))
  28. return 0;
  29. udelay(1);
  30. }
  31. return -ETIMEDOUT;
  32. }
  33. static int ci_ulpi_read(struct device *dev, u8 addr)
  34. {
  35. struct ci_hdrc *ci = dev_get_drvdata(dev);
  36. int ret;
  37. hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
  38. ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
  39. if (ret)
  40. return ret;
  41. hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr));
  42. ret = ci_ulpi_wait(ci, ULPI_RUN);
  43. if (ret)
  44. return ret;
  45. return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8;
  46. }
  47. static int ci_ulpi_write(struct device *dev, u8 addr, u8 val)
  48. {
  49. struct ci_hdrc *ci = dev_get_drvdata(dev);
  50. int ret;
  51. hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
  52. ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
  53. if (ret)
  54. return ret;
  55. hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff,
  56. ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val);
  57. return ci_ulpi_wait(ci, ULPI_RUN);
  58. }
  59. int ci_ulpi_init(struct ci_hdrc *ci)
  60. {
  61. if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
  62. return 0;
  63. /*
  64. * Set PORTSC correctly so we can read/write ULPI registers for
  65. * identification purposes
  66. */
  67. hw_phymode_configure(ci);
  68. ci->ulpi_ops.read = ci_ulpi_read;
  69. ci->ulpi_ops.write = ci_ulpi_write;
  70. ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops);
  71. if (IS_ERR(ci->ulpi))
  72. dev_err(ci->dev, "failed to register ULPI interface");
  73. return PTR_ERR_OR_ZERO(ci->ulpi);
  74. }
  75. void ci_ulpi_exit(struct ci_hdrc *ci)
  76. {
  77. if (ci->ulpi) {
  78. ulpi_unregister_interface(ci->ulpi);
  79. ci->ulpi = NULL;
  80. }
  81. }
  82. int ci_ulpi_resume(struct ci_hdrc *ci)
  83. {
  84. int cnt = 100000;
  85. while (cnt-- > 0) {
  86. if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE))
  87. return 0;
  88. udelay(1);
  89. }
  90. return -ETIMEDOUT;
  91. }