1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3 * Copyright(c) 2010-2017 Intel Corporation
8 #include "ngbe_eeprom.h"
13 * ngbe_init_hw - Generic hardware initialization
14 * @hw: pointer to hardware structure
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
22 s32 ngbe_init_hw(struct ngbe_hw *hw)
26 DEBUGFUNC("ngbe_init_hw");
28 /* Reset the hardware */
29 status = hw->mac.reset_hw(hw);
32 DEBUGOUT("Failed to initialize HW, STATUS = %d\n", status);
38 ngbe_reset_misc_em(struct ngbe_hw *hw)
42 wr32(hw, NGBE_ISBADDRL, hw->isb_dma & 0xFFFFFFFF);
43 wr32(hw, NGBE_ISBADDRH, hw->isb_dma >> 32);
45 /* receive packets that size > 2048 */
46 wr32m(hw, NGBE_MACRXCFG,
47 NGBE_MACRXCFG_JUMBO, NGBE_MACRXCFG_JUMBO);
49 wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK,
50 NGBE_FRMSZ_MAX(NGBE_FRAME_SIZE_DFT));
52 /* clear counters on read */
53 wr32m(hw, NGBE_MACCNTCTL,
54 NGBE_MACCNTCTL_RC, NGBE_MACCNTCTL_RC);
56 wr32m(hw, NGBE_RXFCCFG,
57 NGBE_RXFCCFG_FC, NGBE_RXFCCFG_FC);
58 wr32m(hw, NGBE_TXFCCFG,
59 NGBE_TXFCCFG_FC, NGBE_TXFCCFG_FC);
61 wr32m(hw, NGBE_MACRXFLT,
62 NGBE_MACRXFLT_PROMISC, NGBE_MACRXFLT_PROMISC);
64 wr32m(hw, NGBE_RSTSTAT,
65 NGBE_RSTSTAT_TMRINIT_MASK, NGBE_RSTSTAT_TMRINIT(30));
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);
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);
81 /* set pause frame dst mac addr */
82 wr32(hw, NGBE_RXPBPFCDMACL, 0xC2000001);
83 wr32(hw, NGBE_RXPBPFCDMACH, 0x0180);
85 wr32(hw, NGBE_MDIOMODE, 0xF);
87 wr32m(hw, NGBE_GPIE, NGBE_GPIE_MSIX, NGBE_GPIE_MSIX);
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);
96 hw->mac.init_thermal_sensor_thresh(hw);
98 /* enable mac transmitter */
99 wr32m(hw, NGBE_MACTXCFG, NGBE_MACTXCFG_TE, NGBE_MACTXCFG_TE);
102 wr32m(hw, NGBE_MACTXCFG,
103 NGBE_MACTXCFG_SPEED_MASK, NGBE_MACTXCFG_SPEED_1G);
105 for (i = 0; i < 4; i++)
106 wr32m(hw, NGBE_IVAR(i), 0x80808080, 0);
110 * ngbe_reset_hw_em - Perform hardware reset
111 * @hw: pointer to hardware structure
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)
117 s32 ngbe_reset_hw_em(struct ngbe_hw *hw)
121 DEBUGFUNC("ngbe_reset_hw_em");
123 /* Call adapter stop to disable tx/rx and clear interrupts */
124 status = hw->mac.stop_hw(hw);
128 /* Identify PHY and related function pointers */
129 status = ngbe_init_phy(hw);
134 if (!hw->phy.reset_disable)
135 hw->phy.reset_hw(hw);
137 wr32(hw, NGBE_RST, NGBE_RST_LAN(hw->bus.lan_id));
141 ngbe_reset_misc_em(hw);
149 * ngbe_set_lan_id_multi_port - Set LAN id for PCIe multiple port devices
150 * @hw: pointer to the HW structure
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.
155 void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw)
157 struct ngbe_bus_info *bus = &hw->bus;
160 DEBUGFUNC("ngbe_set_lan_id_multi_port");
162 reg = rd32(hw, NGBE_PORTSTAT);
163 bus->lan_id = NGBE_PORTSTAT_ID(reg);
164 bus->func = bus->lan_id;
168 * ngbe_stop_hw - Generic stop Tx/Rx units
169 * @hw: pointer to hardware structure
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.
176 s32 ngbe_stop_hw(struct ngbe_hw *hw)
181 DEBUGFUNC("ngbe_stop_hw");
184 * Set the adapter_stopped flag so other driver functions stop touching
187 hw->adapter_stopped = true;
189 /* Disable the receive unit */
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);
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);
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);
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);
211 /* flush all queues disables */
219 * ngbe_acquire_swfw_sync - Acquire SWFW semaphore
220 * @hw: pointer to hardware structure
221 * @mask: Mask to specify which semaphore to acquire
223 * Acquires the SWFW semaphore through the MNGSEM register for the specified
224 * function (CSR, PHY0, PHY1, EEPROM, Flash)
226 s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask)
229 u32 swmask = NGBE_MNGSEM_SW(mask);
230 u32 fwmask = NGBE_MNGSEM_FW(mask);
234 DEBUGFUNC("ngbe_acquire_swfw_sync");
236 for (i = 0; i < timeout; i++) {
238 * SW NVM semaphore bit is used for access to all
239 * SW_FW_SYNC bits (not just NVM)
241 if (ngbe_get_eeprom_semaphore(hw))
242 return NGBE_ERR_SWFW_SYNC;
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);
251 wr32(hw, NGBE_MNGSEM, mngsem);
252 ngbe_release_eeprom_semaphore(hw);
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));
262 return NGBE_ERR_SWFW_SYNC;
266 * ngbe_release_swfw_sync - Release SWFW semaphore
267 * @hw: pointer to hardware structure
268 * @mask: Mask to specify which semaphore to release
270 * Releases the SWFW semaphore through the MNGSEM register for the specified
271 * function (CSR, PHY0, PHY1, EEPROM, Flash)
273 void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask)
278 DEBUGFUNC("ngbe_release_swfw_sync");
280 ngbe_get_eeprom_semaphore(hw);
282 mngsem = rd32(hw, NGBE_MNGSEM);
284 wr32(hw, NGBE_MNGSEM, mngsem);
286 ngbe_release_eeprom_semaphore(hw);
290 * ngbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds
291 * @hw: pointer to hardware structure
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
296 s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw)
298 struct ngbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
300 DEBUGFUNC("ngbe_init_thermal_sensor_thresh");
302 memset(data, 0, sizeof(struct ngbe_thermal_sensor_data));
304 if (hw->bus.lan_id != 0)
305 return NGBE_NOT_IMPLEMENTED;
307 wr32(hw, NGBE_TSINTR,
308 NGBE_TSINTR_AEN | NGBE_TSINTR_DEN);
309 wr32(hw, NGBE_TSEN, NGBE_TSEN_ENA);
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);
320 s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw)
325 DEBUGFUNC("ngbe_mac_check_overtemp");
327 /* Check that the LASI temp alarm status was triggered */
328 ts_state = rd32(hw, NGBE_TSALM);
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;
338 void ngbe_disable_rx(struct ngbe_hw *hw)
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;
348 hw->mac.set_lben = false;
351 wr32m(hw, NGBE_PBRXCTL, NGBE_PBRXCTL_ENA, 0);
352 wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_ENA, 0);
356 * ngbe_set_mac_type - Sets MAC type
357 * @hw: pointer to the HW structure
359 * This function sets the mac type of the adapter based on the
360 * vendor ID and device ID stored in the hw structure.
362 s32 ngbe_set_mac_type(struct ngbe_hw *hw)
366 DEBUGFUNC("ngbe_set_mac_type");
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;
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;
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;
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;
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);
396 DEBUGOUT("found mac: %d media: %d, returns: %d\n",
397 hw->mac.type, hw->phy.media_type, err);
401 void ngbe_map_device_id(struct ngbe_hw *hw)
403 u16 oem = hw->sub_system_id & NGBE_OEM_MASK;
404 u16 internal = hw->sub_system_id & NGBE_INTERNAL_MASK;
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;
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;
447 hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_SGMII;
455 * ngbe_init_ops_pf - Inits func ptrs and MAC type
456 * @hw: pointer to hardware structure
458 * Initialize the function pointers and assign the MAC type.
459 * Does not touch the hardware.
461 s32 ngbe_init_ops_pf(struct ngbe_hw *hw)
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;
468 DEBUGFUNC("ngbe_init_ops_pf");
471 bus->set_lan_id = ngbe_set_lan_id_multi_port;
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;
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;
488 /* Manageability interface */
489 mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh;
490 mac->check_overtemp = ngbe_mac_check_overtemp;
493 rom->init_params = ngbe_init_eeprom_params;
494 rom->validate_checksum = ngbe_validate_eeprom_checksum_em;
496 mac->max_rx_queues = NGBE_EM_MAX_RX_QUEUES;
497 mac->max_tx_queues = NGBE_EM_MAX_TX_QUEUES;
503 * ngbe_init_shared_code - Initialize the shared code
504 * @hw: pointer to hardware structure
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
513 s32 ngbe_init_shared_code(struct ngbe_hw *hw)
517 DEBUGFUNC("ngbe_init_shared_code");
522 ngbe_set_mac_type(hw);
524 ngbe_init_ops_dummy(hw);
525 switch (hw->mac.type) {
527 ngbe_init_ops_pf(hw);
530 status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
534 hw->bus.set_lan_id(hw);