1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * r8169_phy_config.c: RealTek 8169/8168/8101 ethernet driver. |
4 | * |
5 | * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw> |
6 | * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com> |
7 | * Copyright (c) a lot of people too. Please respect their work. |
8 | * |
9 | * See MAINTAINERS file for support contact information. |
10 | */ |
11 | |
12 | #include <linux/delay.h> |
13 | #include <linux/phy.h> |
14 | |
15 | #include "r8169.h" |
16 | |
17 | typedef void (*rtl_phy_cfg_fct)(struct rtl8169_private *tp, |
18 | struct phy_device *phydev); |
19 | |
20 | static void r8168d_modify_extpage(struct phy_device *phydev, int extpage, |
21 | int reg, u16 mask, u16 val) |
22 | { |
23 | int oldpage = phy_select_page(phydev, page: 0x0007); |
24 | |
25 | __phy_write(phydev, regnum: 0x1e, val: extpage); |
26 | __phy_modify(phydev, regnum: reg, mask, set: val); |
27 | |
28 | phy_restore_page(phydev, oldpage, ret: 0); |
29 | } |
30 | |
31 | static void r8168d_phy_param(struct phy_device *phydev, u16 parm, |
32 | u16 mask, u16 val) |
33 | { |
34 | int oldpage = phy_select_page(phydev, page: 0x0005); |
35 | |
36 | __phy_write(phydev, regnum: 0x05, val: parm); |
37 | __phy_modify(phydev, regnum: 0x06, mask, set: val); |
38 | |
39 | phy_restore_page(phydev, oldpage, ret: 0); |
40 | } |
41 | |
42 | static void r8168g_phy_param(struct phy_device *phydev, u16 parm, |
43 | u16 mask, u16 val) |
44 | { |
45 | int oldpage = phy_select_page(phydev, page: 0x0a43); |
46 | |
47 | __phy_write(phydev, regnum: 0x13, val: parm); |
48 | __phy_modify(phydev, regnum: 0x14, mask, set: val); |
49 | |
50 | phy_restore_page(phydev, oldpage, ret: 0); |
51 | } |
52 | |
53 | struct phy_reg { |
54 | u16 reg; |
55 | u16 val; |
56 | }; |
57 | |
58 | static void __rtl_writephy_batch(struct phy_device *phydev, |
59 | const struct phy_reg *regs, int len) |
60 | { |
61 | phy_lock_mdio_bus(phydev); |
62 | |
63 | while (len-- > 0) { |
64 | __phy_write(phydev, regnum: regs->reg, val: regs->val); |
65 | regs++; |
66 | } |
67 | |
68 | phy_unlock_mdio_bus(phydev); |
69 | } |
70 | |
71 | #define rtl_writephy_batch(p, a) __rtl_writephy_batch(p, a, ARRAY_SIZE(a)) |
72 | |
73 | static void rtl8168f_config_eee_phy(struct phy_device *phydev) |
74 | { |
75 | r8168d_modify_extpage(phydev, extpage: 0x0020, reg: 0x15, mask: 0, BIT(8)); |
76 | r8168d_phy_param(phydev, parm: 0x8b85, mask: 0, BIT(13)); |
77 | } |
78 | |
79 | static void rtl8168g_config_eee_phy(struct phy_device *phydev) |
80 | { |
81 | phy_modify_paged(phydev, page: 0x0a43, regnum: 0x11, mask: 0, BIT(4)); |
82 | } |
83 | |
84 | static void rtl8168h_config_eee_phy(struct phy_device *phydev) |
85 | { |
86 | rtl8168g_config_eee_phy(phydev); |
87 | |
88 | phy_modify_paged(phydev, page: 0xa4a, regnum: 0x11, mask: 0x0000, set: 0x0200); |
89 | phy_modify_paged(phydev, page: 0xa42, regnum: 0x14, mask: 0x0000, set: 0x0080); |
90 | } |
91 | |
92 | static void rtl8125a_config_eee_phy(struct phy_device *phydev) |
93 | { |
94 | rtl8168h_config_eee_phy(phydev); |
95 | |
96 | phy_modify_paged(phydev, page: 0xa6d, regnum: 0x12, mask: 0x0001, set: 0x0000); |
97 | phy_modify_paged(phydev, page: 0xa6d, regnum: 0x14, mask: 0x0010, set: 0x0000); |
98 | } |
99 | |
100 | static void rtl8125b_config_eee_phy(struct phy_device *phydev) |
101 | { |
102 | phy_modify_paged(phydev, page: 0xa6d, regnum: 0x12, mask: 0x0001, set: 0x0000); |
103 | phy_modify_paged(phydev, page: 0xa6d, regnum: 0x14, mask: 0x0010, set: 0x0000); |
104 | phy_modify_paged(phydev, page: 0xa42, regnum: 0x14, mask: 0x0080, set: 0x0000); |
105 | phy_modify_paged(phydev, page: 0xa4a, regnum: 0x11, mask: 0x0200, set: 0x0000); |
106 | } |
107 | |
108 | static void rtl8169s_hw_phy_config(struct rtl8169_private *tp, |
109 | struct phy_device *phydev) |
110 | { |
111 | static const struct phy_reg phy_reg_init[] = { |
112 | { 0x1f, 0x0001 }, |
113 | { 0x06, 0x006e }, |
114 | { 0x08, 0x0708 }, |
115 | { 0x15, 0x4000 }, |
116 | { 0x18, 0x65c7 }, |
117 | |
118 | { 0x1f, 0x0001 }, |
119 | { 0x03, 0x00a1 }, |
120 | { 0x02, 0x0008 }, |
121 | { 0x01, 0x0120 }, |
122 | { 0x00, 0x1000 }, |
123 | { 0x04, 0x0800 }, |
124 | { 0x04, 0x0000 }, |
125 | |
126 | { 0x03, 0xff41 }, |
127 | { 0x02, 0xdf60 }, |
128 | { 0x01, 0x0140 }, |
129 | { 0x00, 0x0077 }, |
130 | { 0x04, 0x7800 }, |
131 | { 0x04, 0x7000 }, |
132 | |
133 | { 0x03, 0x802f }, |
134 | { 0x02, 0x4f02 }, |
135 | { 0x01, 0x0409 }, |
136 | { 0x00, 0xf0f9 }, |
137 | { 0x04, 0x9800 }, |
138 | { 0x04, 0x9000 }, |
139 | |
140 | { 0x03, 0xdf01 }, |
141 | { 0x02, 0xdf20 }, |
142 | { 0x01, 0xff95 }, |
143 | { 0x00, 0xba00 }, |
144 | { 0x04, 0xa800 }, |
145 | { 0x04, 0xa000 }, |
146 | |
147 | { 0x03, 0xff41 }, |
148 | { 0x02, 0xdf20 }, |
149 | { 0x01, 0x0140 }, |
150 | { 0x00, 0x00bb }, |
151 | { 0x04, 0xb800 }, |
152 | { 0x04, 0xb000 }, |
153 | |
154 | { 0x03, 0xdf41 }, |
155 | { 0x02, 0xdc60 }, |
156 | { 0x01, 0x6340 }, |
157 | { 0x00, 0x007d }, |
158 | { 0x04, 0xd800 }, |
159 | { 0x04, 0xd000 }, |
160 | |
161 | { 0x03, 0xdf01 }, |
162 | { 0x02, 0xdf20 }, |
163 | { 0x01, 0x100a }, |
164 | { 0x00, 0xa0ff }, |
165 | { 0x04, 0xf800 }, |
166 | { 0x04, 0xf000 }, |
167 | |
168 | { 0x1f, 0x0000 }, |
169 | { 0x0b, 0x0000 }, |
170 | { 0x00, 0x9200 } |
171 | }; |
172 | |
173 | rtl_writephy_batch(phydev, phy_reg_init); |
174 | } |
175 | |
176 | static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp, |
177 | struct phy_device *phydev) |
178 | { |
179 | phy_write_paged(phydev, page: 0x0002, regnum: 0x01, val: 0x90d0); |
180 | } |
181 | |
182 | static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp, |
183 | struct phy_device *phydev) |
184 | { |
185 | static const struct phy_reg phy_reg_init[] = { |
186 | { 0x1f, 0x0001 }, |
187 | { 0x04, 0x0000 }, |
188 | { 0x03, 0x00a1 }, |
189 | { 0x02, 0x0008 }, |
190 | { 0x01, 0x0120 }, |
191 | { 0x00, 0x1000 }, |
192 | { 0x04, 0x0800 }, |
193 | { 0x04, 0x9000 }, |
194 | { 0x03, 0x802f }, |
195 | { 0x02, 0x4f02 }, |
196 | { 0x01, 0x0409 }, |
197 | { 0x00, 0xf099 }, |
198 | { 0x04, 0x9800 }, |
199 | { 0x04, 0xa000 }, |
200 | { 0x03, 0xdf01 }, |
201 | { 0x02, 0xdf20 }, |
202 | { 0x01, 0xff95 }, |
203 | { 0x00, 0xba00 }, |
204 | { 0x04, 0xa800 }, |
205 | { 0x04, 0xf000 }, |
206 | { 0x03, 0xdf01 }, |
207 | { 0x02, 0xdf20 }, |
208 | { 0x01, 0x101a }, |
209 | { 0x00, 0xa0ff }, |
210 | { 0x04, 0xf800 }, |
211 | { 0x04, 0x0000 }, |
212 | { 0x1f, 0x0000 }, |
213 | |
214 | { 0x1f, 0x0001 }, |
215 | { 0x10, 0xf41b }, |
216 | { 0x14, 0xfb54 }, |
217 | { 0x18, 0xf5c7 }, |
218 | { 0x1f, 0x0000 }, |
219 | |
220 | { 0x1f, 0x0001 }, |
221 | { 0x17, 0x0cc0 }, |
222 | { 0x1f, 0x0000 } |
223 | }; |
224 | |
225 | rtl_writephy_batch(phydev, phy_reg_init); |
226 | } |
227 | |
228 | static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp, |
229 | struct phy_device *phydev) |
230 | { |
231 | static const struct phy_reg phy_reg_init[] = { |
232 | { 0x1f, 0x0001 }, |
233 | { 0x04, 0x0000 }, |
234 | { 0x03, 0x00a1 }, |
235 | { 0x02, 0x0008 }, |
236 | { 0x01, 0x0120 }, |
237 | { 0x00, 0x1000 }, |
238 | { 0x04, 0x0800 }, |
239 | { 0x04, 0x9000 }, |
240 | { 0x03, 0x802f }, |
241 | { 0x02, 0x4f02 }, |
242 | { 0x01, 0x0409 }, |
243 | { 0x00, 0xf099 }, |
244 | { 0x04, 0x9800 }, |
245 | { 0x04, 0xa000 }, |
246 | { 0x03, 0xdf01 }, |
247 | { 0x02, 0xdf20 }, |
248 | { 0x01, 0xff95 }, |
249 | { 0x00, 0xba00 }, |
250 | { 0x04, 0xa800 }, |
251 | { 0x04, 0xf000 }, |
252 | { 0x03, 0xdf01 }, |
253 | { 0x02, 0xdf20 }, |
254 | { 0x01, 0x101a }, |
255 | { 0x00, 0xa0ff }, |
256 | { 0x04, 0xf800 }, |
257 | { 0x04, 0x0000 }, |
258 | { 0x1f, 0x0000 }, |
259 | |
260 | { 0x1f, 0x0001 }, |
261 | { 0x0b, 0x8480 }, |
262 | { 0x1f, 0x0000 }, |
263 | |
264 | { 0x1f, 0x0001 }, |
265 | { 0x18, 0x67c7 }, |
266 | { 0x04, 0x2000 }, |
267 | { 0x03, 0x002f }, |
268 | { 0x02, 0x4360 }, |
269 | { 0x01, 0x0109 }, |
270 | { 0x00, 0x3022 }, |
271 | { 0x04, 0x2800 }, |
272 | { 0x1f, 0x0000 }, |
273 | |
274 | { 0x1f, 0x0001 }, |
275 | { 0x17, 0x0cc0 }, |
276 | { 0x1f, 0x0000 } |
277 | }; |
278 | |
279 | rtl_writephy_batch(phydev, phy_reg_init); |
280 | } |
281 | |
282 | static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp, |
283 | struct phy_device *phydev) |
284 | { |
285 | phy_write(phydev, regnum: 0x1f, val: 0x0001); |
286 | phy_set_bits(phydev, regnum: 0x16, BIT(0)); |
287 | phy_write(phydev, regnum: 0x10, val: 0xf41b); |
288 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
289 | } |
290 | |
291 | static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp, |
292 | struct phy_device *phydev) |
293 | { |
294 | phy_write_paged(phydev, page: 0x0001, regnum: 0x10, val: 0xf41b); |
295 | } |
296 | |
297 | static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp, |
298 | struct phy_device *phydev) |
299 | { |
300 | phy_write(phydev, regnum: 0x1d, val: 0x0f00); |
301 | phy_write_paged(phydev, page: 0x0002, regnum: 0x0c, val: 0x1ec8); |
302 | } |
303 | |
304 | static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp, |
305 | struct phy_device *phydev) |
306 | { |
307 | phy_set_bits(phydev, regnum: 0x14, BIT(5)); |
308 | phy_set_bits(phydev, regnum: 0x0d, BIT(5)); |
309 | phy_write_paged(phydev, page: 0x0001, regnum: 0x1d, val: 0x3d98); |
310 | } |
311 | |
312 | static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp, |
313 | struct phy_device *phydev) |
314 | { |
315 | static const struct phy_reg phy_reg_init[] = { |
316 | { 0x1f, 0x0001 }, |
317 | { 0x12, 0x2300 }, |
318 | { 0x1f, 0x0002 }, |
319 | { 0x00, 0x88d4 }, |
320 | { 0x01, 0x82b1 }, |
321 | { 0x03, 0x7002 }, |
322 | { 0x08, 0x9e30 }, |
323 | { 0x09, 0x01f0 }, |
324 | { 0x0a, 0x5500 }, |
325 | { 0x0c, 0x00c8 }, |
326 | { 0x1f, 0x0003 }, |
327 | { 0x12, 0xc096 }, |
328 | { 0x16, 0x000a }, |
329 | { 0x1f, 0x0000 }, |
330 | { 0x1f, 0x0000 }, |
331 | { 0x09, 0x2000 }, |
332 | { 0x09, 0x0000 } |
333 | }; |
334 | |
335 | rtl_writephy_batch(phydev, phy_reg_init); |
336 | |
337 | phy_set_bits(phydev, regnum: 0x14, BIT(5)); |
338 | phy_set_bits(phydev, regnum: 0x0d, BIT(5)); |
339 | } |
340 | |
341 | static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp, |
342 | struct phy_device *phydev) |
343 | { |
344 | static const struct phy_reg phy_reg_init[] = { |
345 | { 0x1f, 0x0001 }, |
346 | { 0x12, 0x2300 }, |
347 | { 0x03, 0x802f }, |
348 | { 0x02, 0x4f02 }, |
349 | { 0x01, 0x0409 }, |
350 | { 0x00, 0xf099 }, |
351 | { 0x04, 0x9800 }, |
352 | { 0x04, 0x9000 }, |
353 | { 0x1d, 0x3d98 }, |
354 | { 0x1f, 0x0002 }, |
355 | { 0x0c, 0x7eb8 }, |
356 | { 0x06, 0x0761 }, |
357 | { 0x1f, 0x0003 }, |
358 | { 0x16, 0x0f0a }, |
359 | { 0x1f, 0x0000 } |
360 | }; |
361 | |
362 | rtl_writephy_batch(phydev, phy_reg_init); |
363 | |
364 | phy_set_bits(phydev, regnum: 0x16, BIT(0)); |
365 | phy_set_bits(phydev, regnum: 0x14, BIT(5)); |
366 | phy_set_bits(phydev, regnum: 0x0d, BIT(5)); |
367 | } |
368 | |
369 | static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp, |
370 | struct phy_device *phydev) |
371 | { |
372 | static const struct phy_reg phy_reg_init[] = { |
373 | { 0x1f, 0x0001 }, |
374 | { 0x12, 0x2300 }, |
375 | { 0x1d, 0x3d98 }, |
376 | { 0x1f, 0x0002 }, |
377 | { 0x0c, 0x7eb8 }, |
378 | { 0x06, 0x5461 }, |
379 | { 0x1f, 0x0003 }, |
380 | { 0x16, 0x0f0a }, |
381 | { 0x1f, 0x0000 } |
382 | }; |
383 | |
384 | rtl_writephy_batch(phydev, phy_reg_init); |
385 | |
386 | phy_set_bits(phydev, regnum: 0x16, BIT(0)); |
387 | phy_set_bits(phydev, regnum: 0x14, BIT(5)); |
388 | phy_set_bits(phydev, regnum: 0x0d, BIT(5)); |
389 | } |
390 | |
391 | static const struct phy_reg rtl8168d_1_phy_reg_init_0[] = { |
392 | /* Channel Estimation */ |
393 | { 0x1f, 0x0001 }, |
394 | { 0x06, 0x4064 }, |
395 | { 0x07, 0x2863 }, |
396 | { 0x08, 0x059c }, |
397 | { 0x09, 0x26b4 }, |
398 | { 0x0a, 0x6a19 }, |
399 | { 0x0b, 0xdcc8 }, |
400 | { 0x10, 0xf06d }, |
401 | { 0x14, 0x7f68 }, |
402 | { 0x18, 0x7fd9 }, |
403 | { 0x1c, 0xf0ff }, |
404 | { 0x1d, 0x3d9c }, |
405 | { 0x1f, 0x0003 }, |
406 | { 0x12, 0xf49f }, |
407 | { 0x13, 0x070b }, |
408 | { 0x1a, 0x05ad }, |
409 | { 0x14, 0x94c0 }, |
410 | |
411 | /* |
412 | * Tx Error Issue |
413 | * Enhance line driver power |
414 | */ |
415 | { 0x1f, 0x0002 }, |
416 | { 0x06, 0x5561 }, |
417 | { 0x1f, 0x0005 }, |
418 | { 0x05, 0x8332 }, |
419 | { 0x06, 0x5561 }, |
420 | |
421 | /* |
422 | * Can not link to 1Gbps with bad cable |
423 | * Decrease SNR threshold form 21.07dB to 19.04dB |
424 | */ |
425 | { 0x1f, 0x0001 }, |
426 | { 0x17, 0x0cc0 }, |
427 | |
428 | { 0x1f, 0x0000 }, |
429 | { 0x0d, 0xf880 } |
430 | }; |
431 | |
432 | static void rtl8168d_apply_firmware_cond(struct rtl8169_private *tp, |
433 | struct phy_device *phydev, |
434 | u16 val) |
435 | { |
436 | u16 reg_val; |
437 | |
438 | phy_write(phydev, regnum: 0x1f, val: 0x0005); |
439 | phy_write(phydev, regnum: 0x05, val: 0x001b); |
440 | reg_val = phy_read(phydev, regnum: 0x06); |
441 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
442 | |
443 | if (reg_val != val) |
444 | phydev_warn(phydev, "chipset not ready for firmware\n" ); |
445 | else |
446 | r8169_apply_firmware(tp); |
447 | } |
448 | |
449 | static void rtl8168d_1_common(struct phy_device *phydev) |
450 | { |
451 | u16 val; |
452 | |
453 | phy_write_paged(phydev, page: 0x0002, regnum: 0x05, val: 0x669a); |
454 | r8168d_phy_param(phydev, parm: 0x8330, mask: 0xffff, val: 0x669a); |
455 | phy_write(phydev, regnum: 0x1f, val: 0x0002); |
456 | |
457 | val = phy_read(phydev, regnum: 0x0d); |
458 | |
459 | if ((val & 0x00ff) != 0x006c) { |
460 | static const u16 set[] = { |
461 | 0x0065, 0x0066, 0x0067, 0x0068, |
462 | 0x0069, 0x006a, 0x006b, 0x006c |
463 | }; |
464 | int i; |
465 | |
466 | val &= 0xff00; |
467 | for (i = 0; i < ARRAY_SIZE(set); i++) |
468 | phy_write(phydev, regnum: 0x0d, val: val | set[i]); |
469 | } |
470 | } |
471 | |
472 | static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp, |
473 | struct phy_device *phydev) |
474 | { |
475 | rtl_writephy_batch(phydev, rtl8168d_1_phy_reg_init_0); |
476 | |
477 | /* |
478 | * Rx Error Issue |
479 | * Fine Tune Switching regulator parameter |
480 | */ |
481 | phy_write(phydev, regnum: 0x1f, val: 0x0002); |
482 | phy_modify(phydev, regnum: 0x0b, mask: 0x00ef, set: 0x0010); |
483 | phy_modify(phydev, regnum: 0x0c, mask: 0x5d00, set: 0xa200); |
484 | |
485 | if (rtl8168d_efuse_read(tp, reg_addr: 0x01) == 0xb1) { |
486 | rtl8168d_1_common(phydev); |
487 | } else { |
488 | phy_write_paged(phydev, page: 0x0002, regnum: 0x05, val: 0x6662); |
489 | r8168d_phy_param(phydev, parm: 0x8330, mask: 0xffff, val: 0x6662); |
490 | } |
491 | |
492 | /* RSET couple improve */ |
493 | phy_write(phydev, regnum: 0x1f, val: 0x0002); |
494 | phy_set_bits(phydev, regnum: 0x0d, val: 0x0300); |
495 | phy_set_bits(phydev, regnum: 0x0f, val: 0x0010); |
496 | |
497 | /* Fine tune PLL performance */ |
498 | phy_write(phydev, regnum: 0x1f, val: 0x0002); |
499 | phy_modify(phydev, regnum: 0x02, mask: 0x0600, set: 0x0100); |
500 | phy_clear_bits(phydev, regnum: 0x03, val: 0xe000); |
501 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
502 | |
503 | rtl8168d_apply_firmware_cond(tp, phydev, val: 0xbf00); |
504 | } |
505 | |
506 | static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp, |
507 | struct phy_device *phydev) |
508 | { |
509 | rtl_writephy_batch(phydev, rtl8168d_1_phy_reg_init_0); |
510 | |
511 | if (rtl8168d_efuse_read(tp, reg_addr: 0x01) == 0xb1) { |
512 | rtl8168d_1_common(phydev); |
513 | } else { |
514 | phy_write_paged(phydev, page: 0x0002, regnum: 0x05, val: 0x2642); |
515 | r8168d_phy_param(phydev, parm: 0x8330, mask: 0xffff, val: 0x2642); |
516 | } |
517 | |
518 | /* Fine tune PLL performance */ |
519 | phy_write(phydev, regnum: 0x1f, val: 0x0002); |
520 | phy_modify(phydev, regnum: 0x02, mask: 0x0600, set: 0x0100); |
521 | phy_clear_bits(phydev, regnum: 0x03, val: 0xe000); |
522 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
523 | |
524 | /* Switching regulator Slew rate */ |
525 | phy_modify_paged(phydev, page: 0x0002, regnum: 0x0f, mask: 0x0000, set: 0x0017); |
526 | |
527 | rtl8168d_apply_firmware_cond(tp, phydev, val: 0xb300); |
528 | } |
529 | |
530 | static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp, |
531 | struct phy_device *phydev) |
532 | { |
533 | phy_write_paged(phydev, page: 0x0001, regnum: 0x17, val: 0x0cc0); |
534 | r8168d_modify_extpage(phydev, extpage: 0x002d, reg: 0x18, mask: 0xffff, val: 0x0040); |
535 | phy_set_bits(phydev, regnum: 0x0d, BIT(5)); |
536 | } |
537 | |
538 | static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp, |
539 | struct phy_device *phydev) |
540 | { |
541 | static const struct phy_reg phy_reg_init[] = { |
542 | /* Channel estimation fine tune */ |
543 | { 0x1f, 0x0001 }, |
544 | { 0x0b, 0x6c20 }, |
545 | { 0x07, 0x2872 }, |
546 | { 0x1c, 0xefff }, |
547 | { 0x1f, 0x0003 }, |
548 | { 0x14, 0x6420 }, |
549 | { 0x1f, 0x0000 }, |
550 | }; |
551 | |
552 | r8169_apply_firmware(tp); |
553 | |
554 | /* Enable Delay cap */ |
555 | r8168d_phy_param(phydev, parm: 0x8b80, mask: 0xffff, val: 0xc896); |
556 | |
557 | rtl_writephy_batch(phydev, phy_reg_init); |
558 | |
559 | /* Update PFM & 10M TX idle timer */ |
560 | r8168d_modify_extpage(phydev, extpage: 0x002f, reg: 0x15, mask: 0xffff, val: 0x1919); |
561 | |
562 | r8168d_modify_extpage(phydev, extpage: 0x00ac, reg: 0x18, mask: 0xffff, val: 0x0006); |
563 | |
564 | /* DCO enable for 10M IDLE Power */ |
565 | r8168d_modify_extpage(phydev, extpage: 0x0023, reg: 0x17, mask: 0x0000, val: 0x0006); |
566 | |
567 | /* For impedance matching */ |
568 | phy_modify_paged(phydev, page: 0x0002, regnum: 0x08, mask: 0x7f00, set: 0x8000); |
569 | |
570 | /* PHY auto speed down */ |
571 | r8168d_modify_extpage(phydev, extpage: 0x002d, reg: 0x18, mask: 0x0000, val: 0x0050); |
572 | phy_set_bits(phydev, regnum: 0x14, BIT(15)); |
573 | |
574 | r8168d_phy_param(phydev, parm: 0x8b86, mask: 0x0000, val: 0x0001); |
575 | r8168d_phy_param(phydev, parm: 0x8b85, mask: 0x2000, val: 0x0000); |
576 | |
577 | r8168d_modify_extpage(phydev, extpage: 0x0020, reg: 0x15, mask: 0x1100, val: 0x0000); |
578 | phy_write_paged(phydev, page: 0x0006, regnum: 0x00, val: 0x5a00); |
579 | |
580 | phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val: 0x0000); |
581 | } |
582 | |
583 | static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp, |
584 | struct phy_device *phydev) |
585 | { |
586 | r8169_apply_firmware(tp); |
587 | |
588 | /* Enable Delay cap */ |
589 | r8168d_modify_extpage(phydev, extpage: 0x00ac, reg: 0x18, mask: 0xffff, val: 0x0006); |
590 | |
591 | /* Channel estimation fine tune */ |
592 | phy_write_paged(phydev, page: 0x0003, regnum: 0x09, val: 0xa20f); |
593 | |
594 | /* Green Setting */ |
595 | r8168d_phy_param(phydev, parm: 0x8b5b, mask: 0xffff, val: 0x9222); |
596 | r8168d_phy_param(phydev, parm: 0x8b6d, mask: 0xffff, val: 0x8000); |
597 | r8168d_phy_param(phydev, parm: 0x8b76, mask: 0xffff, val: 0x8000); |
598 | |
599 | /* For 4-corner performance improve */ |
600 | phy_write(phydev, regnum: 0x1f, val: 0x0005); |
601 | phy_write(phydev, regnum: 0x05, val: 0x8b80); |
602 | phy_set_bits(phydev, regnum: 0x17, val: 0x0006); |
603 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
604 | |
605 | /* PHY auto speed down */ |
606 | r8168d_modify_extpage(phydev, extpage: 0x002d, reg: 0x18, mask: 0x0000, val: 0x0010); |
607 | phy_set_bits(phydev, regnum: 0x14, BIT(15)); |
608 | |
609 | /* improve 10M EEE waveform */ |
610 | r8168d_phy_param(phydev, parm: 0x8b86, mask: 0x0000, val: 0x0001); |
611 | |
612 | /* Improve 2-pair detection performance */ |
613 | r8168d_phy_param(phydev, parm: 0x8b85, mask: 0x0000, val: 0x4000); |
614 | |
615 | rtl8168f_config_eee_phy(phydev); |
616 | |
617 | /* Green feature */ |
618 | phy_write(phydev, regnum: 0x1f, val: 0x0003); |
619 | phy_set_bits(phydev, regnum: 0x19, BIT(0)); |
620 | phy_set_bits(phydev, regnum: 0x10, BIT(10)); |
621 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
622 | phy_modify_paged(phydev, page: 0x0005, regnum: 0x01, mask: 0, BIT(8)); |
623 | } |
624 | |
625 | static void rtl8168f_hw_phy_config(struct rtl8169_private *tp, |
626 | struct phy_device *phydev) |
627 | { |
628 | /* For 4-corner performance improve */ |
629 | r8168d_phy_param(phydev, parm: 0x8b80, mask: 0x0000, val: 0x0006); |
630 | |
631 | /* PHY auto speed down */ |
632 | r8168d_modify_extpage(phydev, extpage: 0x002d, reg: 0x18, mask: 0x0000, val: 0x0010); |
633 | phy_set_bits(phydev, regnum: 0x14, BIT(15)); |
634 | |
635 | /* Improve 10M EEE waveform */ |
636 | r8168d_phy_param(phydev, parm: 0x8b86, mask: 0x0000, val: 0x0001); |
637 | |
638 | rtl8168f_config_eee_phy(phydev); |
639 | } |
640 | |
641 | static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp, |
642 | struct phy_device *phydev) |
643 | { |
644 | r8169_apply_firmware(tp); |
645 | |
646 | /* Channel estimation fine tune */ |
647 | phy_write_paged(phydev, page: 0x0003, regnum: 0x09, val: 0xa20f); |
648 | |
649 | /* Modify green table for giga & fnet */ |
650 | r8168d_phy_param(phydev, parm: 0x8b55, mask: 0xffff, val: 0x0000); |
651 | r8168d_phy_param(phydev, parm: 0x8b5e, mask: 0xffff, val: 0x0000); |
652 | r8168d_phy_param(phydev, parm: 0x8b67, mask: 0xffff, val: 0x0000); |
653 | r8168d_phy_param(phydev, parm: 0x8b70, mask: 0xffff, val: 0x0000); |
654 | r8168d_modify_extpage(phydev, extpage: 0x0078, reg: 0x17, mask: 0xffff, val: 0x0000); |
655 | r8168d_modify_extpage(phydev, extpage: 0x0078, reg: 0x19, mask: 0xffff, val: 0x00fb); |
656 | |
657 | /* Modify green table for 10M */ |
658 | r8168d_phy_param(phydev, parm: 0x8b79, mask: 0xffff, val: 0xaa00); |
659 | |
660 | /* Disable hiimpedance detection (RTCT) */ |
661 | phy_write_paged(phydev, page: 0x0003, regnum: 0x01, val: 0x328a); |
662 | |
663 | rtl8168f_hw_phy_config(tp, phydev); |
664 | |
665 | /* Improve 2-pair detection performance */ |
666 | r8168d_phy_param(phydev, parm: 0x8b85, mask: 0x0000, val: 0x4000); |
667 | } |
668 | |
669 | static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp, |
670 | struct phy_device *phydev) |
671 | { |
672 | r8169_apply_firmware(tp); |
673 | |
674 | rtl8168f_hw_phy_config(tp, phydev); |
675 | } |
676 | |
677 | static void rtl8411_hw_phy_config(struct rtl8169_private *tp, |
678 | struct phy_device *phydev) |
679 | { |
680 | r8169_apply_firmware(tp); |
681 | |
682 | rtl8168f_hw_phy_config(tp, phydev); |
683 | |
684 | /* Improve 2-pair detection performance */ |
685 | r8168d_phy_param(phydev, parm: 0x8b85, mask: 0x0000, val: 0x4000); |
686 | |
687 | /* Channel estimation fine tune */ |
688 | phy_write_paged(phydev, page: 0x0003, regnum: 0x09, val: 0xa20f); |
689 | |
690 | /* Modify green table for giga & fnet */ |
691 | r8168d_phy_param(phydev, parm: 0x8b55, mask: 0xffff, val: 0x0000); |
692 | r8168d_phy_param(phydev, parm: 0x8b5e, mask: 0xffff, val: 0x0000); |
693 | r8168d_phy_param(phydev, parm: 0x8b67, mask: 0xffff, val: 0x0000); |
694 | r8168d_phy_param(phydev, parm: 0x8b70, mask: 0xffff, val: 0x0000); |
695 | r8168d_modify_extpage(phydev, extpage: 0x0078, reg: 0x17, mask: 0xffff, val: 0x0000); |
696 | r8168d_modify_extpage(phydev, extpage: 0x0078, reg: 0x19, mask: 0xffff, val: 0x00aa); |
697 | |
698 | /* Modify green table for 10M */ |
699 | r8168d_phy_param(phydev, parm: 0x8b79, mask: 0xffff, val: 0xaa00); |
700 | |
701 | /* Disable hiimpedance detection (RTCT) */ |
702 | phy_write_paged(phydev, page: 0x0003, regnum: 0x01, val: 0x328a); |
703 | |
704 | /* Modify green table for giga */ |
705 | r8168d_phy_param(phydev, parm: 0x8b54, mask: 0x0800, val: 0x0000); |
706 | r8168d_phy_param(phydev, parm: 0x8b5d, mask: 0x0800, val: 0x0000); |
707 | r8168d_phy_param(phydev, parm: 0x8a7c, mask: 0x0100, val: 0x0000); |
708 | r8168d_phy_param(phydev, parm: 0x8a7f, mask: 0x0000, val: 0x0100); |
709 | r8168d_phy_param(phydev, parm: 0x8a82, mask: 0x0100, val: 0x0000); |
710 | r8168d_phy_param(phydev, parm: 0x8a85, mask: 0x0100, val: 0x0000); |
711 | r8168d_phy_param(phydev, parm: 0x8a88, mask: 0x0100, val: 0x0000); |
712 | |
713 | /* uc same-seed solution */ |
714 | r8168d_phy_param(phydev, parm: 0x8b85, mask: 0x0000, val: 0x8000); |
715 | |
716 | /* Green feature */ |
717 | phy_write(phydev, regnum: 0x1f, val: 0x0003); |
718 | phy_clear_bits(phydev, regnum: 0x19, BIT(0)); |
719 | phy_clear_bits(phydev, regnum: 0x10, BIT(10)); |
720 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
721 | } |
722 | |
723 | static void rtl8168g_disable_aldps(struct phy_device *phydev) |
724 | { |
725 | phy_modify_paged(phydev, page: 0x0a43, regnum: 0x10, BIT(2), set: 0); |
726 | } |
727 | |
728 | static void rtl8168g_enable_gphy_10m(struct phy_device *phydev) |
729 | { |
730 | phy_modify_paged(phydev, page: 0x0a44, regnum: 0x11, mask: 0, BIT(11)); |
731 | } |
732 | |
733 | static void rtl8168g_phy_adjust_10m_aldps(struct phy_device *phydev) |
734 | { |
735 | phy_modify_paged(phydev, page: 0x0bcc, regnum: 0x14, BIT(8), set: 0); |
736 | phy_modify_paged(phydev, page: 0x0a44, regnum: 0x11, mask: 0, BIT(7) | BIT(6)); |
737 | r8168g_phy_param(phydev, parm: 0x8084, mask: 0x6000, val: 0x0000); |
738 | phy_modify_paged(phydev, page: 0x0a43, regnum: 0x10, mask: 0x0000, set: 0x1003); |
739 | } |
740 | |
741 | static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp, |
742 | struct phy_device *phydev) |
743 | { |
744 | int ret; |
745 | |
746 | r8169_apply_firmware(tp); |
747 | |
748 | ret = phy_read_paged(phydev, page: 0x0a46, regnum: 0x10); |
749 | if (ret & BIT(8)) |
750 | phy_modify_paged(phydev, page: 0x0bcc, regnum: 0x12, BIT(15), set: 0); |
751 | else |
752 | phy_modify_paged(phydev, page: 0x0bcc, regnum: 0x12, mask: 0, BIT(15)); |
753 | |
754 | ret = phy_read_paged(phydev, page: 0x0a46, regnum: 0x13); |
755 | if (ret & BIT(8)) |
756 | phy_modify_paged(phydev, page: 0x0c41, regnum: 0x15, mask: 0, BIT(1)); |
757 | else |
758 | phy_modify_paged(phydev, page: 0x0c41, regnum: 0x15, BIT(1), set: 0); |
759 | |
760 | /* Enable PHY auto speed down */ |
761 | phy_modify_paged(phydev, page: 0x0a44, regnum: 0x11, mask: 0, BIT(3) | BIT(2)); |
762 | |
763 | rtl8168g_phy_adjust_10m_aldps(phydev); |
764 | |
765 | /* EEE auto-fallback function */ |
766 | phy_modify_paged(phydev, page: 0x0a4b, regnum: 0x11, mask: 0, BIT(2)); |
767 | |
768 | /* Enable UC LPF tune function */ |
769 | r8168g_phy_param(phydev, parm: 0x8012, mask: 0x0000, val: 0x8000); |
770 | |
771 | phy_modify_paged(phydev, page: 0x0c42, regnum: 0x11, BIT(13), BIT(14)); |
772 | |
773 | /* Improve SWR Efficiency */ |
774 | phy_write(phydev, regnum: 0x1f, val: 0x0bcd); |
775 | phy_write(phydev, regnum: 0x14, val: 0x5065); |
776 | phy_write(phydev, regnum: 0x14, val: 0xd065); |
777 | phy_write(phydev, regnum: 0x1f, val: 0x0bc8); |
778 | phy_write(phydev, regnum: 0x11, val: 0x5655); |
779 | phy_write(phydev, regnum: 0x1f, val: 0x0bcd); |
780 | phy_write(phydev, regnum: 0x14, val: 0x1065); |
781 | phy_write(phydev, regnum: 0x14, val: 0x9065); |
782 | phy_write(phydev, regnum: 0x14, val: 0x1065); |
783 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
784 | |
785 | rtl8168g_disable_aldps(phydev); |
786 | rtl8168g_config_eee_phy(phydev); |
787 | } |
788 | |
789 | static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp, |
790 | struct phy_device *phydev) |
791 | { |
792 | r8169_apply_firmware(tp); |
793 | rtl8168g_config_eee_phy(phydev); |
794 | } |
795 | |
796 | static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp, |
797 | struct phy_device *phydev) |
798 | { |
799 | u16 ioffset, rlen; |
800 | u32 data; |
801 | |
802 | r8169_apply_firmware(tp); |
803 | |
804 | /* CHIN EST parameter update */ |
805 | r8168g_phy_param(phydev, parm: 0x808a, mask: 0x003f, val: 0x000a); |
806 | |
807 | /* enable R-tune & PGA-retune function */ |
808 | r8168g_phy_param(phydev, parm: 0x0811, mask: 0x0000, val: 0x0800); |
809 | phy_modify_paged(phydev, page: 0x0a42, regnum: 0x16, mask: 0x0000, set: 0x0002); |
810 | |
811 | rtl8168g_enable_gphy_10m(phydev); |
812 | |
813 | ioffset = rtl8168h_2_get_adc_bias_ioffset(tp); |
814 | if (ioffset != 0xffff) |
815 | phy_write_paged(phydev, page: 0x0bcf, regnum: 0x16, val: ioffset); |
816 | |
817 | /* Modify rlen (TX LPF corner frequency) level */ |
818 | data = phy_read_paged(phydev, page: 0x0bcd, regnum: 0x16); |
819 | data &= 0x000f; |
820 | rlen = 0; |
821 | if (data > 3) |
822 | rlen = data - 3; |
823 | data = rlen | (rlen << 4) | (rlen << 8) | (rlen << 12); |
824 | phy_write_paged(phydev, page: 0x0bcd, regnum: 0x17, val: data); |
825 | |
826 | /* disable phy pfm mode */ |
827 | phy_modify_paged(phydev, page: 0x0a44, regnum: 0x11, BIT(7), set: 0); |
828 | |
829 | /* disable 10m pll off */ |
830 | phy_modify_paged(phydev, page: 0x0a43, regnum: 0x10, BIT(0), set: 0); |
831 | |
832 | rtl8168g_disable_aldps(phydev); |
833 | rtl8168g_config_eee_phy(phydev); |
834 | } |
835 | |
836 | static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp, |
837 | struct phy_device *phydev) |
838 | { |
839 | rtl8168g_phy_adjust_10m_aldps(phydev); |
840 | |
841 | /* Enable UC LPF tune function */ |
842 | r8168g_phy_param(phydev, parm: 0x8012, mask: 0x0000, val: 0x8000); |
843 | |
844 | /* Set rg_sel_sdm_rate */ |
845 | phy_modify_paged(phydev, page: 0x0c42, regnum: 0x11, BIT(13), BIT(14)); |
846 | |
847 | /* Channel estimation parameters */ |
848 | r8168g_phy_param(phydev, parm: 0x80f3, mask: 0xff00, val: 0x8b00); |
849 | r8168g_phy_param(phydev, parm: 0x80f0, mask: 0xff00, val: 0x3a00); |
850 | r8168g_phy_param(phydev, parm: 0x80ef, mask: 0xff00, val: 0x0500); |
851 | r8168g_phy_param(phydev, parm: 0x80f6, mask: 0xff00, val: 0x6e00); |
852 | r8168g_phy_param(phydev, parm: 0x80ec, mask: 0xff00, val: 0x6800); |
853 | r8168g_phy_param(phydev, parm: 0x80ed, mask: 0xff00, val: 0x7c00); |
854 | r8168g_phy_param(phydev, parm: 0x80f2, mask: 0xff00, val: 0xf400); |
855 | r8168g_phy_param(phydev, parm: 0x80f4, mask: 0xff00, val: 0x8500); |
856 | r8168g_phy_param(phydev, parm: 0x8110, mask: 0xff00, val: 0xa800); |
857 | r8168g_phy_param(phydev, parm: 0x810f, mask: 0xff00, val: 0x1d00); |
858 | r8168g_phy_param(phydev, parm: 0x8111, mask: 0xff00, val: 0xf500); |
859 | r8168g_phy_param(phydev, parm: 0x8113, mask: 0xff00, val: 0x6100); |
860 | r8168g_phy_param(phydev, parm: 0x8115, mask: 0xff00, val: 0x9200); |
861 | r8168g_phy_param(phydev, parm: 0x810e, mask: 0xff00, val: 0x0400); |
862 | r8168g_phy_param(phydev, parm: 0x810c, mask: 0xff00, val: 0x7c00); |
863 | r8168g_phy_param(phydev, parm: 0x810b, mask: 0xff00, val: 0x5a00); |
864 | r8168g_phy_param(phydev, parm: 0x80d1, mask: 0xff00, val: 0xff00); |
865 | r8168g_phy_param(phydev, parm: 0x80cd, mask: 0xff00, val: 0x9e00); |
866 | r8168g_phy_param(phydev, parm: 0x80d3, mask: 0xff00, val: 0x0e00); |
867 | r8168g_phy_param(phydev, parm: 0x80d5, mask: 0xff00, val: 0xca00); |
868 | r8168g_phy_param(phydev, parm: 0x80d7, mask: 0xff00, val: 0x8400); |
869 | |
870 | /* Force PWM-mode */ |
871 | phy_write(phydev, regnum: 0x1f, val: 0x0bcd); |
872 | phy_write(phydev, regnum: 0x14, val: 0x5065); |
873 | phy_write(phydev, regnum: 0x14, val: 0xd065); |
874 | phy_write(phydev, regnum: 0x1f, val: 0x0bc8); |
875 | phy_write(phydev, regnum: 0x12, val: 0x00ed); |
876 | phy_write(phydev, regnum: 0x1f, val: 0x0bcd); |
877 | phy_write(phydev, regnum: 0x14, val: 0x1065); |
878 | phy_write(phydev, regnum: 0x14, val: 0x9065); |
879 | phy_write(phydev, regnum: 0x14, val: 0x1065); |
880 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
881 | |
882 | rtl8168g_disable_aldps(phydev); |
883 | rtl8168g_config_eee_phy(phydev); |
884 | } |
885 | |
886 | static void rtl8117_hw_phy_config(struct rtl8169_private *tp, |
887 | struct phy_device *phydev) |
888 | { |
889 | /* CHN EST parameters adjust - fnet */ |
890 | r8168g_phy_param(phydev, parm: 0x808e, mask: 0xff00, val: 0x4800); |
891 | r8168g_phy_param(phydev, parm: 0x8090, mask: 0xff00, val: 0xcc00); |
892 | r8168g_phy_param(phydev, parm: 0x8092, mask: 0xff00, val: 0xb000); |
893 | |
894 | r8168g_phy_param(phydev, parm: 0x8088, mask: 0xff00, val: 0x6000); |
895 | r8168g_phy_param(phydev, parm: 0x808b, mask: 0x3f00, val: 0x0b00); |
896 | r8168g_phy_param(phydev, parm: 0x808d, mask: 0x1f00, val: 0x0600); |
897 | r8168g_phy_param(phydev, parm: 0x808c, mask: 0xff00, val: 0xb000); |
898 | r8168g_phy_param(phydev, parm: 0x80a0, mask: 0xff00, val: 0x2800); |
899 | r8168g_phy_param(phydev, parm: 0x80a2, mask: 0xff00, val: 0x5000); |
900 | r8168g_phy_param(phydev, parm: 0x809b, mask: 0xf800, val: 0xb000); |
901 | r8168g_phy_param(phydev, parm: 0x809a, mask: 0xff00, val: 0x4b00); |
902 | r8168g_phy_param(phydev, parm: 0x809d, mask: 0x3f00, val: 0x0800); |
903 | r8168g_phy_param(phydev, parm: 0x80a1, mask: 0xff00, val: 0x7000); |
904 | r8168g_phy_param(phydev, parm: 0x809f, mask: 0x1f00, val: 0x0300); |
905 | r8168g_phy_param(phydev, parm: 0x809e, mask: 0xff00, val: 0x8800); |
906 | r8168g_phy_param(phydev, parm: 0x80b2, mask: 0xff00, val: 0x2200); |
907 | r8168g_phy_param(phydev, parm: 0x80ad, mask: 0xf800, val: 0x9800); |
908 | r8168g_phy_param(phydev, parm: 0x80af, mask: 0x3f00, val: 0x0800); |
909 | r8168g_phy_param(phydev, parm: 0x80b3, mask: 0xff00, val: 0x6f00); |
910 | r8168g_phy_param(phydev, parm: 0x80b1, mask: 0x1f00, val: 0x0300); |
911 | r8168g_phy_param(phydev, parm: 0x80b0, mask: 0xff00, val: 0x9300); |
912 | |
913 | r8168g_phy_param(phydev, parm: 0x8011, mask: 0x0000, val: 0x0800); |
914 | |
915 | rtl8168g_enable_gphy_10m(phydev); |
916 | |
917 | r8168g_phy_param(phydev, parm: 0x8016, mask: 0x0000, val: 0x0400); |
918 | |
919 | rtl8168g_disable_aldps(phydev); |
920 | rtl8168h_config_eee_phy(phydev); |
921 | } |
922 | |
923 | static void rtl8102e_hw_phy_config(struct rtl8169_private *tp, |
924 | struct phy_device *phydev) |
925 | { |
926 | static const struct phy_reg phy_reg_init[] = { |
927 | { 0x1f, 0x0003 }, |
928 | { 0x08, 0x441d }, |
929 | { 0x01, 0x9100 }, |
930 | { 0x1f, 0x0000 } |
931 | }; |
932 | |
933 | phy_set_bits(phydev, regnum: 0x11, BIT(12)); |
934 | phy_set_bits(phydev, regnum: 0x19, BIT(13)); |
935 | phy_set_bits(phydev, regnum: 0x10, BIT(15)); |
936 | |
937 | rtl_writephy_batch(phydev, phy_reg_init); |
938 | } |
939 | |
940 | static void rtl8401_hw_phy_config(struct rtl8169_private *tp, |
941 | struct phy_device *phydev) |
942 | { |
943 | phy_set_bits(phydev, regnum: 0x11, BIT(12)); |
944 | phy_modify_paged(phydev, page: 0x0002, regnum: 0x0f, mask: 0x0000, set: 0x0003); |
945 | } |
946 | |
947 | static void rtl8105e_hw_phy_config(struct rtl8169_private *tp, |
948 | struct phy_device *phydev) |
949 | { |
950 | /* Disable ALDPS before ram code */ |
951 | phy_write(phydev, regnum: 0x18, val: 0x0310); |
952 | msleep(msecs: 100); |
953 | |
954 | r8169_apply_firmware(tp); |
955 | |
956 | phy_write_paged(phydev, page: 0x0005, regnum: 0x1a, val: 0x0000); |
957 | phy_write_paged(phydev, page: 0x0004, regnum: 0x1c, val: 0x0000); |
958 | phy_write_paged(phydev, page: 0x0001, regnum: 0x15, val: 0x7701); |
959 | } |
960 | |
961 | static void rtl8402_hw_phy_config(struct rtl8169_private *tp, |
962 | struct phy_device *phydev) |
963 | { |
964 | /* Disable ALDPS before setting firmware */ |
965 | phy_write(phydev, regnum: 0x18, val: 0x0310); |
966 | msleep(msecs: 20); |
967 | |
968 | r8169_apply_firmware(tp); |
969 | |
970 | /* EEE setting */ |
971 | phy_write(phydev, regnum: 0x1f, val: 0x0004); |
972 | phy_write(phydev, regnum: 0x10, val: 0x401f); |
973 | phy_write(phydev, regnum: 0x19, val: 0x7030); |
974 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
975 | } |
976 | |
977 | static void rtl8106e_hw_phy_config(struct rtl8169_private *tp, |
978 | struct phy_device *phydev) |
979 | { |
980 | static const struct phy_reg phy_reg_init[] = { |
981 | { 0x1f, 0x0004 }, |
982 | { 0x10, 0xc07f }, |
983 | { 0x19, 0x7030 }, |
984 | { 0x1f, 0x0000 } |
985 | }; |
986 | |
987 | /* Disable ALDPS before ram code */ |
988 | phy_write(phydev, regnum: 0x18, val: 0x0310); |
989 | msleep(msecs: 100); |
990 | |
991 | r8169_apply_firmware(tp); |
992 | |
993 | rtl_writephy_batch(phydev, phy_reg_init); |
994 | } |
995 | |
996 | static void rtl8125_legacy_force_mode(struct phy_device *phydev) |
997 | { |
998 | phy_modify_paged(phydev, page: 0xa5b, regnum: 0x12, BIT(15), set: 0); |
999 | } |
1000 | |
1001 | static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp, |
1002 | struct phy_device *phydev) |
1003 | { |
1004 | int i; |
1005 | |
1006 | phy_modify_paged(phydev, page: 0xad4, regnum: 0x17, mask: 0x0000, set: 0x0010); |
1007 | phy_modify_paged(phydev, page: 0xad1, regnum: 0x13, mask: 0x03ff, set: 0x03ff); |
1008 | phy_modify_paged(phydev, page: 0xad3, regnum: 0x11, mask: 0x003f, set: 0x0006); |
1009 | phy_modify_paged(phydev, page: 0xac0, regnum: 0x14, mask: 0x1100, set: 0x0000); |
1010 | phy_modify_paged(phydev, page: 0xacc, regnum: 0x10, mask: 0x0003, set: 0x0002); |
1011 | phy_modify_paged(phydev, page: 0xad4, regnum: 0x10, mask: 0x00e7, set: 0x0044); |
1012 | phy_modify_paged(phydev, page: 0xac1, regnum: 0x12, mask: 0x0080, set: 0x0000); |
1013 | phy_modify_paged(phydev, page: 0xac8, regnum: 0x10, mask: 0x0300, set: 0x0000); |
1014 | phy_modify_paged(phydev, page: 0xac5, regnum: 0x17, mask: 0x0007, set: 0x0002); |
1015 | phy_write_paged(phydev, page: 0xad4, regnum: 0x16, val: 0x00a8); |
1016 | phy_write_paged(phydev, page: 0xac5, regnum: 0x16, val: 0x01ff); |
1017 | phy_modify_paged(phydev, page: 0xac8, regnum: 0x15, mask: 0x00f0, set: 0x0030); |
1018 | |
1019 | phy_write(phydev, regnum: 0x1f, val: 0x0b87); |
1020 | phy_write(phydev, regnum: 0x16, val: 0x80a2); |
1021 | phy_write(phydev, regnum: 0x17, val: 0x0153); |
1022 | phy_write(phydev, regnum: 0x16, val: 0x809c); |
1023 | phy_write(phydev, regnum: 0x17, val: 0x0153); |
1024 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
1025 | |
1026 | phy_write(phydev, regnum: 0x1f, val: 0x0a43); |
1027 | phy_write(phydev, regnum: 0x13, val: 0x81B3); |
1028 | phy_write(phydev, regnum: 0x14, val: 0x0043); |
1029 | phy_write(phydev, regnum: 0x14, val: 0x00A7); |
1030 | phy_write(phydev, regnum: 0x14, val: 0x00D6); |
1031 | phy_write(phydev, regnum: 0x14, val: 0x00EC); |
1032 | phy_write(phydev, regnum: 0x14, val: 0x00F6); |
1033 | phy_write(phydev, regnum: 0x14, val: 0x00FB); |
1034 | phy_write(phydev, regnum: 0x14, val: 0x00FD); |
1035 | phy_write(phydev, regnum: 0x14, val: 0x00FF); |
1036 | phy_write(phydev, regnum: 0x14, val: 0x00BB); |
1037 | phy_write(phydev, regnum: 0x14, val: 0x0058); |
1038 | phy_write(phydev, regnum: 0x14, val: 0x0029); |
1039 | phy_write(phydev, regnum: 0x14, val: 0x0013); |
1040 | phy_write(phydev, regnum: 0x14, val: 0x0009); |
1041 | phy_write(phydev, regnum: 0x14, val: 0x0004); |
1042 | phy_write(phydev, regnum: 0x14, val: 0x0002); |
1043 | for (i = 0; i < 25; i++) |
1044 | phy_write(phydev, regnum: 0x14, val: 0x0000); |
1045 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
1046 | |
1047 | r8168g_phy_param(phydev, parm: 0x8257, mask: 0xffff, val: 0x020F); |
1048 | r8168g_phy_param(phydev, parm: 0x80ea, mask: 0xffff, val: 0x7843); |
1049 | |
1050 | r8169_apply_firmware(tp); |
1051 | |
1052 | phy_modify_paged(phydev, page: 0xd06, regnum: 0x14, mask: 0x0000, set: 0x2000); |
1053 | |
1054 | r8168g_phy_param(phydev, parm: 0x81a2, mask: 0x0000, val: 0x0100); |
1055 | |
1056 | phy_modify_paged(phydev, page: 0xb54, regnum: 0x16, mask: 0xff00, set: 0xdb00); |
1057 | phy_modify_paged(phydev, page: 0xa45, regnum: 0x12, mask: 0x0001, set: 0x0000); |
1058 | phy_modify_paged(phydev, page: 0xa5d, regnum: 0x12, mask: 0x0000, set: 0x0020); |
1059 | phy_modify_paged(phydev, page: 0xad4, regnum: 0x17, mask: 0x0010, set: 0x0000); |
1060 | phy_modify_paged(phydev, page: 0xa86, regnum: 0x15, mask: 0x0001, set: 0x0000); |
1061 | rtl8168g_enable_gphy_10m(phydev); |
1062 | |
1063 | rtl8125a_config_eee_phy(phydev); |
1064 | } |
1065 | |
1066 | static void rtl8125b_hw_phy_config(struct rtl8169_private *tp, |
1067 | struct phy_device *phydev) |
1068 | { |
1069 | r8169_apply_firmware(tp); |
1070 | |
1071 | phy_modify_paged(phydev, page: 0xa44, regnum: 0x11, mask: 0x0000, set: 0x0800); |
1072 | phy_modify_paged(phydev, page: 0xac4, regnum: 0x13, mask: 0x00f0, set: 0x0090); |
1073 | phy_modify_paged(phydev, page: 0xad3, regnum: 0x10, mask: 0x0003, set: 0x0001); |
1074 | |
1075 | phy_write(phydev, regnum: 0x1f, val: 0x0b87); |
1076 | phy_write(phydev, regnum: 0x16, val: 0x80f5); |
1077 | phy_write(phydev, regnum: 0x17, val: 0x760e); |
1078 | phy_write(phydev, regnum: 0x16, val: 0x8107); |
1079 | phy_write(phydev, regnum: 0x17, val: 0x360e); |
1080 | phy_write(phydev, regnum: 0x16, val: 0x8551); |
1081 | phy_modify(phydev, regnum: 0x17, mask: 0xff00, set: 0x0800); |
1082 | phy_write(phydev, regnum: 0x1f, val: 0x0000); |
1083 | |
1084 | phy_modify_paged(phydev, page: 0xbf0, regnum: 0x10, mask: 0xe000, set: 0xa000); |
1085 | phy_modify_paged(phydev, page: 0xbf4, regnum: 0x13, mask: 0x0f00, set: 0x0300); |
1086 | |
1087 | r8168g_phy_param(phydev, parm: 0x8044, mask: 0xffff, val: 0x2417); |
1088 | r8168g_phy_param(phydev, parm: 0x804a, mask: 0xffff, val: 0x2417); |
1089 | r8168g_phy_param(phydev, parm: 0x8050, mask: 0xffff, val: 0x2417); |
1090 | r8168g_phy_param(phydev, parm: 0x8056, mask: 0xffff, val: 0x2417); |
1091 | r8168g_phy_param(phydev, parm: 0x805c, mask: 0xffff, val: 0x2417); |
1092 | r8168g_phy_param(phydev, parm: 0x8062, mask: 0xffff, val: 0x2417); |
1093 | r8168g_phy_param(phydev, parm: 0x8068, mask: 0xffff, val: 0x2417); |
1094 | r8168g_phy_param(phydev, parm: 0x806e, mask: 0xffff, val: 0x2417); |
1095 | r8168g_phy_param(phydev, parm: 0x8074, mask: 0xffff, val: 0x2417); |
1096 | r8168g_phy_param(phydev, parm: 0x807a, mask: 0xffff, val: 0x2417); |
1097 | |
1098 | phy_modify_paged(phydev, page: 0xa4c, regnum: 0x15, mask: 0x0000, set: 0x0040); |
1099 | phy_modify_paged(phydev, page: 0xbf8, regnum: 0x12, mask: 0xe000, set: 0xa000); |
1100 | |
1101 | rtl8125_legacy_force_mode(phydev); |
1102 | rtl8125b_config_eee_phy(phydev); |
1103 | } |
1104 | |
1105 | static void rtl8126a_hw_phy_config(struct rtl8169_private *tp, |
1106 | struct phy_device *phydev) |
1107 | { |
1108 | r8169_apply_firmware(tp); |
1109 | } |
1110 | |
1111 | void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev, |
1112 | enum mac_version ver) |
1113 | { |
1114 | static const rtl_phy_cfg_fct phy_configs[] = { |
1115 | /* PCI devices. */ |
1116 | [RTL_GIGA_MAC_VER_02] = rtl8169s_hw_phy_config, |
1117 | [RTL_GIGA_MAC_VER_03] = rtl8169s_hw_phy_config, |
1118 | [RTL_GIGA_MAC_VER_04] = rtl8169sb_hw_phy_config, |
1119 | [RTL_GIGA_MAC_VER_05] = rtl8169scd_hw_phy_config, |
1120 | [RTL_GIGA_MAC_VER_06] = rtl8169sce_hw_phy_config, |
1121 | /* PCI-E devices. */ |
1122 | [RTL_GIGA_MAC_VER_07] = rtl8102e_hw_phy_config, |
1123 | [RTL_GIGA_MAC_VER_08] = rtl8102e_hw_phy_config, |
1124 | [RTL_GIGA_MAC_VER_09] = rtl8102e_hw_phy_config, |
1125 | [RTL_GIGA_MAC_VER_10] = NULL, |
1126 | [RTL_GIGA_MAC_VER_11] = rtl8168bb_hw_phy_config, |
1127 | [RTL_GIGA_MAC_VER_14] = rtl8401_hw_phy_config, |
1128 | [RTL_GIGA_MAC_VER_17] = rtl8168bef_hw_phy_config, |
1129 | [RTL_GIGA_MAC_VER_18] = rtl8168cp_1_hw_phy_config, |
1130 | [RTL_GIGA_MAC_VER_19] = rtl8168c_1_hw_phy_config, |
1131 | [RTL_GIGA_MAC_VER_20] = rtl8168c_2_hw_phy_config, |
1132 | [RTL_GIGA_MAC_VER_21] = rtl8168c_3_hw_phy_config, |
1133 | [RTL_GIGA_MAC_VER_22] = rtl8168c_3_hw_phy_config, |
1134 | [RTL_GIGA_MAC_VER_23] = rtl8168cp_2_hw_phy_config, |
1135 | [RTL_GIGA_MAC_VER_24] = rtl8168cp_2_hw_phy_config, |
1136 | [RTL_GIGA_MAC_VER_25] = rtl8168d_1_hw_phy_config, |
1137 | [RTL_GIGA_MAC_VER_26] = rtl8168d_2_hw_phy_config, |
1138 | [RTL_GIGA_MAC_VER_28] = rtl8168d_4_hw_phy_config, |
1139 | [RTL_GIGA_MAC_VER_29] = rtl8105e_hw_phy_config, |
1140 | [RTL_GIGA_MAC_VER_30] = rtl8105e_hw_phy_config, |
1141 | [RTL_GIGA_MAC_VER_31] = NULL, |
1142 | [RTL_GIGA_MAC_VER_32] = rtl8168e_1_hw_phy_config, |
1143 | [RTL_GIGA_MAC_VER_33] = rtl8168e_1_hw_phy_config, |
1144 | [RTL_GIGA_MAC_VER_34] = rtl8168e_2_hw_phy_config, |
1145 | [RTL_GIGA_MAC_VER_35] = rtl8168f_1_hw_phy_config, |
1146 | [RTL_GIGA_MAC_VER_36] = rtl8168f_2_hw_phy_config, |
1147 | [RTL_GIGA_MAC_VER_37] = rtl8402_hw_phy_config, |
1148 | [RTL_GIGA_MAC_VER_38] = rtl8411_hw_phy_config, |
1149 | [RTL_GIGA_MAC_VER_39] = rtl8106e_hw_phy_config, |
1150 | [RTL_GIGA_MAC_VER_40] = rtl8168g_1_hw_phy_config, |
1151 | [RTL_GIGA_MAC_VER_42] = rtl8168g_2_hw_phy_config, |
1152 | [RTL_GIGA_MAC_VER_43] = rtl8168g_2_hw_phy_config, |
1153 | [RTL_GIGA_MAC_VER_44] = rtl8168g_2_hw_phy_config, |
1154 | [RTL_GIGA_MAC_VER_46] = rtl8168h_2_hw_phy_config, |
1155 | [RTL_GIGA_MAC_VER_48] = rtl8168h_2_hw_phy_config, |
1156 | [RTL_GIGA_MAC_VER_51] = rtl8168ep_2_hw_phy_config, |
1157 | [RTL_GIGA_MAC_VER_52] = rtl8117_hw_phy_config, |
1158 | [RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config, |
1159 | [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config, |
1160 | [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config, |
1161 | [RTL_GIGA_MAC_VER_65] = rtl8126a_hw_phy_config, |
1162 | }; |
1163 | |
1164 | if (phy_configs[ver]) |
1165 | phy_configs[ver](tp, phydev); |
1166 | } |
1167 | |