1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* Copyright (C) 2018 Microchip Technology Inc. */ |
3 | |
4 | #include <linux/netdevice.h> |
5 | #include <linux/net_tstamp.h> |
6 | #include <linux/pci.h> |
7 | #include <linux/phy.h> |
8 | #include "lan743x_main.h" |
9 | #include "lan743x_ethtool.h" |
10 | #include <linux/sched.h> |
11 | #include <linux/iopoll.h> |
12 | |
13 | /* eeprom */ |
14 | #define LAN743X_EEPROM_MAGIC (0x74A5) |
15 | #define LAN743X_OTP_MAGIC (0x74F3) |
16 | #define EEPROM_INDICATOR_1 (0xA5) |
17 | #define EEPROM_INDICATOR_2 (0xAA) |
18 | #define EEPROM_MAC_OFFSET (0x01) |
19 | #define MAX_EEPROM_SIZE (512) |
20 | #define MAX_OTP_SIZE (1024) |
21 | #define OTP_INDICATOR_1 (0xF3) |
22 | #define OTP_INDICATOR_2 (0xF7) |
23 | |
24 | #define LOCK_TIMEOUT_MAX_CNT (100) // 1 sec (10 msce * 100) |
25 | |
26 | #define LAN743X_CSR_READ_OP(offset) lan743x_csr_read(adapter, offset) |
27 | |
28 | static int lan743x_otp_power_up(struct lan743x_adapter *adapter) |
29 | { |
30 | u32 reg_value; |
31 | |
32 | reg_value = lan743x_csr_read(adapter, OTP_PWR_DN); |
33 | |
34 | if (reg_value & OTP_PWR_DN_PWRDN_N_) { |
35 | /* clear it and wait to be cleared */ |
36 | reg_value &= ~OTP_PWR_DN_PWRDN_N_; |
37 | lan743x_csr_write(adapter, OTP_PWR_DN, data: reg_value); |
38 | |
39 | usleep_range(min: 100, max: 20000); |
40 | } |
41 | |
42 | return 0; |
43 | } |
44 | |
45 | static void lan743x_otp_power_down(struct lan743x_adapter *adapter) |
46 | { |
47 | u32 reg_value; |
48 | |
49 | reg_value = lan743x_csr_read(adapter, OTP_PWR_DN); |
50 | if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) { |
51 | /* set power down bit */ |
52 | reg_value |= OTP_PWR_DN_PWRDN_N_; |
53 | lan743x_csr_write(adapter, OTP_PWR_DN, data: reg_value); |
54 | } |
55 | } |
56 | |
57 | static void lan743x_otp_set_address(struct lan743x_adapter *adapter, |
58 | u32 address) |
59 | { |
60 | lan743x_csr_write(adapter, OTP_ADDR_HIGH, data: (address >> 8) & 0x03); |
61 | lan743x_csr_write(adapter, OTP_ADDR_LOW, data: address & 0xFF); |
62 | } |
63 | |
64 | static void lan743x_otp_read_go(struct lan743x_adapter *adapter) |
65 | { |
66 | lan743x_csr_write(adapter, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_); |
67 | lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_); |
68 | } |
69 | |
70 | static int lan743x_otp_wait_till_not_busy(struct lan743x_adapter *adapter) |
71 | { |
72 | unsigned long timeout; |
73 | u32 reg_val; |
74 | |
75 | timeout = jiffies + HZ; |
76 | do { |
77 | if (time_after(jiffies, timeout)) { |
78 | netif_warn(adapter, drv, adapter->netdev, |
79 | "Timeout on OTP_STATUS completion\n" ); |
80 | return -EIO; |
81 | } |
82 | udelay(1); |
83 | reg_val = lan743x_csr_read(adapter, OTP_STATUS); |
84 | } while (reg_val & OTP_STATUS_BUSY_); |
85 | |
86 | return 0; |
87 | } |
88 | |
89 | static int lan743x_otp_read(struct lan743x_adapter *adapter, u32 offset, |
90 | u32 length, u8 *data) |
91 | { |
92 | int ret; |
93 | int i; |
94 | |
95 | if (offset + length > MAX_OTP_SIZE) |
96 | return -EINVAL; |
97 | |
98 | ret = lan743x_otp_power_up(adapter); |
99 | if (ret < 0) |
100 | return ret; |
101 | |
102 | ret = lan743x_otp_wait_till_not_busy(adapter); |
103 | if (ret < 0) |
104 | return ret; |
105 | |
106 | for (i = 0; i < length; i++) { |
107 | lan743x_otp_set_address(adapter, address: offset + i); |
108 | |
109 | lan743x_otp_read_go(adapter); |
110 | ret = lan743x_otp_wait_till_not_busy(adapter); |
111 | if (ret < 0) |
112 | return ret; |
113 | data[i] = lan743x_csr_read(adapter, OTP_READ_DATA); |
114 | } |
115 | |
116 | lan743x_otp_power_down(adapter); |
117 | |
118 | return 0; |
119 | } |
120 | |
121 | static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset, |
122 | u32 length, u8 *data) |
123 | { |
124 | int ret; |
125 | int i; |
126 | |
127 | if (offset + length > MAX_OTP_SIZE) |
128 | return -EINVAL; |
129 | |
130 | ret = lan743x_otp_power_up(adapter); |
131 | if (ret < 0) |
132 | return ret; |
133 | |
134 | ret = lan743x_otp_wait_till_not_busy(adapter); |
135 | if (ret < 0) |
136 | return ret; |
137 | |
138 | /* set to BYTE program mode */ |
139 | lan743x_csr_write(adapter, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_); |
140 | |
141 | for (i = 0; i < length; i++) { |
142 | lan743x_otp_set_address(adapter, address: offset + i); |
143 | |
144 | lan743x_csr_write(adapter, OTP_PRGM_DATA, data: data[i]); |
145 | lan743x_csr_write(adapter, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_); |
146 | lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_); |
147 | |
148 | ret = lan743x_otp_wait_till_not_busy(adapter); |
149 | if (ret < 0) |
150 | return ret; |
151 | } |
152 | |
153 | lan743x_otp_power_down(adapter); |
154 | |
155 | return 0; |
156 | } |
157 | |
158 | int lan743x_hs_syslock_acquire(struct lan743x_adapter *adapter, |
159 | u16 timeout) |
160 | { |
161 | u16 timeout_cnt = 0; |
162 | u32 val; |
163 | |
164 | do { |
165 | spin_lock(lock: &adapter->eth_syslock_spinlock); |
166 | if (adapter->eth_syslock_acquire_cnt == 0) { |
167 | lan743x_csr_write(adapter, ETH_SYSTEM_SYS_LOCK_REG, |
168 | SYS_LOCK_REG_ENET_SS_LOCK_); |
169 | val = lan743x_csr_read(adapter, |
170 | ETH_SYSTEM_SYS_LOCK_REG); |
171 | if (val & SYS_LOCK_REG_ENET_SS_LOCK_) { |
172 | adapter->eth_syslock_acquire_cnt++; |
173 | WARN_ON(adapter->eth_syslock_acquire_cnt == 0); |
174 | spin_unlock(lock: &adapter->eth_syslock_spinlock); |
175 | break; |
176 | } |
177 | } else { |
178 | adapter->eth_syslock_acquire_cnt++; |
179 | WARN_ON(adapter->eth_syslock_acquire_cnt == 0); |
180 | spin_unlock(lock: &adapter->eth_syslock_spinlock); |
181 | break; |
182 | } |
183 | |
184 | spin_unlock(lock: &adapter->eth_syslock_spinlock); |
185 | |
186 | if (timeout_cnt++ < timeout) |
187 | usleep_range(min: 10000, max: 11000); |
188 | else |
189 | return -ETIMEDOUT; |
190 | } while (true); |
191 | |
192 | return 0; |
193 | } |
194 | |
195 | void lan743x_hs_syslock_release(struct lan743x_adapter *adapter) |
196 | { |
197 | u32 val; |
198 | |
199 | spin_lock(lock: &adapter->eth_syslock_spinlock); |
200 | WARN_ON(adapter->eth_syslock_acquire_cnt == 0); |
201 | |
202 | if (adapter->eth_syslock_acquire_cnt) { |
203 | adapter->eth_syslock_acquire_cnt--; |
204 | if (adapter->eth_syslock_acquire_cnt == 0) { |
205 | lan743x_csr_write(adapter, ETH_SYSTEM_SYS_LOCK_REG, data: 0); |
206 | val = lan743x_csr_read(adapter, |
207 | ETH_SYSTEM_SYS_LOCK_REG); |
208 | WARN_ON((val & SYS_LOCK_REG_ENET_SS_LOCK_) != 0); |
209 | } |
210 | } |
211 | |
212 | spin_unlock(lock: &adapter->eth_syslock_spinlock); |
213 | } |
214 | |
215 | static void lan743x_hs_otp_power_up(struct lan743x_adapter *adapter) |
216 | { |
217 | u32 reg_value; |
218 | |
219 | reg_value = lan743x_csr_read(adapter, HS_OTP_PWR_DN); |
220 | if (reg_value & OTP_PWR_DN_PWRDN_N_) { |
221 | reg_value &= ~OTP_PWR_DN_PWRDN_N_; |
222 | lan743x_csr_write(adapter, HS_OTP_PWR_DN, data: reg_value); |
223 | /* To flush the posted write so the subsequent delay is |
224 | * guaranteed to happen after the write at the hardware |
225 | */ |
226 | lan743x_csr_read(adapter, HS_OTP_PWR_DN); |
227 | udelay(1); |
228 | } |
229 | } |
230 | |
231 | static void lan743x_hs_otp_power_down(struct lan743x_adapter *adapter) |
232 | { |
233 | u32 reg_value; |
234 | |
235 | reg_value = lan743x_csr_read(adapter, HS_OTP_PWR_DN); |
236 | if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) { |
237 | reg_value |= OTP_PWR_DN_PWRDN_N_; |
238 | lan743x_csr_write(adapter, HS_OTP_PWR_DN, data: reg_value); |
239 | /* To flush the posted write so the subsequent delay is |
240 | * guaranteed to happen after the write at the hardware |
241 | */ |
242 | lan743x_csr_read(adapter, HS_OTP_PWR_DN); |
243 | udelay(1); |
244 | } |
245 | } |
246 | |
247 | static void lan743x_hs_otp_set_address(struct lan743x_adapter *adapter, |
248 | u32 address) |
249 | { |
250 | lan743x_csr_write(adapter, HS_OTP_ADDR_HIGH, data: (address >> 8) & 0x03); |
251 | lan743x_csr_write(adapter, HS_OTP_ADDR_LOW, data: address & 0xFF); |
252 | } |
253 | |
254 | static void lan743x_hs_otp_read_go(struct lan743x_adapter *adapter) |
255 | { |
256 | lan743x_csr_write(adapter, HS_OTP_FUNC_CMD, OTP_FUNC_CMD_READ_); |
257 | lan743x_csr_write(adapter, HS_OTP_CMD_GO, OTP_CMD_GO_GO_); |
258 | } |
259 | |
260 | static int lan743x_hs_otp_cmd_cmplt_chk(struct lan743x_adapter *adapter) |
261 | { |
262 | u32 val; |
263 | |
264 | return readx_poll_timeout(LAN743X_CSR_READ_OP, HS_OTP_STATUS, val, |
265 | !(val & OTP_STATUS_BUSY_), |
266 | 80, 10000); |
267 | } |
268 | |
269 | static int lan743x_hs_otp_read(struct lan743x_adapter *adapter, u32 offset, |
270 | u32 length, u8 *data) |
271 | { |
272 | int ret; |
273 | int i; |
274 | |
275 | ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT); |
276 | if (ret < 0) |
277 | return ret; |
278 | |
279 | lan743x_hs_otp_power_up(adapter); |
280 | |
281 | ret = lan743x_hs_otp_cmd_cmplt_chk(adapter); |
282 | if (ret < 0) |
283 | goto power_down; |
284 | |
285 | lan743x_hs_syslock_release(adapter); |
286 | |
287 | for (i = 0; i < length; i++) { |
288 | ret = lan743x_hs_syslock_acquire(adapter, |
289 | LOCK_TIMEOUT_MAX_CNT); |
290 | if (ret < 0) |
291 | return ret; |
292 | |
293 | lan743x_hs_otp_set_address(adapter, address: offset + i); |
294 | |
295 | lan743x_hs_otp_read_go(adapter); |
296 | ret = lan743x_hs_otp_cmd_cmplt_chk(adapter); |
297 | if (ret < 0) |
298 | goto power_down; |
299 | |
300 | data[i] = lan743x_csr_read(adapter, HS_OTP_READ_DATA); |
301 | |
302 | lan743x_hs_syslock_release(adapter); |
303 | } |
304 | |
305 | ret = lan743x_hs_syslock_acquire(adapter, |
306 | LOCK_TIMEOUT_MAX_CNT); |
307 | if (ret < 0) |
308 | return ret; |
309 | |
310 | power_down: |
311 | lan743x_hs_otp_power_down(adapter); |
312 | lan743x_hs_syslock_release(adapter); |
313 | |
314 | return ret; |
315 | } |
316 | |
317 | static int lan743x_hs_otp_write(struct lan743x_adapter *adapter, u32 offset, |
318 | u32 length, u8 *data) |
319 | { |
320 | int ret; |
321 | int i; |
322 | |
323 | ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT); |
324 | if (ret < 0) |
325 | return ret; |
326 | |
327 | lan743x_hs_otp_power_up(adapter); |
328 | |
329 | ret = lan743x_hs_otp_cmd_cmplt_chk(adapter); |
330 | if (ret < 0) |
331 | goto power_down; |
332 | |
333 | /* set to BYTE program mode */ |
334 | lan743x_csr_write(adapter, HS_OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_); |
335 | |
336 | lan743x_hs_syslock_release(adapter); |
337 | |
338 | for (i = 0; i < length; i++) { |
339 | ret = lan743x_hs_syslock_acquire(adapter, |
340 | LOCK_TIMEOUT_MAX_CNT); |
341 | if (ret < 0) |
342 | return ret; |
343 | |
344 | lan743x_hs_otp_set_address(adapter, address: offset + i); |
345 | |
346 | lan743x_csr_write(adapter, HS_OTP_PRGM_DATA, data: data[i]); |
347 | lan743x_csr_write(adapter, HS_OTP_TST_CMD, |
348 | OTP_TST_CMD_PRGVRFY_); |
349 | lan743x_csr_write(adapter, HS_OTP_CMD_GO, OTP_CMD_GO_GO_); |
350 | |
351 | ret = lan743x_hs_otp_cmd_cmplt_chk(adapter); |
352 | if (ret < 0) |
353 | goto power_down; |
354 | |
355 | lan743x_hs_syslock_release(adapter); |
356 | } |
357 | |
358 | ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT); |
359 | if (ret < 0) |
360 | return ret; |
361 | |
362 | power_down: |
363 | lan743x_hs_otp_power_down(adapter); |
364 | lan743x_hs_syslock_release(adapter); |
365 | |
366 | return ret; |
367 | } |
368 | |
369 | static int lan743x_eeprom_wait(struct lan743x_adapter *adapter) |
370 | { |
371 | unsigned long start_time = jiffies; |
372 | u32 val; |
373 | |
374 | do { |
375 | val = lan743x_csr_read(adapter, E2P_CMD); |
376 | |
377 | if (!(val & E2P_CMD_EPC_BUSY_) || |
378 | (val & E2P_CMD_EPC_TIMEOUT_)) |
379 | break; |
380 | usleep_range(min: 40, max: 100); |
381 | } while (!time_after(jiffies, start_time + HZ)); |
382 | |
383 | if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) { |
384 | netif_warn(adapter, drv, adapter->netdev, |
385 | "EEPROM read operation timeout\n" ); |
386 | return -EIO; |
387 | } |
388 | |
389 | return 0; |
390 | } |
391 | |
392 | static int lan743x_eeprom_confirm_not_busy(struct lan743x_adapter *adapter) |
393 | { |
394 | unsigned long start_time = jiffies; |
395 | u32 val; |
396 | |
397 | do { |
398 | val = lan743x_csr_read(adapter, E2P_CMD); |
399 | |
400 | if (!(val & E2P_CMD_EPC_BUSY_)) |
401 | return 0; |
402 | |
403 | usleep_range(min: 40, max: 100); |
404 | } while (!time_after(jiffies, start_time + HZ)); |
405 | |
406 | netif_warn(adapter, drv, adapter->netdev, "EEPROM is busy\n" ); |
407 | return -EIO; |
408 | } |
409 | |
410 | static int lan743x_eeprom_read(struct lan743x_adapter *adapter, |
411 | u32 offset, u32 length, u8 *data) |
412 | { |
413 | int retval; |
414 | u32 val; |
415 | int i; |
416 | |
417 | if (offset + length > MAX_EEPROM_SIZE) |
418 | return -EINVAL; |
419 | |
420 | retval = lan743x_eeprom_confirm_not_busy(adapter); |
421 | if (retval) |
422 | return retval; |
423 | |
424 | for (i = 0; i < length; i++) { |
425 | val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_; |
426 | val |= (offset & E2P_CMD_EPC_ADDR_MASK_); |
427 | lan743x_csr_write(adapter, E2P_CMD, data: val); |
428 | |
429 | retval = lan743x_eeprom_wait(adapter); |
430 | if (retval < 0) |
431 | return retval; |
432 | |
433 | val = lan743x_csr_read(adapter, E2P_DATA); |
434 | data[i] = val & 0xFF; |
435 | offset++; |
436 | } |
437 | |
438 | return 0; |
439 | } |
440 | |
441 | static int lan743x_eeprom_write(struct lan743x_adapter *adapter, |
442 | u32 offset, u32 length, u8 *data) |
443 | { |
444 | int retval; |
445 | u32 val; |
446 | int i; |
447 | |
448 | if (offset + length > MAX_EEPROM_SIZE) |
449 | return -EINVAL; |
450 | |
451 | retval = lan743x_eeprom_confirm_not_busy(adapter); |
452 | if (retval) |
453 | return retval; |
454 | |
455 | /* Issue write/erase enable command */ |
456 | val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_; |
457 | lan743x_csr_write(adapter, E2P_CMD, data: val); |
458 | |
459 | retval = lan743x_eeprom_wait(adapter); |
460 | if (retval < 0) |
461 | return retval; |
462 | |
463 | for (i = 0; i < length; i++) { |
464 | /* Fill data register */ |
465 | val = data[i]; |
466 | lan743x_csr_write(adapter, E2P_DATA, data: val); |
467 | |
468 | /* Send "write" command */ |
469 | val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_; |
470 | val |= (offset & E2P_CMD_EPC_ADDR_MASK_); |
471 | lan743x_csr_write(adapter, E2P_CMD, data: val); |
472 | |
473 | retval = lan743x_eeprom_wait(adapter); |
474 | if (retval < 0) |
475 | return retval; |
476 | |
477 | offset++; |
478 | } |
479 | |
480 | return 0; |
481 | } |
482 | |
483 | static int lan743x_hs_eeprom_cmd_cmplt_chk(struct lan743x_adapter *adapter) |
484 | { |
485 | u32 val; |
486 | |
487 | return readx_poll_timeout(LAN743X_CSR_READ_OP, HS_E2P_CMD, val, |
488 | (!(val & HS_E2P_CMD_EPC_BUSY_) || |
489 | (val & HS_E2P_CMD_EPC_TIMEOUT_)), |
490 | 50, 10000); |
491 | } |
492 | |
493 | static int lan743x_hs_eeprom_read(struct lan743x_adapter *adapter, |
494 | u32 offset, u32 length, u8 *data) |
495 | { |
496 | int retval; |
497 | u32 val; |
498 | int i; |
499 | |
500 | retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT); |
501 | if (retval < 0) |
502 | return retval; |
503 | |
504 | retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter); |
505 | lan743x_hs_syslock_release(adapter); |
506 | if (retval < 0) |
507 | return retval; |
508 | |
509 | for (i = 0; i < length; i++) { |
510 | retval = lan743x_hs_syslock_acquire(adapter, |
511 | LOCK_TIMEOUT_MAX_CNT); |
512 | if (retval < 0) |
513 | return retval; |
514 | |
515 | val = HS_E2P_CMD_EPC_BUSY_ | HS_E2P_CMD_EPC_CMD_READ_; |
516 | val |= (offset & HS_E2P_CMD_EPC_ADDR_MASK_); |
517 | lan743x_csr_write(adapter, HS_E2P_CMD, data: val); |
518 | retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter); |
519 | if (retval < 0) { |
520 | lan743x_hs_syslock_release(adapter); |
521 | return retval; |
522 | } |
523 | |
524 | val = lan743x_csr_read(adapter, HS_E2P_DATA); |
525 | |
526 | lan743x_hs_syslock_release(adapter); |
527 | |
528 | data[i] = val & 0xFF; |
529 | offset++; |
530 | } |
531 | |
532 | return 0; |
533 | } |
534 | |
535 | static int lan743x_hs_eeprom_write(struct lan743x_adapter *adapter, |
536 | u32 offset, u32 length, u8 *data) |
537 | { |
538 | int retval; |
539 | u32 val; |
540 | int i; |
541 | |
542 | retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT); |
543 | if (retval < 0) |
544 | return retval; |
545 | |
546 | retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter); |
547 | lan743x_hs_syslock_release(adapter); |
548 | if (retval < 0) |
549 | return retval; |
550 | |
551 | for (i = 0; i < length; i++) { |
552 | retval = lan743x_hs_syslock_acquire(adapter, |
553 | LOCK_TIMEOUT_MAX_CNT); |
554 | if (retval < 0) |
555 | return retval; |
556 | |
557 | /* Fill data register */ |
558 | val = data[i]; |
559 | lan743x_csr_write(adapter, HS_E2P_DATA, data: val); |
560 | |
561 | /* Send "write" command */ |
562 | val = HS_E2P_CMD_EPC_BUSY_ | HS_E2P_CMD_EPC_CMD_WRITE_; |
563 | val |= (offset & HS_E2P_CMD_EPC_ADDR_MASK_); |
564 | lan743x_csr_write(adapter, HS_E2P_CMD, data: val); |
565 | |
566 | retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter); |
567 | lan743x_hs_syslock_release(adapter); |
568 | if (retval < 0) |
569 | return retval; |
570 | |
571 | offset++; |
572 | } |
573 | |
574 | return 0; |
575 | } |
576 | |
577 | static void lan743x_ethtool_get_drvinfo(struct net_device *netdev, |
578 | struct ethtool_drvinfo *info) |
579 | { |
580 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
581 | |
582 | strscpy(p: info->driver, DRIVER_NAME, size: sizeof(info->driver)); |
583 | strscpy(p: info->bus_info, |
584 | q: pci_name(pdev: adapter->pdev), size: sizeof(info->bus_info)); |
585 | } |
586 | |
587 | static u32 lan743x_ethtool_get_msglevel(struct net_device *netdev) |
588 | { |
589 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
590 | |
591 | return adapter->msg_enable; |
592 | } |
593 | |
594 | static void lan743x_ethtool_set_msglevel(struct net_device *netdev, |
595 | u32 msglevel) |
596 | { |
597 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
598 | |
599 | adapter->msg_enable = msglevel; |
600 | } |
601 | |
602 | static int lan743x_ethtool_get_eeprom_len(struct net_device *netdev) |
603 | { |
604 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
605 | |
606 | if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) |
607 | return MAX_OTP_SIZE; |
608 | |
609 | return MAX_EEPROM_SIZE; |
610 | } |
611 | |
612 | static int lan743x_ethtool_get_eeprom(struct net_device *netdev, |
613 | struct ethtool_eeprom *ee, u8 *data) |
614 | { |
615 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
616 | int ret = 0; |
617 | |
618 | if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) { |
619 | if (adapter->is_pci11x1x) |
620 | ret = lan743x_hs_otp_read(adapter, offset: ee->offset, |
621 | length: ee->len, data); |
622 | else |
623 | ret = lan743x_otp_read(adapter, offset: ee->offset, |
624 | length: ee->len, data); |
625 | } else { |
626 | if (adapter->is_pci11x1x) |
627 | ret = lan743x_hs_eeprom_read(adapter, offset: ee->offset, |
628 | length: ee->len, data); |
629 | else |
630 | ret = lan743x_eeprom_read(adapter, offset: ee->offset, |
631 | length: ee->len, data); |
632 | } |
633 | |
634 | return ret; |
635 | } |
636 | |
637 | static int lan743x_ethtool_set_eeprom(struct net_device *netdev, |
638 | struct ethtool_eeprom *ee, u8 *data) |
639 | { |
640 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
641 | int ret = -EINVAL; |
642 | |
643 | if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) { |
644 | /* Beware! OTP is One Time Programming ONLY! */ |
645 | if (ee->magic == LAN743X_OTP_MAGIC) { |
646 | if (adapter->is_pci11x1x) |
647 | ret = lan743x_hs_otp_write(adapter, offset: ee->offset, |
648 | length: ee->len, data); |
649 | else |
650 | ret = lan743x_otp_write(adapter, offset: ee->offset, |
651 | length: ee->len, data); |
652 | } |
653 | } else { |
654 | if (ee->magic == LAN743X_EEPROM_MAGIC) { |
655 | if (adapter->is_pci11x1x) |
656 | ret = lan743x_hs_eeprom_write(adapter, |
657 | offset: ee->offset, |
658 | length: ee->len, data); |
659 | else |
660 | ret = lan743x_eeprom_write(adapter, offset: ee->offset, |
661 | length: ee->len, data); |
662 | } |
663 | } |
664 | |
665 | return ret; |
666 | } |
667 | |
668 | static const char lan743x_set0_hw_cnt_strings[][ETH_GSTRING_LEN] = { |
669 | "RX FCS Errors" , |
670 | "RX Alignment Errors" , |
671 | "Rx Fragment Errors" , |
672 | "RX Jabber Errors" , |
673 | "RX Undersize Frame Errors" , |
674 | "RX Oversize Frame Errors" , |
675 | "RX Dropped Frames" , |
676 | "RX Unicast Byte Count" , |
677 | "RX Broadcast Byte Count" , |
678 | "RX Multicast Byte Count" , |
679 | "RX Unicast Frames" , |
680 | "RX Broadcast Frames" , |
681 | "RX Multicast Frames" , |
682 | "RX Pause Frames" , |
683 | "RX 64 Byte Frames" , |
684 | "RX 65 - 127 Byte Frames" , |
685 | "RX 128 - 255 Byte Frames" , |
686 | "RX 256 - 511 Bytes Frames" , |
687 | "RX 512 - 1023 Byte Frames" , |
688 | "RX 1024 - 1518 Byte Frames" , |
689 | "RX Greater 1518 Byte Frames" , |
690 | }; |
691 | |
692 | static const char lan743x_set1_sw_cnt_strings[][ETH_GSTRING_LEN] = { |
693 | "RX Queue 0 Frames" , |
694 | "RX Queue 1 Frames" , |
695 | "RX Queue 2 Frames" , |
696 | "RX Queue 3 Frames" , |
697 | }; |
698 | |
699 | static const char lan743x_tx_queue_cnt_strings[][ETH_GSTRING_LEN] = { |
700 | "TX Queue 0 Frames" , |
701 | "TX Queue 1 Frames" , |
702 | "TX Queue 2 Frames" , |
703 | "TX Queue 3 Frames" , |
704 | "TX Total Queue Frames" , |
705 | }; |
706 | |
707 | static const char lan743x_set2_hw_cnt_strings[][ETH_GSTRING_LEN] = { |
708 | "RX Total Frames" , |
709 | "EEE RX LPI Transitions" , |
710 | "EEE RX LPI Time" , |
711 | "RX Counter Rollover Status" , |
712 | "TX FCS Errors" , |
713 | "TX Excess Deferral Errors" , |
714 | "TX Carrier Errors" , |
715 | "TX Bad Byte Count" , |
716 | "TX Single Collisions" , |
717 | "TX Multiple Collisions" , |
718 | "TX Excessive Collision" , |
719 | "TX Late Collisions" , |
720 | "TX Unicast Byte Count" , |
721 | "TX Broadcast Byte Count" , |
722 | "TX Multicast Byte Count" , |
723 | "TX Unicast Frames" , |
724 | "TX Broadcast Frames" , |
725 | "TX Multicast Frames" , |
726 | "TX Pause Frames" , |
727 | "TX 64 Byte Frames" , |
728 | "TX 65 - 127 Byte Frames" , |
729 | "TX 128 - 255 Byte Frames" , |
730 | "TX 256 - 511 Bytes Frames" , |
731 | "TX 512 - 1023 Byte Frames" , |
732 | "TX 1024 - 1518 Byte Frames" , |
733 | "TX Greater 1518 Byte Frames" , |
734 | "TX Total Frames" , |
735 | "EEE TX LPI Transitions" , |
736 | "EEE TX LPI Time" , |
737 | "TX Counter Rollover Status" , |
738 | }; |
739 | |
740 | static const u32 lan743x_set0_hw_cnt_addr[] = { |
741 | STAT_RX_FCS_ERRORS, |
742 | STAT_RX_ALIGNMENT_ERRORS, |
743 | STAT_RX_FRAGMENT_ERRORS, |
744 | STAT_RX_JABBER_ERRORS, |
745 | STAT_RX_UNDERSIZE_FRAME_ERRORS, |
746 | STAT_RX_OVERSIZE_FRAME_ERRORS, |
747 | STAT_RX_DROPPED_FRAMES, |
748 | STAT_RX_UNICAST_BYTE_COUNT, |
749 | STAT_RX_BROADCAST_BYTE_COUNT, |
750 | STAT_RX_MULTICAST_BYTE_COUNT, |
751 | STAT_RX_UNICAST_FRAMES, |
752 | STAT_RX_BROADCAST_FRAMES, |
753 | STAT_RX_MULTICAST_FRAMES, |
754 | STAT_RX_PAUSE_FRAMES, |
755 | STAT_RX_64_BYTE_FRAMES, |
756 | STAT_RX_65_127_BYTE_FRAMES, |
757 | STAT_RX_128_255_BYTE_FRAMES, |
758 | STAT_RX_256_511_BYTES_FRAMES, |
759 | STAT_RX_512_1023_BYTE_FRAMES, |
760 | STAT_RX_1024_1518_BYTE_FRAMES, |
761 | STAT_RX_GREATER_1518_BYTE_FRAMES, |
762 | }; |
763 | |
764 | static const u32 lan743x_set2_hw_cnt_addr[] = { |
765 | STAT_RX_TOTAL_FRAMES, |
766 | STAT_EEE_RX_LPI_TRANSITIONS, |
767 | STAT_EEE_RX_LPI_TIME, |
768 | STAT_RX_COUNTER_ROLLOVER_STATUS, |
769 | STAT_TX_FCS_ERRORS, |
770 | STAT_TX_EXCESS_DEFERRAL_ERRORS, |
771 | STAT_TX_CARRIER_ERRORS, |
772 | STAT_TX_BAD_BYTE_COUNT, |
773 | STAT_TX_SINGLE_COLLISIONS, |
774 | STAT_TX_MULTIPLE_COLLISIONS, |
775 | STAT_TX_EXCESSIVE_COLLISION, |
776 | STAT_TX_LATE_COLLISIONS, |
777 | STAT_TX_UNICAST_BYTE_COUNT, |
778 | STAT_TX_BROADCAST_BYTE_COUNT, |
779 | STAT_TX_MULTICAST_BYTE_COUNT, |
780 | STAT_TX_UNICAST_FRAMES, |
781 | STAT_TX_BROADCAST_FRAMES, |
782 | STAT_TX_MULTICAST_FRAMES, |
783 | STAT_TX_PAUSE_FRAMES, |
784 | STAT_TX_64_BYTE_FRAMES, |
785 | STAT_TX_65_127_BYTE_FRAMES, |
786 | STAT_TX_128_255_BYTE_FRAMES, |
787 | STAT_TX_256_511_BYTES_FRAMES, |
788 | STAT_TX_512_1023_BYTE_FRAMES, |
789 | STAT_TX_1024_1518_BYTE_FRAMES, |
790 | STAT_TX_GREATER_1518_BYTE_FRAMES, |
791 | STAT_TX_TOTAL_FRAMES, |
792 | STAT_EEE_TX_LPI_TRANSITIONS, |
793 | STAT_EEE_TX_LPI_TIME, |
794 | STAT_TX_COUNTER_ROLLOVER_STATUS |
795 | }; |
796 | |
797 | static const char lan743x_priv_flags_strings[][ETH_GSTRING_LEN] = { |
798 | "OTP_ACCESS" , |
799 | }; |
800 | |
801 | static void lan743x_ethtool_get_strings(struct net_device *netdev, |
802 | u32 stringset, u8 *data) |
803 | { |
804 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
805 | |
806 | switch (stringset) { |
807 | case ETH_SS_STATS: |
808 | memcpy(data, lan743x_set0_hw_cnt_strings, |
809 | sizeof(lan743x_set0_hw_cnt_strings)); |
810 | memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings)], |
811 | lan743x_set1_sw_cnt_strings, |
812 | sizeof(lan743x_set1_sw_cnt_strings)); |
813 | memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings) + |
814 | sizeof(lan743x_set1_sw_cnt_strings)], |
815 | lan743x_set2_hw_cnt_strings, |
816 | sizeof(lan743x_set2_hw_cnt_strings)); |
817 | if (adapter->is_pci11x1x) { |
818 | memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings) + |
819 | sizeof(lan743x_set1_sw_cnt_strings) + |
820 | sizeof(lan743x_set2_hw_cnt_strings)], |
821 | lan743x_tx_queue_cnt_strings, |
822 | sizeof(lan743x_tx_queue_cnt_strings)); |
823 | } |
824 | break; |
825 | case ETH_SS_PRIV_FLAGS: |
826 | memcpy(data, lan743x_priv_flags_strings, |
827 | sizeof(lan743x_priv_flags_strings)); |
828 | break; |
829 | } |
830 | } |
831 | |
832 | static void lan743x_ethtool_get_ethtool_stats(struct net_device *netdev, |
833 | struct ethtool_stats *stats, |
834 | u64 *data) |
835 | { |
836 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
837 | u64 total_queue_count = 0; |
838 | int data_index = 0; |
839 | u64 pkt_cnt; |
840 | u32 buf; |
841 | int i; |
842 | |
843 | for (i = 0; i < ARRAY_SIZE(lan743x_set0_hw_cnt_addr); i++) { |
844 | buf = lan743x_csr_read(adapter, offset: lan743x_set0_hw_cnt_addr[i]); |
845 | data[data_index++] = (u64)buf; |
846 | } |
847 | for (i = 0; i < ARRAY_SIZE(adapter->rx); i++) |
848 | data[data_index++] = (u64)(adapter->rx[i].frame_count); |
849 | for (i = 0; i < ARRAY_SIZE(lan743x_set2_hw_cnt_addr); i++) { |
850 | buf = lan743x_csr_read(adapter, offset: lan743x_set2_hw_cnt_addr[i]); |
851 | data[data_index++] = (u64)buf; |
852 | } |
853 | if (adapter->is_pci11x1x) { |
854 | for (i = 0; i < ARRAY_SIZE(adapter->tx); i++) { |
855 | pkt_cnt = (u64)(adapter->tx[i].frame_count); |
856 | data[data_index++] = pkt_cnt; |
857 | total_queue_count += pkt_cnt; |
858 | } |
859 | data[data_index++] = total_queue_count; |
860 | } |
861 | } |
862 | |
863 | static u32 lan743x_ethtool_get_priv_flags(struct net_device *netdev) |
864 | { |
865 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
866 | |
867 | return adapter->flags; |
868 | } |
869 | |
870 | static int lan743x_ethtool_set_priv_flags(struct net_device *netdev, u32 flags) |
871 | { |
872 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
873 | |
874 | adapter->flags = flags; |
875 | |
876 | return 0; |
877 | } |
878 | |
879 | static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset) |
880 | { |
881 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
882 | |
883 | switch (sset) { |
884 | case ETH_SS_STATS: |
885 | { |
886 | int ret; |
887 | |
888 | ret = ARRAY_SIZE(lan743x_set0_hw_cnt_strings); |
889 | ret += ARRAY_SIZE(lan743x_set1_sw_cnt_strings); |
890 | ret += ARRAY_SIZE(lan743x_set2_hw_cnt_strings); |
891 | if (adapter->is_pci11x1x) |
892 | ret += ARRAY_SIZE(lan743x_tx_queue_cnt_strings); |
893 | return ret; |
894 | } |
895 | case ETH_SS_PRIV_FLAGS: |
896 | return ARRAY_SIZE(lan743x_priv_flags_strings); |
897 | default: |
898 | return -EOPNOTSUPP; |
899 | } |
900 | } |
901 | |
902 | static int lan743x_ethtool_get_rxnfc(struct net_device *netdev, |
903 | struct ethtool_rxnfc *rxnfc, |
904 | u32 *rule_locs) |
905 | { |
906 | switch (rxnfc->cmd) { |
907 | case ETHTOOL_GRXFH: |
908 | rxnfc->data = 0; |
909 | switch (rxnfc->flow_type) { |
910 | case TCP_V4_FLOW:case UDP_V4_FLOW: |
911 | case TCP_V6_FLOW:case UDP_V6_FLOW: |
912 | rxnfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; |
913 | fallthrough; |
914 | case IPV4_FLOW: case IPV6_FLOW: |
915 | rxnfc->data |= RXH_IP_SRC | RXH_IP_DST; |
916 | return 0; |
917 | } |
918 | break; |
919 | case ETHTOOL_GRXRINGS: |
920 | rxnfc->data = LAN743X_USED_RX_CHANNELS; |
921 | return 0; |
922 | } |
923 | return -EOPNOTSUPP; |
924 | } |
925 | |
926 | static u32 lan743x_ethtool_get_rxfh_key_size(struct net_device *netdev) |
927 | { |
928 | return 40; |
929 | } |
930 | |
931 | static u32 lan743x_ethtool_get_rxfh_indir_size(struct net_device *netdev) |
932 | { |
933 | return 128; |
934 | } |
935 | |
936 | static int lan743x_ethtool_get_rxfh(struct net_device *netdev, |
937 | u32 *indir, u8 *key, u8 *hfunc) |
938 | { |
939 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
940 | |
941 | if (indir) { |
942 | int dw_index; |
943 | int byte_index = 0; |
944 | |
945 | for (dw_index = 0; dw_index < 32; dw_index++) { |
946 | u32 four_entries = |
947 | lan743x_csr_read(adapter, RFE_INDX(dw_index)); |
948 | |
949 | byte_index = dw_index << 2; |
950 | indir[byte_index + 0] = |
951 | ((four_entries >> 0) & 0x000000FF); |
952 | indir[byte_index + 1] = |
953 | ((four_entries >> 8) & 0x000000FF); |
954 | indir[byte_index + 2] = |
955 | ((four_entries >> 16) & 0x000000FF); |
956 | indir[byte_index + 3] = |
957 | ((four_entries >> 24) & 0x000000FF); |
958 | } |
959 | } |
960 | if (key) { |
961 | int dword_index; |
962 | int byte_index = 0; |
963 | |
964 | for (dword_index = 0; dword_index < 10; dword_index++) { |
965 | u32 four_entries = |
966 | lan743x_csr_read(adapter, |
967 | RFE_HASH_KEY(dword_index)); |
968 | |
969 | byte_index = dword_index << 2; |
970 | key[byte_index + 0] = |
971 | ((four_entries >> 0) & 0x000000FF); |
972 | key[byte_index + 1] = |
973 | ((four_entries >> 8) & 0x000000FF); |
974 | key[byte_index + 2] = |
975 | ((four_entries >> 16) & 0x000000FF); |
976 | key[byte_index + 3] = |
977 | ((four_entries >> 24) & 0x000000FF); |
978 | } |
979 | } |
980 | if (hfunc) |
981 | (*hfunc) = ETH_RSS_HASH_TOP; |
982 | return 0; |
983 | } |
984 | |
985 | static int lan743x_ethtool_set_rxfh(struct net_device *netdev, |
986 | const u32 *indir, const u8 *key, |
987 | const u8 hfunc) |
988 | { |
989 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
990 | |
991 | if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) |
992 | return -EOPNOTSUPP; |
993 | |
994 | if (indir) { |
995 | u32 indir_value = 0; |
996 | int dword_index = 0; |
997 | int byte_index = 0; |
998 | |
999 | for (dword_index = 0; dword_index < 32; dword_index++) { |
1000 | byte_index = dword_index << 2; |
1001 | indir_value = |
1002 | (((indir[byte_index + 0] & 0x000000FF) << 0) | |
1003 | ((indir[byte_index + 1] & 0x000000FF) << 8) | |
1004 | ((indir[byte_index + 2] & 0x000000FF) << 16) | |
1005 | ((indir[byte_index + 3] & 0x000000FF) << 24)); |
1006 | lan743x_csr_write(adapter, RFE_INDX(dword_index), |
1007 | data: indir_value); |
1008 | } |
1009 | } |
1010 | if (key) { |
1011 | int dword_index = 0; |
1012 | int byte_index = 0; |
1013 | u32 key_value = 0; |
1014 | |
1015 | for (dword_index = 0; dword_index < 10; dword_index++) { |
1016 | byte_index = dword_index << 2; |
1017 | key_value = |
1018 | ((((u32)(key[byte_index + 0])) << 0) | |
1019 | (((u32)(key[byte_index + 1])) << 8) | |
1020 | (((u32)(key[byte_index + 2])) << 16) | |
1021 | (((u32)(key[byte_index + 3])) << 24)); |
1022 | lan743x_csr_write(adapter, RFE_HASH_KEY(dword_index), |
1023 | data: key_value); |
1024 | } |
1025 | } |
1026 | return 0; |
1027 | } |
1028 | |
1029 | static int lan743x_ethtool_get_ts_info(struct net_device *netdev, |
1030 | struct ethtool_ts_info *ts_info) |
1031 | { |
1032 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
1033 | |
1034 | ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | |
1035 | SOF_TIMESTAMPING_RX_SOFTWARE | |
1036 | SOF_TIMESTAMPING_SOFTWARE | |
1037 | SOF_TIMESTAMPING_TX_HARDWARE | |
1038 | SOF_TIMESTAMPING_RX_HARDWARE | |
1039 | SOF_TIMESTAMPING_RAW_HARDWARE; |
1040 | |
1041 | if (adapter->ptp.ptp_clock) |
1042 | ts_info->phc_index = ptp_clock_index(ptp: adapter->ptp.ptp_clock); |
1043 | else |
1044 | ts_info->phc_index = -1; |
1045 | |
1046 | ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) | |
1047 | BIT(HWTSTAMP_TX_ON) | |
1048 | BIT(HWTSTAMP_TX_ONESTEP_SYNC); |
1049 | ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | |
1050 | BIT(HWTSTAMP_FILTER_ALL) | |
1051 | BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); |
1052 | return 0; |
1053 | } |
1054 | |
1055 | static int lan743x_ethtool_get_eee(struct net_device *netdev, |
1056 | struct ethtool_eee *eee) |
1057 | { |
1058 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
1059 | struct phy_device *phydev = netdev->phydev; |
1060 | u32 buf; |
1061 | int ret; |
1062 | |
1063 | if (!phydev) |
1064 | return -EIO; |
1065 | if (!phydev->drv) { |
1066 | netif_err(adapter, drv, adapter->netdev, |
1067 | "Missing PHY Driver\n" ); |
1068 | return -EIO; |
1069 | } |
1070 | |
1071 | ret = phy_ethtool_get_eee(phydev, data: eee); |
1072 | if (ret < 0) |
1073 | return ret; |
1074 | |
1075 | buf = lan743x_csr_read(adapter, MAC_CR); |
1076 | if (buf & MAC_CR_EEE_EN_) { |
1077 | eee->eee_enabled = true; |
1078 | eee->eee_active = !!(eee->advertised & eee->lp_advertised); |
1079 | eee->tx_lpi_enabled = true; |
1080 | /* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */ |
1081 | buf = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT); |
1082 | eee->tx_lpi_timer = buf; |
1083 | } else { |
1084 | eee->eee_enabled = false; |
1085 | eee->eee_active = false; |
1086 | eee->tx_lpi_enabled = false; |
1087 | eee->tx_lpi_timer = 0; |
1088 | } |
1089 | |
1090 | return 0; |
1091 | } |
1092 | |
1093 | static int lan743x_ethtool_set_eee(struct net_device *netdev, |
1094 | struct ethtool_eee *eee) |
1095 | { |
1096 | struct lan743x_adapter *adapter; |
1097 | struct phy_device *phydev; |
1098 | u32 buf = 0; |
1099 | int ret = 0; |
1100 | |
1101 | if (!netdev) |
1102 | return -EINVAL; |
1103 | adapter = netdev_priv(dev: netdev); |
1104 | if (!adapter) |
1105 | return -EINVAL; |
1106 | phydev = netdev->phydev; |
1107 | if (!phydev) |
1108 | return -EIO; |
1109 | if (!phydev->drv) { |
1110 | netif_err(adapter, drv, adapter->netdev, |
1111 | "Missing PHY Driver\n" ); |
1112 | return -EIO; |
1113 | } |
1114 | |
1115 | if (eee->eee_enabled) { |
1116 | ret = phy_init_eee(phydev, clk_stop_enable: false); |
1117 | if (ret) { |
1118 | netif_err(adapter, drv, adapter->netdev, |
1119 | "EEE initialization failed\n" ); |
1120 | return ret; |
1121 | } |
1122 | |
1123 | buf = (u32)eee->tx_lpi_timer; |
1124 | lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, data: buf); |
1125 | |
1126 | buf = lan743x_csr_read(adapter, MAC_CR); |
1127 | buf |= MAC_CR_EEE_EN_; |
1128 | lan743x_csr_write(adapter, MAC_CR, data: buf); |
1129 | } else { |
1130 | buf = lan743x_csr_read(adapter, MAC_CR); |
1131 | buf &= ~MAC_CR_EEE_EN_; |
1132 | lan743x_csr_write(adapter, MAC_CR, data: buf); |
1133 | } |
1134 | |
1135 | return phy_ethtool_set_eee(phydev, data: eee); |
1136 | } |
1137 | |
1138 | #ifdef CONFIG_PM |
1139 | static void lan743x_ethtool_get_wol(struct net_device *netdev, |
1140 | struct ethtool_wolinfo *wol) |
1141 | { |
1142 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
1143 | |
1144 | wol->supported = 0; |
1145 | wol->wolopts = 0; |
1146 | |
1147 | if (netdev->phydev) |
1148 | phy_ethtool_get_wol(phydev: netdev->phydev, wol); |
1149 | |
1150 | wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | |
1151 | WAKE_MAGIC | WAKE_PHY | WAKE_ARP; |
1152 | |
1153 | if (adapter->is_pci11x1x) |
1154 | wol->supported |= WAKE_MAGICSECURE; |
1155 | |
1156 | wol->wolopts |= adapter->wolopts; |
1157 | if (adapter->wolopts & WAKE_MAGICSECURE) |
1158 | memcpy(wol->sopass, adapter->sopass, sizeof(wol->sopass)); |
1159 | } |
1160 | |
1161 | static int lan743x_ethtool_set_wol(struct net_device *netdev, |
1162 | struct ethtool_wolinfo *wol) |
1163 | { |
1164 | struct lan743x_adapter *adapter = netdev_priv(dev: netdev); |
1165 | |
1166 | adapter->wolopts = 0; |
1167 | if (wol->wolopts & WAKE_UCAST) |
1168 | adapter->wolopts |= WAKE_UCAST; |
1169 | if (wol->wolopts & WAKE_MCAST) |
1170 | adapter->wolopts |= WAKE_MCAST; |
1171 | if (wol->wolopts & WAKE_BCAST) |
1172 | adapter->wolopts |= WAKE_BCAST; |
1173 | if (wol->wolopts & WAKE_MAGIC) |
1174 | adapter->wolopts |= WAKE_MAGIC; |
1175 | if (wol->wolopts & WAKE_PHY) |
1176 | adapter->wolopts |= WAKE_PHY; |
1177 | if (wol->wolopts & WAKE_ARP) |
1178 | adapter->wolopts |= WAKE_ARP; |
1179 | if (wol->wolopts & WAKE_MAGICSECURE && |
1180 | wol->wolopts & WAKE_MAGIC) { |
1181 | memcpy(adapter->sopass, wol->sopass, sizeof(wol->sopass)); |
1182 | adapter->wolopts |= WAKE_MAGICSECURE; |
1183 | } else { |
1184 | memset(adapter->sopass, 0, sizeof(u8) * SOPASS_MAX); |
1185 | } |
1186 | |
1187 | device_set_wakeup_enable(dev: &adapter->pdev->dev, enable: (bool)wol->wolopts); |
1188 | |
1189 | return netdev->phydev ? phy_ethtool_set_wol(phydev: netdev->phydev, wol) |
1190 | : -ENETDOWN; |
1191 | } |
1192 | #endif /* CONFIG_PM */ |
1193 | |
1194 | static void lan743x_common_regs(struct net_device *dev, void *p) |
1195 | { |
1196 | struct lan743x_adapter *adapter = netdev_priv(dev); |
1197 | u32 *rb = p; |
1198 | |
1199 | memset(p, 0, (MAX_LAN743X_ETH_COMMON_REGS * sizeof(u32))); |
1200 | |
1201 | rb[ETH_PRIV_FLAGS] = adapter->flags; |
1202 | rb[ETH_ID_REV] = lan743x_csr_read(adapter, ID_REV); |
1203 | rb[ETH_FPGA_REV] = lan743x_csr_read(adapter, FPGA_REV); |
1204 | rb[ETH_STRAP_READ] = lan743x_csr_read(adapter, STRAP_READ); |
1205 | rb[ETH_INT_STS] = lan743x_csr_read(adapter, INT_STS); |
1206 | rb[ETH_HW_CFG] = lan743x_csr_read(adapter, HW_CFG); |
1207 | rb[ETH_PMT_CTL] = lan743x_csr_read(adapter, PMT_CTL); |
1208 | rb[ETH_E2P_CMD] = lan743x_csr_read(adapter, E2P_CMD); |
1209 | rb[ETH_E2P_DATA] = lan743x_csr_read(adapter, E2P_DATA); |
1210 | rb[ETH_MAC_CR] = lan743x_csr_read(adapter, MAC_CR); |
1211 | rb[ETH_MAC_RX] = lan743x_csr_read(adapter, MAC_RX); |
1212 | rb[ETH_MAC_TX] = lan743x_csr_read(adapter, MAC_TX); |
1213 | rb[ETH_FLOW] = lan743x_csr_read(adapter, MAC_FLOW); |
1214 | rb[ETH_MII_ACC] = lan743x_csr_read(adapter, MAC_MII_ACC); |
1215 | rb[ETH_MII_DATA] = lan743x_csr_read(adapter, MAC_MII_DATA); |
1216 | rb[ETH_EEE_TX_LPI_REQ_DLY] = lan743x_csr_read(adapter, |
1217 | MAC_EEE_TX_LPI_REQ_DLY_CNT); |
1218 | rb[ETH_WUCSR] = lan743x_csr_read(adapter, MAC_WUCSR); |
1219 | rb[ETH_WK_SRC] = lan743x_csr_read(adapter, MAC_WK_SRC); |
1220 | } |
1221 | |
1222 | static void lan743x_sgmii_regs(struct net_device *dev, void *p) |
1223 | { |
1224 | struct lan743x_adapter *adp = netdev_priv(dev); |
1225 | u32 *rb = p; |
1226 | u16 idx; |
1227 | int val; |
1228 | struct { |
1229 | u8 id; |
1230 | u8 dev; |
1231 | u16 addr; |
1232 | } regs[] = { |
1233 | { ETH_SR_VSMMD_DEV_ID1, MDIO_MMD_VEND1, 0x0002}, |
1234 | { ETH_SR_VSMMD_DEV_ID2, MDIO_MMD_VEND1, 0x0003}, |
1235 | { ETH_SR_VSMMD_PCS_ID1, MDIO_MMD_VEND1, 0x0004}, |
1236 | { ETH_SR_VSMMD_PCS_ID2, MDIO_MMD_VEND1, 0x0005}, |
1237 | { ETH_SR_VSMMD_STS, MDIO_MMD_VEND1, 0x0008}, |
1238 | { ETH_SR_VSMMD_CTRL, MDIO_MMD_VEND1, 0x0009}, |
1239 | { ETH_SR_MII_CTRL, MDIO_MMD_VEND2, 0x0000}, |
1240 | { ETH_SR_MII_STS, MDIO_MMD_VEND2, 0x0001}, |
1241 | { ETH_SR_MII_DEV_ID1, MDIO_MMD_VEND2, 0x0002}, |
1242 | { ETH_SR_MII_DEV_ID2, MDIO_MMD_VEND2, 0x0003}, |
1243 | { ETH_SR_MII_AN_ADV, MDIO_MMD_VEND2, 0x0004}, |
1244 | { ETH_SR_MII_LP_BABL, MDIO_MMD_VEND2, 0x0005}, |
1245 | { ETH_SR_MII_EXPN, MDIO_MMD_VEND2, 0x0006}, |
1246 | { ETH_SR_MII_EXT_STS, MDIO_MMD_VEND2, 0x000F}, |
1247 | { ETH_SR_MII_TIME_SYNC_ABL, MDIO_MMD_VEND2, 0x0708}, |
1248 | { ETH_SR_MII_TIME_SYNC_TX_MAX_DLY_LWR, MDIO_MMD_VEND2, 0x0709}, |
1249 | { ETH_SR_MII_TIME_SYNC_TX_MAX_DLY_UPR, MDIO_MMD_VEND2, 0x070A}, |
1250 | { ETH_SR_MII_TIME_SYNC_TX_MIN_DLY_LWR, MDIO_MMD_VEND2, 0x070B}, |
1251 | { ETH_SR_MII_TIME_SYNC_TX_MIN_DLY_UPR, MDIO_MMD_VEND2, 0x070C}, |
1252 | { ETH_SR_MII_TIME_SYNC_RX_MAX_DLY_LWR, MDIO_MMD_VEND2, 0x070D}, |
1253 | { ETH_SR_MII_TIME_SYNC_RX_MAX_DLY_UPR, MDIO_MMD_VEND2, 0x070E}, |
1254 | { ETH_SR_MII_TIME_SYNC_RX_MIN_DLY_LWR, MDIO_MMD_VEND2, 0x070F}, |
1255 | { ETH_SR_MII_TIME_SYNC_RX_MIN_DLY_UPR, MDIO_MMD_VEND2, 0x0710}, |
1256 | { ETH_VR_MII_DIG_CTRL1, MDIO_MMD_VEND2, 0x8000}, |
1257 | { ETH_VR_MII_AN_CTRL, MDIO_MMD_VEND2, 0x8001}, |
1258 | { ETH_VR_MII_AN_INTR_STS, MDIO_MMD_VEND2, 0x8002}, |
1259 | { ETH_VR_MII_TC, MDIO_MMD_VEND2, 0x8003}, |
1260 | { ETH_VR_MII_DBG_CTRL, MDIO_MMD_VEND2, 0x8005}, |
1261 | { ETH_VR_MII_EEE_MCTRL0, MDIO_MMD_VEND2, 0x8006}, |
1262 | { ETH_VR_MII_EEE_TXTIMER, MDIO_MMD_VEND2, 0x8008}, |
1263 | { ETH_VR_MII_EEE_RXTIMER, MDIO_MMD_VEND2, 0x8009}, |
1264 | { ETH_VR_MII_LINK_TIMER_CTRL, MDIO_MMD_VEND2, 0x800A}, |
1265 | { ETH_VR_MII_EEE_MCTRL1, MDIO_MMD_VEND2, 0x800B}, |
1266 | { ETH_VR_MII_DIG_STS, MDIO_MMD_VEND2, 0x8010}, |
1267 | { ETH_VR_MII_ICG_ERRCNT1, MDIO_MMD_VEND2, 0x8011}, |
1268 | { ETH_VR_MII_GPIO, MDIO_MMD_VEND2, 0x8015}, |
1269 | { ETH_VR_MII_EEE_LPI_STATUS, MDIO_MMD_VEND2, 0x8016}, |
1270 | { ETH_VR_MII_EEE_WKERR, MDIO_MMD_VEND2, 0x8017}, |
1271 | { ETH_VR_MII_MISC_STS, MDIO_MMD_VEND2, 0x8018}, |
1272 | { ETH_VR_MII_RX_LSTS, MDIO_MMD_VEND2, 0x8020}, |
1273 | { ETH_VR_MII_GEN2_GEN4_TX_BSTCTRL0, MDIO_MMD_VEND2, 0x8038}, |
1274 | { ETH_VR_MII_GEN2_GEN4_TX_LVLCTRL0, MDIO_MMD_VEND2, 0x803A}, |
1275 | { ETH_VR_MII_GEN2_GEN4_TXGENCTRL0, MDIO_MMD_VEND2, 0x803C}, |
1276 | { ETH_VR_MII_GEN2_GEN4_TXGENCTRL1, MDIO_MMD_VEND2, 0x803D}, |
1277 | { ETH_VR_MII_GEN4_TXGENCTRL2, MDIO_MMD_VEND2, 0x803E}, |
1278 | { ETH_VR_MII_GEN2_GEN4_TX_STS, MDIO_MMD_VEND2, 0x8048}, |
1279 | { ETH_VR_MII_GEN2_GEN4_RXGENCTRL0, MDIO_MMD_VEND2, 0x8058}, |
1280 | { ETH_VR_MII_GEN2_GEN4_RXGENCTRL1, MDIO_MMD_VEND2, 0x8059}, |
1281 | { ETH_VR_MII_GEN4_RXEQ_CTRL, MDIO_MMD_VEND2, 0x805B}, |
1282 | { ETH_VR_MII_GEN4_RXLOS_CTRL0, MDIO_MMD_VEND2, 0x805D}, |
1283 | { ETH_VR_MII_GEN2_GEN4_MPLL_CTRL0, MDIO_MMD_VEND2, 0x8078}, |
1284 | { ETH_VR_MII_GEN2_GEN4_MPLL_CTRL1, MDIO_MMD_VEND2, 0x8079}, |
1285 | { ETH_VR_MII_GEN2_GEN4_MPLL_STS, MDIO_MMD_VEND2, 0x8088}, |
1286 | { ETH_VR_MII_GEN2_GEN4_LVL_CTRL, MDIO_MMD_VEND2, 0x8090}, |
1287 | { ETH_VR_MII_GEN4_MISC_CTRL2, MDIO_MMD_VEND2, 0x8093}, |
1288 | { ETH_VR_MII_GEN2_GEN4_MISC_CTRL0, MDIO_MMD_VEND2, 0x8099}, |
1289 | { ETH_VR_MII_GEN2_GEN4_MISC_CTRL1, MDIO_MMD_VEND2, 0x809A}, |
1290 | { ETH_VR_MII_SNPS_CR_CTRL, MDIO_MMD_VEND2, 0x80A0}, |
1291 | { ETH_VR_MII_SNPS_CR_ADDR, MDIO_MMD_VEND2, 0x80A1}, |
1292 | { ETH_VR_MII_SNPS_CR_DATA, MDIO_MMD_VEND2, 0x80A2}, |
1293 | { ETH_VR_MII_DIG_CTRL2, MDIO_MMD_VEND2, 0x80E1}, |
1294 | { ETH_VR_MII_DIG_ERRCNT, MDIO_MMD_VEND2, 0x80E2}, |
1295 | }; |
1296 | |
1297 | for (idx = 0; idx < ARRAY_SIZE(regs); idx++) { |
1298 | val = lan743x_sgmii_read(adapter: adp, mmd: regs[idx].dev, addr: regs[idx].addr); |
1299 | if (val < 0) |
1300 | rb[regs[idx].id] = 0xFFFF; |
1301 | else |
1302 | rb[regs[idx].id] = val; |
1303 | } |
1304 | } |
1305 | |
1306 | static int lan743x_get_regs_len(struct net_device *dev) |
1307 | { |
1308 | struct lan743x_adapter *adapter = netdev_priv(dev); |
1309 | u32 num_regs = MAX_LAN743X_ETH_COMMON_REGS; |
1310 | |
1311 | if (adapter->is_sgmii_en) |
1312 | num_regs += MAX_LAN743X_ETH_SGMII_REGS; |
1313 | |
1314 | return num_regs * sizeof(u32); |
1315 | } |
1316 | |
1317 | static void lan743x_get_regs(struct net_device *dev, |
1318 | struct ethtool_regs *regs, void *p) |
1319 | { |
1320 | struct lan743x_adapter *adapter = netdev_priv(dev); |
1321 | int regs_len; |
1322 | |
1323 | regs_len = lan743x_get_regs_len(dev); |
1324 | memset(p, 0, regs_len); |
1325 | |
1326 | regs->version = LAN743X_ETH_REG_VERSION; |
1327 | regs->len = regs_len; |
1328 | |
1329 | lan743x_common_regs(dev, p); |
1330 | p = (u32 *)p + MAX_LAN743X_ETH_COMMON_REGS; |
1331 | |
1332 | if (adapter->is_sgmii_en) { |
1333 | lan743x_sgmii_regs(dev, p); |
1334 | p = (u32 *)p + MAX_LAN743X_ETH_SGMII_REGS; |
1335 | } |
1336 | } |
1337 | |
1338 | static void lan743x_get_pauseparam(struct net_device *dev, |
1339 | struct ethtool_pauseparam *pause) |
1340 | { |
1341 | struct lan743x_adapter *adapter = netdev_priv(dev); |
1342 | struct lan743x_phy *phy = &adapter->phy; |
1343 | |
1344 | if (phy->fc_request_control & FLOW_CTRL_TX) |
1345 | pause->tx_pause = 1; |
1346 | if (phy->fc_request_control & FLOW_CTRL_RX) |
1347 | pause->rx_pause = 1; |
1348 | pause->autoneg = phy->fc_autoneg; |
1349 | } |
1350 | |
1351 | static int lan743x_set_pauseparam(struct net_device *dev, |
1352 | struct ethtool_pauseparam *pause) |
1353 | { |
1354 | struct lan743x_adapter *adapter = netdev_priv(dev); |
1355 | struct phy_device *phydev = dev->phydev; |
1356 | struct lan743x_phy *phy = &adapter->phy; |
1357 | |
1358 | if (!phydev) |
1359 | return -ENODEV; |
1360 | |
1361 | if (!phy_validate_pause(phydev, pp: pause)) |
1362 | return -EINVAL; |
1363 | |
1364 | phy->fc_request_control = 0; |
1365 | if (pause->rx_pause) |
1366 | phy->fc_request_control |= FLOW_CTRL_RX; |
1367 | |
1368 | if (pause->tx_pause) |
1369 | phy->fc_request_control |= FLOW_CTRL_TX; |
1370 | |
1371 | phy->fc_autoneg = pause->autoneg; |
1372 | |
1373 | if (pause->autoneg == AUTONEG_DISABLE) |
1374 | lan743x_mac_flow_ctrl_set_enables(adapter, tx_enable: pause->tx_pause, |
1375 | rx_enable: pause->rx_pause); |
1376 | else |
1377 | phy_set_asym_pause(phydev, rx: pause->rx_pause, tx: pause->tx_pause); |
1378 | |
1379 | return 0; |
1380 | } |
1381 | |
1382 | const struct ethtool_ops lan743x_ethtool_ops = { |
1383 | .get_drvinfo = lan743x_ethtool_get_drvinfo, |
1384 | .get_msglevel = lan743x_ethtool_get_msglevel, |
1385 | .set_msglevel = lan743x_ethtool_set_msglevel, |
1386 | .get_link = ethtool_op_get_link, |
1387 | |
1388 | .get_eeprom_len = lan743x_ethtool_get_eeprom_len, |
1389 | .get_eeprom = lan743x_ethtool_get_eeprom, |
1390 | .set_eeprom = lan743x_ethtool_set_eeprom, |
1391 | .get_strings = lan743x_ethtool_get_strings, |
1392 | .get_ethtool_stats = lan743x_ethtool_get_ethtool_stats, |
1393 | .get_priv_flags = lan743x_ethtool_get_priv_flags, |
1394 | .set_priv_flags = lan743x_ethtool_set_priv_flags, |
1395 | .get_sset_count = lan743x_ethtool_get_sset_count, |
1396 | .get_rxnfc = lan743x_ethtool_get_rxnfc, |
1397 | .get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size, |
1398 | .get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size, |
1399 | .get_rxfh = lan743x_ethtool_get_rxfh, |
1400 | .set_rxfh = lan743x_ethtool_set_rxfh, |
1401 | .get_ts_info = lan743x_ethtool_get_ts_info, |
1402 | .get_eee = lan743x_ethtool_get_eee, |
1403 | .set_eee = lan743x_ethtool_set_eee, |
1404 | .get_link_ksettings = phy_ethtool_get_link_ksettings, |
1405 | .set_link_ksettings = phy_ethtool_set_link_ksettings, |
1406 | .get_regs_len = lan743x_get_regs_len, |
1407 | .get_regs = lan743x_get_regs, |
1408 | .get_pauseparam = lan743x_get_pauseparam, |
1409 | .set_pauseparam = lan743x_set_pauseparam, |
1410 | #ifdef CONFIG_PM |
1411 | .get_wol = lan743x_ethtool_get_wol, |
1412 | .set_wol = lan743x_ethtool_set_wol, |
1413 | #endif |
1414 | }; |
1415 | |