1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */ |
3 | |
4 | #include <linux/etherdevice.h> |
5 | #include <linux/iopoll.h> |
6 | #include <linux/pci.h> |
7 | |
8 | #include "../libwx/wx_type.h" |
9 | #include "../libwx/wx_hw.h" |
10 | #include "ngbe_type.h" |
11 | #include "ngbe_hw.h" |
12 | |
13 | int ngbe_eeprom_chksum_hostif(struct wx *wx) |
14 | { |
15 | struct wx_hic_read_shadow_ram buffer; |
16 | int status; |
17 | int tmp; |
18 | |
19 | buffer.hdr.req.cmd = NGBE_FW_EEPROM_CHECKSUM_CMD; |
20 | buffer.hdr.req.buf_lenh = 0; |
21 | buffer.hdr.req.buf_lenl = 0; |
22 | buffer.hdr.req.checksum = NGBE_FW_CMD_DEFAULT_CHECKSUM; |
23 | /* convert offset from words to bytes */ |
24 | buffer.address = 0; |
25 | /* one word */ |
26 | buffer.length = 0; |
27 | |
28 | status = wx_host_interface_command(wx, buffer: (u32 *)&buffer, length: sizeof(buffer), |
29 | WX_HI_COMMAND_TIMEOUT, return_data: false); |
30 | |
31 | if (status < 0) |
32 | return status; |
33 | tmp = rd32a(wx, WX_MNG_MBOX, 1); |
34 | if (tmp == NGBE_FW_CMD_ST_PASS) |
35 | return 0; |
36 | return -EIO; |
37 | } |
38 | |
39 | static int ngbe_reset_misc(struct wx *wx) |
40 | { |
41 | wx_reset_misc(wx); |
42 | if (wx->gpio_ctrl) { |
43 | /* gpio0 is used to power on/off control*/ |
44 | wr32(wx, NGBE_GPIO_DDR, 0x1); |
45 | ngbe_sfp_modules_txrx_powerctl(wx, swi: false); |
46 | } |
47 | return 0; |
48 | } |
49 | |
50 | void ngbe_sfp_modules_txrx_powerctl(struct wx *wx, bool swi) |
51 | { |
52 | /* gpio0 is used to power on control . 0 is on */ |
53 | wr32(wx, NGBE_GPIO_DR, swi ? 0 : NGBE_GPIO_DR_0); |
54 | } |
55 | |
56 | /** |
57 | * ngbe_reset_hw - Perform hardware reset |
58 | * @wx: pointer to hardware structure |
59 | * |
60 | * Resets the hardware by resetting the transmit and receive units, masks |
61 | * and clears all interrupts, perform a PHY reset, and perform a link (MAC) |
62 | * reset. |
63 | **/ |
64 | int ngbe_reset_hw(struct wx *wx) |
65 | { |
66 | u32 val = 0; |
67 | int ret = 0; |
68 | |
69 | /* Call wx stop to disable tx/rx and clear interrupts */ |
70 | ret = wx_stop_adapter(wx); |
71 | if (ret != 0) |
72 | return ret; |
73 | |
74 | if (wx->mac_type != em_mac_type_mdi) { |
75 | val = WX_MIS_RST_LAN_RST(wx->bus.func); |
76 | wr32(wx, WX_MIS_RST, val | rd32(wx, WX_MIS_RST)); |
77 | |
78 | ret = read_poll_timeout(rd32, val, |
79 | !(val & (BIT(9) << wx->bus.func)), 1000, |
80 | 100000, false, wx, 0x10028); |
81 | if (ret) { |
82 | wx_err(wx, "Lan reset exceed s maximum times.\n" ); |
83 | return ret; |
84 | } |
85 | } |
86 | ngbe_reset_misc(wx); |
87 | |
88 | wx_clear_hw_cntrs(wx); |
89 | |
90 | /* Store the permanent mac address */ |
91 | wx_get_mac_addr(wx, mac_addr: wx->mac.perm_addr); |
92 | |
93 | /* reset num_rar_entries to 128 */ |
94 | wx->mac.num_rar_entries = NGBE_RAR_ENTRIES; |
95 | wx_init_rx_addrs(wx); |
96 | pci_set_master(dev: wx->pdev); |
97 | |
98 | return 0; |
99 | } |
100 | |