1*0f9e9ec2Sjsg /* $OpenBSD: ixgbe_82598.c,v 1.21 2024/05/13 01:15:51 jsg Exp $ */
2ad013249Sreyk
3ad013249Sreyk /******************************************************************************
4d7a8f955Sjmatthew SPDX-License-Identifier: BSD-3-Clause
5ad013249Sreyk
6d7a8f955Sjmatthew Copyright (c) 2001-2017, Intel Corporation
7ad013249Sreyk All rights reserved.
8ad013249Sreyk
9ad013249Sreyk Redistribution and use in source and binary forms, with or without
10ad013249Sreyk modification, are permitted provided that the following conditions are met:
11ad013249Sreyk
12ad013249Sreyk 1. Redistributions of source code must retain the above copyright notice,
13ad013249Sreyk this list of conditions and the following disclaimer.
14ad013249Sreyk
15ad013249Sreyk 2. Redistributions in binary form must reproduce the above copyright
16ad013249Sreyk notice, this list of conditions and the following disclaimer in the
17ad013249Sreyk documentation and/or other materials provided with the distribution.
18ad013249Sreyk
19ad013249Sreyk 3. Neither the name of the Intel Corporation nor the names of its
20ad013249Sreyk contributors may be used to endorse or promote products derived from
21ad013249Sreyk this software without specific prior written permission.
22ad013249Sreyk
23ad013249Sreyk THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24ad013249Sreyk AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ad013249Sreyk IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ad013249Sreyk ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27ad013249Sreyk LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28ad013249Sreyk CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29ad013249Sreyk SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30ad013249Sreyk INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31ad013249Sreyk CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32ad013249Sreyk ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33ad013249Sreyk POSSIBILITY OF SUCH DAMAGE.
34ad013249Sreyk
35ad013249Sreyk ******************************************************************************/
36d7a8f955Sjmatthew /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82598.c 331224 2018-03-19 20:55:05Z erj $*/
37d7a8f955Sjmatthew
38ad013249Sreyk
39ad013249Sreyk #include <dev/pci/ixgbe.h>
40ad013249Sreyk #include <dev/pci/ixgbe_type.h>
41ad013249Sreyk
429e435848Smikeb #define IXGBE_82598_MAX_TX_QUEUES 32
439e435848Smikeb #define IXGBE_82598_MAX_RX_QUEUES 64
449e435848Smikeb #define IXGBE_82598_RAR_ENTRIES 16
459e435848Smikeb #define IXGBE_82598_MC_TBL_SIZE 128
469e435848Smikeb #define IXGBE_82598_VFT_TBL_SIZE 128
479e435848Smikeb #define IXGBE_82598_RX_PB_SIZE 512
489e435848Smikeb
4935befa56Sreyk int32_t ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
50ad013249Sreyk ixgbe_link_speed *speed,
5111efaf7fSmikeb bool *autoneg);
52ad013249Sreyk enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw);
5311efaf7fSmikeb int32_t ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
543201f924Sjsg int32_t ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
5511efaf7fSmikeb bool autoneg_wait_to_complete);
569feba5bbSclaudio int32_t ixgbe_validate_link_ready(struct ixgbe_hw *hw);
5735befa56Sreyk int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
5811efaf7fSmikeb ixgbe_link_speed *speed, bool *link_up,
5911efaf7fSmikeb bool link_up_wait_to_complete);
603201f924Sjsg int32_t ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
61ad013249Sreyk ixgbe_link_speed speed,
6211efaf7fSmikeb bool autoneg_wait_to_complete);
633201f924Sjsg int32_t ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
64ad013249Sreyk ixgbe_link_speed speed,
6511efaf7fSmikeb bool autoneg_wait_to_complete);
6635befa56Sreyk int32_t ixgbe_reset_hw_82598(struct ixgbe_hw *hw);
67d7a8f955Sjmatthew
683201f924Sjsg int32_t ixgbe_start_hw_82598(struct ixgbe_hw *hw);
6935befa56Sreyk int32_t ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq);
703201f924Sjsg int32_t ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq);
713201f924Sjsg int32_t ixgbe_set_vfta_82598(struct ixgbe_hw *hw, uint32_t vlan,
72d7a8f955Sjmatthew uint32_t vind, bool vlan_on, bool vlvf_bypass);
733201f924Sjsg int32_t ixgbe_clear_vfta_82598(struct ixgbe_hw *hw);
743201f924Sjsg int32_t ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, uint32_t reg, uint8_t *val);
753201f924Sjsg int32_t ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, uint32_t reg, uint8_t val);
7611efaf7fSmikeb int32_t ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, uint8_t dev_addr,
7711efaf7fSmikeb uint8_t byte_offset, uint8_t *eeprom_data);
783201f924Sjsg int32_t ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, uint8_t byte_offset,
793201f924Sjsg uint8_t *eeprom_data);
80d7a8f955Sjmatthew uint64_t ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
813201f924Sjsg int32_t ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
823201f924Sjsg void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
833201f924Sjsg void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
8435e02db6Smikeb int32_t ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, uint32_t regval);
853201f924Sjsg
863201f924Sjsg /**
873201f924Sjsg * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
883201f924Sjsg * @hw: pointer to the HW structure
893201f924Sjsg *
903201f924Sjsg * The defaults for 82598 should be in the range of 50us to 50ms,
913201f924Sjsg * however the hardware default for these parts is 500us to 1ms which is less
923201f924Sjsg * than the 10ms recommended by the pci-e spec. To address this we need to
933201f924Sjsg * increase the value to either 10ms to 250ms for capability version 1 config,
943201f924Sjsg * or 16ms to 55ms for version 2.
953201f924Sjsg **/
ixgbe_set_pcie_completion_timeout(struct ixgbe_hw * hw)963201f924Sjsg void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
973201f924Sjsg {
983201f924Sjsg uint32_t gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
993201f924Sjsg uint16_t pcie_devctl2;
1003201f924Sjsg
1013201f924Sjsg /* only take action if timeout value is defaulted to 0 */
1023201f924Sjsg if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
1033201f924Sjsg goto out;
1043201f924Sjsg
1053201f924Sjsg /*
1064b1a56afSjsg * if capabilities version is type 1 we can write the
1073201f924Sjsg * timeout of 10ms to 250ms through the GCR register
1083201f924Sjsg */
1093201f924Sjsg if (!(gcr & IXGBE_GCR_CAP_VER2)) {
1103201f924Sjsg gcr |= IXGBE_GCR_CMPL_TMOUT_10ms;
1113201f924Sjsg goto out;
1123201f924Sjsg }
1133201f924Sjsg
1143201f924Sjsg /*
1153201f924Sjsg * for version 2 capabilities we need to write the config space
1163201f924Sjsg * directly in order to set the completion timeout value for
1173201f924Sjsg * 16ms to 55ms
1183201f924Sjsg */
1193201f924Sjsg pcie_devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2);
1203201f924Sjsg pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
1213201f924Sjsg IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
1223201f924Sjsg out:
1233201f924Sjsg /* disable completion timeout resend */
1243201f924Sjsg gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND;
1253201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
1263201f924Sjsg }
1273201f924Sjsg
1283201f924Sjsg /**
129ad013249Sreyk * ixgbe_init_ops_82598 - Inits func ptrs and MAC type
130ad013249Sreyk * @hw: pointer to hardware structure
131ad013249Sreyk *
132ad013249Sreyk * Initialize the function pointers and assign the MAC type for 82598.
133ad013249Sreyk * Does not touch the hardware.
134ad013249Sreyk **/
ixgbe_init_ops_82598(struct ixgbe_hw * hw)13535befa56Sreyk int32_t ixgbe_init_ops_82598(struct ixgbe_hw *hw)
136ad013249Sreyk {
137ad013249Sreyk struct ixgbe_mac_info *mac = &hw->mac;
138ad013249Sreyk struct ixgbe_phy_info *phy = &hw->phy;
13935befa56Sreyk int32_t ret_val;
140ad013249Sreyk
14111efaf7fSmikeb DEBUGFUNC("ixgbe_init_ops_82598");
14211efaf7fSmikeb
143ad013249Sreyk ret_val = ixgbe_init_phy_ops_generic(hw);
144ad013249Sreyk ret_val = ixgbe_init_ops_generic(hw);
145ad013249Sreyk
1463201f924Sjsg /* PHY */
1479e435848Smikeb phy->ops.init = ixgbe_init_phy_ops_82598;
148ad013249Sreyk
1493201f924Sjsg /* MAC */
1509e435848Smikeb mac->ops.start_hw = ixgbe_start_hw_82598;
1519e435848Smikeb mac->ops.reset_hw = ixgbe_reset_hw_82598;
1529e435848Smikeb mac->ops.get_media_type = ixgbe_get_media_type_82598;
1533201f924Sjsg mac->ops.get_supported_physical_layer =
1549e435848Smikeb ixgbe_get_supported_physical_layer_82598;
1559e435848Smikeb mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82598;
1569e435848Smikeb mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82598;
1579e435848Smikeb mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie_82598;
15835e02db6Smikeb mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82598;
159ad013249Sreyk
160ad013249Sreyk /* RAR, Multicast, VLAN */
1619e435848Smikeb mac->ops.set_vmdq = ixgbe_set_vmdq_82598;
1629e435848Smikeb mac->ops.clear_vmdq = ixgbe_clear_vmdq_82598;
1639e435848Smikeb mac->ops.set_vfta = ixgbe_set_vfta_82598;
164d7a8f955Sjmatthew mac->ops.set_vlvf = NULL;
1659e435848Smikeb mac->ops.clear_vfta = ixgbe_clear_vfta_82598;
166ad013249Sreyk
167ad013249Sreyk /* Flow Control */
1689e435848Smikeb mac->ops.fc_enable = ixgbe_fc_enable_82598;
169ad013249Sreyk
1709e435848Smikeb mac->mcft_size = IXGBE_82598_MC_TBL_SIZE;
1719e435848Smikeb mac->vft_size = IXGBE_82598_VFT_TBL_SIZE;
1729e435848Smikeb mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
1739e435848Smikeb mac->rx_pb_size = IXGBE_82598_RX_PB_SIZE;
1749e435848Smikeb mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
17535e02db6Smikeb mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
176d7a8f955Sjmatthew mac->max_msix_vectors = 0 /*ixgbe_get_pcie_msix_count_generic(hw)*/;
177ad013249Sreyk
1783201f924Sjsg /* SFP+ Module */
1799e435848Smikeb phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_82598;
1803201f924Sjsg
1813201f924Sjsg /* Link */
1829e435848Smikeb mac->ops.check_link = ixgbe_check_mac_link_82598;
1839e435848Smikeb mac->ops.setup_link = ixgbe_setup_mac_link_82598;
1849feba5bbSclaudio mac->ops.flap_tx_laser = NULL;
1859e435848Smikeb mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82598;
1863201f924Sjsg
1873201f924Sjsg return ret_val;
1883201f924Sjsg }
1893201f924Sjsg
1903201f924Sjsg /**
1913201f924Sjsg * ixgbe_init_phy_ops_82598 - PHY/SFP specific init
1923201f924Sjsg * @hw: pointer to hardware structure
1933201f924Sjsg *
1943201f924Sjsg * Initialize any function pointers that were not able to be
1953201f924Sjsg * set during init_shared_code because the PHY/SFP type was
1963201f924Sjsg * not known. Perform the SFP init if necessary.
1973201f924Sjsg *
1983201f924Sjsg **/
ixgbe_init_phy_ops_82598(struct ixgbe_hw * hw)1993201f924Sjsg int32_t ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
2003201f924Sjsg {
2013201f924Sjsg struct ixgbe_mac_info *mac = &hw->mac;
2023201f924Sjsg struct ixgbe_phy_info *phy = &hw->phy;
2033201f924Sjsg int32_t ret_val = IXGBE_SUCCESS;
2043201f924Sjsg uint16_t list_offset, data_offset;
2053201f924Sjsg
20611efaf7fSmikeb DEBUGFUNC("ixgbe_init_phy_ops_82598");
20711efaf7fSmikeb
2083201f924Sjsg /* Identify the PHY */
2093201f924Sjsg phy->ops.identify(hw);
2103201f924Sjsg
2113201f924Sjsg /* Overwrite the link function pointers if copper PHY */
2123201f924Sjsg if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
2139e435848Smikeb mac->ops.setup_link = ixgbe_setup_copper_link_82598;
2143201f924Sjsg mac->ops.get_link_capabilities =
2159e435848Smikeb ixgbe_get_copper_link_capabilities_generic;
2163201f924Sjsg }
2173201f924Sjsg
2183201f924Sjsg switch (hw->phy.type) {
2193201f924Sjsg case ixgbe_phy_tn:
2209e435848Smikeb phy->ops.setup_link = ixgbe_setup_phy_link_tnx;
2219e435848Smikeb phy->ops.check_link = ixgbe_check_phy_link_tnx;
2223201f924Sjsg phy->ops.get_firmware_version =
2239e435848Smikeb ixgbe_get_phy_firmware_version_tnx;
2243201f924Sjsg break;
2253201f924Sjsg case ixgbe_phy_nl:
2269e435848Smikeb phy->ops.reset = ixgbe_reset_phy_nl;
2273201f924Sjsg
2283201f924Sjsg /* Call SFP+ identify routine to get the SFP+ module type */
2293201f924Sjsg ret_val = phy->ops.identify_sfp(hw);
2303201f924Sjsg if (ret_val != IXGBE_SUCCESS)
2313201f924Sjsg goto out;
2323201f924Sjsg else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
2333201f924Sjsg ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
2343201f924Sjsg goto out;
2353201f924Sjsg }
2363201f924Sjsg
2373201f924Sjsg /* Check to see if SFP+ module is supported */
2383201f924Sjsg ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
2393201f924Sjsg &list_offset,
2403201f924Sjsg &data_offset);
2413201f924Sjsg if (ret_val != IXGBE_SUCCESS) {
2423201f924Sjsg ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
2433201f924Sjsg goto out;
2443201f924Sjsg }
2453201f924Sjsg break;
2463201f924Sjsg default:
2473201f924Sjsg break;
2483201f924Sjsg }
2493201f924Sjsg
2503201f924Sjsg out:
2513201f924Sjsg return ret_val;
2523201f924Sjsg }
2533201f924Sjsg
2543201f924Sjsg /**
2553201f924Sjsg * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx
2563201f924Sjsg * @hw: pointer to hardware structure
2573201f924Sjsg *
2583201f924Sjsg * Starts the hardware using the generic start_hw function.
259d7a8f955Sjmatthew * Disables relaxed ordering Then set pcie completion timeout
26011efaf7fSmikeb *
2613201f924Sjsg **/
ixgbe_start_hw_82598(struct ixgbe_hw * hw)2623201f924Sjsg int32_t ixgbe_start_hw_82598(struct ixgbe_hw *hw)
2633201f924Sjsg {
2643201f924Sjsg uint32_t regval;
2653201f924Sjsg uint32_t i;
2663201f924Sjsg int32_t ret_val = IXGBE_SUCCESS;
2673201f924Sjsg
26811efaf7fSmikeb DEBUGFUNC("ixgbe_start_hw_82598");
26911efaf7fSmikeb
2703201f924Sjsg ret_val = ixgbe_start_hw_generic(hw);
27135e02db6Smikeb if (ret_val)
27235e02db6Smikeb return ret_val;
2733201f924Sjsg
2743201f924Sjsg /* Disable relaxed ordering */
2753201f924Sjsg for (i = 0; ((i < hw->mac.max_tx_queues) &&
2763201f924Sjsg (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
2773201f924Sjsg regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
27811efaf7fSmikeb regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
2793201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval);
2803201f924Sjsg }
2813201f924Sjsg
2823201f924Sjsg for (i = 0; ((i < hw->mac.max_rx_queues) &&
2833201f924Sjsg (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
2843201f924Sjsg regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
28511efaf7fSmikeb regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN |
28611efaf7fSmikeb IXGBE_DCA_RXCTRL_HEAD_WRO_EN);
2873201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
2883201f924Sjsg }
2893201f924Sjsg
2903201f924Sjsg /* set the completion timeout for interface */
2913201f924Sjsg ixgbe_set_pcie_completion_timeout(hw);
2923201f924Sjsg
2933201f924Sjsg return ret_val;
294ad013249Sreyk }
295ad013249Sreyk
296ad013249Sreyk /**
297ad013249Sreyk * ixgbe_get_link_capabilities_82598 - Determines link capabilities
298ad013249Sreyk * @hw: pointer to hardware structure
299ad013249Sreyk * @speed: pointer to link speed
3003201f924Sjsg * @autoneg: boolean auto-negotiation value
301ad013249Sreyk *
302ad013249Sreyk * Determines the link capabilities by reading the AUTOC register.
303ad013249Sreyk **/
ixgbe_get_link_capabilities_82598(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)30435befa56Sreyk int32_t ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
305ad013249Sreyk ixgbe_link_speed *speed,
30611efaf7fSmikeb bool *autoneg)
307ad013249Sreyk {
30835befa56Sreyk int32_t status = IXGBE_SUCCESS;
3093201f924Sjsg uint32_t autoc = 0;
310ad013249Sreyk
31111efaf7fSmikeb DEBUGFUNC("ixgbe_get_link_capabilities_82598");
31211efaf7fSmikeb
3133201f924Sjsg /*
3143201f924Sjsg * Determine link capabilities based on the stored value of AUTOC,
3153201f924Sjsg * which represents EEPROM defaults. If AUTOC value has not been
3163201f924Sjsg * stored, use the current register value.
3173201f924Sjsg */
3183201f924Sjsg if (hw->mac.orig_link_settings_stored)
3193201f924Sjsg autoc = hw->mac.orig_autoc;
3203201f924Sjsg else
3213201f924Sjsg autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
322ad013249Sreyk
3233201f924Sjsg switch (autoc & IXGBE_AUTOC_LMS_MASK) {
324ad013249Sreyk case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
325ad013249Sreyk *speed = IXGBE_LINK_SPEED_1GB_FULL;
326ad013249Sreyk *autoneg = FALSE;
327ad013249Sreyk break;
328ad013249Sreyk
329ad013249Sreyk case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
330ad013249Sreyk *speed = IXGBE_LINK_SPEED_10GB_FULL;
331ad013249Sreyk *autoneg = FALSE;
332ad013249Sreyk break;
333ad013249Sreyk
334ad013249Sreyk case IXGBE_AUTOC_LMS_1G_AN:
335ad013249Sreyk *speed = IXGBE_LINK_SPEED_1GB_FULL;
336ad013249Sreyk *autoneg = TRUE;
337ad013249Sreyk break;
338ad013249Sreyk
339ad013249Sreyk case IXGBE_AUTOC_LMS_KX4_AN:
340ad013249Sreyk case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
341ad013249Sreyk *speed = IXGBE_LINK_SPEED_UNKNOWN;
3423201f924Sjsg if (autoc & IXGBE_AUTOC_KX4_SUPP)
343ad013249Sreyk *speed |= IXGBE_LINK_SPEED_10GB_FULL;
3443201f924Sjsg if (autoc & IXGBE_AUTOC_KX_SUPP)
345ad013249Sreyk *speed |= IXGBE_LINK_SPEED_1GB_FULL;
346ad013249Sreyk *autoneg = TRUE;
347ad013249Sreyk break;
348ad013249Sreyk
349ad013249Sreyk default:
350ad013249Sreyk status = IXGBE_ERR_LINK_SETUP;
351ad013249Sreyk break;
352ad013249Sreyk }
353ad013249Sreyk
354ad013249Sreyk return status;
355ad013249Sreyk }
356ad013249Sreyk
357ad013249Sreyk /**
358ad013249Sreyk * ixgbe_get_media_type_82598 - Determines media type
359ad013249Sreyk * @hw: pointer to hardware structure
360ad013249Sreyk *
361ad013249Sreyk * Returns the media type (fiber, copper, backplane)
362ad013249Sreyk **/
ixgbe_get_media_type_82598(struct ixgbe_hw * hw)363ad013249Sreyk enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
364ad013249Sreyk {
365ad013249Sreyk enum ixgbe_media_type media_type;
366ad013249Sreyk
36711efaf7fSmikeb DEBUGFUNC("ixgbe_get_media_type_82598");
36811efaf7fSmikeb
3693201f924Sjsg /* Detect if there is a copper PHY attached. */
3709feba5bbSclaudio switch (hw->phy.type) {
3719feba5bbSclaudio case ixgbe_phy_cu_unknown:
3729feba5bbSclaudio case ixgbe_phy_tn:
3733201f924Sjsg media_type = ixgbe_media_type_copper;
3743201f924Sjsg goto out;
3759feba5bbSclaudio default:
3769feba5bbSclaudio break;
3773201f924Sjsg }
3783201f924Sjsg
379ad013249Sreyk /* Media type for I82598 is based on device ID */
380ad013249Sreyk switch (hw->device_id) {
3813201f924Sjsg case IXGBE_DEV_ID_82598:
3823201f924Sjsg case IXGBE_DEV_ID_82598_BX:
3833201f924Sjsg /* Default device ID is mezzanine card KX/KX4 */
3843201f924Sjsg media_type = ixgbe_media_type_backplane;
3853201f924Sjsg break;
386ad013249Sreyk case IXGBE_DEV_ID_82598AF_DUAL_PORT:
387ad013249Sreyk case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
388ad013249Sreyk case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
389ad013249Sreyk case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
390ad013249Sreyk case IXGBE_DEV_ID_82598EB_XF_LR:
3913201f924Sjsg case IXGBE_DEV_ID_82598EB_SFP_LOM:
392ad013249Sreyk media_type = ixgbe_media_type_fiber;
393ad013249Sreyk break;
3943201f924Sjsg case IXGBE_DEV_ID_82598EB_CX4:
3953201f924Sjsg case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
3963201f924Sjsg media_type = ixgbe_media_type_cx4;
397ad013249Sreyk break;
3983201f924Sjsg case IXGBE_DEV_ID_82598AT:
3993201f924Sjsg case IXGBE_DEV_ID_82598AT2:
400ad013249Sreyk media_type = ixgbe_media_type_copper;
401ad013249Sreyk break;
402ad013249Sreyk default:
403ad013249Sreyk media_type = ixgbe_media_type_unknown;
404ad013249Sreyk break;
405ad013249Sreyk }
4063201f924Sjsg out:
407ad013249Sreyk return media_type;
408ad013249Sreyk }
409ad013249Sreyk
410ad013249Sreyk /**
4113201f924Sjsg * ixgbe_fc_enable_82598 - Enable flow control
412ad013249Sreyk * @hw: pointer to hardware structure
413ad013249Sreyk *
4143201f924Sjsg * Enable flow control according to the current settings.
415ad013249Sreyk **/
ixgbe_fc_enable_82598(struct ixgbe_hw * hw)41611efaf7fSmikeb int32_t ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
417ad013249Sreyk {
4183201f924Sjsg int32_t ret_val = IXGBE_SUCCESS;
4193201f924Sjsg uint32_t fctrl_reg;
42035befa56Sreyk uint32_t rmcs_reg;
4213201f924Sjsg uint32_t reg;
42211efaf7fSmikeb uint32_t fcrtl, fcrth;
4233201f924Sjsg uint32_t link_speed = 0;
42411efaf7fSmikeb int i;
42511efaf7fSmikeb bool link_up;
42611efaf7fSmikeb
42711efaf7fSmikeb DEBUGFUNC("ixgbe_fc_enable_82598");
42811efaf7fSmikeb
42911efaf7fSmikeb /* Validate the water mark configuration */
43011efaf7fSmikeb if (!hw->fc.pause_time) {
43111efaf7fSmikeb ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
43211efaf7fSmikeb goto out;
43311efaf7fSmikeb }
43411efaf7fSmikeb
43511efaf7fSmikeb /* Low water mark of zero causes XOFF floods */
43611efaf7fSmikeb for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
43711efaf7fSmikeb if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
43811efaf7fSmikeb hw->fc.high_water[i]) {
43911efaf7fSmikeb if (!hw->fc.low_water[i] ||
44011efaf7fSmikeb hw->fc.low_water[i] >= hw->fc.high_water[i]) {
44111efaf7fSmikeb DEBUGOUT("Invalid water mark configuration\n");
44211efaf7fSmikeb ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
44311efaf7fSmikeb goto out;
44411efaf7fSmikeb }
44511efaf7fSmikeb }
44611efaf7fSmikeb }
447ad013249Sreyk
4483201f924Sjsg /*
4499feba5bbSclaudio * On 82598 having Rx FC on causes resets while doing 1G
4509feba5bbSclaudio * so if it's on turn it off once we know link_speed. For
4519feba5bbSclaudio * more details see 82598 Specification update.
4523201f924Sjsg */
4533201f924Sjsg hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE);
4549feba5bbSclaudio if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) {
4559feba5bbSclaudio switch (hw->fc.requested_mode) {
4569feba5bbSclaudio case ixgbe_fc_full:
4579feba5bbSclaudio hw->fc.requested_mode = ixgbe_fc_tx_pause;
4589feba5bbSclaudio break;
4599feba5bbSclaudio case ixgbe_fc_rx_pause:
4603201f924Sjsg hw->fc.requested_mode = ixgbe_fc_none;
4619feba5bbSclaudio break;
4629feba5bbSclaudio default:
4639feba5bbSclaudio /* no change */
4649feba5bbSclaudio break;
4659feba5bbSclaudio }
466ad013249Sreyk }
467ad013249Sreyk
4683201f924Sjsg /* Negotiate the fc mode to use */
46911efaf7fSmikeb ixgbe_fc_autoneg(hw);
4703201f924Sjsg
4713201f924Sjsg /* Disable any previous flow control settings */
4723201f924Sjsg fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
4733201f924Sjsg fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
474ad013249Sreyk
475ad013249Sreyk rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
476ad013249Sreyk rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X);
477ad013249Sreyk
478ad013249Sreyk /*
4793201f924Sjsg * The possible values of fc.current_mode are:
480ad013249Sreyk * 0: Flow control is completely disabled
4813201f924Sjsg * 1: Rx flow control is enabled (we can receive pause frames,
4823201f924Sjsg * but not send pause frames).
4833201f924Sjsg * 2: Tx flow control is enabled (we can send pause frames but
4843201f924Sjsg * we do not support receiving pause frames).
485ad013249Sreyk * 3: Both Rx and Tx flow control (symmetric) are enabled.
486ad013249Sreyk * other: Invalid.
487ad013249Sreyk */
4883201f924Sjsg switch (hw->fc.current_mode) {
489ad013249Sreyk case ixgbe_fc_none:
4909feba5bbSclaudio /*
4919feba5bbSclaudio * Flow control is disabled by software override or autoneg.
4923201f924Sjsg * The code below will actually disable it in the HW.
4933201f924Sjsg */
494ad013249Sreyk break;
495ad013249Sreyk case ixgbe_fc_rx_pause:
496ad013249Sreyk /*
4973201f924Sjsg * Rx Flow control is enabled and Tx Flow control is
4983201f924Sjsg * disabled by software override. Since there really
4993201f924Sjsg * isn't a way to advertise that we are capable of RX
5003201f924Sjsg * Pause ONLY, we will advertise that we support both
5013201f924Sjsg * symmetric and asymmetric Rx PAUSE. Later, we will
5023201f924Sjsg * disable the adapter's ability to send PAUSE frames.
503ad013249Sreyk */
5043201f924Sjsg fctrl_reg |= IXGBE_FCTRL_RFCE;
505ad013249Sreyk break;
506ad013249Sreyk case ixgbe_fc_tx_pause:
507ad013249Sreyk /*
5083201f924Sjsg * Tx Flow control is enabled, and Rx Flow control is
5093201f924Sjsg * disabled by software override.
510ad013249Sreyk */
511ad013249Sreyk rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
512ad013249Sreyk break;
513ad013249Sreyk case ixgbe_fc_full:
5143201f924Sjsg /* Flow control (both Rx and Tx) is enabled by SW override. */
5153201f924Sjsg fctrl_reg |= IXGBE_FCTRL_RFCE;
516ad013249Sreyk rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
517ad013249Sreyk break;
518ad013249Sreyk default:
519ad013249Sreyk DEBUGOUT("Flow control param set incorrectly\n");
5203201f924Sjsg ret_val = IXGBE_ERR_CONFIG;
5213201f924Sjsg goto out;
522ad013249Sreyk break;
523ad013249Sreyk }
524ad013249Sreyk
5253201f924Sjsg /* Set 802.3x based flow control settings. */
5263201f924Sjsg fctrl_reg |= IXGBE_FCTRL_DPF;
5273201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
528ad013249Sreyk IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
529ad013249Sreyk
5303201f924Sjsg /* Set up and enable Rx high/low water mark thresholds, enable XON. */
53111efaf7fSmikeb for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
53211efaf7fSmikeb if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
53311efaf7fSmikeb hw->fc.high_water[i]) {
53411efaf7fSmikeb fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
53511efaf7fSmikeb fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
53611efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
53711efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
53811efaf7fSmikeb } else {
53911efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
54011efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
54111efaf7fSmikeb }
5423201f924Sjsg
543ad013249Sreyk }
544ad013249Sreyk
5453201f924Sjsg /* Configure pause time (2 TCs per register) */
546109b20f8Sbluhm reg = (uint32_t)hw->fc.pause_time * 0x00010001;
54711efaf7fSmikeb for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++)
54811efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
5493201f924Sjsg
55011efaf7fSmikeb /* Configure flow control refresh threshold value */
55111efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
552ad013249Sreyk
5533201f924Sjsg out:
5543201f924Sjsg return ret_val;
555ad013249Sreyk }
556ad013249Sreyk
557ad013249Sreyk /**
5583201f924Sjsg * ixgbe_start_mac_link_82598 - Configures MAC link settings
559ad013249Sreyk * @hw: pointer to hardware structure
560d7a8f955Sjmatthew * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
561ad013249Sreyk *
562ad013249Sreyk * Configures link settings based on values in the ixgbe_hw struct.
563ad013249Sreyk * Restarts the link. Performs autonegotiation if needed.
564ad013249Sreyk **/
ixgbe_start_mac_link_82598(struct ixgbe_hw * hw,bool autoneg_wait_to_complete)5653201f924Sjsg int32_t ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
56611efaf7fSmikeb bool autoneg_wait_to_complete)
567ad013249Sreyk {
56835befa56Sreyk uint32_t autoc_reg;
56935befa56Sreyk uint32_t links_reg;
57035befa56Sreyk uint32_t i;
57135befa56Sreyk int32_t status = IXGBE_SUCCESS;
572ad013249Sreyk
57311efaf7fSmikeb DEBUGFUNC("ixgbe_start_mac_link_82598");
57411efaf7fSmikeb
575ad013249Sreyk /* Restart link */
5763201f924Sjsg autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
577ad013249Sreyk autoc_reg |= IXGBE_AUTOC_AN_RESTART;
578ad013249Sreyk IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
579ad013249Sreyk
580ad013249Sreyk /* Only poll for autoneg to complete if specified to do so */
5813201f924Sjsg if (autoneg_wait_to_complete) {
5823201f924Sjsg if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
5833201f924Sjsg IXGBE_AUTOC_LMS_KX4_AN ||
5843201f924Sjsg (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
5853201f924Sjsg IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
586ad013249Sreyk links_reg = 0; /* Just in case Autoneg time = 0 */
587ad013249Sreyk for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
588ad013249Sreyk links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
589ad013249Sreyk if (links_reg & IXGBE_LINKS_KX_AN_COMP)
590ad013249Sreyk break;
591ad013249Sreyk msec_delay(100);
592ad013249Sreyk }
593ad013249Sreyk if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
594ad013249Sreyk status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
595ad013249Sreyk DEBUGOUT("Autonegotiation did not complete.\n");
596ad013249Sreyk }
597ad013249Sreyk }
598ad013249Sreyk }
599ad013249Sreyk
600ad013249Sreyk /* Add delay to filter out noises during initial link setup */
601ad013249Sreyk msec_delay(50);
602ad013249Sreyk
603ad013249Sreyk return status;
604ad013249Sreyk }
605ad013249Sreyk
606ad013249Sreyk /**
6079feba5bbSclaudio * ixgbe_validate_link_ready - Function looks for phy link
6089feba5bbSclaudio * @hw: pointer to hardware structure
6099feba5bbSclaudio *
6109feba5bbSclaudio * Function indicates success when phy link is available. If phy is not ready
6119feba5bbSclaudio * within 5 seconds of MAC indicating link, the function returns error.
6129feba5bbSclaudio **/
ixgbe_validate_link_ready(struct ixgbe_hw * hw)6139feba5bbSclaudio int32_t ixgbe_validate_link_ready(struct ixgbe_hw *hw)
6149feba5bbSclaudio {
6159feba5bbSclaudio uint32_t timeout;
6169feba5bbSclaudio uint16_t an_reg;
6179feba5bbSclaudio
6189feba5bbSclaudio if (hw->device_id != IXGBE_DEV_ID_82598AT2)
6199feba5bbSclaudio return IXGBE_SUCCESS;
6209feba5bbSclaudio
6219feba5bbSclaudio for (timeout = 0;
6229feba5bbSclaudio timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) {
6239feba5bbSclaudio hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
6249feba5bbSclaudio IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_reg);
6259feba5bbSclaudio
6269feba5bbSclaudio if ((an_reg & IXGBE_MII_AUTONEG_COMPLETE) &&
6279feba5bbSclaudio (an_reg & IXGBE_MII_AUTONEG_LINK_UP))
6289feba5bbSclaudio break;
6299feba5bbSclaudio
6309feba5bbSclaudio msec_delay(100);
6319feba5bbSclaudio }
6329feba5bbSclaudio
6339feba5bbSclaudio if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) {
6349feba5bbSclaudio DEBUGOUT("Link was indicated but link is down\n");
6359feba5bbSclaudio return IXGBE_ERR_LINK_SETUP;
6369feba5bbSclaudio }
6379feba5bbSclaudio
6389feba5bbSclaudio return IXGBE_SUCCESS;
6399feba5bbSclaudio }
6409feba5bbSclaudio
6419feba5bbSclaudio /**
642ad013249Sreyk * ixgbe_check_mac_link_82598 - Get link/speed status
643ad013249Sreyk * @hw: pointer to hardware structure
644ad013249Sreyk * @speed: pointer to link speed
645ad013249Sreyk * @link_up: TRUE is link is up, FALSE otherwise
6463201f924Sjsg * @link_up_wait_to_complete: bool used to wait for link up or not
647ad013249Sreyk *
648ad013249Sreyk * Reads the links register to determine if link is up and the current speed
649ad013249Sreyk **/
ixgbe_check_mac_link_82598(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up,bool link_up_wait_to_complete)65011efaf7fSmikeb int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
65111efaf7fSmikeb ixgbe_link_speed *speed, bool *link_up,
65211efaf7fSmikeb bool link_up_wait_to_complete)
653ad013249Sreyk {
65435befa56Sreyk uint32_t links_reg;
65535befa56Sreyk uint32_t i;
65635befa56Sreyk uint16_t link_reg, adapt_comp_reg;
657ad013249Sreyk
65811efaf7fSmikeb DEBUGFUNC("ixgbe_check_mac_link_82598");
65911efaf7fSmikeb
6603201f924Sjsg /*
6613201f924Sjsg * SERDES PHY requires us to read link status from undocumented
6623201f924Sjsg * register 0xC79F. Bit 0 set indicates link is up/ready; clear
6633201f924Sjsg * indicates link down. OxC00C is read to check that the XAUI lanes
6643201f924Sjsg * are active. Bit 0 clear indicates active; set indicates inactive.
6653201f924Sjsg */
666ad013249Sreyk if (hw->phy.type == ixgbe_phy_nl) {
6673201f924Sjsg hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
6683201f924Sjsg hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
669ad013249Sreyk hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
670ad013249Sreyk &adapt_comp_reg);
671ad013249Sreyk if (link_up_wait_to_complete) {
6722f63561bSmikeb for (i = 0; i < hw->mac.max_link_up_time; i++) {
6733201f924Sjsg if ((link_reg & 1) &&
674ad013249Sreyk ((adapt_comp_reg & 1) == 0)) {
675ad013249Sreyk *link_up = TRUE;
676ad013249Sreyk break;
677ad013249Sreyk } else {
678ad013249Sreyk *link_up = FALSE;
679ad013249Sreyk }
680ad013249Sreyk msec_delay(100);
6813201f924Sjsg hw->phy.ops.read_reg(hw, 0xC79F,
6823201f924Sjsg IXGBE_TWINAX_DEV,
683ad013249Sreyk &link_reg);
684ad013249Sreyk hw->phy.ops.read_reg(hw, 0xC00C,
685ad013249Sreyk IXGBE_TWINAX_DEV,
686ad013249Sreyk &adapt_comp_reg);
687ad013249Sreyk }
688ad013249Sreyk } else {
6899feba5bbSclaudio if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0))
690ad013249Sreyk *link_up = TRUE;
691ad013249Sreyk else
692ad013249Sreyk *link_up = FALSE;
693ad013249Sreyk }
694ad013249Sreyk
695ad013249Sreyk if (*link_up == FALSE)
696ad013249Sreyk goto out;
697ad013249Sreyk }
698ad013249Sreyk
699ad013249Sreyk links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
700ad013249Sreyk if (link_up_wait_to_complete) {
7012f63561bSmikeb for (i = 0; i < hw->mac.max_link_up_time; i++) {
702ad013249Sreyk if (links_reg & IXGBE_LINKS_UP) {
703ad013249Sreyk *link_up = TRUE;
704ad013249Sreyk break;
705ad013249Sreyk } else {
706ad013249Sreyk *link_up = FALSE;
707ad013249Sreyk }
708ad013249Sreyk msec_delay(100);
709ad013249Sreyk links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
710ad013249Sreyk }
711ad013249Sreyk } else {
712ad013249Sreyk if (links_reg & IXGBE_LINKS_UP)
713ad013249Sreyk *link_up = TRUE;
714ad013249Sreyk else
715ad013249Sreyk *link_up = FALSE;
716ad013249Sreyk }
717ad013249Sreyk
718ad013249Sreyk if (links_reg & IXGBE_LINKS_SPEED)
719ad013249Sreyk *speed = IXGBE_LINK_SPEED_10GB_FULL;
720ad013249Sreyk else
721ad013249Sreyk *speed = IXGBE_LINK_SPEED_1GB_FULL;
722ad013249Sreyk
7233201f924Sjsg if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == TRUE) &&
7243201f924Sjsg (ixgbe_validate_link_ready(hw) != IXGBE_SUCCESS))
7253201f924Sjsg *link_up = FALSE;
7263201f924Sjsg
727ad013249Sreyk out:
728ad013249Sreyk return IXGBE_SUCCESS;
729ad013249Sreyk }
730ad013249Sreyk
731ad013249Sreyk /**
7323201f924Sjsg * ixgbe_setup_mac_link_82598 - Set MAC link speed
733ad013249Sreyk * @hw: pointer to hardware structure
734ad013249Sreyk * @speed: new link speed
7353201f924Sjsg * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
736ad013249Sreyk *
737ad013249Sreyk * Set the link speed in the AUTOC register and restarts link.
738ad013249Sreyk **/
ixgbe_setup_mac_link_82598(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)7393201f924Sjsg int32_t ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
74011efaf7fSmikeb ixgbe_link_speed speed,
74111efaf7fSmikeb bool autoneg_wait_to_complete)
742ad013249Sreyk {
74311efaf7fSmikeb bool autoneg = FALSE;
74435befa56Sreyk int32_t status = IXGBE_SUCCESS;
7453201f924Sjsg ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
7463201f924Sjsg uint32_t curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
7473201f924Sjsg uint32_t autoc = curr_autoc;
7483201f924Sjsg uint32_t link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
749ad013249Sreyk
75011efaf7fSmikeb DEBUGFUNC("ixgbe_setup_mac_link_82598");
75111efaf7fSmikeb
7523201f924Sjsg /* Check to see if speed passed in is supported. */
753d7a8f955Sjmatthew hw->mac.ops.get_link_capabilities(hw, &link_capabilities, &autoneg);
7543201f924Sjsg speed &= link_capabilities;
7553201f924Sjsg
7563201f924Sjsg if (speed == IXGBE_LINK_SPEED_UNKNOWN)
757ad013249Sreyk status = IXGBE_ERR_LINK_SETUP;
7583201f924Sjsg
7593201f924Sjsg /* Set KX4/KX support according to speed requested */
7603201f924Sjsg else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN ||
7613201f924Sjsg link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
7623201f924Sjsg autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK;
7633201f924Sjsg if (speed & IXGBE_LINK_SPEED_10GB_FULL)
7643201f924Sjsg autoc |= IXGBE_AUTOC_KX4_SUPP;
7653201f924Sjsg if (speed & IXGBE_LINK_SPEED_1GB_FULL)
7663201f924Sjsg autoc |= IXGBE_AUTOC_KX_SUPP;
7673201f924Sjsg if (autoc != curr_autoc)
7683201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
769ad013249Sreyk }
770ad013249Sreyk
771ad013249Sreyk if (status == IXGBE_SUCCESS) {
772ad013249Sreyk /*
773ad013249Sreyk * Setup and restart the link based on the new values in
774ad013249Sreyk * ixgbe_hw This will write the AUTOC register based on the new
775ad013249Sreyk * stored values
776ad013249Sreyk */
7773201f924Sjsg status = ixgbe_start_mac_link_82598(hw,
7783201f924Sjsg autoneg_wait_to_complete);
779ad013249Sreyk }
780ad013249Sreyk
781ad013249Sreyk return status;
782ad013249Sreyk }
783ad013249Sreyk
7849feba5bbSclaudio
785ad013249Sreyk /**
7863201f924Sjsg * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field
787ad013249Sreyk * @hw: pointer to hardware structure
788ad013249Sreyk * @speed: new link speed
789ad013249Sreyk * @autoneg_wait_to_complete: TRUE if waiting is needed to complete
790ad013249Sreyk *
791ad013249Sreyk * Sets the link speed in the AUTOC register in the MAC and restarts link.
792ad013249Sreyk **/
ixgbe_setup_copper_link_82598(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)7933201f924Sjsg int32_t ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
794ad013249Sreyk ixgbe_link_speed speed,
79511efaf7fSmikeb bool autoneg_wait_to_complete)
796ad013249Sreyk {
79735befa56Sreyk int32_t status;
798ad013249Sreyk
79911efaf7fSmikeb DEBUGFUNC("ixgbe_setup_copper_link_82598");
80011efaf7fSmikeb
801ad013249Sreyk /* Setup the PHY according to input speed */
80211efaf7fSmikeb status = hw->phy.ops.setup_link_speed(hw, speed,
803ad013249Sreyk autoneg_wait_to_complete);
804ad013249Sreyk /* Set up MAC */
8053201f924Sjsg ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
806ad013249Sreyk
807ad013249Sreyk return status;
808ad013249Sreyk }
809ad013249Sreyk
810ad013249Sreyk /**
811ad013249Sreyk * ixgbe_reset_hw_82598 - Performs hardware reset
812ad013249Sreyk * @hw: pointer to hardware structure
813ad013249Sreyk *
814ad013249Sreyk * Resets the hardware by resetting the transmit and receive units, masks and
815ad013249Sreyk * clears all interrupts, performing a PHY reset, and performing a link (MAC)
816ad013249Sreyk * reset.
817ad013249Sreyk **/
ixgbe_reset_hw_82598(struct ixgbe_hw * hw)81835befa56Sreyk int32_t ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
819ad013249Sreyk {
82035befa56Sreyk int32_t status = IXGBE_SUCCESS;
8213201f924Sjsg int32_t phy_status = IXGBE_SUCCESS;
82235befa56Sreyk uint32_t ctrl;
82335befa56Sreyk uint32_t gheccr;
82435befa56Sreyk uint32_t i;
82535befa56Sreyk uint32_t autoc;
82635befa56Sreyk uint8_t analog_val;
827ad013249Sreyk
82811efaf7fSmikeb DEBUGFUNC("ixgbe_reset_hw_82598");
82911efaf7fSmikeb
830ad013249Sreyk /* Call adapter stop to disable tx/rx and clear interrupts */
83111efaf7fSmikeb status = hw->mac.ops.stop_adapter(hw);
83211efaf7fSmikeb if (status != IXGBE_SUCCESS)
83311efaf7fSmikeb goto reset_hw_out;
834ad013249Sreyk
835ad013249Sreyk /*
836ad013249Sreyk * Power up the Atlas Tx lanes if they are currently powered down.
837ad013249Sreyk * Atlas Tx lanes are powered down for MAC loopback tests, but
838ad013249Sreyk * they are not automatically restored on reset.
839ad013249Sreyk */
840ad013249Sreyk hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val);
841ad013249Sreyk if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) {
842ad013249Sreyk /* Enable Tx Atlas so packets can be transmitted again */
843ad013249Sreyk hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK,
844ad013249Sreyk &analog_val);
845ad013249Sreyk analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN;
846ad013249Sreyk hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK,
847ad013249Sreyk analog_val);
848ad013249Sreyk
849ad013249Sreyk hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G,
850ad013249Sreyk &analog_val);
851ad013249Sreyk analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL;
852ad013249Sreyk hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G,
853ad013249Sreyk analog_val);
854ad013249Sreyk
855ad013249Sreyk hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G,
856ad013249Sreyk &analog_val);
857ad013249Sreyk analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL;
858ad013249Sreyk hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G,
859ad013249Sreyk analog_val);
860ad013249Sreyk
861ad013249Sreyk hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN,
862ad013249Sreyk &analog_val);
863ad013249Sreyk analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL;
864ad013249Sreyk hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN,
865ad013249Sreyk analog_val);
866ad013249Sreyk }
867ad013249Sreyk
868ad013249Sreyk /* Reset PHY */
8693201f924Sjsg if (hw->phy.reset_disable == FALSE) {
8703201f924Sjsg /* PHY ops must be identified and initialized prior to reset */
871ad013249Sreyk
8723201f924Sjsg /* Init PHY and function pointers, perform SFP setup */
8733201f924Sjsg phy_status = hw->phy.ops.init(hw);
8743201f924Sjsg if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
8753201f924Sjsg goto reset_hw_out;
87611efaf7fSmikeb if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
87711efaf7fSmikeb goto mac_reset_top;
8783201f924Sjsg
8793201f924Sjsg hw->phy.ops.reset(hw);
8803201f924Sjsg }
8813201f924Sjsg
8829feba5bbSclaudio mac_reset_top:
883ad013249Sreyk /*
884ad013249Sreyk * Issue global reset to the MAC. This needs to be a SW reset.
885ad013249Sreyk * If link reset is used, it might reset the MAC when mng is using it
886ad013249Sreyk */
88711efaf7fSmikeb ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST;
88811efaf7fSmikeb IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
889ad013249Sreyk IXGBE_WRITE_FLUSH(hw);
890ad013249Sreyk
891ad013249Sreyk /* Poll for reset bit to self-clear indicating reset is complete */
892ad013249Sreyk for (i = 0; i < 10; i++) {
893ad013249Sreyk usec_delay(1);
894ad013249Sreyk ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
895ad013249Sreyk if (!(ctrl & IXGBE_CTRL_RST))
896ad013249Sreyk break;
897ad013249Sreyk }
898ad013249Sreyk if (ctrl & IXGBE_CTRL_RST) {
899ad013249Sreyk status = IXGBE_ERR_RESET_FAILED;
900ad013249Sreyk DEBUGOUT("Reset polling failed to complete.\n");
901ad013249Sreyk }
902ad013249Sreyk
90354ed48bfSmikeb msec_delay(50);
90454ed48bfSmikeb
9059feba5bbSclaudio /*
9069feba5bbSclaudio * Double resets are required for recovery from certain error
9079feba5bbSclaudio * conditions. Between resets, it is necessary to stall to allow time
90854ed48bfSmikeb * for any pending HW events to complete.
9099feba5bbSclaudio */
9109feba5bbSclaudio if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
9119feba5bbSclaudio hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
9129feba5bbSclaudio goto mac_reset_top;
9139feba5bbSclaudio }
9149feba5bbSclaudio
915ad013249Sreyk gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
916ad013249Sreyk gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6));
917ad013249Sreyk IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr);
918ad013249Sreyk
919ad013249Sreyk /*
9203201f924Sjsg * Store the original AUTOC value if it has not been
9213201f924Sjsg * stored off yet. Otherwise restore the stored original
9224b1a56afSjsg * AUTOC value since the reset operation sets back to defaults.
923ad013249Sreyk */
924ad013249Sreyk autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
9253201f924Sjsg if (hw->mac.orig_link_settings_stored == FALSE) {
9263201f924Sjsg hw->mac.orig_autoc = autoc;
9273201f924Sjsg hw->mac.orig_link_settings_stored = TRUE;
9289feba5bbSclaudio } else if (autoc != hw->mac.orig_autoc) {
9293201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
9309feba5bbSclaudio }
931ad013249Sreyk
932ad013249Sreyk /* Store the permanent mac address */
933ad013249Sreyk hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
934ad013249Sreyk
9353201f924Sjsg /*
9363201f924Sjsg * Store MAC address from RAR0, clear receive address registers, and
9373201f924Sjsg * clear the multicast table
9383201f924Sjsg */
9393201f924Sjsg hw->mac.ops.init_rx_addrs(hw);
9403201f924Sjsg
9413201f924Sjsg reset_hw_out:
9423201f924Sjsg if (phy_status != IXGBE_SUCCESS)
9433201f924Sjsg status = phy_status;
9449feba5bbSclaudio
945ad013249Sreyk return status;
946ad013249Sreyk }
947ad013249Sreyk
948ad013249Sreyk /**
949ad013249Sreyk * ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address
950ad013249Sreyk * @hw: pointer to hardware struct
951ad013249Sreyk * @rar: receive address register index to associate with a VMDq index
952ad013249Sreyk * @vmdq: VMDq set index
953ad013249Sreyk **/
ixgbe_set_vmdq_82598(struct ixgbe_hw * hw,uint32_t rar,uint32_t vmdq)95435befa56Sreyk int32_t ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq)
955ad013249Sreyk {
95635befa56Sreyk uint32_t rar_high;
9579feba5bbSclaudio uint32_t rar_entries = hw->mac.num_rar_entries;
9589feba5bbSclaudio
95911efaf7fSmikeb DEBUGFUNC("ixgbe_set_vmdq_82598");
96011efaf7fSmikeb
9619feba5bbSclaudio /* Make sure we are using a valid rar index range */
9629feba5bbSclaudio if (rar >= rar_entries) {
9639feba5bbSclaudio DEBUGOUT1("RAR index %d is out of range.\n", rar);
9649feba5bbSclaudio return IXGBE_ERR_INVALID_ARGUMENT;
9659feba5bbSclaudio }
966ad013249Sreyk
967ad013249Sreyk rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
968ad013249Sreyk rar_high &= ~IXGBE_RAH_VIND_MASK;
969ad013249Sreyk rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK);
970ad013249Sreyk IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
971ad013249Sreyk return IXGBE_SUCCESS;
972ad013249Sreyk }
973ad013249Sreyk
974ad013249Sreyk /**
9753201f924Sjsg * ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address
9763201f924Sjsg * @hw: pointer to hardware struct
9773201f924Sjsg * @rar: receive address register index to associate with a VMDq index
9783201f924Sjsg * @vmdq: VMDq clear index (not used in 82598, but elsewhere)
979ad013249Sreyk **/
ixgbe_clear_vmdq_82598(struct ixgbe_hw * hw,uint32_t rar,uint32_t vmdq)9803201f924Sjsg int32_t ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq)
981ad013249Sreyk {
9823201f924Sjsg uint32_t rar_high;
9833201f924Sjsg uint32_t rar_entries = hw->mac.num_rar_entries;
984ad013249Sreyk
9859feba5bbSclaudio /* Make sure we are using a valid rar index range */
9869feba5bbSclaudio if (rar >= rar_entries) {
9879feba5bbSclaudio DEBUGOUT1("RAR index %d is out of range.\n", rar);
9889feba5bbSclaudio return IXGBE_ERR_INVALID_ARGUMENT;
9899feba5bbSclaudio }
9909feba5bbSclaudio
9913201f924Sjsg rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
9923201f924Sjsg if (rar_high & IXGBE_RAH_VIND_MASK) {
9933201f924Sjsg rar_high &= ~IXGBE_RAH_VIND_MASK;
9943201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
995ad013249Sreyk }
996ad013249Sreyk
997ad013249Sreyk return IXGBE_SUCCESS;
998ad013249Sreyk }
999ad013249Sreyk
1000ad013249Sreyk /**
10013201f924Sjsg * ixgbe_set_vfta_82598 - Set VLAN filter table
1002ad013249Sreyk * @hw: pointer to hardware structure
10033201f924Sjsg * @vlan: VLAN id to write to VLAN filter
10043201f924Sjsg * @vind: VMDq output index that maps queue to VLAN id in VFTA
10053201f924Sjsg * @vlan_on: boolean flag to turn on/off VLAN in VFTA
1006d7a8f955Sjmatthew * @vlvf_bypass: boolean flag - unused
10073201f924Sjsg *
10083201f924Sjsg * Turn on/off specified VLAN in the VLAN filter table.
1009ad013249Sreyk **/
ixgbe_set_vfta_82598(struct ixgbe_hw * hw,uint32_t vlan,uint32_t vind,bool vlan_on,bool vlvf_bypass)10103201f924Sjsg int32_t ixgbe_set_vfta_82598(struct ixgbe_hw *hw, uint32_t vlan, uint32_t vind,
1011d7a8f955Sjmatthew bool vlan_on, bool vlvf_bypass)
1012ad013249Sreyk {
10133201f924Sjsg uint32_t regindex;
10143201f924Sjsg uint32_t bitindex;
10153201f924Sjsg uint32_t bits;
10163201f924Sjsg uint32_t vftabyte;
1017ad013249Sreyk
101811efaf7fSmikeb DEBUGFUNC("ixgbe_set_vfta_82598");
101911efaf7fSmikeb
10203201f924Sjsg if (vlan > 4095)
10213201f924Sjsg return IXGBE_ERR_PARAM;
1022ad013249Sreyk
10233201f924Sjsg /* Determine 32-bit word position in array */
10243201f924Sjsg regindex = (vlan >> 5) & 0x7F; /* upper seven bits */
10253201f924Sjsg
10263201f924Sjsg /* Determine the location of the (VMD) queue index */
10273201f924Sjsg vftabyte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */
10283201f924Sjsg bitindex = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */
10293201f924Sjsg
10303201f924Sjsg /* Set the nibble for VMD queue index */
10313201f924Sjsg bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex));
10323201f924Sjsg bits &= (~(0x0F << bitindex));
10333201f924Sjsg bits |= (vind << bitindex);
10343201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits);
10353201f924Sjsg
10363201f924Sjsg /* Determine the location of the bit for this VLAN id */
10373201f924Sjsg bitindex = vlan & 0x1F; /* lower five bits */
10383201f924Sjsg
10393201f924Sjsg bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
10403201f924Sjsg if (vlan_on)
10413201f924Sjsg /* Turn on this VLAN id */
10423201f924Sjsg bits |= (1 << bitindex);
10433201f924Sjsg else
10443201f924Sjsg /* Turn off this VLAN id */
10453201f924Sjsg bits &= ~(1 << bitindex);
10463201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
10473201f924Sjsg
10483201f924Sjsg return IXGBE_SUCCESS;
10493201f924Sjsg }
10503201f924Sjsg
10513201f924Sjsg /**
10523201f924Sjsg * ixgbe_clear_vfta_82598 - Clear VLAN filter table
10533201f924Sjsg * @hw: pointer to hardware structure
10543201f924Sjsg *
10553201f924Sjsg * Clears the VLAN filer table, and the VMDq index associated with the filter
10563201f924Sjsg **/
ixgbe_clear_vfta_82598(struct ixgbe_hw * hw)10573201f924Sjsg int32_t ixgbe_clear_vfta_82598(struct ixgbe_hw *hw)
10583201f924Sjsg {
10593201f924Sjsg uint32_t offset;
10603201f924Sjsg uint32_t vlanbyte;
10613201f924Sjsg
106211efaf7fSmikeb DEBUGFUNC("ixgbe_clear_vfta_82598");
106311efaf7fSmikeb
10643201f924Sjsg for (offset = 0; offset < hw->mac.vft_size; offset++)
10653201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
10663201f924Sjsg
10673201f924Sjsg for (vlanbyte = 0; vlanbyte < 4; vlanbyte++)
10683201f924Sjsg for (offset = 0; offset < hw->mac.vft_size; offset++)
10693201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset),
10703201f924Sjsg 0);
10713201f924Sjsg
10723201f924Sjsg return IXGBE_SUCCESS;
10733201f924Sjsg }
10743201f924Sjsg
10753201f924Sjsg /**
10763201f924Sjsg * ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register
10773201f924Sjsg * @hw: pointer to hardware structure
10783201f924Sjsg * @reg: analog register to read
10793201f924Sjsg * @val: read value
10803201f924Sjsg *
10813201f924Sjsg * Performs read operation to Atlas analog register specified.
10823201f924Sjsg **/
ixgbe_read_analog_reg8_82598(struct ixgbe_hw * hw,uint32_t reg,uint8_t * val)10833201f924Sjsg int32_t ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, uint32_t reg, uint8_t *val)
10843201f924Sjsg {
10853201f924Sjsg uint32_t atlas_ctl;
10863201f924Sjsg
108711efaf7fSmikeb DEBUGFUNC("ixgbe_read_analog_reg8_82598");
108811efaf7fSmikeb
10893201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL,
10903201f924Sjsg IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
1091ad013249Sreyk IXGBE_WRITE_FLUSH(hw);
10923201f924Sjsg usec_delay(10);
10933201f924Sjsg atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
10943201f924Sjsg *val = (uint8_t)atlas_ctl;
10953201f924Sjsg
10963201f924Sjsg return IXGBE_SUCCESS;
10973201f924Sjsg }
10983201f924Sjsg
10993201f924Sjsg /**
11003201f924Sjsg * ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register
11013201f924Sjsg * @hw: pointer to hardware structure
11023201f924Sjsg * @reg: atlas register to write
11033201f924Sjsg * @val: value to write
11043201f924Sjsg *
11053201f924Sjsg * Performs write operation to Atlas analog register specified.
11063201f924Sjsg **/
ixgbe_write_analog_reg8_82598(struct ixgbe_hw * hw,uint32_t reg,uint8_t val)11073201f924Sjsg int32_t ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, uint32_t reg, uint8_t val)
11083201f924Sjsg {
11093201f924Sjsg uint32_t atlas_ctl;
11103201f924Sjsg
111111efaf7fSmikeb DEBUGFUNC("ixgbe_write_analog_reg8_82598");
111211efaf7fSmikeb
11133201f924Sjsg atlas_ctl = (reg << 8) | val;
11143201f924Sjsg IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
11153201f924Sjsg IXGBE_WRITE_FLUSH(hw);
11163201f924Sjsg usec_delay(10);
11173201f924Sjsg
11183201f924Sjsg return IXGBE_SUCCESS;
11193201f924Sjsg }
11203201f924Sjsg
11213201f924Sjsg /**
112211efaf7fSmikeb * ixgbe_read_i2c_phy_82598 - Reads 8 bit word over I2C interface.
11233201f924Sjsg * @hw: pointer to hardware structure
112411efaf7fSmikeb * @dev_addr: address to read from
112511efaf7fSmikeb * @byte_offset: byte offset to read from dev_addr
11263201f924Sjsg * @eeprom_data: value read
11273201f924Sjsg *
11283201f924Sjsg * Performs 8 byte read operation to SFP module's EEPROM over I2C interface.
11293201f924Sjsg **/
ixgbe_read_i2c_phy_82598(struct ixgbe_hw * hw,uint8_t dev_addr,uint8_t byte_offset,uint8_t * eeprom_data)113011efaf7fSmikeb int32_t ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, uint8_t dev_addr,
113111efaf7fSmikeb uint8_t byte_offset, uint8_t *eeprom_data)
11323201f924Sjsg {
11333201f924Sjsg int32_t status = IXGBE_SUCCESS;
11343201f924Sjsg uint16_t sfp_addr = 0;
11353201f924Sjsg uint16_t sfp_data = 0;
11363201f924Sjsg uint16_t sfp_stat = 0;
113711efaf7fSmikeb uint16_t gssr;
11383201f924Sjsg uint32_t i;
11393201f924Sjsg
114011efaf7fSmikeb DEBUGFUNC("ixgbe_read_i2c_phy_82598");
114111efaf7fSmikeb
114211efaf7fSmikeb if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
114311efaf7fSmikeb gssr = IXGBE_GSSR_PHY1_SM;
114411efaf7fSmikeb else
114511efaf7fSmikeb gssr = IXGBE_GSSR_PHY0_SM;
114611efaf7fSmikeb
114711efaf7fSmikeb if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
114811efaf7fSmikeb return IXGBE_ERR_SWFW_SYNC;
114911efaf7fSmikeb
11503201f924Sjsg if (hw->phy.type == ixgbe_phy_nl) {
11513201f924Sjsg /*
11523201f924Sjsg * NetLogic phy SDA/SCL registers are at addresses 0xC30A to
11533201f924Sjsg * 0xC30D. These registers are used to talk to the SFP+
11543201f924Sjsg * module's EEPROM through the SDA/SCL (I2C) interface.
11553201f924Sjsg */
115611efaf7fSmikeb sfp_addr = (dev_addr << 8) + byte_offset;
11573201f924Sjsg sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
115811efaf7fSmikeb hw->phy.ops.write_reg_mdi(hw,
11593201f924Sjsg IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
11603201f924Sjsg IXGBE_MDIO_PMA_PMD_DEV_TYPE,
11613201f924Sjsg sfp_addr);
11623201f924Sjsg
11633201f924Sjsg /* Poll status */
11643201f924Sjsg for (i = 0; i < 100; i++) {
116511efaf7fSmikeb hw->phy.ops.read_reg_mdi(hw,
11663201f924Sjsg IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
11673201f924Sjsg IXGBE_MDIO_PMA_PMD_DEV_TYPE,
11683201f924Sjsg &sfp_stat);
11693201f924Sjsg sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
11703201f924Sjsg if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
11713201f924Sjsg break;
11723201f924Sjsg msec_delay(10);
11733201f924Sjsg }
11743201f924Sjsg
11753201f924Sjsg if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
11763201f924Sjsg DEBUGOUT("EEPROM read did not pass.\n");
11773201f924Sjsg status = IXGBE_ERR_SFP_NOT_PRESENT;
11783201f924Sjsg goto out;
11793201f924Sjsg }
11803201f924Sjsg
11813201f924Sjsg /* Read data */
118211efaf7fSmikeb hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
11833201f924Sjsg IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
11843201f924Sjsg
11853201f924Sjsg *eeprom_data = (uint8_t)(sfp_data >> 8);
11863201f924Sjsg } else {
11873201f924Sjsg status = IXGBE_ERR_PHY;
11883201f924Sjsg }
11893201f924Sjsg
11903201f924Sjsg out:
119111efaf7fSmikeb hw->mac.ops.release_swfw_sync(hw, gssr);
11923201f924Sjsg return status;
11933201f924Sjsg }
11943201f924Sjsg
11953201f924Sjsg /**
119611efaf7fSmikeb * ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface.
119711efaf7fSmikeb * @hw: pointer to hardware structure
119811efaf7fSmikeb * @byte_offset: EEPROM byte offset to read
119911efaf7fSmikeb * @eeprom_data: value read
120011efaf7fSmikeb *
120111efaf7fSmikeb * Performs 8 byte read operation to SFP module's EEPROM over I2C interface.
120211efaf7fSmikeb **/
ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw * hw,uint8_t byte_offset,uint8_t * eeprom_data)120311efaf7fSmikeb int32_t ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, uint8_t byte_offset,
120411efaf7fSmikeb uint8_t *eeprom_data)
120511efaf7fSmikeb {
120611efaf7fSmikeb return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR,
120711efaf7fSmikeb byte_offset, eeprom_data);
120811efaf7fSmikeb }
120911efaf7fSmikeb
121011efaf7fSmikeb /**
12113201f924Sjsg * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
12123201f924Sjsg * @hw: pointer to hardware structure
12133201f924Sjsg *
12143201f924Sjsg * Determines physical layer capabilities of the current configuration.
12153201f924Sjsg **/
ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw * hw)1216d7a8f955Sjmatthew uint64_t ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
12173201f924Sjsg {
1218d7a8f955Sjmatthew uint64_t physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
12193201f924Sjsg uint32_t autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
12203201f924Sjsg uint32_t pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
12213201f924Sjsg uint32_t pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
12223201f924Sjsg uint16_t ext_ability = 0;
12233201f924Sjsg
122411efaf7fSmikeb DEBUGFUNC("ixgbe_get_supported_physical_layer_82598");
122511efaf7fSmikeb
12263201f924Sjsg hw->phy.ops.identify(hw);
12273201f924Sjsg
12283201f924Sjsg /* Copper PHY must be checked before AUTOC LMS to determine correct
12293201f924Sjsg * physical layer because 10GBase-T PHYs use LMS = KX4/KX */
12309feba5bbSclaudio switch (hw->phy.type) {
12319feba5bbSclaudio case ixgbe_phy_tn:
12329feba5bbSclaudio case ixgbe_phy_cu_unknown:
12333201f924Sjsg hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
12343201f924Sjsg IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
12353201f924Sjsg if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
12363201f924Sjsg physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
12373201f924Sjsg if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
12383201f924Sjsg physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
12393201f924Sjsg if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
12403201f924Sjsg physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
12413201f924Sjsg goto out;
12429feba5bbSclaudio default:
12439feba5bbSclaudio break;
12443201f924Sjsg }
12453201f924Sjsg
12463201f924Sjsg switch (autoc & IXGBE_AUTOC_LMS_MASK) {
12473201f924Sjsg case IXGBE_AUTOC_LMS_1G_AN:
12483201f924Sjsg case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
12493201f924Sjsg if (pma_pmd_1g == IXGBE_AUTOC_1G_KX)
12503201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
12513201f924Sjsg else
12523201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
12533201f924Sjsg break;
12543201f924Sjsg case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
12553201f924Sjsg if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4)
12563201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
12573201f924Sjsg else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4)
12583201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
1259d7a8f955Sjmatthew else /* XAUI */
1260d7a8f955Sjmatthew physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
12613201f924Sjsg break;
12623201f924Sjsg case IXGBE_AUTOC_LMS_KX4_AN:
12633201f924Sjsg case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
12643201f924Sjsg if (autoc & IXGBE_AUTOC_KX_SUPP)
12653201f924Sjsg physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
12663201f924Sjsg if (autoc & IXGBE_AUTOC_KX4_SUPP)
12673201f924Sjsg physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
12683201f924Sjsg break;
12693201f924Sjsg default:
12703201f924Sjsg break;
12713201f924Sjsg }
12723201f924Sjsg
12733201f924Sjsg if (hw->phy.type == ixgbe_phy_nl) {
12743201f924Sjsg hw->phy.ops.identify_sfp(hw);
12753201f924Sjsg
12763201f924Sjsg switch (hw->phy.sfp_type) {
12773201f924Sjsg case ixgbe_sfp_type_da_cu:
12783201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
12793201f924Sjsg break;
12803201f924Sjsg case ixgbe_sfp_type_sr:
12813201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
12823201f924Sjsg break;
12833201f924Sjsg case ixgbe_sfp_type_lr:
12843201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
12853201f924Sjsg break;
12863201f924Sjsg default:
12873201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
12883201f924Sjsg break;
12893201f924Sjsg }
12903201f924Sjsg }
12913201f924Sjsg
12923201f924Sjsg switch (hw->device_id) {
12933201f924Sjsg case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
12943201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
12953201f924Sjsg break;
12963201f924Sjsg case IXGBE_DEV_ID_82598AF_DUAL_PORT:
12973201f924Sjsg case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
12983201f924Sjsg case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
12993201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
13003201f924Sjsg break;
13013201f924Sjsg case IXGBE_DEV_ID_82598EB_XF_LR:
13023201f924Sjsg physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
13033201f924Sjsg break;
13043201f924Sjsg default:
13053201f924Sjsg break;
13063201f924Sjsg }
13073201f924Sjsg
13083201f924Sjsg out:
13093201f924Sjsg return physical_layer;
13103201f924Sjsg }
13113201f924Sjsg
13123201f924Sjsg /**
13133201f924Sjsg * ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple
13143201f924Sjsg * port devices.
13153201f924Sjsg * @hw: pointer to the HW structure
13163201f924Sjsg *
13173201f924Sjsg * Calls common function and corrects issue with some single port devices
13183201f924Sjsg * that enable LAN1 but not LAN0.
13193201f924Sjsg **/
ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw * hw)13203201f924Sjsg void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
13213201f924Sjsg {
13223201f924Sjsg struct ixgbe_bus_info *bus = &hw->bus;
132311efaf7fSmikeb uint16_t pci_gen = 0;
132411efaf7fSmikeb uint16_t pci_ctrl2 = 0;
132511efaf7fSmikeb
132611efaf7fSmikeb DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie_82598");
13273201f924Sjsg
13283201f924Sjsg ixgbe_set_lan_id_multi_port_pcie(hw);
13293201f924Sjsg
13303201f924Sjsg /* check if LAN0 is disabled */
13313201f924Sjsg hw->eeprom.ops.read(hw, IXGBE_PCIE_GENERAL_PTR, &pci_gen);
13323201f924Sjsg if ((pci_gen != 0) && (pci_gen != 0xFFFF)) {
13333201f924Sjsg
13343201f924Sjsg hw->eeprom.ops.read(hw, pci_gen + IXGBE_PCIE_CTRL2, &pci_ctrl2);
13353201f924Sjsg
13363201f924Sjsg /* if LAN0 is completely disabled force function to 0 */
13373201f924Sjsg if ((pci_ctrl2 & IXGBE_PCIE_CTRL2_LAN_DISABLE) &&
13383201f924Sjsg !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DISABLE_SELECT) &&
13393201f924Sjsg !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DUMMY_ENABLE)) {
13403201f924Sjsg
13413201f924Sjsg bus->func = 0;
13423201f924Sjsg }
13433201f924Sjsg }
13443201f924Sjsg }
134535e02db6Smikeb
134635e02db6Smikeb /**
134735e02db6Smikeb * ixgbe_enable_rx_dma_82598 - Enable the Rx DMA unit
134835e02db6Smikeb * @hw: pointer to hardware structure
134935e02db6Smikeb * @regval: register value to write to RXCTRL
135035e02db6Smikeb *
135135e02db6Smikeb * Enables the Rx DMA unit
135235e02db6Smikeb **/
ixgbe_enable_rx_dma_82598(struct ixgbe_hw * hw,uint32_t regval)135335e02db6Smikeb int32_t ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, uint32_t regval)
135435e02db6Smikeb {
135535e02db6Smikeb DEBUGFUNC("ixgbe_enable_rx_dma_82598");
135635e02db6Smikeb
135735e02db6Smikeb IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
135835e02db6Smikeb
135935e02db6Smikeb return IXGBE_SUCCESS;
136035e02db6Smikeb }
1361