phy-qcom-ufs-qmp-14nm.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  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. */
  14. #include "phy-qcom-ufs-qmp-14nm.h"
  15. #define UFS_PHY_NAME "ufs_phy_qmp_14nm"
  16. #define UFS_PHY_VDDA_PHY_UV (925000)
  17. static
  18. int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
  19. bool is_rate_B)
  20. {
  21. int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
  22. int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
  23. int err;
  24. err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A,
  25. tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B);
  26. if (err)
  27. dev_err(ufs_qcom_phy->dev,
  28. "%s: ufs_qcom_phy_calibrate() failed %d\n",
  29. __func__, err);
  30. return err;
  31. }
  32. static
  33. void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
  34. {
  35. phy_common->quirks =
  36. UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
  37. }
  38. static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
  39. {
  40. struct ufs_qcom_phy_qmp_14nm *phy = phy_get_drvdata(generic_phy);
  41. struct ufs_qcom_phy *phy_common = &phy->common_cfg;
  42. int err;
  43. err = ufs_qcom_phy_init_clks(generic_phy, phy_common);
  44. if (err) {
  45. dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n",
  46. __func__, err);
  47. goto out;
  48. }
  49. err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common);
  50. if (err) {
  51. dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n",
  52. __func__, err);
  53. goto out;
  54. }
  55. phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV;
  56. phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV;
  57. ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common);
  58. out:
  59. return err;
  60. }
  61. static
  62. void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool val)
  63. {
  64. writel_relaxed(val ? 0x1 : 0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
  65. /*
  66. * Before any transactions involving PHY, ensure PHY knows
  67. * that it's analog rail is powered ON (or OFF).
  68. */
  69. mb();
  70. }
  71. static inline
  72. void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
  73. {
  74. /*
  75. * 14nm PHY does not have TX_LANE_ENABLE register.
  76. * Implement this function so as not to propagate error to caller.
  77. */
  78. }
  79. static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy *phy)
  80. {
  81. u32 tmp;
  82. tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START);
  83. tmp &= ~MASK_SERDES_START;
  84. tmp |= (1 << OFFSET_SERDES_START);
  85. writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START);
  86. /* Ensure register value is committed */
  87. mb();
  88. }
  89. static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
  90. {
  91. int err = 0;
  92. u32 val;
  93. err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS,
  94. val, (val & MASK_PCS_READY), 10, 1000000);
  95. if (err)
  96. dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n",
  97. __func__, err);
  98. return err;
  99. }
  100. static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
  101. .init = ufs_qcom_phy_qmp_14nm_init,
  102. .exit = ufs_qcom_phy_exit,
  103. .power_on = ufs_qcom_phy_power_on,
  104. .power_off = ufs_qcom_phy_power_off,
  105. .owner = THIS_MODULE,
  106. };
  107. static struct ufs_qcom_phy_specific_ops phy_14nm_ops = {
  108. .calibrate_phy = ufs_qcom_phy_qmp_14nm_phy_calibrate,
  109. .start_serdes = ufs_qcom_phy_qmp_14nm_start_serdes,
  110. .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready,
  111. .set_tx_lane_enable = ufs_qcom_phy_qmp_14nm_set_tx_lane_enable,
  112. .power_control = ufs_qcom_phy_qmp_14nm_power_control,
  113. };
  114. static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
  115. {
  116. struct device *dev = &pdev->dev;
  117. struct phy *generic_phy;
  118. struct ufs_qcom_phy_qmp_14nm *phy;
  119. int err = 0;
  120. phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
  121. if (!phy) {
  122. err = -ENOMEM;
  123. goto out;
  124. }
  125. generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg,
  126. &ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops);
  127. if (!generic_phy) {
  128. dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n",
  129. __func__);
  130. err = -EIO;
  131. goto out;
  132. }
  133. phy_set_drvdata(generic_phy, phy);
  134. strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
  135. sizeof(phy->common_cfg.name));
  136. out:
  137. return err;
  138. }
  139. static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev)
  140. {
  141. struct device *dev = &pdev->dev;
  142. struct phy *generic_phy = to_phy(dev);
  143. struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
  144. int err = 0;
  145. err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy);
  146. if (err)
  147. dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n",
  148. __func__, err);
  149. return err;
  150. }
  151. static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = {
  152. {.compatible = "qcom,ufs-phy-qmp-14nm"},
  153. {},
  154. };
  155. MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match);
  156. static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = {
  157. .probe = ufs_qcom_phy_qmp_14nm_probe,
  158. .remove = ufs_qcom_phy_qmp_14nm_remove,
  159. .driver = {
  160. .of_match_table = ufs_qcom_phy_qmp_14nm_of_match,
  161. .name = "ufs_qcom_phy_qmp_14nm",
  162. },
  163. };
  164. module_platform_driver(ufs_qcom_phy_qmp_14nm_driver);
  165. MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 14nm");
  166. MODULE_LICENSE("GPL v2");