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