net/ngbe: add HW initialization
[dpdk.git] / drivers / net / ngbe / base / ngbe_hw.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5
6 #include "ngbe_type.h"
7 #include "ngbe_eeprom.h"
8 #include "ngbe_mng.h"
9 #include "ngbe_hw.h"
10
11 /**
12  *  ngbe_init_hw - Generic hardware initialization
13  *  @hw: pointer to hardware structure
14  *
15  *  Initialize the hardware by resetting the hardware, filling the bus info
16  *  structure and media type, clears all on chip counters, initializes receive
17  *  address registers, multicast table, VLAN filter table, calls routine to set
18  *  up link and flow control settings, and leaves transmit and receive units
19  *  disabled and uninitialized
20  **/
21 s32 ngbe_init_hw(struct ngbe_hw *hw)
22 {
23         s32 status;
24
25         DEBUGFUNC("ngbe_init_hw");
26
27         /* Reset the hardware */
28         status = hw->mac.reset_hw(hw);
29
30         if (status != 0)
31                 DEBUGOUT("Failed to initialize HW, STATUS = %d\n", status);
32
33         return status;
34 }
35
36 static void
37 ngbe_reset_misc_em(struct ngbe_hw *hw)
38 {
39         int i;
40
41         wr32(hw, NGBE_ISBADDRL, hw->isb_dma & 0xFFFFFFFF);
42         wr32(hw, NGBE_ISBADDRH, hw->isb_dma >> 32);
43
44         /* receive packets that size > 2048 */
45         wr32m(hw, NGBE_MACRXCFG,
46                 NGBE_MACRXCFG_JUMBO, NGBE_MACRXCFG_JUMBO);
47
48         wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK,
49                 NGBE_FRMSZ_MAX(NGBE_FRAME_SIZE_DFT));
50
51         /* clear counters on read */
52         wr32m(hw, NGBE_MACCNTCTL,
53                 NGBE_MACCNTCTL_RC, NGBE_MACCNTCTL_RC);
54
55         wr32m(hw, NGBE_RXFCCFG,
56                 NGBE_RXFCCFG_FC, NGBE_RXFCCFG_FC);
57         wr32m(hw, NGBE_TXFCCFG,
58                 NGBE_TXFCCFG_FC, NGBE_TXFCCFG_FC);
59
60         wr32m(hw, NGBE_MACRXFLT,
61                 NGBE_MACRXFLT_PROMISC, NGBE_MACRXFLT_PROMISC);
62
63         wr32m(hw, NGBE_RSTSTAT,
64                 NGBE_RSTSTAT_TMRINIT_MASK, NGBE_RSTSTAT_TMRINIT(30));
65
66         /* errata 4: initialize mng flex tbl and wakeup flex tbl*/
67         wr32(hw, NGBE_MNGFLEXSEL, 0);
68         for (i = 0; i < 16; i++) {
69                 wr32(hw, NGBE_MNGFLEXDWL(i), 0);
70                 wr32(hw, NGBE_MNGFLEXDWH(i), 0);
71                 wr32(hw, NGBE_MNGFLEXMSK(i), 0);
72         }
73         wr32(hw, NGBE_LANFLEXSEL, 0);
74         for (i = 0; i < 16; i++) {
75                 wr32(hw, NGBE_LANFLEXDWL(i), 0);
76                 wr32(hw, NGBE_LANFLEXDWH(i), 0);
77                 wr32(hw, NGBE_LANFLEXMSK(i), 0);
78         }
79
80         /* set pause frame dst mac addr */
81         wr32(hw, NGBE_RXPBPFCDMACL, 0xC2000001);
82         wr32(hw, NGBE_RXPBPFCDMACH, 0x0180);
83
84         wr32(hw, NGBE_MDIOMODE, 0xF);
85
86         wr32m(hw, NGBE_GPIE, NGBE_GPIE_MSIX, NGBE_GPIE_MSIX);
87
88         if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
89                 (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
90                 /* gpio0 is used to power on/off control*/
91                 wr32(hw, NGBE_GPIODIR, NGBE_GPIODIR_DDR(1));
92                 wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
93         }
94
95         hw->mac.init_thermal_sensor_thresh(hw);
96
97         /* enable mac transmitter */
98         wr32m(hw, NGBE_MACTXCFG, NGBE_MACTXCFG_TE, NGBE_MACTXCFG_TE);
99
100         /* sellect GMII */
101         wr32m(hw, NGBE_MACTXCFG,
102                 NGBE_MACTXCFG_SPEED_MASK, NGBE_MACTXCFG_SPEED_1G);
103
104         for (i = 0; i < 4; i++)
105                 wr32m(hw, NGBE_IVAR(i), 0x80808080, 0);
106 }
107
108 /**
109  *  ngbe_reset_hw_em - Perform hardware reset
110  *  @hw: pointer to hardware structure
111  *
112  *  Resets the hardware by resetting the transmit and receive units, masks
113  *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
114  *  reset.
115  **/
116 s32 ngbe_reset_hw_em(struct ngbe_hw *hw)
117 {
118         s32 status;
119
120         DEBUGFUNC("ngbe_reset_hw_em");
121
122         /* Call adapter stop to disable tx/rx and clear interrupts */
123         status = hw->mac.stop_hw(hw);
124         if (status != 0)
125                 return status;
126
127         wr32(hw, NGBE_RST, NGBE_RST_LAN(hw->bus.lan_id));
128         ngbe_flush(hw);
129         msec_delay(50);
130
131         ngbe_reset_misc_em(hw);
132
133         msec_delay(50);
134
135         return status;
136 }
137
138 /**
139  *  ngbe_set_lan_id_multi_port - Set LAN id for PCIe multiple port devices
140  *  @hw: pointer to the HW structure
141  *
142  *  Determines the LAN function id by reading memory-mapped registers and swaps
143  *  the port value if requested, and set MAC instance for devices.
144  **/
145 void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw)
146 {
147         struct ngbe_bus_info *bus = &hw->bus;
148         u32 reg = 0;
149
150         DEBUGFUNC("ngbe_set_lan_id_multi_port");
151
152         reg = rd32(hw, NGBE_PORTSTAT);
153         bus->lan_id = NGBE_PORTSTAT_ID(reg);
154         bus->func = bus->lan_id;
155 }
156
157 /**
158  *  ngbe_stop_hw - Generic stop Tx/Rx units
159  *  @hw: pointer to hardware structure
160  *
161  *  Sets the adapter_stopped flag within ngbe_hw struct. Clears interrupts,
162  *  disables transmit and receive units. The adapter_stopped flag is used by
163  *  the shared code and drivers to determine if the adapter is in a stopped
164  *  state and should not touch the hardware.
165  **/
166 s32 ngbe_stop_hw(struct ngbe_hw *hw)
167 {
168         u32 reg_val;
169         u16 i;
170
171         DEBUGFUNC("ngbe_stop_hw");
172
173         /*
174          * Set the adapter_stopped flag so other driver functions stop touching
175          * the hardware
176          */
177         hw->adapter_stopped = true;
178
179         /* Disable the receive unit */
180         ngbe_disable_rx(hw);
181
182         /* Clear interrupt mask to stop interrupts from being generated */
183         wr32(hw, NGBE_IENMISC, 0);
184         wr32(hw, NGBE_IMS(0), NGBE_IMS_MASK);
185
186         /* Clear any pending interrupts, flush previous writes */
187         wr32(hw, NGBE_ICRMISC, NGBE_ICRMISC_MASK);
188         wr32(hw, NGBE_ICR(0), NGBE_ICR_MASK);
189
190         /* Disable the transmit unit.  Each queue must be disabled. */
191         for (i = 0; i < hw->mac.max_tx_queues; i++)
192                 wr32(hw, NGBE_TXCFG(i), NGBE_TXCFG_FLUSH);
193
194         /* Disable the receive unit by stopping each queue */
195         for (i = 0; i < hw->mac.max_rx_queues; i++) {
196                 reg_val = rd32(hw, NGBE_RXCFG(i));
197                 reg_val &= ~NGBE_RXCFG_ENA;
198                 wr32(hw, NGBE_RXCFG(i), reg_val);
199         }
200
201         /* flush all queues disables */
202         ngbe_flush(hw);
203         msec_delay(2);
204
205         return 0;
206 }
207
208 /**
209  *  ngbe_acquire_swfw_sync - Acquire SWFW semaphore
210  *  @hw: pointer to hardware structure
211  *  @mask: Mask to specify which semaphore to acquire
212  *
213  *  Acquires the SWFW semaphore through the MNGSEM register for the specified
214  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
215  **/
216 s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask)
217 {
218         u32 mngsem = 0;
219         u32 swmask = NGBE_MNGSEM_SW(mask);
220         u32 fwmask = NGBE_MNGSEM_FW(mask);
221         u32 timeout = 200;
222         u32 i;
223
224         DEBUGFUNC("ngbe_acquire_swfw_sync");
225
226         for (i = 0; i < timeout; i++) {
227                 /*
228                  * SW NVM semaphore bit is used for access to all
229                  * SW_FW_SYNC bits (not just NVM)
230                  */
231                 if (ngbe_get_eeprom_semaphore(hw))
232                         return NGBE_ERR_SWFW_SYNC;
233
234                 mngsem = rd32(hw, NGBE_MNGSEM);
235                 if (mngsem & (fwmask | swmask)) {
236                         /* Resource is currently in use by FW or SW */
237                         ngbe_release_eeprom_semaphore(hw);
238                         msec_delay(5);
239                 } else {
240                         mngsem |= swmask;
241                         wr32(hw, NGBE_MNGSEM, mngsem);
242                         ngbe_release_eeprom_semaphore(hw);
243                         return 0;
244                 }
245         }
246
247         /* If time expired clear the bits holding the lock and retry */
248         if (mngsem & (fwmask | swmask))
249                 ngbe_release_swfw_sync(hw, mngsem & (fwmask | swmask));
250
251         msec_delay(5);
252         return NGBE_ERR_SWFW_SYNC;
253 }
254
255 /**
256  *  ngbe_release_swfw_sync - Release SWFW semaphore
257  *  @hw: pointer to hardware structure
258  *  @mask: Mask to specify which semaphore to release
259  *
260  *  Releases the SWFW semaphore through the MNGSEM register for the specified
261  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
262  **/
263 void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask)
264 {
265         u32 mngsem;
266         u32 swmask = mask;
267
268         DEBUGFUNC("ngbe_release_swfw_sync");
269
270         ngbe_get_eeprom_semaphore(hw);
271
272         mngsem = rd32(hw, NGBE_MNGSEM);
273         mngsem &= ~swmask;
274         wr32(hw, NGBE_MNGSEM, mngsem);
275
276         ngbe_release_eeprom_semaphore(hw);
277 }
278
279 /**
280  *  ngbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds
281  *  @hw: pointer to hardware structure
282  *
283  *  Inits the thermal sensor thresholds according to the NVM map
284  *  and save off the threshold and location values into mac.thermal_sensor_data
285  **/
286 s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw)
287 {
288         struct ngbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
289
290         DEBUGFUNC("ngbe_init_thermal_sensor_thresh");
291
292         memset(data, 0, sizeof(struct ngbe_thermal_sensor_data));
293
294         if (hw->bus.lan_id != 0)
295                 return NGBE_NOT_IMPLEMENTED;
296
297         wr32(hw, NGBE_TSINTR,
298                 NGBE_TSINTR_AEN | NGBE_TSINTR_DEN);
299         wr32(hw, NGBE_TSEN, NGBE_TSEN_ENA);
300
301
302         data->sensor[0].alarm_thresh = 115;
303         wr32(hw, NGBE_TSATHRE, 0x344);
304         data->sensor[0].dalarm_thresh = 110;
305         wr32(hw, NGBE_TSDTHRE, 0x330);
306
307         return 0;
308 }
309
310 void ngbe_disable_rx(struct ngbe_hw *hw)
311 {
312         u32 pfdtxgswc;
313
314         pfdtxgswc = rd32(hw, NGBE_PSRCTL);
315         if (pfdtxgswc & NGBE_PSRCTL_LBENA) {
316                 pfdtxgswc &= ~NGBE_PSRCTL_LBENA;
317                 wr32(hw, NGBE_PSRCTL, pfdtxgswc);
318                 hw->mac.set_lben = true;
319         } else {
320                 hw->mac.set_lben = false;
321         }
322
323         wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, 0);
324         wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0);
325 }
326
327 /**
328  *  ngbe_set_mac_type - Sets MAC type
329  *  @hw: pointer to the HW structure
330  *
331  *  This function sets the mac type of the adapter based on the
332  *  vendor ID and device ID stored in the hw structure.
333  **/
334 s32 ngbe_set_mac_type(struct ngbe_hw *hw)
335 {
336         s32 err = 0;
337
338         DEBUGFUNC("ngbe_set_mac_type");
339
340         if (hw->vendor_id != PCI_VENDOR_ID_WANGXUN) {
341                 DEBUGOUT("Unsupported vendor id: %x", hw->vendor_id);
342                 return NGBE_ERR_DEVICE_NOT_SUPPORTED;
343         }
344
345         switch (hw->sub_device_id) {
346         case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
347         case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
348                 hw->phy.media_type = ngbe_media_type_copper;
349                 hw->mac.type = ngbe_mac_em;
350                 break;
351         case NGBE_SUB_DEV_ID_EM_MVL_SFP:
352         case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
353                 hw->phy.media_type = ngbe_media_type_fiber;
354                 hw->mac.type = ngbe_mac_em;
355                 break;
356         case NGBE_SUB_DEV_ID_EM_VF:
357                 hw->phy.media_type = ngbe_media_type_virtual;
358                 hw->mac.type = ngbe_mac_em_vf;
359                 break;
360         default:
361                 err = NGBE_ERR_DEVICE_NOT_SUPPORTED;
362                 hw->phy.media_type = ngbe_media_type_unknown;
363                 hw->mac.type = ngbe_mac_unknown;
364                 DEBUGOUT("Unsupported device id: %x", hw->device_id);
365                 break;
366         }
367
368         DEBUGOUT("found mac: %d media: %d, returns: %d\n",
369                   hw->mac.type, hw->phy.media_type, err);
370         return err;
371 }
372
373 void ngbe_map_device_id(struct ngbe_hw *hw)
374 {
375         u16 oem = hw->sub_system_id & NGBE_OEM_MASK;
376         u16 internal = hw->sub_system_id & NGBE_INTERNAL_MASK;
377         hw->is_pf = true;
378
379         /* move subsystem_device_id to device_id */
380         switch (hw->device_id) {
381         case NGBE_DEV_ID_EM_WX1860AL_W_VF:
382         case NGBE_DEV_ID_EM_WX1860A2_VF:
383         case NGBE_DEV_ID_EM_WX1860A2S_VF:
384         case NGBE_DEV_ID_EM_WX1860A4_VF:
385         case NGBE_DEV_ID_EM_WX1860A4S_VF:
386         case NGBE_DEV_ID_EM_WX1860AL2_VF:
387         case NGBE_DEV_ID_EM_WX1860AL2S_VF:
388         case NGBE_DEV_ID_EM_WX1860AL4_VF:
389         case NGBE_DEV_ID_EM_WX1860AL4S_VF:
390         case NGBE_DEV_ID_EM_WX1860NCSI_VF:
391         case NGBE_DEV_ID_EM_WX1860A1_VF:
392         case NGBE_DEV_ID_EM_WX1860A1L_VF:
393                 hw->device_id = NGBE_DEV_ID_EM_VF;
394                 hw->sub_device_id = NGBE_SUB_DEV_ID_EM_VF;
395                 hw->is_pf = false;
396                 break;
397         case NGBE_DEV_ID_EM_WX1860AL_W:
398         case NGBE_DEV_ID_EM_WX1860A2:
399         case NGBE_DEV_ID_EM_WX1860A2S:
400         case NGBE_DEV_ID_EM_WX1860A4:
401         case NGBE_DEV_ID_EM_WX1860A4S:
402         case NGBE_DEV_ID_EM_WX1860AL2:
403         case NGBE_DEV_ID_EM_WX1860AL2S:
404         case NGBE_DEV_ID_EM_WX1860AL4:
405         case NGBE_DEV_ID_EM_WX1860AL4S:
406         case NGBE_DEV_ID_EM_WX1860NCSI:
407         case NGBE_DEV_ID_EM_WX1860A1:
408         case NGBE_DEV_ID_EM_WX1860A1L:
409                 hw->device_id = NGBE_DEV_ID_EM;
410                 if (oem == NGBE_LY_M88E1512_SFP ||
411                                 internal == NGBE_INTERNAL_SFP)
412                         hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_SFP;
413                 else if (hw->sub_system_id == NGBE_SUB_DEV_ID_EM_M88E1512_RJ45)
414                         hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_RGMII;
415                 else if (oem == NGBE_YT8521S_SFP ||
416                                 oem == NGBE_LY_YT8521S_SFP)
417                         hw->sub_device_id = NGBE_SUB_DEV_ID_EM_YT8521S_SFP;
418                 else
419                         hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_SGMII;
420                 break;
421         default:
422                 break;
423         }
424 }
425
426 /**
427  *  ngbe_init_ops_pf - Inits func ptrs and MAC type
428  *  @hw: pointer to hardware structure
429  *
430  *  Initialize the function pointers and assign the MAC type.
431  *  Does not touch the hardware.
432  **/
433 s32 ngbe_init_ops_pf(struct ngbe_hw *hw)
434 {
435         struct ngbe_bus_info *bus = &hw->bus;
436         struct ngbe_mac_info *mac = &hw->mac;
437         struct ngbe_rom_info *rom = &hw->rom;
438
439         DEBUGFUNC("ngbe_init_ops_pf");
440
441         /* BUS */
442         bus->set_lan_id = ngbe_set_lan_id_multi_port;
443
444         /* MAC */
445         mac->init_hw = ngbe_init_hw;
446         mac->reset_hw = ngbe_reset_hw_em;
447         mac->stop_hw = ngbe_stop_hw;
448         mac->acquire_swfw_sync = ngbe_acquire_swfw_sync;
449         mac->release_swfw_sync = ngbe_release_swfw_sync;
450
451         /* Manageability interface */
452         mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh;
453
454         /* EEPROM */
455         rom->init_params = ngbe_init_eeprom_params;
456         rom->validate_checksum = ngbe_validate_eeprom_checksum_em;
457
458         mac->max_rx_queues      = NGBE_EM_MAX_RX_QUEUES;
459         mac->max_tx_queues      = NGBE_EM_MAX_TX_QUEUES;
460
461         return 0;
462 }
463
464 /**
465  *  ngbe_init_shared_code - Initialize the shared code
466  *  @hw: pointer to hardware structure
467  *
468  *  This will assign function pointers and assign the MAC type and PHY code.
469  *  Does not touch the hardware. This function must be called prior to any
470  *  other function in the shared code. The ngbe_hw structure should be
471  *  memset to 0 prior to calling this function.  The following fields in
472  *  hw structure should be filled in prior to calling this function:
473  *  hw_addr, back, device_id, vendor_id, subsystem_device_id
474  **/
475 s32 ngbe_init_shared_code(struct ngbe_hw *hw)
476 {
477         s32 status = 0;
478
479         DEBUGFUNC("ngbe_init_shared_code");
480
481         /*
482          * Set the mac type
483          */
484         ngbe_set_mac_type(hw);
485
486         ngbe_init_ops_dummy(hw);
487         switch (hw->mac.type) {
488         case ngbe_mac_em:
489                 ngbe_init_ops_pf(hw);
490                 break;
491         default:
492                 status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
493                 break;
494         }
495
496         hw->bus.set_lan_id(hw);
497
498         return status;
499 }
500