phy-tegra194-p2u.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * P2U (PIPE to UPHY) driver for Tegra T194 SoC
  4. *
  5. * Copyright (C) 2019-2022 NVIDIA Corporation.
  6. *
  7. * Author: Vidya Sagar <[email protected]>
  8. */
  9. #include <linux/err.h>
  10. #include <linux/io.h>
  11. #include <linux/module.h>
  12. #include <linux/of.h>
  13. #include <linux/of_platform.h>
  14. #include <linux/phy/phy.h>
  15. #define P2U_CONTROL_CMN 0x74
  16. #define P2U_CONTROL_CMN_SKP_SIZE_PROTECTION_EN BIT(20)
  17. #define P2U_PERIODIC_EQ_CTRL_GEN3 0xc0
  18. #define P2U_PERIODIC_EQ_CTRL_GEN3_PERIODIC_EQ_EN BIT(0)
  19. #define P2U_PERIODIC_EQ_CTRL_GEN3_INIT_PRESET_EQ_TRAIN_EN BIT(1)
  20. #define P2U_PERIODIC_EQ_CTRL_GEN4 0xc4
  21. #define P2U_PERIODIC_EQ_CTRL_GEN4_INIT_PRESET_EQ_TRAIN_EN BIT(1)
  22. #define P2U_RX_DEBOUNCE_TIME 0xa4
  23. #define P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_MASK 0xffff
  24. #define P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_VAL 160
  25. #define P2U_DIR_SEARCH_CTRL 0xd4
  26. #define P2U_DIR_SEARCH_CTRL_GEN4_FINE_GRAIN_SEARCH_TWICE BIT(18)
  27. struct tegra_p2u_of_data {
  28. bool one_dir_search;
  29. };
  30. struct tegra_p2u {
  31. void __iomem *base;
  32. bool skip_sz_protection_en; /* Needed to support two retimers */
  33. struct tegra_p2u_of_data *of_data;
  34. };
  35. static inline void p2u_writel(struct tegra_p2u *phy, const u32 value,
  36. const u32 reg)
  37. {
  38. writel_relaxed(value, phy->base + reg);
  39. }
  40. static inline u32 p2u_readl(struct tegra_p2u *phy, const u32 reg)
  41. {
  42. return readl_relaxed(phy->base + reg);
  43. }
  44. static int tegra_p2u_power_on(struct phy *x)
  45. {
  46. struct tegra_p2u *phy = phy_get_drvdata(x);
  47. u32 val;
  48. if (phy->skip_sz_protection_en) {
  49. val = p2u_readl(phy, P2U_CONTROL_CMN);
  50. val |= P2U_CONTROL_CMN_SKP_SIZE_PROTECTION_EN;
  51. p2u_writel(phy, val, P2U_CONTROL_CMN);
  52. }
  53. val = p2u_readl(phy, P2U_PERIODIC_EQ_CTRL_GEN3);
  54. val &= ~P2U_PERIODIC_EQ_CTRL_GEN3_PERIODIC_EQ_EN;
  55. val |= P2U_PERIODIC_EQ_CTRL_GEN3_INIT_PRESET_EQ_TRAIN_EN;
  56. p2u_writel(phy, val, P2U_PERIODIC_EQ_CTRL_GEN3);
  57. val = p2u_readl(phy, P2U_PERIODIC_EQ_CTRL_GEN4);
  58. val |= P2U_PERIODIC_EQ_CTRL_GEN4_INIT_PRESET_EQ_TRAIN_EN;
  59. p2u_writel(phy, val, P2U_PERIODIC_EQ_CTRL_GEN4);
  60. val = p2u_readl(phy, P2U_RX_DEBOUNCE_TIME);
  61. val &= ~P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_MASK;
  62. val |= P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_VAL;
  63. p2u_writel(phy, val, P2U_RX_DEBOUNCE_TIME);
  64. if (phy->of_data->one_dir_search) {
  65. val = p2u_readl(phy, P2U_DIR_SEARCH_CTRL);
  66. val &= ~P2U_DIR_SEARCH_CTRL_GEN4_FINE_GRAIN_SEARCH_TWICE;
  67. p2u_writel(phy, val, P2U_DIR_SEARCH_CTRL);
  68. }
  69. return 0;
  70. }
  71. static const struct phy_ops ops = {
  72. .power_on = tegra_p2u_power_on,
  73. .owner = THIS_MODULE,
  74. };
  75. static int tegra_p2u_probe(struct platform_device *pdev)
  76. {
  77. struct phy_provider *phy_provider;
  78. struct device *dev = &pdev->dev;
  79. struct phy *generic_phy;
  80. struct tegra_p2u *phy;
  81. phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
  82. if (!phy)
  83. return -ENOMEM;
  84. phy->of_data =
  85. (struct tegra_p2u_of_data *)of_device_get_match_data(dev);
  86. if (!phy->of_data)
  87. return -EINVAL;
  88. phy->base = devm_platform_ioremap_resource_byname(pdev, "ctl");
  89. if (IS_ERR(phy->base))
  90. return PTR_ERR(phy->base);
  91. phy->skip_sz_protection_en =
  92. of_property_read_bool(dev->of_node,
  93. "nvidia,skip-sz-protect-en");
  94. platform_set_drvdata(pdev, phy);
  95. generic_phy = devm_phy_create(dev, NULL, &ops);
  96. if (IS_ERR(generic_phy))
  97. return PTR_ERR(generic_phy);
  98. phy_set_drvdata(generic_phy, phy);
  99. phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
  100. if (IS_ERR(phy_provider))
  101. return PTR_ERR(phy_provider);
  102. return 0;
  103. }
  104. static const struct tegra_p2u_of_data tegra194_p2u_of_data = {
  105. .one_dir_search = false,
  106. };
  107. static const struct tegra_p2u_of_data tegra234_p2u_of_data = {
  108. .one_dir_search = true,
  109. };
  110. static const struct of_device_id tegra_p2u_id_table[] = {
  111. {
  112. .compatible = "nvidia,tegra194-p2u",
  113. .data = &tegra194_p2u_of_data,
  114. },
  115. {
  116. .compatible = "nvidia,tegra234-p2u",
  117. .data = &tegra234_p2u_of_data,
  118. },
  119. {}
  120. };
  121. MODULE_DEVICE_TABLE(of, tegra_p2u_id_table);
  122. static struct platform_driver tegra_p2u_driver = {
  123. .probe = tegra_p2u_probe,
  124. .driver = {
  125. .name = "tegra194-p2u",
  126. .of_match_table = tegra_p2u_id_table,
  127. },
  128. };
  129. module_platform_driver(tegra_p2u_driver);
  130. MODULE_AUTHOR("Vidya Sagar <[email protected]>");
  131. MODULE_DESCRIPTION("NVIDIA Tegra194 PIPE2UPHY PHY driver");
  132. MODULE_LICENSE("GPL v2");