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_driver.h>
11 : :
12 : : #include "r8169_fiber.h"
13 : :
14 : : static bool
15 : : rtl8127_wait_8127_sds_cmd_done(struct rtl_hw *hw)
16 : : {
17 : : u32 timeout = 0;
18 : : u32 waitcount = 100;
19 : :
20 : : do {
21 [ # # # # ]: 0 : if (RTL_R16(hw, R8127_SDS_8127_CMD) & R8127_SDS_8127_CMD_IN)
22 : 0 : rte_delay_us(1);
23 : : else
24 : : return true;
25 [ # # # # ]: 0 : } while (++timeout < waitcount);
26 : :
27 : : return false;
28 : : }
29 : :
30 : : static u16
31 : 0 : rtl8127_sds_phy_read_8127(struct rtl_hw *hw, u16 index, u16 page, u16 reg)
32 : : {
33 : 0 : RTL_W16(hw, R8127_SDS_8127_ADDR,
34 : : R8127_MAKE_SDS_8127_ADDR(index, page, reg));
35 : 0 : RTL_W16(hw, R8127_SDS_8127_CMD, R8127_SDS_8127_CMD_IN);
36 : :
37 [ # # ]: 0 : if (rtl8127_wait_8127_sds_cmd_done(hw))
38 : 0 : return RTL_R16(hw, R8127_SDS_8127_DATA_OUT);
39 : : else
40 : : return 0xffff;
41 : : }
42 : :
43 : : static void
44 : 0 : rtl8127_sds_phy_write_8127(struct rtl_hw *hw, u16 index, u16 page, u16 reg,
45 : : u16 val)
46 : : {
47 : 0 : RTL_W16(hw, R8127_SDS_8127_DATA_IN, val);
48 : 0 : RTL_W16(hw, R8127_SDS_8127_ADDR,
49 : : R8127_MAKE_SDS_8127_ADDR(index, page, reg));
50 : 0 : RTL_W16(hw, R8127_SDS_8127_CMD,
51 : : R8127_SDS_8127_CMD_IN | R8127_SDS_8127_WE_IN);
52 : :
53 : : rtl8127_wait_8127_sds_cmd_done(hw);
54 : 0 : }
55 : :
56 : : static void
57 : 0 : rtl8127_clear_and_set_sds_phy_bit(struct rtl_hw *hw, u16 index, u16 page,
58 : : u16 addr, u16 clearmask, u16 setmask)
59 : : {
60 : : u16 val;
61 : :
62 : 0 : val = rtl8127_sds_phy_read_8127(hw, index, page, addr);
63 : 0 : val &= ~clearmask;
64 : 0 : val |= setmask;
65 : 0 : rtl8127_sds_phy_write_8127(hw, index, page, addr, val);
66 : 0 : }
67 : :
68 : : static void
69 : : rtl8127_clear_sds_phy_bit(struct rtl_hw *hw, u16 index, u16 page,
70 : : u16 addr, u16 mask)
71 : : {
72 : 0 : rtl8127_clear_and_set_sds_phy_bit(hw, index, page, addr, mask, 0);
73 : 0 : }
74 : :
75 : : static void
76 : : rtl8127_set_sds_phy_bit(struct rtl_hw *hw, u16 index, u16 page, u16 addr,
77 : : u16 mask)
78 : : {
79 : 0 : rtl8127_clear_and_set_sds_phy_bit(hw, index, page, addr, 0, mask);
80 : 0 : }
81 : :
82 : : static void
83 : 0 : rtl8127_sds_phy_reset_8127(struct rtl_hw *hw)
84 : : {
85 : 0 : RTL_W8(hw, 0x2350, RTL_R8(hw, 0x2350) & ~BIT_0);
86 : 0 : rte_delay_us(1);
87 : :
88 : 0 : RTL_W16(hw, 0x233A, 0x801F);
89 : 0 : RTL_W8(hw, 0x2350, RTL_R8(hw, 0x2350) | BIT_0);
90 : 0 : rte_delay_us(10);
91 : 0 : }
92 : :
93 : : static void
94 : : rtl8127_sds_phy_reset(struct rtl_hw *hw)
95 : : {
96 [ # # ]: 0 : switch (hw->HwFiberModeVer) {
97 : 0 : case FIBER_MODE_RTL8127ATF:
98 : 0 : rtl8127_sds_phy_reset_8127(hw);
99 : 0 : break;
100 : : default:
101 : : break;
102 : : }
103 : : }
104 : :
105 : : static void
106 : 0 : rtl8127_set_sds_phy_caps_1g_8127(struct rtl_hw *hw)
107 : : {
108 : : u16 val;
109 : :
110 [ # # ]: 0 : if (hw->fcpause == rtl_fc_full)
111 : : rtl8127_set_sds_phy_bit(hw, 0, 2, 4, BIT_8 | BIT_7);
112 : : else
113 : : rtl8127_clear_sds_phy_bit(hw, 0, 2, 4, BIT_8 | BIT_7);
114 : :
115 : : rtl8127_set_sds_phy_bit(hw, 0, 1, 31, BIT_3);
116 : 0 : rtl8127_clear_and_set_sds_phy_bit(hw, 0, 2, 0, BIT_13 | BIT_12 | BIT_6,
117 : : BIT_12 | BIT_6);
118 : : rtl8127_set_sds_phy_bit(hw, 0, 0, 4, BIT_2);
119 : 0 : RTL_W16(hw, 0x233A, 0x8004);
120 : :
121 : 0 : val = RTL_R16(hw, 0x233E);
122 : 0 : val &= ~(BIT_13 | BIT_12 | BIT_1 | BIT_0);
123 : 0 : val |= BIT_1;
124 : 0 : RTL_W16(hw, 0x233E, val);
125 : :
126 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC40A, 0x0);
127 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC466, 0x0);
128 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC808, 0x0);
129 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC80A, 0x0);
130 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(hw, 0xC804, 0x000F, 0x000C);
131 : 0 : }
132 : :
133 : : static void
134 : 0 : rtl8127_sds_phy_exit_1g_8127(struct rtl_hw *hw)
135 : : {
136 : : rtl8127_clear_sds_phy_bit(hw, 0, 1, 31, BIT_3);
137 : 0 : rtl8127_clear_and_set_sds_phy_bit(hw, 0, 2, 0, BIT_13 | BIT_12 | BIT_6,
138 : : BIT_6);
139 : :
140 : : rtl8127_sds_phy_reset(hw);
141 : 0 : }
142 : :
143 : : static void
144 : 0 : rtl8127_set_sds_phy_caps_10g_8127(struct rtl_hw *hw)
145 : : {
146 : : u16 val;
147 : :
148 [ # # ]: 0 : if (hw->fcpause == rtl_fc_full)
149 : : rtl8127_set_sds_phy_bit(hw, 0, 31, 11, BIT_3 | BIT_2);
150 : : else
151 : : rtl8127_clear_sds_phy_bit(hw, 0, 31, 11, BIT_3 | BIT_2);
152 : :
153 : 0 : RTL_W16(hw, 0x233A, 0x801A);
154 : :
155 : 0 : val = RTL_R16(hw, 0x233E);
156 : 0 : val &= ~(BIT_13 | BIT_12 | BIT_1 | BIT_0);
157 : 0 : val |= BIT_12;
158 : 0 : RTL_W16(hw, 0x233E, val);
159 : :
160 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC40A, 0x0);
161 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC466, 0x3);
162 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC808, 0x0);
163 : 0 : rtl_mdio_direct_write_phy_ocp(hw, 0xC80A, 0x0);
164 : 0 : rtl_clear_and_set_eth_phy_ocp_bit(hw, 0xC804, 0x000F, 0x000C);
165 : 0 : }
166 : :
167 : : static void
168 : 0 : rtl8127_set_sds_phy_caps_8127(struct rtl_hw *hw)
169 : : {
170 : 0 : rtl8127_sds_phy_exit_1g_8127(hw);
171 : :
172 [ # # # ]: 0 : switch (hw->speed) {
173 : 0 : case SPEED_10000:
174 : 0 : rtl8127_set_sds_phy_caps_10g_8127(hw);
175 : 0 : break;
176 : 0 : case SPEED_1000:
177 : 0 : rtl8127_set_sds_phy_caps_1g_8127(hw);
178 : 0 : break;
179 : : default:
180 : : break;
181 : : }
182 : 0 : }
183 : :
184 : : static void
185 : : rtl8127_set_sds_phy_caps(struct rtl_hw *hw)
186 : : {
187 : : switch (hw->HwFiberModeVer) {
188 : 0 : case FIBER_MODE_RTL8127ATF:
189 : 0 : rtl8127_set_sds_phy_caps_8127(hw);
190 : : break;
191 : : default:
192 : : break;
193 : : }
194 : : }
195 : :
196 : : static void
197 : : rtl8127_hw_sds_phy_config(struct rtl_hw *hw)
198 : : {
199 : : rtl8127_set_sds_phy_caps(hw);
200 : 0 : }
201 : :
202 : : void
203 : 0 : rtl8127_hw_fiber_phy_config(struct rtl_hw *hw)
204 : : {
205 [ # # ]: 0 : switch (hw->HwFiberModeVer) {
206 : : case FIBER_MODE_RTL8127ATF:
207 : : rtl8127_hw_sds_phy_config(hw);
208 : : break;
209 : : default:
210 : : break;
211 : : }
212 : 0 : }
|