qca83xx.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <linux/phy.h>
  3. #include <linux/module.h>
  4. #include "qcom.h"
  5. #define AT803X_DEBUG_REG_3C 0x3C
  6. #define AT803X_DEBUG_REG_GREEN 0x3D
  7. #define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6)
  8. #define MDIO_AZ_DEBUG 0x800D
  9. #define QCA8327_A_PHY_ID 0x004dd033
  10. #define QCA8327_B_PHY_ID 0x004dd034
  11. #define QCA8337_PHY_ID 0x004dd036
  12. #define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0)
  13. static struct at803x_hw_stat qca83xx_hw_stats[] = {
  14. { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY},
  15. { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY},
  16. { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
  17. };
  18. struct qca83xx_priv {
  19. u64 stats[ARRAY_SIZE(qca83xx_hw_stats)];
  20. };
  21. MODULE_DESCRIPTION("Qualcomm Atheros QCA83XX PHY driver");
  22. MODULE_AUTHOR("Matus Ujhelyi");
  23. MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
  24. MODULE_LICENSE("GPL");
  25. static int qca83xx_get_sset_count(struct phy_device *phydev)
  26. {
  27. return ARRAY_SIZE(qca83xx_hw_stats);
  28. }
  29. static void qca83xx_get_strings(struct phy_device *phydev, u8 *data)
  30. {
  31. int i;
  32. for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) {
  33. strscpy(data + i * ETH_GSTRING_LEN,
  34. qca83xx_hw_stats[i].string, ETH_GSTRING_LEN);
  35. }
  36. }
  37. static u64 qca83xx_get_stat(struct phy_device *phydev, int i)
  38. {
  39. struct at803x_hw_stat stat = qca83xx_hw_stats[i];
  40. struct qca83xx_priv *priv = phydev->priv;
  41. int val;
  42. u64 ret;
  43. if (stat.access_type == MMD)
  44. val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg);
  45. else
  46. val = phy_read(phydev, stat.reg);
  47. if (val < 0) {
  48. ret = U64_MAX;
  49. } else {
  50. val = val & stat.mask;
  51. priv->stats[i] += val;
  52. ret = priv->stats[i];
  53. }
  54. return ret;
  55. }
  56. static void qca83xx_get_stats(struct phy_device *phydev,
  57. struct ethtool_stats *stats, u64 *data)
  58. {
  59. int i;
  60. for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
  61. data[i] = qca83xx_get_stat(phydev, i);
  62. }
  63. static int qca83xx_probe(struct phy_device *phydev)
  64. {
  65. struct device *dev = &phydev->mdio.dev;
  66. struct qca83xx_priv *priv;
  67. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  68. if (!priv)
  69. return -ENOMEM;
  70. phydev->priv = priv;
  71. return 0;
  72. }
  73. static int qca83xx_config_init(struct phy_device *phydev)
  74. {
  75. u8 switch_revision;
  76. switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK;
  77. switch (switch_revision) {
  78. case 1:
  79. /* For 100M waveform */
  80. at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea);
  81. /* Turn on Gigabit clock */
  82. at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0);
  83. break;
  84. case 2:
  85. phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);
  86. fallthrough;
  87. case 4:
  88. phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f);
  89. at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860);
  90. at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46);
  91. at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000);
  92. break;
  93. }
  94. /* Following original QCA sourcecode set port to prefer master */
  95. phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER);
  96. return 0;
  97. }
  98. static int qca8327_config_init(struct phy_device *phydev)
  99. {
  100. /* QCA8327 require DAC amplitude adjustment for 100m set to +6%.
  101. * Disable on init and enable only with 100m speed following
  102. * qca original source code.
  103. */
  104. at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
  105. QCA8327_DEBUG_MANU_CTRL_EN, 0);
  106. return qca83xx_config_init(phydev);
  107. }
  108. static void qca83xx_link_change_notify(struct phy_device *phydev)
  109. {
  110. /* Set DAC Amplitude adjustment to +6% for 100m on link running */
  111. if (phydev->state == PHY_RUNNING) {
  112. if (phydev->speed == SPEED_100)
  113. at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
  114. QCA8327_DEBUG_MANU_CTRL_EN,
  115. QCA8327_DEBUG_MANU_CTRL_EN);
  116. } else {
  117. /* Reset DAC Amplitude adjustment */
  118. at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
  119. QCA8327_DEBUG_MANU_CTRL_EN, 0);
  120. }
  121. }
  122. static int qca83xx_resume(struct phy_device *phydev)
  123. {
  124. int ret, val;
  125. /* Skip reset if not suspended */
  126. if (!phydev->suspended)
  127. return 0;
  128. /* Reinit the port, reset values set by suspend */
  129. qca83xx_config_init(phydev);
  130. /* Reset the port on port resume */
  131. phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
  132. /* On resume from suspend the switch execute a reset and
  133. * restart auto-negotiation. Wait for reset to complete.
  134. */
  135. ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
  136. 50000, 600000, true);
  137. if (ret)
  138. return ret;
  139. usleep_range(1000, 2000);
  140. return 0;
  141. }
  142. static int qca83xx_suspend(struct phy_device *phydev)
  143. {
  144. at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN,
  145. AT803X_DEBUG_GATE_CLK_IN1000, 0);
  146. at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL,
  147. AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE |
  148. AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0);
  149. return 0;
  150. }
  151. static int qca8337_suspend(struct phy_device *phydev)
  152. {
  153. /* Only QCA8337 support actual suspend. */
  154. genphy_suspend(phydev);
  155. return qca83xx_suspend(phydev);
  156. }
  157. static int qca8327_suspend(struct phy_device *phydev)
  158. {
  159. u16 mask = 0;
  160. /* QCA8327 cause port unreliability when phy suspend
  161. * is set.
  162. */
  163. mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX);
  164. phy_modify(phydev, MII_BMCR, mask, 0);
  165. return qca83xx_suspend(phydev);
  166. }
  167. static struct phy_driver qca83xx_driver[] = {
  168. {
  169. /* QCA8337 */
  170. PHY_ID_MATCH_EXACT(QCA8337_PHY_ID),
  171. .name = "Qualcomm Atheros 8337 internal PHY",
  172. /* PHY_GBIT_FEATURES */
  173. .probe = qca83xx_probe,
  174. .flags = PHY_IS_INTERNAL,
  175. .config_init = qca83xx_config_init,
  176. .soft_reset = genphy_soft_reset,
  177. .get_sset_count = qca83xx_get_sset_count,
  178. .get_strings = qca83xx_get_strings,
  179. .get_stats = qca83xx_get_stats,
  180. .suspend = qca8337_suspend,
  181. .resume = qca83xx_resume,
  182. }, {
  183. /* QCA8327-A from switch QCA8327-AL1A */
  184. PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID),
  185. .name = "Qualcomm Atheros 8327-A internal PHY",
  186. /* PHY_GBIT_FEATURES */
  187. .link_change_notify = qca83xx_link_change_notify,
  188. .probe = qca83xx_probe,
  189. .flags = PHY_IS_INTERNAL,
  190. .config_init = qca8327_config_init,
  191. .soft_reset = genphy_soft_reset,
  192. .get_sset_count = qca83xx_get_sset_count,
  193. .get_strings = qca83xx_get_strings,
  194. .get_stats = qca83xx_get_stats,
  195. .suspend = qca8327_suspend,
  196. .resume = qca83xx_resume,
  197. }, {
  198. /* QCA8327-B from switch QCA8327-BL1A */
  199. PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID),
  200. .name = "Qualcomm Atheros 8327-B internal PHY",
  201. /* PHY_GBIT_FEATURES */
  202. .link_change_notify = qca83xx_link_change_notify,
  203. .probe = qca83xx_probe,
  204. .flags = PHY_IS_INTERNAL,
  205. .config_init = qca8327_config_init,
  206. .soft_reset = genphy_soft_reset,
  207. .get_sset_count = qca83xx_get_sset_count,
  208. .get_strings = qca83xx_get_strings,
  209. .get_stats = qca83xx_get_stats,
  210. .suspend = qca8327_suspend,
  211. .resume = qca83xx_resume,
  212. }, };
  213. module_phy_driver(qca83xx_driver);
  214. static struct mdio_device_id __maybe_unused qca83xx_tbl[] = {
  215. { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
  216. { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) },
  217. { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
  218. { }
  219. };
  220. MODULE_DEVICE_TABLE(mdio, qca83xx_tbl);