phy-tusb1210.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /**
  3. * tusb1210.c - TUSB1210 USB ULPI PHY driver
  4. *
  5. * Copyright (C) 2015 Intel Corporation
  6. *
  7. * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/ulpi/driver.h>
  11. #include <linux/ulpi/regs.h>
  12. #include <linux/gpio/consumer.h>
  13. #include <linux/phy/ulpi_phy.h>
  14. #define TUSB1210_VENDOR_SPECIFIC2 0x80
  15. #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT 0
  16. #define TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT 4
  17. #define TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT 6
  18. struct tusb1210 {
  19. struct ulpi *ulpi;
  20. struct phy *phy;
  21. struct gpio_desc *gpio_reset;
  22. struct gpio_desc *gpio_cs;
  23. u8 vendor_specific2;
  24. };
  25. static int tusb1210_power_on(struct phy *phy)
  26. {
  27. struct tusb1210 *tusb = phy_get_drvdata(phy);
  28. gpiod_set_value_cansleep(tusb->gpio_reset, 1);
  29. gpiod_set_value_cansleep(tusb->gpio_cs, 1);
  30. /* Restore the optional eye diagram optimization value */
  31. if (tusb->vendor_specific2)
  32. ulpi_write(tusb->ulpi, TUSB1210_VENDOR_SPECIFIC2,
  33. tusb->vendor_specific2);
  34. return 0;
  35. }
  36. static int tusb1210_power_off(struct phy *phy)
  37. {
  38. struct tusb1210 *tusb = phy_get_drvdata(phy);
  39. gpiod_set_value_cansleep(tusb->gpio_reset, 0);
  40. gpiod_set_value_cansleep(tusb->gpio_cs, 0);
  41. return 0;
  42. }
  43. static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode)
  44. {
  45. struct tusb1210 *tusb = phy_get_drvdata(phy);
  46. int ret;
  47. ret = ulpi_read(tusb->ulpi, ULPI_OTG_CTRL);
  48. if (ret < 0)
  49. return ret;
  50. switch (mode) {
  51. case PHY_MODE_USB_HOST:
  52. ret |= (ULPI_OTG_CTRL_DRVVBUS_EXT
  53. | ULPI_OTG_CTRL_ID_PULLUP
  54. | ULPI_OTG_CTRL_DP_PULLDOWN
  55. | ULPI_OTG_CTRL_DM_PULLDOWN);
  56. ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
  57. ret |= ULPI_OTG_CTRL_DRVVBUS;
  58. break;
  59. case PHY_MODE_USB_DEVICE:
  60. ret &= ~(ULPI_OTG_CTRL_DRVVBUS
  61. | ULPI_OTG_CTRL_DP_PULLDOWN
  62. | ULPI_OTG_CTRL_DM_PULLDOWN);
  63. ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
  64. ret &= ~ULPI_OTG_CTRL_DRVVBUS_EXT;
  65. break;
  66. default:
  67. /* nothing */
  68. return 0;
  69. }
  70. return ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
  71. }
  72. static const struct phy_ops phy_ops = {
  73. .power_on = tusb1210_power_on,
  74. .power_off = tusb1210_power_off,
  75. .set_mode = tusb1210_set_mode,
  76. .owner = THIS_MODULE,
  77. };
  78. static int tusb1210_probe(struct ulpi *ulpi)
  79. {
  80. struct tusb1210 *tusb;
  81. u8 val, reg;
  82. tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
  83. if (!tusb)
  84. return -ENOMEM;
  85. tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
  86. GPIOD_OUT_LOW);
  87. if (IS_ERR(tusb->gpio_reset))
  88. return PTR_ERR(tusb->gpio_reset);
  89. gpiod_set_value_cansleep(tusb->gpio_reset, 1);
  90. tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
  91. GPIOD_OUT_LOW);
  92. if (IS_ERR(tusb->gpio_cs))
  93. return PTR_ERR(tusb->gpio_cs);
  94. gpiod_set_value_cansleep(tusb->gpio_cs, 1);
  95. /*
  96. * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
  97. * diagram optimization and DP/DM swap.
  98. */
  99. /* High speed output drive strength configuration */
  100. device_property_read_u8(&ulpi->dev, "ihstx", &val);
  101. reg = val << TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT;
  102. /* High speed output impedance configuration */
  103. device_property_read_u8(&ulpi->dev, "zhsdrv", &val);
  104. reg |= val << TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT;
  105. /* DP/DM swap control */
  106. device_property_read_u8(&ulpi->dev, "datapolarity", &val);
  107. reg |= val << TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT;
  108. if (reg) {
  109. ulpi_write(ulpi, TUSB1210_VENDOR_SPECIFIC2, reg);
  110. tusb->vendor_specific2 = reg;
  111. }
  112. tusb->phy = ulpi_phy_create(ulpi, &phy_ops);
  113. if (IS_ERR(tusb->phy))
  114. return PTR_ERR(tusb->phy);
  115. tusb->ulpi = ulpi;
  116. phy_set_drvdata(tusb->phy, tusb);
  117. ulpi_set_drvdata(ulpi, tusb);
  118. return 0;
  119. }
  120. static void tusb1210_remove(struct ulpi *ulpi)
  121. {
  122. struct tusb1210 *tusb = ulpi_get_drvdata(ulpi);
  123. ulpi_phy_destroy(ulpi, tusb->phy);
  124. }
  125. #define TI_VENDOR_ID 0x0451
  126. static const struct ulpi_device_id tusb1210_ulpi_id[] = {
  127. { TI_VENDOR_ID, 0x1507, }, /* TUSB1210 */
  128. { TI_VENDOR_ID, 0x1508, }, /* TUSB1211 */
  129. { },
  130. };
  131. MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
  132. static struct ulpi_driver tusb1210_driver = {
  133. .id_table = tusb1210_ulpi_id,
  134. .probe = tusb1210_probe,
  135. .remove = tusb1210_remove,
  136. .driver = {
  137. .name = "tusb1210",
  138. .owner = THIS_MODULE,
  139. },
  140. };
  141. module_ulpi_driver(tusb1210_driver);
  142. MODULE_AUTHOR("Intel Corporation");
  143. MODULE_LICENSE("GPL v2");
  144. MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver");