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