1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2018 Intel Corporation */ |
3 | |
4 | #include <linux/delay.h> |
5 | |
6 | #include "igc_hw.h" |
7 | #include "igc_i225.h" |
8 | #include "igc_mac.h" |
9 | #include "igc_base.h" |
10 | #include "igc.h" |
11 | |
12 | /** |
13 | * igc_reset_hw_base - Reset hardware |
14 | * @hw: pointer to the HW structure |
15 | * |
16 | * This resets the hardware into a known state. This is a |
17 | * function pointer entry point called by the api module. |
18 | */ |
19 | static s32 igc_reset_hw_base(struct igc_hw *hw) |
20 | { |
21 | s32 ret_val; |
22 | u32 ctrl; |
23 | |
24 | /* Prevent the PCI-E bus from sticking if there is no TLP connection |
25 | * on the last TLP read/write transaction when MAC is reset. |
26 | */ |
27 | ret_val = igc_disable_pcie_master(hw); |
28 | if (ret_val) |
29 | hw_dbg("PCI-E Master disable polling has failed\n" ); |
30 | |
31 | hw_dbg("Masking off all interrupts\n" ); |
32 | wr32(IGC_IMC, 0xffffffff); |
33 | |
34 | wr32(IGC_RCTL, 0); |
35 | wr32(IGC_TCTL, IGC_TCTL_PSP); |
36 | wrfl(); |
37 | |
38 | usleep_range(min: 10000, max: 20000); |
39 | |
40 | ctrl = rd32(IGC_CTRL); |
41 | |
42 | hw_dbg("Issuing a global reset to MAC\n" ); |
43 | wr32(IGC_CTRL, ctrl | IGC_CTRL_RST); |
44 | |
45 | ret_val = igc_get_auto_rd_done(hw); |
46 | if (ret_val) { |
47 | /* When auto config read does not complete, do not |
48 | * return with an error. This can happen in situations |
49 | * where there is no eeprom and prevents getting link. |
50 | */ |
51 | hw_dbg("Auto Read Done did not complete\n" ); |
52 | } |
53 | |
54 | /* Clear any pending interrupt events. */ |
55 | wr32(IGC_IMC, 0xffffffff); |
56 | rd32(IGC_ICR); |
57 | |
58 | return ret_val; |
59 | } |
60 | |
61 | /** |
62 | * igc_init_nvm_params_base - Init NVM func ptrs. |
63 | * @hw: pointer to the HW structure |
64 | */ |
65 | static s32 igc_init_nvm_params_base(struct igc_hw *hw) |
66 | { |
67 | struct igc_nvm_info *nvm = &hw->nvm; |
68 | u32 eecd = rd32(IGC_EECD); |
69 | u16 size; |
70 | |
71 | size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >> |
72 | IGC_EECD_SIZE_EX_SHIFT); |
73 | |
74 | /* Added to a constant, "size" becomes the left-shift value |
75 | * for setting word_size. |
76 | */ |
77 | size += NVM_WORD_SIZE_BASE_SHIFT; |
78 | |
79 | /* Just in case size is out of range, cap it to the largest |
80 | * EEPROM size supported |
81 | */ |
82 | if (size > 15) |
83 | size = 15; |
84 | |
85 | nvm->type = igc_nvm_eeprom_spi; |
86 | nvm->word_size = BIT(size); |
87 | nvm->opcode_bits = 8; |
88 | nvm->delay_usec = 1; |
89 | |
90 | nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8; |
91 | nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ? |
92 | 16 : 8; |
93 | |
94 | if (nvm->word_size == BIT(15)) |
95 | nvm->page_size = 128; |
96 | |
97 | return 0; |
98 | } |
99 | |
100 | /** |
101 | * igc_setup_copper_link_base - Configure copper link settings |
102 | * @hw: pointer to the HW structure |
103 | * |
104 | * Configures the link for auto-neg or forced speed and duplex. Then we check |
105 | * for link, once link is established calls to configure collision distance |
106 | * and flow control are called. |
107 | */ |
108 | static s32 igc_setup_copper_link_base(struct igc_hw *hw) |
109 | { |
110 | s32 ret_val = 0; |
111 | u32 ctrl; |
112 | |
113 | ctrl = rd32(IGC_CTRL); |
114 | ctrl |= IGC_CTRL_SLU; |
115 | ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX); |
116 | wr32(IGC_CTRL, ctrl); |
117 | |
118 | ret_val = igc_setup_copper_link(hw); |
119 | |
120 | return ret_val; |
121 | } |
122 | |
123 | /** |
124 | * igc_init_mac_params_base - Init MAC func ptrs. |
125 | * @hw: pointer to the HW structure |
126 | */ |
127 | static s32 igc_init_mac_params_base(struct igc_hw *hw) |
128 | { |
129 | struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base; |
130 | struct igc_mac_info *mac = &hw->mac; |
131 | |
132 | /* Set mta register count */ |
133 | mac->mta_reg_count = 128; |
134 | mac->rar_entry_count = IGC_RAR_ENTRIES; |
135 | |
136 | /* reset */ |
137 | mac->ops.reset_hw = igc_reset_hw_base; |
138 | |
139 | mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225; |
140 | mac->ops.release_swfw_sync = igc_release_swfw_sync_i225; |
141 | |
142 | /* Allow a single clear of the SW semaphore on I225 */ |
143 | if (mac->type == igc_i225) |
144 | dev_spec->clear_semaphore_once = true; |
145 | |
146 | /* physical interface link setup */ |
147 | mac->ops.setup_physical_interface = igc_setup_copper_link_base; |
148 | |
149 | return 0; |
150 | } |
151 | |
152 | /** |
153 | * igc_init_phy_params_base - Init PHY func ptrs. |
154 | * @hw: pointer to the HW structure |
155 | */ |
156 | static s32 igc_init_phy_params_base(struct igc_hw *hw) |
157 | { |
158 | struct igc_phy_info *phy = &hw->phy; |
159 | s32 ret_val = 0; |
160 | |
161 | phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500; |
162 | phy->reset_delay_us = 100; |
163 | |
164 | /* set lan id */ |
165 | hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >> |
166 | IGC_STATUS_FUNC_SHIFT; |
167 | |
168 | /* Make sure the PHY is in a good state. Several people have reported |
169 | * firmware leaving the PHY's page select register set to something |
170 | * other than the default of zero, which causes the PHY ID read to |
171 | * access something other than the intended register. |
172 | */ |
173 | ret_val = hw->phy.ops.reset(hw); |
174 | if (ret_val) { |
175 | hw_dbg("Error resetting the PHY\n" ); |
176 | goto out; |
177 | } |
178 | |
179 | ret_val = igc_get_phy_id(hw); |
180 | if (ret_val) |
181 | return ret_val; |
182 | |
183 | igc_check_for_copper_link(hw); |
184 | |
185 | out: |
186 | return ret_val; |
187 | } |
188 | |
189 | static s32 igc_get_invariants_base(struct igc_hw *hw) |
190 | { |
191 | struct igc_mac_info *mac = &hw->mac; |
192 | s32 ret_val = 0; |
193 | |
194 | switch (hw->device_id) { |
195 | case IGC_DEV_ID_I225_LM: |
196 | case IGC_DEV_ID_I225_V: |
197 | case IGC_DEV_ID_I225_I: |
198 | case IGC_DEV_ID_I220_V: |
199 | case IGC_DEV_ID_I225_K: |
200 | case IGC_DEV_ID_I225_K2: |
201 | case IGC_DEV_ID_I226_K: |
202 | case IGC_DEV_ID_I225_LMVP: |
203 | case IGC_DEV_ID_I226_LMVP: |
204 | case IGC_DEV_ID_I225_IT: |
205 | case IGC_DEV_ID_I226_LM: |
206 | case IGC_DEV_ID_I226_V: |
207 | case IGC_DEV_ID_I226_IT: |
208 | case IGC_DEV_ID_I221_V: |
209 | case IGC_DEV_ID_I226_BLANK_NVM: |
210 | case IGC_DEV_ID_I225_BLANK_NVM: |
211 | mac->type = igc_i225; |
212 | break; |
213 | default: |
214 | return -IGC_ERR_MAC_INIT; |
215 | } |
216 | |
217 | hw->phy.media_type = igc_media_type_copper; |
218 | |
219 | /* mac initialization and operations */ |
220 | ret_val = igc_init_mac_params_base(hw); |
221 | if (ret_val) |
222 | goto out; |
223 | |
224 | /* NVM initialization */ |
225 | ret_val = igc_init_nvm_params_base(hw); |
226 | switch (hw->mac.type) { |
227 | case igc_i225: |
228 | ret_val = igc_init_nvm_params_i225(hw); |
229 | break; |
230 | default: |
231 | break; |
232 | } |
233 | |
234 | /* setup PHY parameters */ |
235 | ret_val = igc_init_phy_params_base(hw); |
236 | if (ret_val) |
237 | goto out; |
238 | |
239 | out: |
240 | return ret_val; |
241 | } |
242 | |
243 | /** |
244 | * igc_acquire_phy_base - Acquire rights to access PHY |
245 | * @hw: pointer to the HW structure |
246 | * |
247 | * Acquire access rights to the correct PHY. This is a |
248 | * function pointer entry point called by the api module. |
249 | */ |
250 | static s32 igc_acquire_phy_base(struct igc_hw *hw) |
251 | { |
252 | u16 mask = IGC_SWFW_PHY0_SM; |
253 | |
254 | return hw->mac.ops.acquire_swfw_sync(hw, mask); |
255 | } |
256 | |
257 | /** |
258 | * igc_release_phy_base - Release rights to access PHY |
259 | * @hw: pointer to the HW structure |
260 | * |
261 | * A wrapper to release access rights to the correct PHY. This is a |
262 | * function pointer entry point called by the api module. |
263 | */ |
264 | static void igc_release_phy_base(struct igc_hw *hw) |
265 | { |
266 | u16 mask = IGC_SWFW_PHY0_SM; |
267 | |
268 | hw->mac.ops.release_swfw_sync(hw, mask); |
269 | } |
270 | |
271 | /** |
272 | * igc_init_hw_base - Initialize hardware |
273 | * @hw: pointer to the HW structure |
274 | * |
275 | * This inits the hardware readying it for operation. |
276 | */ |
277 | static s32 igc_init_hw_base(struct igc_hw *hw) |
278 | { |
279 | struct igc_mac_info *mac = &hw->mac; |
280 | u16 i, rar_count = mac->rar_entry_count; |
281 | s32 ret_val = 0; |
282 | |
283 | /* Setup the receive address */ |
284 | igc_init_rx_addrs(hw, rar_count); |
285 | |
286 | /* Zero out the Multicast HASH table */ |
287 | hw_dbg("Zeroing the MTA\n" ); |
288 | for (i = 0; i < mac->mta_reg_count; i++) |
289 | array_wr32(IGC_MTA, i, 0); |
290 | |
291 | /* Zero out the Unicast HASH table */ |
292 | hw_dbg("Zeroing the UTA\n" ); |
293 | for (i = 0; i < mac->uta_reg_count; i++) |
294 | array_wr32(IGC_UTA, i, 0); |
295 | |
296 | /* Setup link and flow control */ |
297 | ret_val = igc_setup_link(hw); |
298 | |
299 | /* Clear all of the statistics registers (clear on read). It is |
300 | * important that we do this after we have tried to establish link |
301 | * because the symbol error count will increment wildly if there |
302 | * is no link. |
303 | */ |
304 | igc_clear_hw_cntrs_base(hw); |
305 | |
306 | return ret_val; |
307 | } |
308 | |
309 | /** |
310 | * igc_power_down_phy_copper_base - Remove link during PHY power down |
311 | * @hw: pointer to the HW structure |
312 | * |
313 | * In the case of a PHY power down to save power, or to turn off link during a |
314 | * driver unload, or wake on lan is not enabled, remove the link. |
315 | */ |
316 | void igc_power_down_phy_copper_base(struct igc_hw *hw) |
317 | { |
318 | /* If the management interface is not enabled, then power down */ |
319 | if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw))) |
320 | igc_power_down_phy_copper(hw); |
321 | } |
322 | |
323 | /** |
324 | * igc_rx_fifo_flush_base - Clean rx fifo after Rx enable |
325 | * @hw: pointer to the HW structure |
326 | * |
327 | * After Rx enable, if manageability is enabled then there is likely some |
328 | * bad data at the start of the fifo and possibly in the DMA fifo. This |
329 | * function clears the fifos and flushes any packets that came in as rx was |
330 | * being enabled. |
331 | */ |
332 | void igc_rx_fifo_flush_base(struct igc_hw *hw) |
333 | { |
334 | u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; |
335 | int i, ms_wait; |
336 | |
337 | /* disable IPv6 options as per hardware errata */ |
338 | rfctl = rd32(IGC_RFCTL); |
339 | rfctl |= IGC_RFCTL_IPV6_EX_DIS; |
340 | wr32(IGC_RFCTL, rfctl); |
341 | |
342 | if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN)) |
343 | return; |
344 | |
345 | /* Disable all Rx queues */ |
346 | for (i = 0; i < 4; i++) { |
347 | rxdctl[i] = rd32(IGC_RXDCTL(i)); |
348 | wr32(IGC_RXDCTL(i), |
349 | rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE); |
350 | } |
351 | /* Poll all queues to verify they have shut down */ |
352 | for (ms_wait = 0; ms_wait < 10; ms_wait++) { |
353 | usleep_range(min: 1000, max: 2000); |
354 | rx_enabled = 0; |
355 | for (i = 0; i < 4; i++) |
356 | rx_enabled |= rd32(IGC_RXDCTL(i)); |
357 | if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE)) |
358 | break; |
359 | } |
360 | |
361 | if (ms_wait == 10) |
362 | hw_dbg("Queue disable timed out after 10ms\n" ); |
363 | |
364 | /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all |
365 | * incoming packets are rejected. Set enable and wait 2ms so that |
366 | * any packet that was coming in as RCTL.EN was set is flushed |
367 | */ |
368 | wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF); |
369 | |
370 | rlpml = rd32(IGC_RLPML); |
371 | wr32(IGC_RLPML, 0); |
372 | |
373 | rctl = rd32(IGC_RCTL); |
374 | temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP); |
375 | temp_rctl |= IGC_RCTL_LPE; |
376 | |
377 | wr32(IGC_RCTL, temp_rctl); |
378 | wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN); |
379 | wrfl(); |
380 | usleep_range(min: 2000, max: 3000); |
381 | |
382 | /* Enable Rx queues that were previously enabled and restore our |
383 | * previous state |
384 | */ |
385 | for (i = 0; i < 4; i++) |
386 | wr32(IGC_RXDCTL(i), rxdctl[i]); |
387 | wr32(IGC_RCTL, rctl); |
388 | wrfl(); |
389 | |
390 | wr32(IGC_RLPML, rlpml); |
391 | wr32(IGC_RFCTL, rfctl); |
392 | |
393 | /* Flush receive errors generated by workaround */ |
394 | rd32(IGC_ROC); |
395 | rd32(IGC_RNBC); |
396 | rd32(IGC_MPC); |
397 | } |
398 | |
399 | bool igc_is_device_id_i225(struct igc_hw *hw) |
400 | { |
401 | switch (hw->device_id) { |
402 | case IGC_DEV_ID_I225_LM: |
403 | case IGC_DEV_ID_I225_V: |
404 | case IGC_DEV_ID_I225_I: |
405 | case IGC_DEV_ID_I225_K: |
406 | case IGC_DEV_ID_I225_K2: |
407 | case IGC_DEV_ID_I225_LMVP: |
408 | case IGC_DEV_ID_I225_IT: |
409 | return true; |
410 | default: |
411 | return false; |
412 | } |
413 | } |
414 | |
415 | bool igc_is_device_id_i226(struct igc_hw *hw) |
416 | { |
417 | switch (hw->device_id) { |
418 | case IGC_DEV_ID_I226_LM: |
419 | case IGC_DEV_ID_I226_V: |
420 | case IGC_DEV_ID_I226_K: |
421 | case IGC_DEV_ID_I226_IT: |
422 | return true; |
423 | default: |
424 | return false; |
425 | } |
426 | } |
427 | |
428 | static struct igc_mac_operations igc_mac_ops_base = { |
429 | .init_hw = igc_init_hw_base, |
430 | .check_for_link = igc_check_for_copper_link, |
431 | .rar_set = igc_rar_set, |
432 | .read_mac_addr = igc_read_mac_addr, |
433 | .get_speed_and_duplex = igc_get_speed_and_duplex_copper, |
434 | }; |
435 | |
436 | static const struct igc_phy_operations igc_phy_ops_base = { |
437 | .acquire = igc_acquire_phy_base, |
438 | .release = igc_release_phy_base, |
439 | .reset = igc_phy_hw_reset, |
440 | .read_reg = igc_read_phy_reg_gpy, |
441 | .write_reg = igc_write_phy_reg_gpy, |
442 | }; |
443 | |
444 | const struct igc_info igc_base_info = { |
445 | .get_invariants = igc_get_invariants_base, |
446 | .mac_ops = &igc_mac_ops_base, |
447 | .phy_ops = &igc_phy_ops_base, |
448 | }; |
449 | |