Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 Realtek Corporation. All rights reserved
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <errno.h>
7 : : #include <stdint.h>
8 : :
9 : : #include <rte_ether.h>
10 : : #include <ethdev_pci.h>
11 : :
12 : : #include "r8169_ethdev.h"
13 : : #include "r8169_hw.h"
14 : : #include "r8169_phy.h"
15 : : #include "r8169_logs.h"
16 : :
17 : : static void
18 : 0 : rtl_clear_set_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 clearmask,
19 : : u16 setmask)
20 : : {
21 : : u16 phy_reg_value;
22 : :
23 : 0 : phy_reg_value = rtl_mac_ocp_read(hw, addr);
24 : 0 : phy_reg_value &= ~clearmask;
25 : 0 : phy_reg_value |= setmask;
26 : 0 : rtl_mac_ocp_write(hw, addr, phy_reg_value);
27 : 0 : }
28 : :
29 : : void
30 : 0 : rtl_clear_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
31 : : {
32 : 0 : rtl_clear_set_mac_ocp_bit(hw, addr, mask, 0);
33 : 0 : }
34 : :
35 : : void
36 : 0 : rtl_set_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
37 : : {
38 : 0 : rtl_clear_set_mac_ocp_bit(hw, addr, 0, mask);
39 : 0 : }
40 : :
41 : : static u16
42 : : rtl_map_phy_ocp_addr(u16 PageNum, u8 RegNum)
43 : : {
44 : : u8 ocp_reg_num = 0;
45 : : u16 ocp_page_num = 0;
46 : : u16 ocp_phy_address = 0;
47 : :
48 : 0 : if (PageNum == 0) {
49 : 0 : ocp_page_num = OCP_STD_PHY_BASE_PAGE + (RegNum / 8);
50 : 0 : ocp_reg_num = 0x10 + (RegNum % 8);
51 : : } else {
52 : : ocp_page_num = PageNum;
53 : : ocp_reg_num = RegNum;
54 : : }
55 : :
56 : 0 : ocp_page_num <<= 4;
57 : :
58 [ # # # # ]: 0 : if (ocp_reg_num < 16) {
59 : : ocp_phy_address = 0;
60 : : } else {
61 : 0 : ocp_reg_num -= 16;
62 : 0 : ocp_reg_num <<= 1;
63 : :
64 : 0 : ocp_phy_address = ocp_page_num + ocp_reg_num;
65 : : }
66 : :
67 : : return ocp_phy_address;
68 : : }
69 : :
70 : : static u32
71 : 0 : rtl_mdio_real_read_phy_ocp(struct rtl_hw *hw, u32 RegAddr)
72 : : {
73 : : u32 data32;
74 : : int i, value = 0;
75 : :
76 : 0 : data32 = RegAddr / 2;
77 : 0 : data32 <<= OCPR_Addr_Reg_shift;
78 : :
79 : 0 : RTL_W32(hw, PHYOCP, data32);
80 [ # # ]: 0 : for (i = 0; i < 100; i++) {
81 : 0 : rte_delay_us(1);
82 : :
83 [ # # ]: 0 : if (RTL_R32(hw, PHYOCP) & OCPR_Flag)
84 : : break;
85 : : }
86 : 0 : value = RTL_R32(hw, PHYOCP) & OCPDR_Data_Mask;
87 : :
88 : 0 : return value;
89 : : }
90 : :
91 : : u32
92 : 0 : rtl_mdio_direct_read_phy_ocp(struct rtl_hw *hw, u32 RegAddr)
93 : : {
94 : 0 : return rtl_mdio_real_read_phy_ocp(hw, RegAddr);
95 : : }
96 : :
97 : : static u32
98 : 0 : rtl_mdio_read_phy_ocp(struct rtl_hw *hw, u16 PageNum, u32 RegAddr)
99 : : {
100 : : u16 ocp_addr;
101 : :
102 [ # # ]: 0 : ocp_addr = rtl_map_phy_ocp_addr(PageNum, RegAddr);
103 : :
104 : 0 : return rtl_mdio_direct_read_phy_ocp(hw, ocp_addr);
105 : : }
106 : :
107 : : static u32
108 : : rtl_mdio_real_read(struct rtl_hw *hw, u32 RegAddr)
109 : : {
110 : 0 : return rtl_mdio_read_phy_ocp(hw, hw->cur_page, RegAddr);
111 : : }
112 : :
113 : : static void
114 : 0 : rtl_mdio_real_write_phy_ocp(struct rtl_hw *hw, u32 RegAddr, u32 value)
115 : : {
116 : : u32 data32;
117 : : int i;
118 : :
119 : 0 : data32 = RegAddr / 2;
120 : 0 : data32 <<= OCPR_Addr_Reg_shift;
121 : 0 : data32 |= OCPR_Write | value;
122 : :
123 : 0 : RTL_W32(hw, PHYOCP, data32);
124 [ # # ]: 0 : for (i = 0; i < 100; i++) {
125 : 0 : rte_delay_us(1);
126 : :
127 [ # # ]: 0 : if (!(RTL_R32(hw, PHYOCP) & OCPR_Flag))
128 : : break;
129 : : }
130 : 0 : }
131 : :
132 : : void
133 : 0 : rtl_mdio_direct_write_phy_ocp(struct rtl_hw *hw, u32 RegAddr, u32 value)
134 : : {
135 : 0 : rtl_mdio_real_write_phy_ocp(hw, RegAddr, value);
136 : 0 : }
137 : :
138 : : static void
139 : 0 : rtl_mdio_write_phy_ocp(struct rtl_hw *hw, u16 PageNum, u32 RegAddr, u32 value)
140 : : {
141 : : u16 ocp_addr;
142 : :
143 [ # # ]: 0 : ocp_addr = rtl_map_phy_ocp_addr(PageNum, RegAddr);
144 : :
145 : 0 : rtl_mdio_direct_write_phy_ocp(hw, ocp_addr, value);
146 : 0 : }
147 : :
148 : : static void
149 : : rtl_mdio_real_write(struct rtl_hw *hw, u32 RegAddr, u32 value)
150 : : {
151 : 0 : if (RegAddr == 0x1F)
152 : 0 : hw->cur_page = value;
153 : 0 : rtl_mdio_write_phy_ocp(hw, hw->cur_page, RegAddr, value);
154 : : }
155 : :
156 : : u32
157 : 0 : rtl_mdio_read(struct rtl_hw *hw, u32 RegAddr)
158 : : {
159 : 0 : return rtl_mdio_real_read(hw, RegAddr);
160 : : }
161 : :
162 : : void
163 [ # # ]: 0 : rtl_mdio_write(struct rtl_hw *hw, u32 RegAddr, u32 value)
164 : : {
165 : : rtl_mdio_real_write(hw, RegAddr, value);
166 : 0 : }
167 : :
168 : : void
169 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 clearmask,
170 : : u16 setmask)
171 : : {
172 : : u16 phy_reg_value;
173 : :
174 : 0 : phy_reg_value = rtl_mdio_direct_read_phy_ocp(hw, addr);
175 : 0 : phy_reg_value &= ~clearmask;
176 : 0 : phy_reg_value |= setmask;
177 : 0 : rtl_mdio_direct_write_phy_ocp(hw, addr, phy_reg_value);
178 : 0 : }
179 : :
180 : : void
181 : 0 : rtl_clear_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
182 : : {
183 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(hw, addr, mask, 0);
184 : 0 : }
185 : :
186 : : void
187 : 0 : rtl_set_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
188 : : {
189 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(hw, addr, 0, mask);
190 : 0 : }
191 : :
192 : : void
193 : 0 : rtl_ephy_write(struct rtl_hw *hw, int addr, int value)
194 : : {
195 : : int i;
196 : :
197 : 0 : RTL_W32(hw, EPHYAR, EPHYAR_Write |
198 : : (addr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift |
199 : : (value & EPHYAR_Data_Mask));
200 : :
201 [ # # ]: 0 : for (i = 0; i < 10; i++) {
202 : 0 : rte_delay_us(100);
203 : :
204 : : /* Check if the NIC has completed EPHY write */
205 [ # # ]: 0 : if (!(RTL_R32(hw, EPHYAR) & EPHYAR_Flag))
206 : : break;
207 : : }
208 : :
209 : 0 : rte_delay_us(20);
210 : 0 : }
211 : :
212 : : static u16
213 : 0 : rtl_ephy_read(struct rtl_hw *hw, int addr)
214 : : {
215 : : int i;
216 : : u16 value = 0xffff;
217 : :
218 : 0 : RTL_W32(hw, EPHYAR, EPHYAR_Read | (addr & EPHYAR_Reg_Mask_v2) <<
219 : : EPHYAR_Reg_shift);
220 : :
221 [ # # ]: 0 : for (i = 0; i < 10; i++) {
222 : 0 : rte_delay_us(100);
223 : :
224 : : /* Check if the NIC has completed EPHY read */
225 [ # # ]: 0 : if (RTL_R32(hw, EPHYAR) & EPHYAR_Flag) {
226 : 0 : value = (u16)(RTL_R32(hw, EPHYAR) & EPHYAR_Data_Mask);
227 : 0 : break;
228 : : }
229 : : }
230 : :
231 : 0 : rte_delay_us(20);
232 : :
233 : 0 : return value;
234 : : }
235 : :
236 : : void
237 : 0 : rtl_clear_and_set_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 clearmask,
238 : : u16 setmask)
239 : : {
240 : : u16 ephy_value;
241 : :
242 : 0 : ephy_value = rtl_ephy_read(hw, addr);
243 : 0 : ephy_value &= ~clearmask;
244 : 0 : ephy_value |= setmask;
245 : 0 : rtl_ephy_write(hw, addr, ephy_value);
246 : 0 : }
247 : :
248 : : void
249 : 0 : rtl_clear_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 mask)
250 : : {
251 : 0 : rtl_clear_and_set_pcie_phy_bit(hw, addr, mask, 0);
252 : 0 : }
253 : :
254 : : void
255 : 0 : rtl_set_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 mask)
256 : : {
257 : 0 : rtl_clear_and_set_pcie_phy_bit(hw, addr, 0, mask);
258 : 0 : }
259 : :
260 : : bool
261 : 0 : rtl_set_phy_mcu_patch_request(struct rtl_hw *hw)
262 : : {
263 : : u16 gphy_val;
264 : : u16 wait_cnt;
265 : : bool bool_success = TRUE;
266 : :
267 : 0 : rtl_set_eth_phy_ocp_bit(hw, 0xB820, BIT_4);
268 : :
269 : : wait_cnt = 0;
270 : : do {
271 : 0 : gphy_val = rtl_mdio_direct_read_phy_ocp(hw, 0xB800);
272 : 0 : rte_delay_us(100);
273 : 0 : wait_cnt++;
274 [ # # # # ]: 0 : } while (!(gphy_val & BIT_6) && (wait_cnt < 1000));
275 : :
276 [ # # # # ]: 0 : if (!(gphy_val & BIT_6) && wait_cnt == 1000)
277 : : bool_success = FALSE;
278 : :
279 : : if (!bool_success)
280 : 0 : PMD_INIT_LOG(NOTICE, "%s fail.", __func__);
281 : :
282 : 0 : return bool_success;
283 : : }
284 : :
285 : : bool
286 : 0 : rtl_clear_phy_mcu_patch_request(struct rtl_hw *hw)
287 : : {
288 : : u16 gphy_val;
289 : : u16 wait_cnt;
290 : : bool bool_success = TRUE;
291 : :
292 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xB820, BIT_4);
293 : :
294 : : wait_cnt = 0;
295 : : do {
296 : 0 : gphy_val = rtl_mdio_direct_read_phy_ocp(hw, 0xB800);
297 : 0 : rte_delay_us(100);
298 : 0 : wait_cnt++;
299 [ # # # # ]: 0 : } while ((gphy_val & BIT_6) && (wait_cnt < 1000));
300 : :
301 [ # # # # ]: 0 : if ((gphy_val & BIT_6) && wait_cnt == 1000)
302 : : bool_success = FALSE;
303 : :
304 : : if (!bool_success)
305 : 0 : PMD_INIT_LOG(NOTICE, "%s fail.", __func__);
306 : :
307 : 0 : return bool_success;
308 : : }
309 : :
310 : : void
311 : 0 : rtl_set_phy_mcu_ram_code(struct rtl_hw *hw, const u16 *ramcode, u16 codesize)
312 : : {
313 : : u16 i;
314 : : u16 addr;
315 : : u16 val;
316 : :
317 [ # # # # ]: 0 : if (ramcode == NULL || codesize % 2)
318 : 0 : goto out;
319 : :
320 [ # # ]: 0 : for (i = 0; i < codesize; i += 2) {
321 : 0 : addr = ramcode[i];
322 : 0 : val = ramcode[i + 1];
323 [ # # ]: 0 : if (addr == 0xFFFF && val == 0xFFFF)
324 : : break;
325 : 0 : rtl_mdio_direct_write_phy_ocp(hw, addr, val);
326 : : }
327 : :
328 : 0 : out:
329 : 0 : return;
330 : : }
331 : :
332 : : static u8
333 : : rtl_is_phy_disable_mode_enabled(struct rtl_hw *hw)
334 : : {
335 : : u8 phy_disable_mode_enabled = FALSE;
336 : :
337 : 0 : switch (hw->HwSuppCheckPhyDisableModeVer) {
338 : 0 : case 3:
339 [ # # ]: 0 : if (RTL_R8(hw, 0xF2) & BIT_5)
340 : : phy_disable_mode_enabled = TRUE;
341 : : break;
342 : : }
343 : :
344 : : return phy_disable_mode_enabled;
345 : : }
346 : :
347 : : static u8
348 : : rtl_is_gpio_low(struct rtl_hw *hw)
349 : : {
350 : : u8 gpio_low = FALSE;
351 : :
352 [ # # ]: 0 : switch (hw->HwSuppCheckPhyDisableModeVer) {
353 : 0 : case 3:
354 [ # # ]: 0 : if (!(rtl_mac_ocp_read(hw, 0xDC04) & BIT_13))
355 : : gpio_low = TRUE;
356 : : break;
357 : : }
358 : :
359 : : return gpio_low;
360 : : }
361 : :
362 : : static u8
363 [ # # ]: 0 : rtl_is_in_phy_disable_mode(struct rtl_hw *hw)
364 : : {
365 : : u8 in_phy_disable_mode = FALSE;
366 : :
367 : : if (rtl_is_phy_disable_mode_enabled(hw) && rtl_is_gpio_low(hw))
368 : : in_phy_disable_mode = TRUE;
369 : :
370 : 0 : return in_phy_disable_mode;
371 : : }
372 : :
373 : : static void
374 : 0 : rtl_wait_phy_ups_resume(struct rtl_hw *hw, u16 PhyState)
375 : : {
376 : : u16 tmp_phy_state;
377 : : int i = 0;
378 : :
379 [ # # ]: 0 : switch (hw->mcfg) {
380 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
381 : : case CFG_METHOD_69 ... CFG_METHOD_71:
382 : : do {
383 : 0 : tmp_phy_state = rtl_mdio_direct_read_phy_ocp(hw, 0xA420);
384 : 0 : tmp_phy_state &= 0x7;
385 : : rte_delay_ms(1);
386 : 0 : i++;
387 [ # # ]: 0 : } while ((i < 100) && (tmp_phy_state != PhyState));
388 : : }
389 : 0 : }
390 : :
391 : : static void
392 : 0 : rtl_phy_power_up(struct rtl_hw *hw)
393 : : {
394 [ # # ]: 0 : if (rtl_is_in_phy_disable_mode(hw))
395 : : return;
396 : :
397 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
398 : 0 : rtl_mdio_write(hw, MII_BMCR, BMCR_ANENABLE);
399 : :
400 : : /* Wait ups resume (phy state 3) */
401 [ # # ]: 0 : switch (hw->mcfg) {
402 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
403 : : case CFG_METHOD_69 ... CFG_METHOD_71:
404 : 0 : rtl_wait_phy_ups_resume(hw, 3);
405 : : }
406 : : }
407 : :
408 : : void
409 : 0 : rtl_powerup_pll(struct rtl_hw *hw)
410 : : {
411 [ # # ]: 0 : switch (hw->mcfg) {
412 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
413 : : case CFG_METHOD_69 ... CFG_METHOD_71:
414 : 0 : RTL_W8(hw, PMCH, RTL_R8(hw, PMCH) | BIT_7 | BIT_6);
415 : : }
416 : :
417 : 0 : rtl_phy_power_up(hw);
418 : 0 : }
419 : :
420 : : static void
421 : 0 : rtl_phy_power_down(struct rtl_hw *hw)
422 : : {
423 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
424 : 0 : rtl_mdio_write(hw, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
425 : 0 : }
426 : :
427 : : void
428 : 0 : rtl_powerdown_pll(struct rtl_hw *hw)
429 : : {
430 [ # # ]: 0 : if (hw->DASH)
431 : : return;
432 : :
433 : 0 : rtl_phy_power_down(hw);
434 : :
435 [ # # ]: 0 : switch (hw->mcfg) {
436 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
437 : : case CFG_METHOD_69 ... CFG_METHOD_71:
438 : 0 : RTL_W8(hw, PMCH, RTL_R8(hw, PMCH) & ~BIT_7);
439 : : break;
440 : : }
441 : : }
442 : :
443 : : void
444 : 0 : rtl_hw_ephy_config(struct rtl_hw *hw)
445 : : {
446 : 0 : hw->hw_ops.hw_ephy_config(hw);
447 : 0 : }
448 : :
449 : : static int
450 : 0 : rtl_wait_phy_reset_complete(struct rtl_hw *hw)
451 : : {
452 : : int i, val;
453 : :
454 [ # # ]: 0 : for (i = 0; i < 2500; i++) {
455 : 0 : val = rtl_mdio_read(hw, MII_BMCR) & BMCR_RESET;
456 [ # # ]: 0 : if (!val)
457 : : return 0;
458 : :
459 : : rte_delay_ms(1);
460 : : }
461 : :
462 : : return -1;
463 : : }
464 : :
465 : : static void
466 : 0 : rtl_xmii_reset_enable(struct rtl_hw *hw)
467 : : {
468 [ # # ]: 0 : if (rtl_is_in_phy_disable_mode(hw))
469 : : return;
470 : :
471 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
472 : 0 : rtl_mdio_write(hw, MII_ADVERTISE, rtl_mdio_read(hw, MII_ADVERTISE) &
473 : : ~(ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
474 : : ADVERTISE_100FULL));
475 : 0 : rtl_mdio_write(hw, MII_CTRL1000, rtl_mdio_read(hw, MII_CTRL1000) &
476 : : ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL));
477 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xA5D4, rtl_mdio_direct_read_phy_ocp(hw, 0xA5D4) &
478 : : ~(RTK_ADVERTISE_2500FULL | RTK_ADVERTISE_5000FULL));
479 : 0 : rtl_mdio_write(hw, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
480 : :
481 : 0 : if (rtl_wait_phy_reset_complete(hw) == 0)
482 : : return;
483 : : }
484 : :
485 : : static void
486 : 0 : rtl8125_set_hw_phy_before_init_phy_mcu(struct rtl_hw *hw)
487 : : {
488 : : u16 phy_reg_value;
489 : :
490 [ # # ]: 0 : switch (hw->mcfg) {
491 : 0 : case CFG_METHOD_4:
492 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xBF86, 0x9000);
493 : :
494 : 0 : rtl_set_eth_phy_ocp_bit(hw, 0xC402, BIT_10);
495 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xC402, BIT_10);
496 : :
497 : 0 : phy_reg_value = rtl_mdio_direct_read_phy_ocp(hw, 0xBF86);
498 : 0 : phy_reg_value &= (BIT_1 | BIT_0);
499 [ # # ]: 0 : if (phy_reg_value != 0)
500 : 0 : PMD_INIT_LOG(NOTICE, "PHY watch dog not clear, value = 0x%x",
501 : : phy_reg_value);
502 : :
503 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xBD86, 0x1010);
504 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xBD88, 0x1010);
505 : :
506 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(hw, 0xBD4E, (BIT_11 | BIT_10), BIT_11);
507 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(hw, 0xBF46, (BIT_11 | BIT_10 | BIT_9 | BIT_8),
508 : : (BIT_10 | BIT_9 | BIT_8));
509 : 0 : break;
510 : : }
511 : 0 : }
512 : :
513 : : static u16
514 : 0 : rtl_get_hw_phy_mcu_code_ver(struct rtl_hw *hw)
515 : : {
516 : : u16 hw_ram_code_ver = ~0;
517 : :
518 [ # # ]: 0 : switch (hw->mcfg) {
519 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
520 : : case CFG_METHOD_69 ... CFG_METHOD_71:
521 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xA436, 0x801E);
522 : 0 : hw_ram_code_ver = rtl_mdio_direct_read_phy_ocp(hw, 0xA438);
523 : 0 : break;
524 : : }
525 : :
526 : 0 : return hw_ram_code_ver;
527 : : }
528 : :
529 : : static int
530 : : rtl_check_hw_phy_mcu_code_ver(struct rtl_hw *hw)
531 : : {
532 : : int ram_code_ver_match = 0;
533 : :
534 : 0 : hw->hw_ram_code_ver = rtl_get_hw_phy_mcu_code_ver(hw);
535 : :
536 [ # # ]: 0 : if (hw->hw_ram_code_ver == hw->sw_ram_code_ver) {
537 : : ram_code_ver_match = 1;
538 : 0 : hw->HwHasWrRamCodeToMicroP = TRUE;
539 : : } else {
540 : 0 : hw->HwHasWrRamCodeToMicroP = FALSE;
541 : : }
542 : :
543 : : return ram_code_ver_match;
544 : : }
545 : :
546 : : static void
547 : 0 : rtl_write_hw_phy_mcu_code_ver(struct rtl_hw *hw)
548 : : {
549 [ # # ]: 0 : switch (hw->mcfg) {
550 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
551 : : case CFG_METHOD_69 ... CFG_METHOD_71:
552 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xA436, 0x801E);
553 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xA438, hw->sw_ram_code_ver);
554 : 0 : hw->hw_ram_code_ver = hw->sw_ram_code_ver;
555 : 0 : break;
556 : : }
557 : 0 : }
558 : :
559 : : static void
560 : : rtl_enable_phy_disable_mode(struct rtl_hw *hw)
561 : : {
562 [ # # ]: 0 : switch (hw->HwSuppCheckPhyDisableModeVer) {
563 : 0 : case 3:
564 : 0 : RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) | BIT_5);
565 : : break;
566 : : }
567 : : }
568 : :
569 : : static void
570 : : rtl_disable_phy_disable_mode(struct rtl_hw *hw)
571 : : {
572 [ # # ]: 0 : switch (hw->HwSuppCheckPhyDisableModeVer) {
573 : 0 : case 3:
574 : 0 : RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) & ~BIT_5);
575 : : break;
576 : : }
577 : :
578 : : rte_delay_ms(1);
579 : 0 : }
580 : :
581 : : static void
582 : 0 : rtl_init_hw_phy_mcu(struct rtl_hw *hw)
583 : : {
584 : : u8 require_disable_phy_disable_mode = FALSE;
585 : :
586 [ # # ]: 0 : if (hw->NotWrRamCodeToMicroP)
587 : : return;
588 : :
589 : : if (rtl_check_hw_phy_mcu_code_ver(hw))
590 : 0 : return;
591 : :
592 [ # # # # ]: 0 : if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(hw) && rtl_is_in_phy_disable_mode(hw))
593 : : require_disable_phy_disable_mode = TRUE;
594 : :
595 : : if (require_disable_phy_disable_mode)
596 : : rtl_disable_phy_disable_mode(hw);
597 : :
598 : 0 : hw->hw_ops.hw_phy_mcu_config(hw);
599 : :
600 [ # # ]: 0 : if (require_disable_phy_disable_mode)
601 : : rtl_enable_phy_disable_mode(hw);
602 : :
603 : 0 : rtl_write_hw_phy_mcu_code_ver(hw);
604 : :
605 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
606 : :
607 : 0 : hw->HwHasWrRamCodeToMicroP = TRUE;
608 : : }
609 : :
610 : : static void
611 : 0 : rtl_disable_aldps(struct rtl_hw *hw)
612 : : {
613 : : u16 tmp_ushort;
614 : : u32 timeout, wait_cnt;
615 : :
616 : 0 : tmp_ushort = rtl_mdio_real_read_phy_ocp(hw, 0xA430);
617 [ # # ]: 0 : if (tmp_ushort & BIT_2) {
618 : : timeout = 0;
619 : : wait_cnt = 200;
620 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA430, BIT_2);
621 : :
622 : : do {
623 : 0 : rte_delay_us(100);
624 : :
625 : 0 : tmp_ushort = rtl_mac_ocp_read(hw, 0xE908);
626 : :
627 : 0 : timeout++;
628 [ # # # # ]: 0 : } while (!(tmp_ushort & BIT_7) && timeout < wait_cnt);
629 : : }
630 : 0 : }
631 : :
632 : : static bool
633 : 0 : rtl_is_adv_eee_enabled(struct rtl_hw *hw)
634 : : {
635 [ # # ]: 0 : switch (hw->mcfg) {
636 : 0 : case CFG_METHOD_48 ... CFG_METHOD_55:
637 : : case CFG_METHOD_69 ... CFG_METHOD_71:
638 [ # # ]: 0 : if (rtl_mdio_direct_read_phy_ocp(hw, 0xA430) & BIT_15)
639 : 0 : return true;
640 : : break;
641 : : default:
642 : : break;
643 : : }
644 : :
645 : : return false;
646 : : }
647 : :
648 : : static void
649 : 0 : _rtl_disable_adv_eee(struct rtl_hw *hw)
650 : : {
651 : : bool lock;
652 : :
653 [ # # ]: 0 : if (rtl_is_adv_eee_enabled(hw))
654 : : lock = true;
655 : : else
656 : : lock = false;
657 : :
658 : : if (lock)
659 : 0 : rtl_set_phy_mcu_patch_request(hw);
660 : :
661 : 0 : rtl_clear_mac_ocp_bit(hw, 0xE052, BIT_0);
662 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA442, (BIT_12 | BIT_13));
663 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA430, BIT_15);
664 : :
665 [ # # ]: 0 : if (lock)
666 : 0 : rtl_clear_phy_mcu_patch_request(hw);
667 : 0 : }
668 : :
669 : : static void
670 : 0 : rtl_disable_adv_eee(struct rtl_hw *hw)
671 : : {
672 [ # # ]: 0 : switch (hw->mcfg) {
673 : 0 : case CFG_METHOD_48:
674 : : case CFG_METHOD_49:
675 : : case CFG_METHOD_52:
676 : : case CFG_METHOD_54:
677 : : case CFG_METHOD_55:
678 : 0 : rtl8125_oob_mutex_lock(hw);
679 : 0 : break;
680 : : }
681 : :
682 : 0 : _rtl_disable_adv_eee(hw);
683 : :
684 [ # # ]: 0 : switch (hw->mcfg) {
685 : 0 : case CFG_METHOD_48:
686 : : case CFG_METHOD_49:
687 : : case CFG_METHOD_52:
688 : : case CFG_METHOD_54:
689 : : case CFG_METHOD_55:
690 : 0 : rtl8125_oob_mutex_unlock(hw);
691 : 0 : break;
692 : : }
693 : 0 : }
694 : :
695 : : static void
696 : 0 : rtl_disable_eee(struct rtl_hw *hw)
697 : : {
698 [ # # # # ]: 0 : switch (hw->mcfg) {
699 : 0 : case CFG_METHOD_48:
700 : : case CFG_METHOD_49:
701 : : case CFG_METHOD_52:
702 : 0 : rtl_clear_mac_ocp_bit(hw, 0xE040, (BIT_1 | BIT_0));
703 : 0 : rtl_clear_mac_ocp_bit(hw, 0xEB62, (BIT_2 | BIT_1));
704 : :
705 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA432, BIT_4);
706 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA5D0, (BIT_2 | BIT_1));
707 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D4, BIT_0);
708 : :
709 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D8, BIT_4);
710 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA428, BIT_7);
711 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA4A2, BIT_9);
712 : 0 : break;
713 : 0 : case CFG_METHOD_50:
714 : : case CFG_METHOD_51:
715 : : case CFG_METHOD_53 ... CFG_METHOD_57:
716 : 0 : rtl_clear_mac_ocp_bit(hw, 0xE040, (BIT_1 | BIT_0));
717 : :
718 : 0 : rtl_set_eth_phy_ocp_bit(hw, 0xA432, BIT_4);
719 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA5D0, (BIT_2 | BIT_1));
720 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D4, BIT_0);
721 : :
722 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D8, BIT_4);
723 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA428, BIT_7);
724 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA4A2, BIT_9);
725 : 0 : break;
726 : 0 : case CFG_METHOD_69 ... CFG_METHOD_71:
727 : 0 : rtl_clear_mac_ocp_bit(hw, 0xE040, (BIT_1 | BIT_0));
728 : :
729 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA5D0, (MDIO_EEE_100TX | MDIO_EEE_1000T));
730 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D4, MDIO_EEE_2_5GT);
731 [ # # ]: 0 : if (HW_SUPP_PHY_LINK_SPEED_5000M(hw))
732 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D4, MDIO_EEE_5GT);
733 : :
734 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA6D8, BIT_4);
735 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA428, BIT_7);
736 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA4A2, BIT_9);
737 : 0 : break;
738 : : default:
739 : : /* Not support EEE */
740 : : break;
741 : : }
742 : :
743 : : /* Advanced EEE */
744 : 0 : rtl_disable_adv_eee(hw);
745 : 0 : }
746 : :
747 : : void
748 : 0 : rtl_hw_phy_config(struct rtl_hw *hw)
749 : : {
750 : 0 : rtl_xmii_reset_enable(hw);
751 : :
752 : 0 : rtl8125_set_hw_phy_before_init_phy_mcu(hw);
753 : :
754 : 0 : rtl_init_hw_phy_mcu(hw);
755 : :
756 : 0 : hw->hw_ops.hw_phy_config(hw);
757 : :
758 [ # # ]: 0 : switch (hw->mcfg) {
759 : 0 : case CFG_METHOD_48 ... CFG_METHOD_57:
760 : : case CFG_METHOD_69 ... CFG_METHOD_71:
761 : 0 : rtl_disable_aldps(hw);
762 : 0 : break;
763 : : }
764 : :
765 : : /* Legacy force mode (chap 22) */
766 : : switch (hw->mcfg) {
767 : : case CFG_METHOD_48 ... CFG_METHOD_57:
768 : : case CFG_METHOD_69 ... CFG_METHOD_71:
769 : : default:
770 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA5B4, BIT_15);
771 : : break;
772 : : }
773 : :
774 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
775 : :
776 [ # # ]: 0 : if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(hw))
777 : 0 : rtl_disable_eee(hw);
778 : 0 : }
779 : :
780 : : static void
781 : 0 : rtl_phy_restart_nway(struct rtl_hw *hw)
782 : : {
783 [ # # ]: 0 : if (rtl_is_in_phy_disable_mode(hw))
784 : : return;
785 : :
786 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
787 : 0 : rtl_mdio_write(hw, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
788 : : }
789 : :
790 : : static void
791 : 0 : rtl_phy_setup_force_mode(struct rtl_hw *hw, u32 speed, u8 duplex)
792 : : {
793 : : u16 bmcr_true_force = 0;
794 : :
795 [ # # ]: 0 : if (rtl_is_in_phy_disable_mode(hw))
796 : : return;
797 : :
798 [ # # ]: 0 : if (speed == SPEED_10 && duplex == DUPLEX_HALF)
799 : : bmcr_true_force = BMCR_SPEED10;
800 [ # # ]: 0 : else if (speed == SPEED_10 && duplex == DUPLEX_FULL)
801 : : bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX;
802 [ # # ]: 0 : else if (speed == SPEED_100 && duplex == DUPLEX_HALF)
803 : : bmcr_true_force = BMCR_SPEED100;
804 [ # # ]: 0 : else if (speed == SPEED_100 && duplex == DUPLEX_FULL)
805 : : bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX;
806 : : else
807 : : return;
808 : :
809 : 0 : rtl_mdio_write(hw, 0x1F, 0x0000);
810 : 0 : rtl_mdio_write(hw, MII_BMCR, bmcr_true_force);
811 : : }
812 : :
813 : : static int
814 : 0 : rtl_set_speed_xmii(struct rtl_hw *hw, u8 autoneg, u32 speed, u8 duplex, u32 adv)
815 : : {
816 : : int auto_nego = 0;
817 : : int giga_ctrl = 0;
818 : : int ctrl_2500 = 0;
819 : : int rc = -EINVAL;
820 : :
821 : : /* Disable giga lite */
822 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA428, BIT_9);
823 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA5EA, BIT_0);
824 : :
825 [ # # ]: 0 : if (HW_SUPP_PHY_LINK_SPEED_5000M(hw))
826 : 0 : rtl_clear_eth_phy_ocp_bit(hw, 0xA5EA, BIT_1);
827 : :
828 [ # # ]: 0 : if (!rtl_is_speed_mode_valid(speed)) {
829 : 0 : speed = hw->HwSuppMaxPhyLinkSpeed;
830 : : duplex = DUPLEX_FULL;
831 : 0 : adv |= hw->advertising;
832 : : }
833 : :
834 : 0 : giga_ctrl = rtl_mdio_read(hw, MII_CTRL1000);
835 : 0 : giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
836 : 0 : ctrl_2500 = rtl_mdio_direct_read_phy_ocp(hw, 0xA5D4);
837 : 0 : ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL | RTK_ADVERTISE_5000FULL);
838 : :
839 [ # # ]: 0 : if (autoneg == AUTONEG_ENABLE) {
840 : : /* N-way force */
841 : 0 : auto_nego = rtl_mdio_read(hw, MII_ADVERTISE);
842 : 0 : auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
843 : : ADVERTISE_100HALF | ADVERTISE_100FULL |
844 : : ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
845 : :
846 [ # # ]: 0 : if (adv & ADVERTISE_10_HALF)
847 : 0 : auto_nego |= ADVERTISE_10HALF;
848 [ # # ]: 0 : if (adv & ADVERTISE_10_FULL)
849 : 0 : auto_nego |= ADVERTISE_10FULL;
850 [ # # ]: 0 : if (adv & ADVERTISE_100_HALF)
851 : 0 : auto_nego |= ADVERTISE_100HALF;
852 [ # # ]: 0 : if (adv & ADVERTISE_100_FULL)
853 : 0 : auto_nego |= ADVERTISE_100FULL;
854 [ # # ]: 0 : if (adv & ADVERTISE_1000_HALF)
855 : 0 : giga_ctrl |= ADVERTISE_1000HALF;
856 [ # # ]: 0 : if (adv & ADVERTISE_1000_FULL)
857 : 0 : giga_ctrl |= ADVERTISE_1000FULL;
858 [ # # ]: 0 : if (adv & ADVERTISE_2500_FULL)
859 : 0 : ctrl_2500 |= RTK_ADVERTISE_2500FULL;
860 [ # # ]: 0 : if (adv & ADVERTISE_5000_FULL)
861 : 0 : ctrl_2500 |= RTK_ADVERTISE_5000FULL;
862 : :
863 : : /* Flow control */
864 [ # # ]: 0 : if (hw->fcpause == rtl_fc_full)
865 : 0 : auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
866 : :
867 : 0 : rtl_mdio_write(hw, 0x1f, 0x0000);
868 : 0 : rtl_mdio_write(hw, MII_ADVERTISE, auto_nego);
869 : 0 : rtl_mdio_write(hw, MII_CTRL1000, giga_ctrl);
870 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xA5D4, ctrl_2500);
871 : 0 : rtl_phy_restart_nway(hw);
872 : : rte_delay_ms(20);
873 : : } else {
874 : : /* True force */
875 [ # # ]: 0 : if (speed == SPEED_10 || speed == SPEED_100)
876 : 0 : rtl_phy_setup_force_mode(hw, speed, duplex);
877 : : else
878 : 0 : goto out;
879 : : }
880 : 0 : hw->autoneg = autoneg;
881 : 0 : hw->speed = speed;
882 : 0 : hw->duplex = duplex;
883 : 0 : hw->advertising = adv;
884 : :
885 : : rc = 0;
886 : 0 : out:
887 : 0 : return rc;
888 : : }
889 : :
890 : : int
891 : 0 : rtl_set_speed(struct rtl_hw *hw)
892 : : {
893 : : int ret;
894 : :
895 : 0 : ret = rtl_set_speed_xmii(hw, hw->autoneg, hw->speed, hw->duplex,
896 : : hw->advertising);
897 : :
898 : 0 : return ret;
899 : : }
|