xref: /dpdk/drivers/net/ngbe/base/ngbe_phy_rtl.c (revision b53d106d34b5c638f5a2cbdfee0da5bd42d4383f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  */
4 
5 #include "ngbe_phy_rtl.h"
6 
7 #define RTL_PHY_RST_WAIT_PERIOD               5
8 
9 s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw,
10 		u32 reg_addr, u32 device_type, u16 *phy_data)
11 {
12 	mdi_reg_t reg;
13 	mdi_reg_22_t reg22;
14 
15 	reg.device_type = device_type;
16 	reg.addr = reg_addr;
17 	ngbe_mdi_map_register(&reg, &reg22);
18 
19 	wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
20 	*phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr));
21 
22 	return 0;
23 }
24 
25 s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
26 		u32 reg_addr, u32 device_type, u16 phy_data)
27 {
28 	mdi_reg_t reg;
29 	mdi_reg_22_t reg22;
30 
31 	reg.device_type = device_type;
32 	reg.addr = reg_addr;
33 	ngbe_mdi_map_register(&reg, &reg22);
34 
35 	wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
36 	wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data);
37 
38 	return 0;
39 }
40 
41 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
42 {
43 	int i;
44 	u16 value = 0;
45 
46 	/* enable interrupts, only link status change and an done is allowed */
47 	value = RTL_INER_LSC | RTL_INER_ANC;
48 	hw->phy.write_reg(hw, RTL_INER, 0xa42, value);
49 
50 	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
51 
52 	for (i = 0; i < 15; i++) {
53 		if (!rd32m(hw, NGBE_STAT,
54 			NGBE_STAT_GPHY_IN_RST(hw->bus.lan_id)))
55 			break;
56 
57 		msec_delay(10);
58 	}
59 	if (i == 15) {
60 		DEBUGOUT("GPhy reset exceeds maximum times.\n");
61 		return NGBE_ERR_PHY_TIMEOUT;
62 	}
63 
64 	for (i = 0; i < 1000; i++) {
65 		hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
66 		if (value & RTL_INSR_ACCESS)
67 			break;
68 	}
69 
70 	hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
71 	for (i = 0; i < 1000; i++) {
72 		hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
73 		if (value & RTL_INSR_ACCESS)
74 			break;
75 	}
76 	if (i == 1000)
77 		return NGBE_ERR_PHY_TIMEOUT;
78 
79 	hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
80 	for (i = 0; i < 1000; i++) {
81 		hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
82 		if (value & RTL_INSR_ACCESS)
83 			break;
84 	}
85 	if (i == 1000)
86 		return NGBE_ERR_PHY_TIMEOUT;
87 
88 	for (i = 0; i < 1000; i++) {
89 		hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value);
90 		if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON)
91 			break;
92 	}
93 	if (i == 1000)
94 		return NGBE_ERR_PHY_TIMEOUT;
95 
96 	return 0;
97 }
98 
99 /**
100  *  ngbe_setup_phy_link_rtl - Set and restart auto-neg
101  *  @hw: pointer to hardware structure
102  *
103  *  Restart auto-negotiation and PHY and waits for completion.
104  **/
105 s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
106 		u32 speed, bool autoneg_wait_to_complete)
107 {
108 	u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
109 	u16 value = 0;
110 
111 	DEBUGFUNC("ngbe_setup_phy_link_rtl");
112 
113 	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
114 
115 	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
116 
117 	if (!hw->mac.autoneg) {
118 		hw->phy.reset_hw(hw);
119 
120 		switch (speed) {
121 		case NGBE_LINK_SPEED_1GB_FULL:
122 			value = RTL_BMCR_SPEED_SELECT1;
123 			break;
124 		case NGBE_LINK_SPEED_100M_FULL:
125 			value = RTL_BMCR_SPEED_SELECT0;
126 			break;
127 		case NGBE_LINK_SPEED_10M_FULL:
128 			value = 0;
129 			break;
130 		default:
131 			value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
132 			DEBUGOUT("unknown speed = 0x%x.\n", speed);
133 			break;
134 		}
135 		/* duplex full */
136 		value |= RTL_BMCR_DUPLEX;
137 		hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
138 
139 		goto skip_an;
140 	}
141 
142 	/*
143 	 * Clear autoneg_advertised and set new values based on input link
144 	 * speed.
145 	 */
146 	if (speed) {
147 		hw->phy.autoneg_advertised = 0;
148 
149 		if (speed & NGBE_LINK_SPEED_1GB_FULL)
150 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
151 
152 		if (speed & NGBE_LINK_SPEED_100M_FULL)
153 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
154 
155 		if (speed & NGBE_LINK_SPEED_10M_FULL)
156 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
157 	}
158 
159 	/* disable 10/100M Half Duplex */
160 	hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg);
161 	autoneg_reg &= 0xFF5F;
162 	hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg);
163 
164 	/* set advertise enable according to input speed */
165 	if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) {
166 		hw->phy.read_reg(hw, RTL_GBCR,
167 			RTL_DEV_ZERO, &autoneg_reg);
168 		autoneg_reg &= ~RTL_GBCR_1000F;
169 		hw->phy.write_reg(hw, RTL_GBCR,
170 			RTL_DEV_ZERO, autoneg_reg);
171 	} else {
172 		hw->phy.read_reg(hw, RTL_GBCR,
173 			RTL_DEV_ZERO, &autoneg_reg);
174 		autoneg_reg |= RTL_GBCR_1000F;
175 		hw->phy.write_reg(hw, RTL_GBCR,
176 			RTL_DEV_ZERO, autoneg_reg);
177 	}
178 
179 	if (!(speed & NGBE_LINK_SPEED_100M_FULL)) {
180 		hw->phy.read_reg(hw, RTL_ANAR,
181 			RTL_DEV_ZERO, &autoneg_reg);
182 		autoneg_reg &= ~RTL_ANAR_100F;
183 		autoneg_reg &= ~RTL_ANAR_100H;
184 		hw->phy.write_reg(hw, RTL_ANAR,
185 			RTL_DEV_ZERO, autoneg_reg);
186 	} else {
187 		hw->phy.read_reg(hw, RTL_ANAR,
188 			RTL_DEV_ZERO, &autoneg_reg);
189 		autoneg_reg |= RTL_ANAR_100F;
190 		hw->phy.write_reg(hw, RTL_ANAR,
191 			RTL_DEV_ZERO, autoneg_reg);
192 	}
193 
194 	if (!(speed & NGBE_LINK_SPEED_10M_FULL)) {
195 		hw->phy.read_reg(hw, RTL_ANAR,
196 			RTL_DEV_ZERO, &autoneg_reg);
197 		autoneg_reg &= ~RTL_ANAR_10F;
198 		autoneg_reg &= ~RTL_ANAR_10H;
199 		hw->phy.write_reg(hw, RTL_ANAR,
200 			RTL_DEV_ZERO, autoneg_reg);
201 	} else {
202 		hw->phy.read_reg(hw, RTL_ANAR,
203 			RTL_DEV_ZERO, &autoneg_reg);
204 		autoneg_reg |= RTL_ANAR_10F;
205 		hw->phy.write_reg(hw, RTL_ANAR,
206 			RTL_DEV_ZERO, autoneg_reg);
207 	}
208 
209 	/* restart AN and wait AN done interrupt */
210 	autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE;
211 	hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
212 
213 skip_an:
214 	autoneg_reg = 0x205B;
215 	hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg);
216 	hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
217 
218 	hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg);
219 	autoneg_reg = autoneg_reg & 0xFFFC;
220 	/* act led blinking mode set to 60ms */
221 	autoneg_reg |= 0x2;
222 	hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg);
223 
224 	return 0;
225 }
226 
227 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
228 {
229 	u16 value = 0, i;
230 	s32 status = 0;
231 
232 	DEBUGFUNC("ngbe_reset_phy_rtl");
233 
234 	value |= RTL_BMCR_RESET;
235 	status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
236 
237 	for (i = 0; i < RTL_PHY_RST_WAIT_PERIOD; i++) {
238 		status = hw->phy.read_reg(hw, RTL_BMCR, RTL_DEV_ZERO, &value);
239 		if (!(value & RTL_BMCR_RESET))
240 			break;
241 		msleep(1);
242 	}
243 
244 	if (i == RTL_PHY_RST_WAIT_PERIOD) {
245 		DEBUGOUT("PHY reset polling failed to complete.\n");
246 		return NGBE_ERR_RESET_FAILED;
247 	}
248 
249 	return status;
250 }
251 
252 s32 ngbe_get_phy_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
253 {
254 	u16 value;
255 	s32 status = 0;
256 
257 	status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
258 	value &= RTL_ANAR_APAUSE | RTL_ANAR_PAUSE;
259 	*pause_bit = (u8)(value >> 10);
260 	return status;
261 }
262 
263 s32 ngbe_get_phy_lp_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
264 {
265 	u16 value;
266 	s32 status = 0;
267 
268 	status = hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
269 
270 	status = hw->phy.read_reg(hw, RTL_BMSR, RTL_DEV_ZERO, &value);
271 	value = value & RTL_BMSR_ANC;
272 
273 	/* if AN complete then check lp adv pause */
274 	status = hw->phy.read_reg(hw, RTL_ANLPAR, RTL_DEV_ZERO, &value);
275 	value &= RTL_ANLPAR_LP;
276 	*pause_bit = (u8)(value >> 10);
277 	return status;
278 }
279 
280 s32 ngbe_set_phy_pause_adv_rtl(struct ngbe_hw *hw, u16 pause_bit)
281 {
282 	u16 value;
283 	s32 status = 0;
284 
285 	status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
286 	value &= ~(RTL_ANAR_APAUSE | RTL_ANAR_PAUSE);
287 	value |= pause_bit;
288 
289 	status = hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, value);
290 
291 	return status;
292 }
293 
294 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
295 {
296 	s32 status = 0;
297 	u16 phy_link = 0;
298 	u16 phy_speed = 0;
299 	u16 phy_data = 0;
300 	u16 insr = 0;
301 
302 	DEBUGFUNC("ngbe_check_phy_link_rtl");
303 
304 	hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
305 
306 	/* Initialize speed and link to default case */
307 	*link_up = false;
308 	*speed = NGBE_LINK_SPEED_UNKNOWN;
309 
310 	/*
311 	 * Check current speed and link status of the PHY register.
312 	 * This is a vendor specific register and may have to
313 	 * be changed for other copper PHYs.
314 	 */
315 	status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data);
316 	phy_link = phy_data & RTL_PHYSR_RTLS;
317 	phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP);
318 	if (phy_link == RTL_PHYSR_RTLS) {
319 		*link_up = true;
320 
321 		if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP))
322 			*speed = NGBE_LINK_SPEED_1GB_FULL;
323 		else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP))
324 			*speed = NGBE_LINK_SPEED_100M_FULL;
325 		else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP))
326 			*speed = NGBE_LINK_SPEED_10M_FULL;
327 	}
328 
329 	return status;
330 }
331 
332