pcs-xpcs-nxp.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright 2021 NXP
  3. */
  4. #include <linux/pcs/pcs-xpcs.h>
  5. #include "pcs-xpcs.h"
  6. /* LANE_DRIVER1_0 register */
  7. #define SJA1110_LANE_DRIVER1_0 0x8038
  8. #define SJA1110_TXDRV(x) (((x) << 12) & GENMASK(14, 12))
  9. /* LANE_DRIVER2_0 register */
  10. #define SJA1110_LANE_DRIVER2_0 0x803a
  11. #define SJA1110_TXDRVTRIM_LSB(x) ((x) & GENMASK_ULL(15, 0))
  12. /* LANE_DRIVER2_1 register */
  13. #define SJA1110_LANE_DRIVER2_1 0x803b
  14. #define SJA1110_LANE_DRIVER2_1_RSV BIT(9)
  15. #define SJA1110_TXDRVTRIM_MSB(x) (((x) & GENMASK_ULL(23, 16)) >> 16)
  16. /* LANE_TRIM register */
  17. #define SJA1110_LANE_TRIM 0x8040
  18. #define SJA1110_TXTEN BIT(11)
  19. #define SJA1110_TXRTRIM(x) (((x) << 8) & GENMASK(10, 8))
  20. #define SJA1110_TXPLL_BWSEL BIT(7)
  21. #define SJA1110_RXTEN BIT(6)
  22. #define SJA1110_RXRTRIM(x) (((x) << 3) & GENMASK(5, 3))
  23. #define SJA1110_CDR_GAIN BIT(2)
  24. #define SJA1110_ACCOUPLE_RXVCM_EN BIT(0)
  25. /* LANE_DATAPATH_1 register */
  26. #define SJA1110_LANE_DATAPATH_1 0x8037
  27. /* POWERDOWN_ENABLE register */
  28. #define SJA1110_POWERDOWN_ENABLE 0x8041
  29. #define SJA1110_TXPLL_PD BIT(12)
  30. #define SJA1110_TXPD BIT(11)
  31. #define SJA1110_RXPKDETEN BIT(10)
  32. #define SJA1110_RXCH_PD BIT(9)
  33. #define SJA1110_RXBIAS_PD BIT(8)
  34. #define SJA1110_RESET_SER_EN BIT(7)
  35. #define SJA1110_RESET_SER BIT(6)
  36. #define SJA1110_RESET_DES BIT(5)
  37. #define SJA1110_RCVEN BIT(4)
  38. /* RXPLL_CTRL0 register */
  39. #define SJA1110_RXPLL_CTRL0 0x8065
  40. #define SJA1110_RXPLL_FBDIV(x) (((x) << 2) & GENMASK(9, 2))
  41. /* RXPLL_CTRL1 register */
  42. #define SJA1110_RXPLL_CTRL1 0x8066
  43. #define SJA1110_RXPLL_REFDIV(x) ((x) & GENMASK(4, 0))
  44. /* TXPLL_CTRL0 register */
  45. #define SJA1110_TXPLL_CTRL0 0x806d
  46. #define SJA1110_TXPLL_FBDIV(x) ((x) & GENMASK(11, 0))
  47. /* TXPLL_CTRL1 register */
  48. #define SJA1110_TXPLL_CTRL1 0x806e
  49. #define SJA1110_TXPLL_REFDIV(x) ((x) & GENMASK(5, 0))
  50. /* RX_DATA_DETECT register */
  51. #define SJA1110_RX_DATA_DETECT 0x8045
  52. /* RX_CDR_CTLE register */
  53. #define SJA1110_RX_CDR_CTLE 0x8042
  54. /* In NXP SJA1105, the PCS is integrated with a PMA that has the TX lane
  55. * polarity inverted by default (PLUS is MINUS, MINUS is PLUS). To obtain
  56. * normal non-inverted behavior, the TX lane polarity must be inverted in the
  57. * PCS, via the DIGITAL_CONTROL_2 register.
  58. */
  59. int nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs)
  60. {
  61. return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL2,
  62. DW_VR_MII_DIG_CTRL2_TX_POL_INV);
  63. }
  64. static int nxp_sja1110_pma_config(struct dw_xpcs *xpcs,
  65. u16 txpll_fbdiv, u16 txpll_refdiv,
  66. u16 rxpll_fbdiv, u16 rxpll_refdiv,
  67. u16 rx_cdr_ctle)
  68. {
  69. u16 val;
  70. int ret;
  71. /* Program TX PLL feedback divider and reference divider settings for
  72. * correct oscillation frequency.
  73. */
  74. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL0,
  75. SJA1110_TXPLL_FBDIV(txpll_fbdiv));
  76. if (ret < 0)
  77. return ret;
  78. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL1,
  79. SJA1110_TXPLL_REFDIV(txpll_refdiv));
  80. if (ret < 0)
  81. return ret;
  82. /* Program transmitter amplitude and disable amplitude trimming */
  83. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER1_0,
  84. SJA1110_TXDRV(0x5));
  85. if (ret < 0)
  86. return ret;
  87. val = SJA1110_TXDRVTRIM_LSB(0xffffffull);
  88. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER2_0, val);
  89. if (ret < 0)
  90. return ret;
  91. val = SJA1110_TXDRVTRIM_MSB(0xffffffull) | SJA1110_LANE_DRIVER2_1_RSV;
  92. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER2_1, val);
  93. if (ret < 0)
  94. return ret;
  95. /* Enable input and output resistor terminations for low BER. */
  96. val = SJA1110_ACCOUPLE_RXVCM_EN | SJA1110_CDR_GAIN |
  97. SJA1110_RXRTRIM(4) | SJA1110_RXTEN | SJA1110_TXPLL_BWSEL |
  98. SJA1110_TXRTRIM(3) | SJA1110_TXTEN;
  99. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_TRIM, val);
  100. if (ret < 0)
  101. return ret;
  102. /* Select PCS as transmitter data source. */
  103. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DATAPATH_1, 0);
  104. if (ret < 0)
  105. return ret;
  106. /* Program RX PLL feedback divider and reference divider for correct
  107. * oscillation frequency.
  108. */
  109. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL0,
  110. SJA1110_RXPLL_FBDIV(rxpll_fbdiv));
  111. if (ret < 0)
  112. return ret;
  113. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL1,
  114. SJA1110_RXPLL_REFDIV(rxpll_refdiv));
  115. if (ret < 0)
  116. return ret;
  117. /* Program threshold for receiver signal detector.
  118. * Enable control of RXPLL by receiver signal detector to disable RXPLL
  119. * when an input signal is not present.
  120. */
  121. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_DATA_DETECT, 0x0005);
  122. if (ret < 0)
  123. return ret;
  124. /* Enable TX and RX PLLs and circuits.
  125. * Release reset of PMA to enable data flow to/from PCS.
  126. */
  127. ret = xpcs_read(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE);
  128. if (ret < 0)
  129. return ret;
  130. val = ret & ~(SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
  131. SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
  132. SJA1110_RESET_SER | SJA1110_RESET_DES);
  133. val |= SJA1110_RXPKDETEN | SJA1110_RCVEN;
  134. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE, val);
  135. if (ret < 0)
  136. return ret;
  137. /* Program continuous-time linear equalizer (CTLE) settings. */
  138. ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
  139. rx_cdr_ctle);
  140. if (ret < 0)
  141. return ret;
  142. return 0;
  143. }
  144. int nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs)
  145. {
  146. return nxp_sja1110_pma_config(xpcs, 0x19, 0x1, 0x19, 0x1, 0x212a);
  147. }
  148. int nxp_sja1110_2500basex_pma_config(struct dw_xpcs *xpcs)
  149. {
  150. return nxp_sja1110_pma_config(xpcs, 0x7d, 0x2, 0x7d, 0x2, 0x732a);
  151. }