xref: /linux/drivers/net/pcs/pcs-xpcs-wx.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
3 
4 #include <linux/pcs/pcs-xpcs.h>
5 #include <linux/mdio.h>
6 #include "pcs-xpcs.h"
7 
8 /* VR_XS_PMA_MMD */
9 #define TXGBE_PMA_MMD			0x8020
10 #define TXGBE_TX_GENCTL1		0x11
11 #define TXGBE_TX_GENCTL1_VBOOST_LVL	GENMASK(10, 8)
12 #define TXGBE_TX_GENCTL1_VBOOST_EN0	BIT(4)
13 #define TXGBE_TX_GEN_CTL2		0x12
14 #define TXGBE_TX_GEN_CTL2_TX0_WIDTH(v)	FIELD_PREP(GENMASK(9, 8), v)
15 #define TXGBE_TX_RATE_CTL		0x14
16 #define TXGBE_TX_RATE_CTL_TX0_RATE(v)	FIELD_PREP(GENMASK(2, 0), v)
17 #define TXGBE_RX_GEN_CTL2		0x32
18 #define TXGBE_RX_GEN_CTL2_RX0_WIDTH(v)	FIELD_PREP(GENMASK(9, 8), v)
19 #define TXGBE_RX_GEN_CTL3		0x33
20 #define TXGBE_RX_GEN_CTL3_LOS_TRSHLD0	GENMASK(2, 0)
21 #define TXGBE_RX_RATE_CTL		0x34
22 #define TXGBE_RX_RATE_CTL_RX0_RATE(v)	FIELD_PREP(GENMASK(1, 0), v)
23 #define TXGBE_RX_EQ_ATTN_CTL		0x37
24 #define TXGBE_RX_EQ_ATTN_LVL0		GENMASK(2, 0)
25 #define TXGBE_RX_EQ_CTL0		0x38
26 #define TXGBE_RX_EQ_CTL0_VGA1_GAIN(v)	FIELD_PREP(GENMASK(15, 12), v)
27 #define TXGBE_RX_EQ_CTL0_VGA2_GAIN(v)	FIELD_PREP(GENMASK(11, 8), v)
28 #define TXGBE_RX_EQ_CTL0_CTLE_POLE(v)	FIELD_PREP(GENMASK(7, 5), v)
29 #define TXGBE_RX_EQ_CTL0_CTLE_BOOST(v)	FIELD_PREP(GENMASK(4, 0), v)
30 #define TXGBE_RX_EQ_CTL4		0x3C
31 #define TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0	BIT(4)
32 #define TXGBE_RX_EQ_CTL4_CONT_ADAPT0	BIT(0)
33 #define TXGBE_AFE_DFE_ENABLE		0x3D
34 #define TXGBE_DFE_EN_0			BIT(4)
35 #define TXGBE_AFE_EN_0			BIT(0)
36 #define TXGBE_DFE_TAP_CTL0		0x3E
37 #define TXGBE_MPLLA_CTL0		0x51
38 #define TXGBE_MPLLA_CTL2		0x53
39 #define TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN	BIT(10)
40 #define TXGBE_MPLLA_CTL2_DIV10_CLK_EN	BIT(9)
41 #define TXGBE_MPLLA_CTL3		0x57
42 #define TXGBE_MISC_CTL0			0x70
43 #define TXGBE_MISC_CTL0_PLL		BIT(15)
44 #define TXGBE_MISC_CTL0_CR_PARA_SEL	BIT(14)
45 #define TXGBE_MISC_CTL0_RX_VREF(v)	FIELD_PREP(GENMASK(12, 8), v)
46 #define TXGBE_VCO_CAL_LD0		0x72
47 #define TXGBE_VCO_CAL_REF0		0x76
48 
49 static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val)
50 {
51 	return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
52 }
53 
54 static int txgbe_modify_pma(struct dw_xpcs *xpcs, int reg, u16 mask, u16 set)
55 {
56 	return xpcs_modify(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, mask,
57 			   set);
58 }
59 
60 static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
61 {
62 	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x21);
63 	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0);
64 	txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1, TXGBE_TX_GENCTL1_VBOOST_LVL,
65 			 FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
66 	txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
67 			TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
68 	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x549);
69 	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x29);
70 	txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, 0);
71 	txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, 0);
72 	txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(3));
73 	txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(3));
74 	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN |
75 			TXGBE_MPLLA_CTL2_DIV10_CLK_EN);
76 
77 	txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_CTLE_POLE(2) |
78 			TXGBE_RX_EQ_CTL0_CTLE_BOOST(5));
79 	txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
80 	txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0xBE);
81 	txgbe_modify_pma(xpcs, TXGBE_AFE_DFE_ENABLE,
82 			 TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0, 0);
83 	txgbe_modify_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_ADAPT0,
84 			 0);
85 }
86 
87 static void txgbe_pma_config_1g(struct dw_xpcs *xpcs)
88 {
89 	txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1,
90 			 TXGBE_TX_GENCTL1_VBOOST_LVL |
91 			 TXGBE_TX_GENCTL1_VBOOST_EN0,
92 			 FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
93 	txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
94 			TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
95 
96 	txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_VGA1_GAIN(7) |
97 			TXGBE_RX_EQ_CTL0_VGA2_GAIN(7) | TXGBE_RX_EQ_CTL0_CTLE_BOOST(6));
98 	txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
99 	txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0);
100 	txgbe_modify_pma(xpcs, TXGBE_RX_GEN_CTL3, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0,
101 			 FIELD_PREP(TXGBE_RX_GEN_CTL3_LOS_TRSHLD0, 0x4));
102 
103 	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x20);
104 	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0x46);
105 	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x540);
106 	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x2A);
107 	txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, 0);
108 	txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0);
109 	txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, TXGBE_TX_RATE_CTL_TX0_RATE(3));
110 	txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, TXGBE_RX_RATE_CTL_RX0_RATE(3));
111 	txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(1));
112 	txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(1));
113 	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV10_CLK_EN);
114 }
115 
116 static int txgbe_pcs_poll_power_up(struct dw_xpcs *xpcs)
117 {
118 	int val, ret;
119 
120 	/* Wait xpcs power-up good */
121 	ret = read_poll_timeout(xpcs_read_vpcs, val,
122 				(val & DW_PSEQ_ST) == DW_PSEQ_ST_GOOD,
123 				10000, 1000000, false,
124 				xpcs, DW_VR_XS_PCS_DIG_STS);
125 	if (ret < 0)
126 		dev_err(&xpcs->mdiodev->dev, "xpcs power-up timeout\n");
127 
128 	return ret;
129 }
130 
131 static int txgbe_pma_init_done(struct dw_xpcs *xpcs)
132 {
133 	int val, ret;
134 
135 	xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_VR_RST | DW_EN_VSMMD1);
136 
137 	/* wait pma initialization done */
138 	ret = read_poll_timeout(xpcs_read_vpcs, val, !(val & DW_VR_RST),
139 				100000, 10000000, false,
140 				xpcs, DW_VR_XS_PCS_DIG_CTRL1);
141 	if (ret < 0)
142 		dev_err(&xpcs->mdiodev->dev, "xpcs pma initialization timeout\n");
143 
144 	return ret;
145 }
146 
147 static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs)
148 {
149 	int ret;
150 
151 	/* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */
152 	ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2);
153 	ret &= MDIO_PCS_CTRL2_TYPE;
154 	if ((ret == MDIO_PCS_CTRL2_10GBR &&
155 	     xpcs->interface != PHY_INTERFACE_MODE_10GBASER) ||
156 	    xpcs->interface == PHY_INTERFACE_MODE_SGMII)
157 		return true;
158 
159 	return false;
160 }
161 
162 int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
163 {
164 	int ret;
165 
166 	switch (interface) {
167 	case PHY_INTERFACE_MODE_10GBASER:
168 	case PHY_INTERFACE_MODE_SGMII:
169 	case PHY_INTERFACE_MODE_1000BASEX:
170 		break;
171 	default:
172 		return 0;
173 	}
174 
175 	if (xpcs->interface == interface && !txgbe_xpcs_mode_quirk(xpcs))
176 		return 0;
177 
178 	xpcs->interface = interface;
179 
180 	ret = txgbe_pcs_poll_power_up(xpcs);
181 	if (ret < 0)
182 		return ret;
183 
184 	if (interface == PHY_INTERFACE_MODE_10GBASER) {
185 		xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR);
186 		xpcs_modify(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1,
187 			    MDIO_CTRL1_SPEED10G, MDIO_CTRL1_SPEED10G);
188 		txgbe_pma_config_10gbaser(xpcs);
189 	} else {
190 		xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX);
191 		xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, 0);
192 		xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL1, 0);
193 		txgbe_pma_config_1g(xpcs);
194 	}
195 
196 	return txgbe_pma_init_done(xpcs);
197 }
198