19ca4041bSJack F Vogel /****************************************************************************** 213705f88SJack F Vogel 30ac6dfecSJack F Vogel Copyright (c) 2001-2009, Intel Corporation 413705f88SJack F Vogel All rights reserved. 513705f88SJack F Vogel 613705f88SJack F Vogel Redistribution and use in source and binary forms, with or without 713705f88SJack F Vogel modification, are permitted provided that the following conditions are met: 813705f88SJack F Vogel 913705f88SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 1013705f88SJack F Vogel this list of conditions and the following disclaimer. 1113705f88SJack F Vogel 1213705f88SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 1313705f88SJack F Vogel notice, this list of conditions and the following disclaimer in the 1413705f88SJack F Vogel documentation and/or other materials provided with the distribution. 1513705f88SJack F Vogel 1613705f88SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 1713705f88SJack F Vogel contributors may be used to endorse or promote products derived from 1813705f88SJack F Vogel this software without specific prior written permission. 1913705f88SJack F Vogel 2013705f88SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2113705f88SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2213705f88SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2313705f88SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2413705f88SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2513705f88SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2613705f88SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2713705f88SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2813705f88SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2913705f88SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3013705f88SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 3113705f88SJack F Vogel 329ca4041bSJack F Vogel ******************************************************************************/ 3313705f88SJack F Vogel /*$FreeBSD$*/ 3413705f88SJack F Vogel 3513705f88SJack F Vogel #include "ixgbe_common.h" 3613705f88SJack F Vogel #include "ixgbe_api.h" 3713705f88SJack F Vogel 3813705f88SJack F Vogel static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw); 3913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 4013705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 4113705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 4213705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 4313705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 4413705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 4513705f88SJack F Vogel u16 count); 4613705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 4713705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 4813705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 4913705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw); 5013705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); 5113705f88SJack F Vogel 5213705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 5313705f88SJack F Vogel 5413705f88SJack F Vogel /** 559ca4041bSJack F Vogel * ixgbe_init_ops_generic - Inits function ptrs 569ca4041bSJack F Vogel * @hw: pointer to the hardware structure 5713705f88SJack F Vogel * 589ca4041bSJack F Vogel * Initialize the function pointers. 5913705f88SJack F Vogel **/ 609ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 6113705f88SJack F Vogel { 629ca4041bSJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 639ca4041bSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 649ca4041bSJack F Vogel u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 6513705f88SJack F Vogel 6613705f88SJack F Vogel /* EEPROM */ 679ca4041bSJack F Vogel eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; 689ca4041bSJack F Vogel /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 699ca4041bSJack F Vogel if (eec & (1 << 8)) 709ca4041bSJack F Vogel eeprom->ops.read = &ixgbe_read_eeprom_generic; 719ca4041bSJack F Vogel else 729ca4041bSJack F Vogel eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; 739ca4041bSJack F Vogel eeprom->ops.write = &ixgbe_write_eeprom_generic; 749ca4041bSJack F Vogel eeprom->ops.validate_checksum = 7513705f88SJack F Vogel &ixgbe_validate_eeprom_checksum_generic; 769ca4041bSJack F Vogel eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; 779ca4041bSJack F Vogel 789ca4041bSJack F Vogel /* MAC */ 799ca4041bSJack F Vogel mac->ops.init_hw = &ixgbe_init_hw_generic; 809ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 819ca4041bSJack F Vogel mac->ops.start_hw = &ixgbe_start_hw_generic; 829ca4041bSJack F Vogel mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; 839ca4041bSJack F Vogel mac->ops.get_media_type = NULL; 841b6e0dbaSJack F Vogel mac->ops.get_supported_physical_layer = NULL; 850ac6dfecSJack F Vogel mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic; 869ca4041bSJack F Vogel mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic; 879ca4041bSJack F Vogel mac->ops.stop_adapter = &ixgbe_stop_adapter_generic; 889ca4041bSJack F Vogel mac->ops.get_bus_info = &ixgbe_get_bus_info_generic; 891b6e0dbaSJack F Vogel mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie; 909ca4041bSJack F Vogel 919ca4041bSJack F Vogel /* LEDs */ 929ca4041bSJack F Vogel mac->ops.led_on = &ixgbe_led_on_generic; 939ca4041bSJack F Vogel mac->ops.led_off = &ixgbe_led_off_generic; 940ac6dfecSJack F Vogel mac->ops.blink_led_start = &ixgbe_blink_led_start_generic; 950ac6dfecSJack F Vogel mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic; 969ca4041bSJack F Vogel 9713705f88SJack F Vogel /* RAR, Multicast, VLAN */ 989ca4041bSJack F Vogel mac->ops.set_rar = &ixgbe_set_rar_generic; 995b7f4cedSJack F Vogel mac->ops.clear_rar = &ixgbe_clear_rar_generic; 1000ac6dfecSJack F Vogel mac->ops.insert_mac_addr = NULL; 1019ca4041bSJack F Vogel mac->ops.set_vmdq = NULL; 1025b7f4cedSJack F Vogel mac->ops.clear_vmdq = NULL; 1039ca4041bSJack F Vogel mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic; 1049ca4041bSJack F Vogel mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic; 1059ca4041bSJack F Vogel mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic; 1069ca4041bSJack F Vogel mac->ops.enable_mc = &ixgbe_enable_mc_generic; 1079ca4041bSJack F Vogel mac->ops.disable_mc = &ixgbe_disable_mc_generic; 1085b7f4cedSJack F Vogel mac->ops.clear_vfta = NULL; 1095b7f4cedSJack F Vogel mac->ops.set_vfta = NULL; 1105b7f4cedSJack F Vogel mac->ops.init_uta_tables = NULL; 1119ca4041bSJack F Vogel 1120ac6dfecSJack F Vogel /* Flow Control */ 1130ac6dfecSJack F Vogel mac->ops.fc_enable = &ixgbe_fc_enable_generic; 1149ca4041bSJack F Vogel 1159ca4041bSJack F Vogel /* Link */ 1169ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1179ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1189ca4041bSJack F Vogel mac->ops.setup_link_speed = NULL; 1199ca4041bSJack F Vogel mac->ops.check_link = NULL; 12013705f88SJack F Vogel 12113705f88SJack F Vogel return IXGBE_SUCCESS; 12213705f88SJack F Vogel } 12313705f88SJack F Vogel 12413705f88SJack F Vogel /** 1259ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 12613705f88SJack F Vogel * @hw: pointer to hardware structure 12713705f88SJack F Vogel * 12813705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 12913705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 13013705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 13113705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 13213705f88SJack F Vogel **/ 13313705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 13413705f88SJack F Vogel { 13513705f88SJack F Vogel u32 ctrl_ext; 1360ac6dfecSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 13713705f88SJack F Vogel 13813705f88SJack F Vogel /* Set the media type */ 1399ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 14013705f88SJack F Vogel 1410ac6dfecSJack F Vogel /* PHY ops initialization must be done in reset_hw() */ 14213705f88SJack F Vogel 14313705f88SJack F Vogel /* Clear the VLAN filter table */ 1449ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 14513705f88SJack F Vogel 14613705f88SJack F Vogel /* Clear statistics registers */ 1479ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 14813705f88SJack F Vogel 14913705f88SJack F Vogel /* Set No Snoop Disable */ 15013705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 15113705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 15213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 1539ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 15413705f88SJack F Vogel 1550ac6dfecSJack F Vogel /* Setup flow control */ 1560ac6dfecSJack F Vogel ixgbe_setup_fc(hw, 0); 1570ac6dfecSJack F Vogel 15813705f88SJack F Vogel /* Clear adapter stopped flag */ 15913705f88SJack F Vogel hw->adapter_stopped = FALSE; 16013705f88SJack F Vogel 1610ac6dfecSJack F Vogel return ret_val; 16213705f88SJack F Vogel } 16313705f88SJack F Vogel 16413705f88SJack F Vogel /** 16513705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 16613705f88SJack F Vogel * @hw: pointer to hardware structure 16713705f88SJack F Vogel * 1689ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 16913705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 17013705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 17113705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 17213705f88SJack F Vogel * disabled and uninitialized 17313705f88SJack F Vogel **/ 17413705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 17513705f88SJack F Vogel { 1760ac6dfecSJack F Vogel s32 status = IXGBE_SUCCESS; 1770ac6dfecSJack F Vogel 17813705f88SJack F Vogel /* Reset the hardware */ 1790ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 18013705f88SJack F Vogel 1810ac6dfecSJack F Vogel if (status == IXGBE_SUCCESS) { 18213705f88SJack F Vogel /* Start the HW */ 1830ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 1840ac6dfecSJack F Vogel } 18513705f88SJack F Vogel 1860ac6dfecSJack F Vogel return status; 18713705f88SJack F Vogel } 18813705f88SJack F Vogel 18913705f88SJack F Vogel /** 19013705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 19113705f88SJack F Vogel * @hw: pointer to hardware structure 19213705f88SJack F Vogel * 19313705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 19413705f88SJack F Vogel * Statistics counters are clear on read. 19513705f88SJack F Vogel **/ 19613705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 19713705f88SJack F Vogel { 19813705f88SJack F Vogel u16 i = 0; 19913705f88SJack F Vogel 20013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 20113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 20213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 20313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 20413705f88SJack F Vogel for (i = 0; i < 8; i++) 20513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 20613705f88SJack F Vogel 20713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 20813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 20913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 21013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 21113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 2120ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 2130ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 2140ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 2150ac6dfecSJack F Vogel } else { 2161b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 21713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 2180ac6dfecSJack F Vogel } 21913705f88SJack F Vogel 22013705f88SJack F Vogel for (i = 0; i < 8; i++) { 22113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 22213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 2230ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 2240ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 2250ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 2260ac6dfecSJack F Vogel } else { 2271b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 22813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 22913705f88SJack F Vogel } 2300ac6dfecSJack F Vogel } 2310ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 2320ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 2330ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 23413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 23513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 23613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 23713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 23813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 23913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 24013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 24113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 24213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 24313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 24413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 24513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 24613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 24713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 24813705f88SJack F Vogel for (i = 0; i < 8; i++) 24913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 25013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 25113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 25213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 25313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 25413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 25513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 25613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 25713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 25813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 25913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 26013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 26113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 26213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 26313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 26413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 26513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 26613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 26713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 26813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 26913705f88SJack F Vogel for (i = 0; i < 16; i++) { 27013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 27113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 27213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 27313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 27413705f88SJack F Vogel } 27513705f88SJack F Vogel 27613705f88SJack F Vogel return IXGBE_SUCCESS; 27713705f88SJack F Vogel } 27813705f88SJack F Vogel 27913705f88SJack F Vogel /** 2801b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 2819ca4041bSJack F Vogel * @hw: pointer to hardware structure 2829ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 2839ca4041bSJack F Vogel * 2849ca4041bSJack F Vogel * Reads the part number from the EEPROM. 2859ca4041bSJack F Vogel **/ 2869ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 2879ca4041bSJack F Vogel { 2889ca4041bSJack F Vogel s32 ret_val; 2899ca4041bSJack F Vogel u16 data; 2909ca4041bSJack F Vogel 2919ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 2929ca4041bSJack F Vogel 2939ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 2949ca4041bSJack F Vogel if (ret_val) { 2959ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2969ca4041bSJack F Vogel return ret_val; 2979ca4041bSJack F Vogel } 2989ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 2999ca4041bSJack F Vogel 3009ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 3019ca4041bSJack F Vogel if (ret_val) { 3029ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 3039ca4041bSJack F Vogel return ret_val; 3049ca4041bSJack F Vogel } 3059ca4041bSJack F Vogel *pba_num |= data; 3069ca4041bSJack F Vogel 3079ca4041bSJack F Vogel return IXGBE_SUCCESS; 3089ca4041bSJack F Vogel } 3099ca4041bSJack F Vogel 3109ca4041bSJack F Vogel /** 31113705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 31213705f88SJack F Vogel * @hw: pointer to hardware structure 31313705f88SJack F Vogel * @mac_addr: Adapter MAC address 31413705f88SJack F Vogel * 31513705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 31613705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 31713705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 31813705f88SJack F Vogel **/ 31913705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 32013705f88SJack F Vogel { 32113705f88SJack F Vogel u32 rar_high; 32213705f88SJack F Vogel u32 rar_low; 32313705f88SJack F Vogel u16 i; 32413705f88SJack F Vogel 32513705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 32613705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 32713705f88SJack F Vogel 32813705f88SJack F Vogel for (i = 0; i < 4; i++) 32913705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 33013705f88SJack F Vogel 33113705f88SJack F Vogel for (i = 0; i < 2; i++) 33213705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 33313705f88SJack F Vogel 33413705f88SJack F Vogel return IXGBE_SUCCESS; 33513705f88SJack F Vogel } 33613705f88SJack F Vogel 33713705f88SJack F Vogel /** 33813705f88SJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 33913705f88SJack F Vogel * @hw: pointer to hardware structure 34013705f88SJack F Vogel * 34113705f88SJack F Vogel * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure 34213705f88SJack F Vogel **/ 34313705f88SJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 34413705f88SJack F Vogel { 3451b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 34613705f88SJack F Vogel u16 link_status; 34713705f88SJack F Vogel 34813705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 34913705f88SJack F Vogel 35013705f88SJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 35113705f88SJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 35213705f88SJack F Vogel 35313705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 35413705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 35513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 35613705f88SJack F Vogel break; 35713705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 35813705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 35913705f88SJack F Vogel break; 36013705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 36113705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 36213705f88SJack F Vogel break; 36313705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 36413705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 36513705f88SJack F Vogel break; 36613705f88SJack F Vogel default: 36713705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 36813705f88SJack F Vogel break; 36913705f88SJack F Vogel } 37013705f88SJack F Vogel 37113705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 37213705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 37313705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 37413705f88SJack F Vogel break; 37513705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 37613705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 37713705f88SJack F Vogel break; 37813705f88SJack F Vogel default: 37913705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 38013705f88SJack F Vogel break; 38113705f88SJack F Vogel } 38213705f88SJack F Vogel 3831b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 3841b6e0dbaSJack F Vogel 38513705f88SJack F Vogel return IXGBE_SUCCESS; 38613705f88SJack F Vogel } 38713705f88SJack F Vogel 38813705f88SJack F Vogel /** 3891b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 3901b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 3911b6e0dbaSJack F Vogel * 3921b6e0dbaSJack F Vogel * Determines the LAN function id by reading memory-mapped registers 3931b6e0dbaSJack F Vogel * and swaps the port value if requested. 3941b6e0dbaSJack F Vogel **/ 3951b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 3961b6e0dbaSJack F Vogel { 3971b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 3981b6e0dbaSJack F Vogel u32 reg; 3991b6e0dbaSJack F Vogel 4001b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 4011b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 4020ac6dfecSJack F Vogel bus->lan_id = bus->func; 4031b6e0dbaSJack F Vogel 4041b6e0dbaSJack F Vogel /* check for a port swap */ 4051b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_FACTPS); 4061b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 4071b6e0dbaSJack F Vogel bus->func ^= 0x1; 4081b6e0dbaSJack F Vogel } 4091b6e0dbaSJack F Vogel 4101b6e0dbaSJack F Vogel /** 4119ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 41213705f88SJack F Vogel * @hw: pointer to hardware structure 41313705f88SJack F Vogel * 41413705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 41513705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 41613705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 41713705f88SJack F Vogel * state and should not touch the hardware. 41813705f88SJack F Vogel **/ 41913705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 42013705f88SJack F Vogel { 42113705f88SJack F Vogel u32 number_of_queues; 42213705f88SJack F Vogel u32 reg_val; 42313705f88SJack F Vogel u16 i; 42413705f88SJack F Vogel 42513705f88SJack F Vogel /* 42613705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 42713705f88SJack F Vogel * the hardware 42813705f88SJack F Vogel */ 42913705f88SJack F Vogel hw->adapter_stopped = TRUE; 43013705f88SJack F Vogel 43113705f88SJack F Vogel /* Disable the receive unit */ 43213705f88SJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 43313705f88SJack F Vogel reg_val &= ~(IXGBE_RXCTRL_RXEN); 43413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); 4359ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 43613705f88SJack F Vogel msec_delay(2); 43713705f88SJack F Vogel 43813705f88SJack F Vogel /* Clear interrupt mask to stop from interrupts being generated */ 43913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 44013705f88SJack F Vogel 44113705f88SJack F Vogel /* Clear any pending interrupts */ 44213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 44313705f88SJack F Vogel 44413705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 4459ca4041bSJack F Vogel number_of_queues = hw->mac.max_tx_queues; 44613705f88SJack F Vogel for (i = 0; i < number_of_queues; i++) { 44713705f88SJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); 44813705f88SJack F Vogel if (reg_val & IXGBE_TXDCTL_ENABLE) { 44913705f88SJack F Vogel reg_val &= ~IXGBE_TXDCTL_ENABLE; 45013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val); 45113705f88SJack F Vogel } 45213705f88SJack F Vogel } 45313705f88SJack F Vogel 4549ca4041bSJack F Vogel /* 4559ca4041bSJack F Vogel * Prevent the PCI-E bus from from hanging by disabling PCI-E master 4569ca4041bSJack F Vogel * access and verify no pending requests 4579ca4041bSJack F Vogel */ 4581b6e0dbaSJack F Vogel if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) 4599ca4041bSJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 4609ca4041bSJack F Vogel 46113705f88SJack F Vogel return IXGBE_SUCCESS; 46213705f88SJack F Vogel } 46313705f88SJack F Vogel 46413705f88SJack F Vogel /** 46513705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 46613705f88SJack F Vogel * @hw: pointer to hardware structure 46713705f88SJack F Vogel * @index: led number to turn on 46813705f88SJack F Vogel **/ 46913705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 47013705f88SJack F Vogel { 47113705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 47213705f88SJack F Vogel 47313705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 47413705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 47513705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 47613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 4779ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 47813705f88SJack F Vogel 47913705f88SJack F Vogel return IXGBE_SUCCESS; 48013705f88SJack F Vogel } 48113705f88SJack F Vogel 48213705f88SJack F Vogel /** 48313705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 48413705f88SJack F Vogel * @hw: pointer to hardware structure 48513705f88SJack F Vogel * @index: led number to turn off 48613705f88SJack F Vogel **/ 48713705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 48813705f88SJack F Vogel { 48913705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 49013705f88SJack F Vogel 49113705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 49213705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 49313705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 49413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 4959ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 49613705f88SJack F Vogel 49713705f88SJack F Vogel return IXGBE_SUCCESS; 49813705f88SJack F Vogel } 49913705f88SJack F Vogel 50013705f88SJack F Vogel /** 50113705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 50213705f88SJack F Vogel * @hw: pointer to hardware structure 50313705f88SJack F Vogel * 50413705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 50513705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 50613705f88SJack F Vogel **/ 50713705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 50813705f88SJack F Vogel { 50913705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 51013705f88SJack F Vogel u32 eec; 51113705f88SJack F Vogel u16 eeprom_size; 51213705f88SJack F Vogel 51313705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 51413705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 5155b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 5165b7f4cedSJack F Vogel * tested value */ 5175b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 51813705f88SJack F Vogel 51913705f88SJack F Vogel /* 52013705f88SJack F Vogel * Check for EEPROM present first. 52113705f88SJack F Vogel * If not present leave as none 52213705f88SJack F Vogel */ 52313705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 52413705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 52513705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 52613705f88SJack F Vogel 52713705f88SJack F Vogel /* 52813705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 52913705f88SJack F Vogel * change if a future EEPROM is not SPI. 53013705f88SJack F Vogel */ 53113705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 53213705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 53313705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 53413705f88SJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 53513705f88SJack F Vogel } 53613705f88SJack F Vogel 53713705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 53813705f88SJack F Vogel eeprom->address_bits = 16; 53913705f88SJack F Vogel else 54013705f88SJack F Vogel eeprom->address_bits = 8; 54113705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 54213705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 54313705f88SJack F Vogel eeprom->address_bits); 54413705f88SJack F Vogel } 54513705f88SJack F Vogel 54613705f88SJack F Vogel return IXGBE_SUCCESS; 54713705f88SJack F Vogel } 54813705f88SJack F Vogel 54913705f88SJack F Vogel /** 55013705f88SJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 55113705f88SJack F Vogel * @hw: pointer to hardware structure 55213705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 55313705f88SJack F Vogel * @data: 16 bit word to be written to the EEPROM 55413705f88SJack F Vogel * 55513705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 55613705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 55713705f88SJack F Vogel **/ 55813705f88SJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 55913705f88SJack F Vogel { 56013705f88SJack F Vogel s32 status; 56113705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 56213705f88SJack F Vogel 5639ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 5649ca4041bSJack F Vogel 5659ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 5669ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 5679ca4041bSJack F Vogel goto out; 5689ca4041bSJack F Vogel } 5699ca4041bSJack F Vogel 57013705f88SJack F Vogel /* Prepare the EEPROM for writing */ 57113705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 57213705f88SJack F Vogel 57313705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 57413705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 57513705f88SJack F Vogel ixgbe_release_eeprom(hw); 57613705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 57713705f88SJack F Vogel } 57813705f88SJack F Vogel } 57913705f88SJack F Vogel 58013705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 58113705f88SJack F Vogel ixgbe_standby_eeprom(hw); 58213705f88SJack F Vogel 58313705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 58413705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, 58513705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 58613705f88SJack F Vogel 58713705f88SJack F Vogel ixgbe_standby_eeprom(hw); 58813705f88SJack F Vogel 58913705f88SJack F Vogel /* 59013705f88SJack F Vogel * Some SPI eeproms use the 8th address bit embedded in the 59113705f88SJack F Vogel * opcode 59213705f88SJack F Vogel */ 59313705f88SJack F Vogel if ((hw->eeprom.address_bits == 8) && (offset >= 128)) 59413705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 59513705f88SJack F Vogel 59613705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 59713705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 59813705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 59913705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), 60013705f88SJack F Vogel hw->eeprom.address_bits); 60113705f88SJack F Vogel 60213705f88SJack F Vogel /* Send the data */ 60313705f88SJack F Vogel data = (data >> 8) | (data << 8); 60413705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, data, 16); 60513705f88SJack F Vogel ixgbe_standby_eeprom(hw); 60613705f88SJack F Vogel 60713705f88SJack F Vogel /* Done with writing - release the EEPROM */ 60813705f88SJack F Vogel ixgbe_release_eeprom(hw); 60913705f88SJack F Vogel } 61013705f88SJack F Vogel 6119ca4041bSJack F Vogel out: 61213705f88SJack F Vogel return status; 61313705f88SJack F Vogel } 61413705f88SJack F Vogel 61513705f88SJack F Vogel /** 61613705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 61713705f88SJack F Vogel * @hw: pointer to hardware structure 61813705f88SJack F Vogel * @offset: offset within the EEPROM to be read 61913705f88SJack F Vogel * @data: read 16 bit value from EEPROM 62013705f88SJack F Vogel * 62113705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 62213705f88SJack F Vogel **/ 62313705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 62413705f88SJack F Vogel u16 *data) 62513705f88SJack F Vogel { 62613705f88SJack F Vogel s32 status; 62713705f88SJack F Vogel u16 word_in; 62813705f88SJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 62913705f88SJack F Vogel 6309ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 6319ca4041bSJack F Vogel 6329ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 6339ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 6349ca4041bSJack F Vogel goto out; 6359ca4041bSJack F Vogel } 6369ca4041bSJack F Vogel 63713705f88SJack F Vogel /* Prepare the EEPROM for reading */ 63813705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 63913705f88SJack F Vogel 64013705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 64113705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 64213705f88SJack F Vogel ixgbe_release_eeprom(hw); 64313705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 64413705f88SJack F Vogel } 64513705f88SJack F Vogel } 64613705f88SJack F Vogel 64713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 64813705f88SJack F Vogel ixgbe_standby_eeprom(hw); 64913705f88SJack F Vogel 65013705f88SJack F Vogel /* 65113705f88SJack F Vogel * Some SPI eeproms use the 8th address bit embedded in the 65213705f88SJack F Vogel * opcode 65313705f88SJack F Vogel */ 65413705f88SJack F Vogel if ((hw->eeprom.address_bits == 8) && (offset >= 128)) 65513705f88SJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 65613705f88SJack F Vogel 65713705f88SJack F Vogel /* Send the READ command (opcode + addr) */ 65813705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 65913705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 66013705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), 66113705f88SJack F Vogel hw->eeprom.address_bits); 66213705f88SJack F Vogel 66313705f88SJack F Vogel /* Read the data. */ 66413705f88SJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 66513705f88SJack F Vogel *data = (word_in >> 8) | (word_in << 8); 66613705f88SJack F Vogel 66713705f88SJack F Vogel /* End this read operation */ 66813705f88SJack F Vogel ixgbe_release_eeprom(hw); 66913705f88SJack F Vogel } 67013705f88SJack F Vogel 6719ca4041bSJack F Vogel out: 67213705f88SJack F Vogel return status; 67313705f88SJack F Vogel } 67413705f88SJack F Vogel 67513705f88SJack F Vogel /** 67613705f88SJack F Vogel * ixgbe_read_eeprom_generic - Read EEPROM word using EERD 67713705f88SJack F Vogel * @hw: pointer to hardware structure 67813705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 67913705f88SJack F Vogel * @data: word read from the EEPROM 68013705f88SJack F Vogel * 68113705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 68213705f88SJack F Vogel **/ 68313705f88SJack F Vogel s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 68413705f88SJack F Vogel { 68513705f88SJack F Vogel u32 eerd; 68613705f88SJack F Vogel s32 status; 68713705f88SJack F Vogel 6889ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 6899ca4041bSJack F Vogel 6909ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 6919ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 6929ca4041bSJack F Vogel goto out; 6939ca4041bSJack F Vogel } 6949ca4041bSJack F Vogel 69513705f88SJack F Vogel eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + 69613705f88SJack F Vogel IXGBE_EEPROM_READ_REG_START; 69713705f88SJack F Vogel 69813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 69913705f88SJack F Vogel status = ixgbe_poll_eeprom_eerd_done(hw); 70013705f88SJack F Vogel 70113705f88SJack F Vogel if (status == IXGBE_SUCCESS) 70213705f88SJack F Vogel *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 70313705f88SJack F Vogel IXGBE_EEPROM_READ_REG_DATA); 70413705f88SJack F Vogel else 70513705f88SJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 70613705f88SJack F Vogel 7079ca4041bSJack F Vogel out: 70813705f88SJack F Vogel return status; 70913705f88SJack F Vogel } 71013705f88SJack F Vogel 71113705f88SJack F Vogel /** 71213705f88SJack F Vogel * ixgbe_poll_eeprom_eerd_done - Poll EERD status 71313705f88SJack F Vogel * @hw: pointer to hardware structure 71413705f88SJack F Vogel * 71513705f88SJack F Vogel * Polls the status bit (bit 1) of the EERD to determine when the read is done. 71613705f88SJack F Vogel **/ 71713705f88SJack F Vogel static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw) 71813705f88SJack F Vogel { 71913705f88SJack F Vogel u32 i; 72013705f88SJack F Vogel u32 reg; 72113705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 72213705f88SJack F Vogel 72313705f88SJack F Vogel for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) { 72413705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 72513705f88SJack F Vogel if (reg & IXGBE_EEPROM_READ_REG_DONE) { 72613705f88SJack F Vogel status = IXGBE_SUCCESS; 72713705f88SJack F Vogel break; 72813705f88SJack F Vogel } 72913705f88SJack F Vogel usec_delay(5); 73013705f88SJack F Vogel } 73113705f88SJack F Vogel return status; 73213705f88SJack F Vogel } 73313705f88SJack F Vogel 73413705f88SJack F Vogel /** 73513705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 73613705f88SJack F Vogel * @hw: pointer to hardware structure 73713705f88SJack F Vogel * 73813705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 73913705f88SJack F Vogel * be called before issuing a command to the EEPROM. 74013705f88SJack F Vogel **/ 74113705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 74213705f88SJack F Vogel { 74313705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 74413705f88SJack F Vogel u32 eec; 74513705f88SJack F Vogel u32 i; 74613705f88SJack F Vogel 74713705f88SJack F Vogel if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS) 74813705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 74913705f88SJack F Vogel 75013705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 75113705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 75213705f88SJack F Vogel 75313705f88SJack F Vogel /* Request EEPROM Access */ 75413705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 75513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 75613705f88SJack F Vogel 75713705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 75813705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 75913705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 76013705f88SJack F Vogel break; 76113705f88SJack F Vogel usec_delay(5); 76213705f88SJack F Vogel } 76313705f88SJack F Vogel 7649ca4041bSJack F Vogel /* Release if grant not acquired */ 76513705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 76613705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 76713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 76813705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 76913705f88SJack F Vogel 77013705f88SJack F Vogel ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 77113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 77213705f88SJack F Vogel } 77313705f88SJack F Vogel } 77413705f88SJack F Vogel 77513705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 77613705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 77713705f88SJack F Vogel /* Clear CS and SK */ 77813705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 77913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 78013705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 78113705f88SJack F Vogel usec_delay(1); 78213705f88SJack F Vogel } 78313705f88SJack F Vogel return status; 78413705f88SJack F Vogel } 78513705f88SJack F Vogel 78613705f88SJack F Vogel /** 78713705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 78813705f88SJack F Vogel * @hw: pointer to hardware structure 78913705f88SJack F Vogel * 79013705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 79113705f88SJack F Vogel **/ 79213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 79313705f88SJack F Vogel { 79413705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 79513705f88SJack F Vogel u32 timeout; 79613705f88SJack F Vogel u32 i; 79713705f88SJack F Vogel u32 swsm; 79813705f88SJack F Vogel 79913705f88SJack F Vogel /* Set timeout value based on size of EEPROM */ 80013705f88SJack F Vogel timeout = hw->eeprom.word_size + 1; 80113705f88SJack F Vogel 80213705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 80313705f88SJack F Vogel for (i = 0; i < timeout; i++) { 80413705f88SJack F Vogel /* 80513705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 80613705f88SJack F Vogel * set and we have the semaphore 80713705f88SJack F Vogel */ 80813705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 80913705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 81013705f88SJack F Vogel status = IXGBE_SUCCESS; 81113705f88SJack F Vogel break; 81213705f88SJack F Vogel } 8130ac6dfecSJack F Vogel usec_delay(50); 81413705f88SJack F Vogel } 81513705f88SJack F Vogel 81613705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 81713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 81813705f88SJack F Vogel for (i = 0; i < timeout; i++) { 81913705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 82013705f88SJack F Vogel 82113705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 82213705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 82313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 82413705f88SJack F Vogel 82513705f88SJack F Vogel /* 82613705f88SJack F Vogel * If we set the bit successfully then we got the 82713705f88SJack F Vogel * semaphore. 82813705f88SJack F Vogel */ 82913705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 83013705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 83113705f88SJack F Vogel break; 83213705f88SJack F Vogel 83313705f88SJack F Vogel usec_delay(50); 83413705f88SJack F Vogel } 83513705f88SJack F Vogel 83613705f88SJack F Vogel /* 83713705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 83813705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 83913705f88SJack F Vogel */ 84013705f88SJack F Vogel if (i >= timeout) { 8410ac6dfecSJack F Vogel DEBUGOUT("SWESMBI Software EEPROM semaphore " 84213705f88SJack F Vogel "not granted.\n"); 84313705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 84413705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 84513705f88SJack F Vogel } 8460ac6dfecSJack F Vogel } else { 8470ac6dfecSJack F Vogel DEBUGOUT("Software semaphore SMBI between device drivers " 8480ac6dfecSJack F Vogel "not granted.\n"); 84913705f88SJack F Vogel } 85013705f88SJack F Vogel 85113705f88SJack F Vogel return status; 85213705f88SJack F Vogel } 85313705f88SJack F Vogel 85413705f88SJack F Vogel /** 85513705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 85613705f88SJack F Vogel * @hw: pointer to hardware structure 85713705f88SJack F Vogel * 85813705f88SJack F Vogel * This function clears hardware semaphore bits. 85913705f88SJack F Vogel **/ 86013705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 86113705f88SJack F Vogel { 86213705f88SJack F Vogel u32 swsm; 86313705f88SJack F Vogel 86413705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 86513705f88SJack F Vogel 86613705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 86713705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 86813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 8699ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 87013705f88SJack F Vogel } 87113705f88SJack F Vogel 87213705f88SJack F Vogel /** 87313705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 87413705f88SJack F Vogel * @hw: pointer to hardware structure 87513705f88SJack F Vogel **/ 87613705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 87713705f88SJack F Vogel { 87813705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 87913705f88SJack F Vogel u16 i; 88013705f88SJack F Vogel u8 spi_stat_reg; 88113705f88SJack F Vogel 88213705f88SJack F Vogel /* 88313705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 88413705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 88513705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 88613705f88SJack F Vogel * 5 milliseconds, then error out. 88713705f88SJack F Vogel */ 88813705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 88913705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 89013705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 89113705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 89213705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 89313705f88SJack F Vogel break; 89413705f88SJack F Vogel 89513705f88SJack F Vogel usec_delay(5); 89613705f88SJack F Vogel ixgbe_standby_eeprom(hw); 89713705f88SJack F Vogel }; 89813705f88SJack F Vogel 89913705f88SJack F Vogel /* 90013705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 90113705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 90213705f88SJack F Vogel */ 90313705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 90413705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 90513705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 90613705f88SJack F Vogel } 90713705f88SJack F Vogel 90813705f88SJack F Vogel return status; 90913705f88SJack F Vogel } 91013705f88SJack F Vogel 91113705f88SJack F Vogel /** 91213705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 91313705f88SJack F Vogel * @hw: pointer to hardware structure 91413705f88SJack F Vogel **/ 91513705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 91613705f88SJack F Vogel { 91713705f88SJack F Vogel u32 eec; 91813705f88SJack F Vogel 91913705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 92013705f88SJack F Vogel 92113705f88SJack F Vogel /* Toggle CS to flush commands */ 92213705f88SJack F Vogel eec |= IXGBE_EEC_CS; 92313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 92413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 92513705f88SJack F Vogel usec_delay(1); 92613705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 92713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 92813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 92913705f88SJack F Vogel usec_delay(1); 93013705f88SJack F Vogel } 93113705f88SJack F Vogel 93213705f88SJack F Vogel /** 93313705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 93413705f88SJack F Vogel * @hw: pointer to hardware structure 93513705f88SJack F Vogel * @data: data to send to the EEPROM 93613705f88SJack F Vogel * @count: number of bits to shift out 93713705f88SJack F Vogel **/ 93813705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 93913705f88SJack F Vogel u16 count) 94013705f88SJack F Vogel { 94113705f88SJack F Vogel u32 eec; 94213705f88SJack F Vogel u32 mask; 94313705f88SJack F Vogel u32 i; 94413705f88SJack F Vogel 94513705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 94613705f88SJack F Vogel 94713705f88SJack F Vogel /* 94813705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 94913705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 95013705f88SJack F Vogel */ 95113705f88SJack F Vogel mask = 0x01 << (count - 1); 95213705f88SJack F Vogel 95313705f88SJack F Vogel for (i = 0; i < count; i++) { 95413705f88SJack F Vogel /* 95513705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 95613705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 95713705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 95813705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 95913705f88SJack F Vogel * raising and then lowering the clock. 96013705f88SJack F Vogel */ 96113705f88SJack F Vogel if (data & mask) 96213705f88SJack F Vogel eec |= IXGBE_EEC_DI; 96313705f88SJack F Vogel else 96413705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 96513705f88SJack F Vogel 96613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 96713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 96813705f88SJack F Vogel 96913705f88SJack F Vogel usec_delay(1); 97013705f88SJack F Vogel 97113705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 97213705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 97313705f88SJack F Vogel 97413705f88SJack F Vogel /* 97513705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 97613705f88SJack F Vogel * EEPROM 97713705f88SJack F Vogel */ 97813705f88SJack F Vogel mask = mask >> 1; 97913705f88SJack F Vogel }; 98013705f88SJack F Vogel 98113705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 98213705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 98313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 98413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 98513705f88SJack F Vogel } 98613705f88SJack F Vogel 98713705f88SJack F Vogel /** 98813705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 98913705f88SJack F Vogel * @hw: pointer to hardware structure 99013705f88SJack F Vogel **/ 99113705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 99213705f88SJack F Vogel { 99313705f88SJack F Vogel u32 eec; 99413705f88SJack F Vogel u32 i; 99513705f88SJack F Vogel u16 data = 0; 99613705f88SJack F Vogel 99713705f88SJack F Vogel /* 99813705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 99913705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 100013705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 100113705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 100213705f88SJack F Vogel * "DI" bit should always be clear. 100313705f88SJack F Vogel */ 100413705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 100513705f88SJack F Vogel 100613705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 100713705f88SJack F Vogel 100813705f88SJack F Vogel for (i = 0; i < count; i++) { 100913705f88SJack F Vogel data = data << 1; 101013705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 101113705f88SJack F Vogel 101213705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 101313705f88SJack F Vogel 101413705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 101513705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 101613705f88SJack F Vogel data |= 1; 101713705f88SJack F Vogel 101813705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 101913705f88SJack F Vogel } 102013705f88SJack F Vogel 102113705f88SJack F Vogel return data; 102213705f88SJack F Vogel } 102313705f88SJack F Vogel 102413705f88SJack F Vogel /** 102513705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 102613705f88SJack F Vogel * @hw: pointer to hardware structure 102713705f88SJack F Vogel * @eec: EEC register's current value 102813705f88SJack F Vogel **/ 102913705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 103013705f88SJack F Vogel { 103113705f88SJack F Vogel /* 103213705f88SJack F Vogel * Raise the clock input to the EEPROM 103313705f88SJack F Vogel * (setting the SK bit), then delay 103413705f88SJack F Vogel */ 103513705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 103613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 103713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 103813705f88SJack F Vogel usec_delay(1); 103913705f88SJack F Vogel } 104013705f88SJack F Vogel 104113705f88SJack F Vogel /** 104213705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 104313705f88SJack F Vogel * @hw: pointer to hardware structure 104413705f88SJack F Vogel * @eecd: EECD's current value 104513705f88SJack F Vogel **/ 104613705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 104713705f88SJack F Vogel { 104813705f88SJack F Vogel /* 104913705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 105013705f88SJack F Vogel * delay 105113705f88SJack F Vogel */ 105213705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 105313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 105413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 105513705f88SJack F Vogel usec_delay(1); 105613705f88SJack F Vogel } 105713705f88SJack F Vogel 105813705f88SJack F Vogel /** 105913705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 106013705f88SJack F Vogel * @hw: pointer to hardware structure 106113705f88SJack F Vogel **/ 106213705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 106313705f88SJack F Vogel { 106413705f88SJack F Vogel u32 eec; 106513705f88SJack F Vogel 106613705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 106713705f88SJack F Vogel 106813705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 106913705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 107013705f88SJack F Vogel 107113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 107213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 107313705f88SJack F Vogel 107413705f88SJack F Vogel usec_delay(1); 107513705f88SJack F Vogel 107613705f88SJack F Vogel /* Stop requesting EEPROM access */ 107713705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 107813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 107913705f88SJack F Vogel 108013705f88SJack F Vogel ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 108113705f88SJack F Vogel } 108213705f88SJack F Vogel 108313705f88SJack F Vogel /** 108413705f88SJack F Vogel * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum 108513705f88SJack F Vogel * @hw: pointer to hardware structure 108613705f88SJack F Vogel **/ 108713705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) 108813705f88SJack F Vogel { 108913705f88SJack F Vogel u16 i; 109013705f88SJack F Vogel u16 j; 109113705f88SJack F Vogel u16 checksum = 0; 109213705f88SJack F Vogel u16 length = 0; 109313705f88SJack F Vogel u16 pointer = 0; 109413705f88SJack F Vogel u16 word = 0; 109513705f88SJack F Vogel 109613705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 109713705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 10989ca4041bSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { 109913705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 110013705f88SJack F Vogel break; 110113705f88SJack F Vogel } 110213705f88SJack F Vogel checksum += word; 110313705f88SJack F Vogel } 110413705f88SJack F Vogel 110513705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 110613705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 11079ca4041bSJack F Vogel hw->eeprom.ops.read(hw, i, &pointer); 110813705f88SJack F Vogel 110913705f88SJack F Vogel /* Make sure the pointer seems valid */ 111013705f88SJack F Vogel if (pointer != 0xFFFF && pointer != 0) { 11119ca4041bSJack F Vogel hw->eeprom.ops.read(hw, pointer, &length); 111213705f88SJack F Vogel 111313705f88SJack F Vogel if (length != 0xFFFF && length != 0) { 111413705f88SJack F Vogel for (j = pointer+1; j <= pointer+length; j++) { 11159ca4041bSJack F Vogel hw->eeprom.ops.read(hw, j, &word); 111613705f88SJack F Vogel checksum += word; 111713705f88SJack F Vogel } 111813705f88SJack F Vogel } 111913705f88SJack F Vogel } 112013705f88SJack F Vogel } 112113705f88SJack F Vogel 112213705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 112313705f88SJack F Vogel 112413705f88SJack F Vogel return checksum; 112513705f88SJack F Vogel } 112613705f88SJack F Vogel 112713705f88SJack F Vogel /** 112813705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 112913705f88SJack F Vogel * @hw: pointer to hardware structure 113013705f88SJack F Vogel * @checksum_val: calculated checksum 113113705f88SJack F Vogel * 113213705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 113313705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 113413705f88SJack F Vogel **/ 113513705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 113613705f88SJack F Vogel u16 *checksum_val) 113713705f88SJack F Vogel { 113813705f88SJack F Vogel s32 status; 113913705f88SJack F Vogel u16 checksum; 114013705f88SJack F Vogel u16 read_checksum = 0; 114113705f88SJack F Vogel 114213705f88SJack F Vogel /* 114313705f88SJack F Vogel * Read the first word from the EEPROM. If this times out or fails, do 114413705f88SJack F Vogel * not continue or we could be in for a very long wait while every 114513705f88SJack F Vogel * EEPROM read fails 114613705f88SJack F Vogel */ 11479ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 114813705f88SJack F Vogel 114913705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 115013705f88SJack F Vogel checksum = ixgbe_calc_eeprom_checksum(hw); 115113705f88SJack F Vogel 11529ca4041bSJack F Vogel hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 115313705f88SJack F Vogel 115413705f88SJack F Vogel /* 115513705f88SJack F Vogel * Verify read checksum from EEPROM is the same as 115613705f88SJack F Vogel * calculated checksum 115713705f88SJack F Vogel */ 11589ca4041bSJack F Vogel if (read_checksum != checksum) 115913705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 116013705f88SJack F Vogel 116113705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 11629ca4041bSJack F Vogel if (checksum_val) 116313705f88SJack F Vogel *checksum_val = checksum; 116413705f88SJack F Vogel } else { 116513705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 116613705f88SJack F Vogel } 116713705f88SJack F Vogel 116813705f88SJack F Vogel return status; 116913705f88SJack F Vogel } 117013705f88SJack F Vogel 117113705f88SJack F Vogel /** 11729ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 117313705f88SJack F Vogel * @hw: pointer to hardware structure 117413705f88SJack F Vogel **/ 117513705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 117613705f88SJack F Vogel { 117713705f88SJack F Vogel s32 status; 117813705f88SJack F Vogel u16 checksum; 117913705f88SJack F Vogel 118013705f88SJack F Vogel /* 118113705f88SJack F Vogel * Read the first word from the EEPROM. If this times out or fails, do 118213705f88SJack F Vogel * not continue or we could be in for a very long wait while every 118313705f88SJack F Vogel * EEPROM read fails 118413705f88SJack F Vogel */ 11859ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 118613705f88SJack F Vogel 118713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 118813705f88SJack F Vogel checksum = ixgbe_calc_eeprom_checksum(hw); 11899ca4041bSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, 119013705f88SJack F Vogel checksum); 119113705f88SJack F Vogel } else { 119213705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 119313705f88SJack F Vogel } 119413705f88SJack F Vogel 119513705f88SJack F Vogel return status; 119613705f88SJack F Vogel } 119713705f88SJack F Vogel 119813705f88SJack F Vogel /** 119913705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 120013705f88SJack F Vogel * @mac_addr: pointer to MAC address. 120113705f88SJack F Vogel * 120213705f88SJack F Vogel * Tests a MAC address to ensure it is a valid Individual Address 120313705f88SJack F Vogel **/ 120413705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 120513705f88SJack F Vogel { 120613705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 120713705f88SJack F Vogel 120813705f88SJack F Vogel /* Make sure it is not a multicast address */ 120913705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 121013705f88SJack F Vogel DEBUGOUT("MAC address is multicast\n"); 121113705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 121213705f88SJack F Vogel /* Not a broadcast address */ 121313705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 121413705f88SJack F Vogel DEBUGOUT("MAC address is broadcast\n"); 121513705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 121613705f88SJack F Vogel /* Reject the zero address */ 121713705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 121813705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 121913705f88SJack F Vogel DEBUGOUT("MAC address is all zeros\n"); 122013705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 122113705f88SJack F Vogel } 122213705f88SJack F Vogel return status; 122313705f88SJack F Vogel } 122413705f88SJack F Vogel 122513705f88SJack F Vogel /** 12269ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 122713705f88SJack F Vogel * @hw: pointer to hardware structure 122813705f88SJack F Vogel * @index: Receive address register to write 12299ca4041bSJack F Vogel * @addr: Address to put into receive address register 12309ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 123113705f88SJack F Vogel * @enable_addr: set flag that address is active 123213705f88SJack F Vogel * 123313705f88SJack F Vogel * Puts an ethernet address into a receive address register. 123413705f88SJack F Vogel **/ 12359ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 123613705f88SJack F Vogel u32 enable_addr) 123713705f88SJack F Vogel { 123813705f88SJack F Vogel u32 rar_low, rar_high; 12399ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 124013705f88SJack F Vogel 12419ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 12429ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 12439ca4041bSJack F Vogel 12449ca4041bSJack F Vogel /* Make sure we are using a valid rar index range */ 12459ca4041bSJack F Vogel if (index < rar_entries) { 124613705f88SJack F Vogel /* 12479ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 12489ca4041bSJack F Vogel * order from network order (big endian) to little endian 124913705f88SJack F Vogel */ 125013705f88SJack F Vogel rar_low = ((u32)addr[0] | 125113705f88SJack F Vogel ((u32)addr[1] << 8) | 125213705f88SJack F Vogel ((u32)addr[2] << 16) | 125313705f88SJack F Vogel ((u32)addr[3] << 24)); 12549ca4041bSJack F Vogel /* 12559ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 12569ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 12579ca4041bSJack F Vogel * of the address and the address valid bit. 12589ca4041bSJack F Vogel */ 12599ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 12609ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 12619ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 126213705f88SJack F Vogel 126313705f88SJack F Vogel if (enable_addr != 0) 126413705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 126513705f88SJack F Vogel 126613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 126713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 12689ca4041bSJack F Vogel } else { 12695b7f4cedSJack F Vogel DEBUGOUT1("RAR index %d is out of range.\n", index); 12709ca4041bSJack F Vogel } 127113705f88SJack F Vogel 127213705f88SJack F Vogel return IXGBE_SUCCESS; 127313705f88SJack F Vogel } 127413705f88SJack F Vogel 127513705f88SJack F Vogel /** 12765b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 12775b7f4cedSJack F Vogel * @hw: pointer to hardware structure 12785b7f4cedSJack F Vogel * @index: Receive address register to write 12795b7f4cedSJack F Vogel * 12805b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 12815b7f4cedSJack F Vogel **/ 12825b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 12835b7f4cedSJack F Vogel { 12845b7f4cedSJack F Vogel u32 rar_high; 12855b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 12865b7f4cedSJack F Vogel 12875b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 12885b7f4cedSJack F Vogel if (index < rar_entries) { 12895b7f4cedSJack F Vogel /* 12905b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 12915b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 12925b7f4cedSJack F Vogel * of the address and the address valid bit. 12935b7f4cedSJack F Vogel */ 12945b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 12955b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 12965b7f4cedSJack F Vogel 12975b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 12985b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 12995b7f4cedSJack F Vogel } else { 13005b7f4cedSJack F Vogel DEBUGOUT1("RAR index %d is out of range.\n", index); 13015b7f4cedSJack F Vogel } 13025b7f4cedSJack F Vogel 13035b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 13045b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 13055b7f4cedSJack F Vogel 13065b7f4cedSJack F Vogel return IXGBE_SUCCESS; 13075b7f4cedSJack F Vogel } 13085b7f4cedSJack F Vogel 13095b7f4cedSJack F Vogel /** 131013705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 131113705f88SJack F Vogel * @hw: pointer to hardware structure 131213705f88SJack F Vogel * 131313705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 13149ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 131513705f88SJack F Vogel * the receiver is in reset when the routine is called. 131613705f88SJack F Vogel **/ 131713705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 131813705f88SJack F Vogel { 131913705f88SJack F Vogel u32 i; 13209ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 132113705f88SJack F Vogel 132213705f88SJack F Vogel /* 132313705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 132413705f88SJack F Vogel * to the permanent address. 132513705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 132613705f88SJack F Vogel */ 132713705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 132813705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 132913705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 13309ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 133113705f88SJack F Vogel 133213705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 133313705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 133413705f88SJack F Vogel hw->mac.addr[2]); 133513705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 133613705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 133713705f88SJack F Vogel } else { 133813705f88SJack F Vogel /* Setup the receive address. */ 133913705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 134013705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 134113705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 134213705f88SJack F Vogel hw->mac.addr[2]); 134313705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 134413705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 134513705f88SJack F Vogel 13469ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 134713705f88SJack F Vogel } 13489ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 134913705f88SJack F Vogel 135013705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 135113705f88SJack F Vogel 135213705f88SJack F Vogel /* Zero out the other receive addresses. */ 13539ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 135413705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 135513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 135613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 135713705f88SJack F Vogel } 135813705f88SJack F Vogel 135913705f88SJack F Vogel /* Clear the MTA */ 136013705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 136113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 136213705f88SJack F Vogel 136313705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 13649ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 136513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 136613705f88SJack F Vogel 13675b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 13685b7f4cedSJack F Vogel 136913705f88SJack F Vogel return IXGBE_SUCCESS; 137013705f88SJack F Vogel } 137113705f88SJack F Vogel 137213705f88SJack F Vogel /** 13739ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 13749ca4041bSJack F Vogel * @hw: pointer to hardware structure 13759ca4041bSJack F Vogel * @addr: new address 13769ca4041bSJack F Vogel * 13779ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 13789ca4041bSJack F Vogel **/ 13799ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 13809ca4041bSJack F Vogel { 13819ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 13829ca4041bSJack F Vogel u32 rar; 13839ca4041bSJack F Vogel 13849ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 13859ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 13869ca4041bSJack F Vogel 13879ca4041bSJack F Vogel /* 13889ca4041bSJack F Vogel * Place this address in the RAR if there is room, 13899ca4041bSJack F Vogel * else put the controller into promiscuous mode 13909ca4041bSJack F Vogel */ 13919ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 13920ac6dfecSJack F Vogel rar = hw->addr_ctrl.rar_used_count; 13939ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 13949ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 13959ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 13969ca4041bSJack F Vogel } else { 13979ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 13989ca4041bSJack F Vogel } 13999ca4041bSJack F Vogel 14009ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 14019ca4041bSJack F Vogel } 14029ca4041bSJack F Vogel 14039ca4041bSJack F Vogel /** 14049ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 14059ca4041bSJack F Vogel * @hw: pointer to hardware structure 14069ca4041bSJack F Vogel * @addr_list: the list of new addresses 14079ca4041bSJack F Vogel * @addr_count: number of addresses 14089ca4041bSJack F Vogel * @next: iterator function to walk the address list 14099ca4041bSJack F Vogel * 14109ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 14119ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 14129ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 14139ca4041bSJack F Vogel * 14149ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 14159ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 14169ca4041bSJack F Vogel **/ 14179ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 14189ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 14199ca4041bSJack F Vogel { 14209ca4041bSJack F Vogel u8 *addr; 14219ca4041bSJack F Vogel u32 i; 14229ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 14239ca4041bSJack F Vogel u32 uc_addr_in_use; 14249ca4041bSJack F Vogel u32 fctrl; 14259ca4041bSJack F Vogel u32 vmdq; 14269ca4041bSJack F Vogel 14279ca4041bSJack F Vogel /* 14289ca4041bSJack F Vogel * Clear accounting of old secondary address list, 14299ca4041bSJack F Vogel * don't count RAR[0] 14309ca4041bSJack F Vogel */ 14310ac6dfecSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 14329ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 14339ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 14349ca4041bSJack F Vogel 14359ca4041bSJack F Vogel /* Zero out the other receive addresses */ 14360ac6dfecSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", hw->addr_ctrl.rar_used_count); 14370ac6dfecSJack F Vogel for (i = 1; i <= hw->addr_ctrl.rar_used_count; i++) { 14389ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 14399ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 14409ca4041bSJack F Vogel } 14419ca4041bSJack F Vogel 14429ca4041bSJack F Vogel /* Add the new addresses */ 14439ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 14449ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 14459ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 14469ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 14479ca4041bSJack F Vogel } 14489ca4041bSJack F Vogel 14499ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 14509ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 14519ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 14529ca4041bSJack F Vogel DEBUGOUT(" Entering address overflow promisc mode\n"); 14539ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 14549ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 14559ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 14569ca4041bSJack F Vogel } 14579ca4041bSJack F Vogel } else { 14589ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 14599ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 14609ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 14619ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 14629ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 14639ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 14649ca4041bSJack F Vogel } 14659ca4041bSJack F Vogel } 14669ca4041bSJack F Vogel 14679ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 14689ca4041bSJack F Vogel return IXGBE_SUCCESS; 14699ca4041bSJack F Vogel } 14709ca4041bSJack F Vogel 14719ca4041bSJack F Vogel /** 147213705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 147313705f88SJack F Vogel * @hw: pointer to hardware structure 147413705f88SJack F Vogel * @mc_addr: the multicast address 147513705f88SJack F Vogel * 147613705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 147713705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 147813705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 147913705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 14809ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 148113705f88SJack F Vogel * to mc_filter_type. 148213705f88SJack F Vogel **/ 148313705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 148413705f88SJack F Vogel { 148513705f88SJack F Vogel u32 vector = 0; 148613705f88SJack F Vogel 148713705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 148813705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 148913705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 149013705f88SJack F Vogel break; 149113705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 149213705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 149313705f88SJack F Vogel break; 149413705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 149513705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 149613705f88SJack F Vogel break; 149713705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 149813705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 149913705f88SJack F Vogel break; 150013705f88SJack F Vogel default: /* Invalid mc_filter_type */ 150113705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 150213705f88SJack F Vogel ASSERT(0); 150313705f88SJack F Vogel break; 150413705f88SJack F Vogel } 150513705f88SJack F Vogel 150613705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 150713705f88SJack F Vogel vector &= 0xFFF; 150813705f88SJack F Vogel return vector; 150913705f88SJack F Vogel } 151013705f88SJack F Vogel 151113705f88SJack F Vogel /** 151213705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 151313705f88SJack F Vogel * @hw: pointer to hardware structure 151413705f88SJack F Vogel * @hash_value: Multicast address hash value 151513705f88SJack F Vogel * 151613705f88SJack F Vogel * Sets the bit-vector in the multicast table. 151713705f88SJack F Vogel **/ 151813705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 151913705f88SJack F Vogel { 152013705f88SJack F Vogel u32 vector; 152113705f88SJack F Vogel u32 vector_bit; 152213705f88SJack F Vogel u32 vector_reg; 152313705f88SJack F Vogel u32 mta_reg; 152413705f88SJack F Vogel 152513705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 152613705f88SJack F Vogel 152713705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 152813705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 152913705f88SJack F Vogel 153013705f88SJack F Vogel /* 153113705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 153213705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 153313705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 153413705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 153513705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 153613705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 153713705f88SJack F Vogel * the value. 153813705f88SJack F Vogel */ 153913705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 154013705f88SJack F Vogel vector_bit = vector & 0x1F; 154113705f88SJack F Vogel mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); 154213705f88SJack F Vogel mta_reg |= (1 << vector_bit); 154313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); 154413705f88SJack F Vogel } 154513705f88SJack F Vogel 154613705f88SJack F Vogel /** 154713705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 154813705f88SJack F Vogel * @hw: pointer to hardware structure 154913705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 155013705f88SJack F Vogel * @mc_addr_count: number of addresses 15519ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 155213705f88SJack F Vogel * 155313705f88SJack F Vogel * The given list replaces any existing list. Clears the MC addrs from receive 15549ca4041bSJack F Vogel * address registers and the multicast table. Uses unused receive address 155513705f88SJack F Vogel * registers for the first multicast addresses, and hashes the rest into the 155613705f88SJack F Vogel * multicast table. 155713705f88SJack F Vogel **/ 155813705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 15599ca4041bSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next) 156013705f88SJack F Vogel { 156113705f88SJack F Vogel u32 i; 15629ca4041bSJack F Vogel u32 vmdq; 156313705f88SJack F Vogel 156413705f88SJack F Vogel /* 156513705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 156613705f88SJack F Vogel * use. 156713705f88SJack F Vogel */ 156813705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 156913705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 157013705f88SJack F Vogel 157113705f88SJack F Vogel /* Clear the MTA */ 157213705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 15739ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 157413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 157513705f88SJack F Vogel 157613705f88SJack F Vogel /* Add the new addresses */ 157713705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 157813705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 15790ac6dfecSJack F Vogel ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 158013705f88SJack F Vogel } 158113705f88SJack F Vogel 158213705f88SJack F Vogel /* Enable mta */ 158313705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 158413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 158513705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 158613705f88SJack F Vogel 158713705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 158813705f88SJack F Vogel return IXGBE_SUCCESS; 158913705f88SJack F Vogel } 159013705f88SJack F Vogel 159113705f88SJack F Vogel /** 159213705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 159313705f88SJack F Vogel * @hw: pointer to hardware structure 159413705f88SJack F Vogel * 159513705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 159613705f88SJack F Vogel **/ 159713705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 159813705f88SJack F Vogel { 159913705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 160013705f88SJack F Vogel 160113705f88SJack F Vogel if (a->mta_in_use > 0) 160213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 160313705f88SJack F Vogel hw->mac.mc_filter_type); 160413705f88SJack F Vogel 160513705f88SJack F Vogel return IXGBE_SUCCESS; 160613705f88SJack F Vogel } 160713705f88SJack F Vogel 160813705f88SJack F Vogel /** 16099ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 161013705f88SJack F Vogel * @hw: pointer to hardware structure 161113705f88SJack F Vogel * 161213705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 161313705f88SJack F Vogel **/ 161413705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 161513705f88SJack F Vogel { 161613705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 161713705f88SJack F Vogel 161813705f88SJack F Vogel if (a->mta_in_use > 0) 161913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 162013705f88SJack F Vogel 162113705f88SJack F Vogel return IXGBE_SUCCESS; 162213705f88SJack F Vogel } 162313705f88SJack F Vogel 16241b6e0dbaSJack F Vogel /** 16250ac6dfecSJack F Vogel * ixgbe_fc_enable_generic - Enable flow control 16261b6e0dbaSJack F Vogel * @hw: pointer to hardware structure 16270ac6dfecSJack F Vogel * @packetbuf_num: packet buffer number (0-7) 16281b6e0dbaSJack F Vogel * 16290ac6dfecSJack F Vogel * Enable flow control according to the current settings. 16301b6e0dbaSJack F Vogel **/ 16310ac6dfecSJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) 16321b6e0dbaSJack F Vogel { 16331b6e0dbaSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 16340ac6dfecSJack F Vogel u32 mflcn_reg, fccfg_reg; 16350ac6dfecSJack F Vogel u32 reg; 16361b6e0dbaSJack F Vogel 16370ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_enable_generic"); 16381b6e0dbaSJack F Vogel 16390ac6dfecSJack F Vogel /* Negotiate the fc mode to use */ 16400ac6dfecSJack F Vogel ret_val = ixgbe_fc_autoneg(hw); 16410ac6dfecSJack F Vogel if (ret_val) 16420ac6dfecSJack F Vogel goto out; 16430ac6dfecSJack F Vogel 16440ac6dfecSJack F Vogel /* Disable any previous flow control settings */ 16450ac6dfecSJack F Vogel mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 16460ac6dfecSJack F Vogel mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE); 16470ac6dfecSJack F Vogel 16480ac6dfecSJack F Vogel fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 16490ac6dfecSJack F Vogel fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 16501b6e0dbaSJack F Vogel 16511b6e0dbaSJack F Vogel /* 16521b6e0dbaSJack F Vogel * The possible values of fc.current_mode are: 16531b6e0dbaSJack F Vogel * 0: Flow control is completely disabled 16541b6e0dbaSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 16551b6e0dbaSJack F Vogel * but not send pause frames). 16561b6e0dbaSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 16571b6e0dbaSJack F Vogel * we do not support receiving pause frames). 16581b6e0dbaSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 16591b6e0dbaSJack F Vogel * other: Invalid. 16601b6e0dbaSJack F Vogel */ 16611b6e0dbaSJack F Vogel switch (hw->fc.current_mode) { 16621b6e0dbaSJack F Vogel case ixgbe_fc_none: 16630ac6dfecSJack F Vogel /* Flow control is disabled by software override or autoneg. 16640ac6dfecSJack F Vogel * The code below will actually disable it in the HW. 16650ac6dfecSJack F Vogel */ 16661b6e0dbaSJack F Vogel break; 16671b6e0dbaSJack F Vogel case ixgbe_fc_rx_pause: 16681b6e0dbaSJack F Vogel /* 16691b6e0dbaSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 16701b6e0dbaSJack F Vogel * disabled by software override. Since there really 16711b6e0dbaSJack F Vogel * isn't a way to advertise that we are capable of RX 16721b6e0dbaSJack F Vogel * Pause ONLY, we will advertise that we support both 16731b6e0dbaSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 16741b6e0dbaSJack F Vogel * disable the adapter's ability to send PAUSE frames. 16751b6e0dbaSJack F Vogel */ 16760ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 16771b6e0dbaSJack F Vogel break; 16781b6e0dbaSJack F Vogel case ixgbe_fc_tx_pause: 16791b6e0dbaSJack F Vogel /* 16801b6e0dbaSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 16811b6e0dbaSJack F Vogel * disabled by software override. 16821b6e0dbaSJack F Vogel */ 16830ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 16841b6e0dbaSJack F Vogel break; 16851b6e0dbaSJack F Vogel case ixgbe_fc_full: 16861b6e0dbaSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 16870ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 16880ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 16891b6e0dbaSJack F Vogel break; 16901b6e0dbaSJack F Vogel default: 16911b6e0dbaSJack F Vogel DEBUGOUT("Flow control param set incorrectly\n"); 16921b6e0dbaSJack F Vogel ret_val = -IXGBE_ERR_CONFIG; 16931b6e0dbaSJack F Vogel goto out; 16941b6e0dbaSJack F Vogel break; 16951b6e0dbaSJack F Vogel } 16961b6e0dbaSJack F Vogel 16970ac6dfecSJack F Vogel /* Set 802.3x based flow control settings. */ 16980ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_DPF; 16990ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 17000ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 17011b6e0dbaSJack F Vogel 17020ac6dfecSJack F Vogel /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 17030ac6dfecSJack F Vogel if (hw->fc.current_mode & ixgbe_fc_tx_pause) { 17040ac6dfecSJack F Vogel if (hw->fc.send_xon) { 17050ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), 17060ac6dfecSJack F Vogel (hw->fc.low_water | IXGBE_FCRTL_XONE)); 17070ac6dfecSJack F Vogel } else { 17080ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), 17090ac6dfecSJack F Vogel hw->fc.low_water); 17101b6e0dbaSJack F Vogel } 17111b6e0dbaSJack F Vogel 17120ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), 17130ac6dfecSJack F Vogel (hw->fc.high_water | IXGBE_FCRTH_FCEN)); 17140ac6dfecSJack F Vogel } 17150ac6dfecSJack F Vogel 17160ac6dfecSJack F Vogel /* Configure pause time (2 TCs per register) */ 17170ac6dfecSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num)); 17180ac6dfecSJack F Vogel if ((packetbuf_num & 1) == 0) 17190ac6dfecSJack F Vogel reg = (reg & 0xFFFF0000) | hw->fc.pause_time; 17200ac6dfecSJack F Vogel else 17210ac6dfecSJack F Vogel reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16); 17220ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg); 17230ac6dfecSJack F Vogel 17240ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); 17250ac6dfecSJack F Vogel 17260ac6dfecSJack F Vogel out: 17270ac6dfecSJack F Vogel return ret_val; 17280ac6dfecSJack F Vogel } 17290ac6dfecSJack F Vogel 17300ac6dfecSJack F Vogel /** 17310ac6dfecSJack F Vogel * ixgbe_fc_autoneg - Configure flow control 17320ac6dfecSJack F Vogel * @hw: pointer to hardware structure 17330ac6dfecSJack F Vogel * 17340ac6dfecSJack F Vogel * Compares our advertised flow control capabilities to those advertised by 17350ac6dfecSJack F Vogel * our link partner, and determines the proper flow control mode to use. 17360ac6dfecSJack F Vogel **/ 17370ac6dfecSJack F Vogel s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) 17380ac6dfecSJack F Vogel { 17390ac6dfecSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 17400ac6dfecSJack F Vogel ixgbe_link_speed speed; 17410ac6dfecSJack F Vogel u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 17420ac6dfecSJack F Vogel bool link_up; 17430ac6dfecSJack F Vogel 17440ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_autoneg"); 17450ac6dfecSJack F Vogel 17460ac6dfecSJack F Vogel /* 17470ac6dfecSJack F Vogel * AN should have completed when the cable was plugged in. 17480ac6dfecSJack F Vogel * Look for reasons to bail out. Bail out if: 17490ac6dfecSJack F Vogel * - FC autoneg is disabled, or if 17500ac6dfecSJack F Vogel * - we don't have multispeed fiber, or if 17510ac6dfecSJack F Vogel * - we're not running at 1G, or if 17520ac6dfecSJack F Vogel * - link is not up, or if 17530ac6dfecSJack F Vogel * - link is up but AN did not complete, or if 17540ac6dfecSJack F Vogel * - link is up and AN completed but timed out 17550ac6dfecSJack F Vogel * 17560ac6dfecSJack F Vogel * Since we're being called from an LSC, link is already know to be up. 17570ac6dfecSJack F Vogel * So use link_up_wait_to_complete=FALSE. 17580ac6dfecSJack F Vogel */ 17590ac6dfecSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 17600ac6dfecSJack F Vogel linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 17610ac6dfecSJack F Vogel 17620ac6dfecSJack F Vogel if (hw->fc.disable_fc_autoneg || 17630ac6dfecSJack F Vogel !hw->phy.multispeed_fiber || 17640ac6dfecSJack F Vogel (speed != IXGBE_LINK_SPEED_1GB_FULL) || 17650ac6dfecSJack F Vogel !link_up || 17660ac6dfecSJack F Vogel ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 17670ac6dfecSJack F Vogel ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 17680ac6dfecSJack F Vogel hw->fc.fc_was_autonegged = FALSE; 17690ac6dfecSJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 17700ac6dfecSJack F Vogel DEBUGOUT("Autoneg FC was skipped.\n"); 17711b6e0dbaSJack F Vogel goto out; 17721b6e0dbaSJack F Vogel } 17731b6e0dbaSJack F Vogel 17741b6e0dbaSJack F Vogel /* 17751b6e0dbaSJack F Vogel * Read the AN advertisement and LP ability registers and resolve 17761b6e0dbaSJack F Vogel * local flow control settings accordingly 17771b6e0dbaSJack F Vogel */ 17781b6e0dbaSJack F Vogel pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 17791b6e0dbaSJack F Vogel pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 17801b6e0dbaSJack F Vogel if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 17811b6e0dbaSJack F Vogel (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { 17821b6e0dbaSJack F Vogel /* 17831b6e0dbaSJack F Vogel * Now we need to check if the user selected Rx ONLY 17841b6e0dbaSJack F Vogel * of pause frames. In this case, we had to advertise 17851b6e0dbaSJack F Vogel * FULL flow control because we could not advertise RX 17861b6e0dbaSJack F Vogel * ONLY. Hence, we must now check to see if we need to 17871b6e0dbaSJack F Vogel * turn OFF the TRANSMISSION of PAUSE frames. 17881b6e0dbaSJack F Vogel */ 17891b6e0dbaSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_full) { 17901b6e0dbaSJack F Vogel hw->fc.current_mode = ixgbe_fc_full; 17911b6e0dbaSJack F Vogel DEBUGOUT("Flow Control = FULL.\n"); 17921b6e0dbaSJack F Vogel } else { 17931b6e0dbaSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 17941b6e0dbaSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 17951b6e0dbaSJack F Vogel } 17961b6e0dbaSJack F Vogel } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 17971b6e0dbaSJack F Vogel (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && 17981b6e0dbaSJack F Vogel (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 17991b6e0dbaSJack F Vogel (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { 18001b6e0dbaSJack F Vogel hw->fc.current_mode = ixgbe_fc_tx_pause; 18011b6e0dbaSJack F Vogel DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 18021b6e0dbaSJack F Vogel } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 18031b6e0dbaSJack F Vogel (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && 18041b6e0dbaSJack F Vogel !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 18051b6e0dbaSJack F Vogel (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { 18061b6e0dbaSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 18071b6e0dbaSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 18081b6e0dbaSJack F Vogel } else { 18091b6e0dbaSJack F Vogel hw->fc.current_mode = ixgbe_fc_none; 18101b6e0dbaSJack F Vogel DEBUGOUT("Flow Control = NONE.\n"); 18111b6e0dbaSJack F Vogel } 18121b6e0dbaSJack F Vogel 18130ac6dfecSJack F Vogel /* Record that current_mode is the result of a successful autoneg */ 18140ac6dfecSJack F Vogel hw->fc.fc_was_autonegged = TRUE; 18150ac6dfecSJack F Vogel 18161b6e0dbaSJack F Vogel out: 18171b6e0dbaSJack F Vogel return ret_val; 18181b6e0dbaSJack F Vogel } 18191b6e0dbaSJack F Vogel 18200ac6dfecSJack F Vogel /** 18210ac6dfecSJack F Vogel * ixgbe_setup_fc - Set up flow control 18220ac6dfecSJack F Vogel * @hw: pointer to hardware structure 18230ac6dfecSJack F Vogel * 18240ac6dfecSJack F Vogel * Called at init time to set up flow control. 18250ac6dfecSJack F Vogel **/ 18260ac6dfecSJack F Vogel s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) 18270ac6dfecSJack F Vogel { 18280ac6dfecSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 18290ac6dfecSJack F Vogel u32 reg; 18300ac6dfecSJack F Vogel 18310ac6dfecSJack F Vogel 18320ac6dfecSJack F Vogel /* Validate the packetbuf configuration */ 18330ac6dfecSJack F Vogel if (packetbuf_num < 0 || packetbuf_num > 7) { 18340ac6dfecSJack F Vogel DEBUGOUT1("Invalid packet buffer number [%d], expected range is" 18350ac6dfecSJack F Vogel " 0-7\n", packetbuf_num); 18360ac6dfecSJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 18370ac6dfecSJack F Vogel goto out; 18380ac6dfecSJack F Vogel } 18390ac6dfecSJack F Vogel 18400ac6dfecSJack F Vogel /* 18410ac6dfecSJack F Vogel * Validate the water mark configuration. Zero water marks are invalid 18420ac6dfecSJack F Vogel * because it causes the controller to just blast out fc packets. 18430ac6dfecSJack F Vogel */ 18440ac6dfecSJack F Vogel if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { 18450ac6dfecSJack F Vogel DEBUGOUT("Invalid water mark configuration\n"); 18460ac6dfecSJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 18470ac6dfecSJack F Vogel goto out; 18480ac6dfecSJack F Vogel } 18490ac6dfecSJack F Vogel 18500ac6dfecSJack F Vogel /* 18510ac6dfecSJack F Vogel * Validate the requested mode. Strict IEEE mode does not allow 18520ac6dfecSJack F Vogel * ixgbe_fc_rx_pause because it will cause us to fail at UNH. 18530ac6dfecSJack F Vogel */ 18540ac6dfecSJack F Vogel if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 18550ac6dfecSJack F Vogel DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 18560ac6dfecSJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 18570ac6dfecSJack F Vogel goto out; 18580ac6dfecSJack F Vogel } 18590ac6dfecSJack F Vogel 18600ac6dfecSJack F Vogel /* 18610ac6dfecSJack F Vogel * 10gig parts do not have a word in the EEPROM to determine the 18620ac6dfecSJack F Vogel * default flow control setting, so we explicitly set it to full. 18630ac6dfecSJack F Vogel */ 18640ac6dfecSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_default) 18650ac6dfecSJack F Vogel hw->fc.requested_mode = ixgbe_fc_full; 18660ac6dfecSJack F Vogel 18670ac6dfecSJack F Vogel /* 18680ac6dfecSJack F Vogel * Set up the 1G flow control advertisement registers so the HW will be 18690ac6dfecSJack F Vogel * able to do fc autoneg once the cable is plugged in. If we end up 18700ac6dfecSJack F Vogel * using 10g instead, this is harmless. 18710ac6dfecSJack F Vogel */ 18720ac6dfecSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 18730ac6dfecSJack F Vogel 18740ac6dfecSJack F Vogel /* 18750ac6dfecSJack F Vogel * The possible values of fc.requested_mode are: 18760ac6dfecSJack F Vogel * 0: Flow control is completely disabled 18770ac6dfecSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 18780ac6dfecSJack F Vogel * but not send pause frames). 18790ac6dfecSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 18800ac6dfecSJack F Vogel * we do not support receiving pause frames). 18810ac6dfecSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 18820ac6dfecSJack F Vogel * other: Invalid. 18830ac6dfecSJack F Vogel */ 18840ac6dfecSJack F Vogel switch (hw->fc.requested_mode) { 18850ac6dfecSJack F Vogel case ixgbe_fc_none: 18860ac6dfecSJack F Vogel /* Flow control completely disabled by software override. */ 18870ac6dfecSJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 18880ac6dfecSJack F Vogel break; 18890ac6dfecSJack F Vogel case ixgbe_fc_rx_pause: 18900ac6dfecSJack F Vogel /* 18910ac6dfecSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 18920ac6dfecSJack F Vogel * disabled by software override. Since there really 18930ac6dfecSJack F Vogel * isn't a way to advertise that we are capable of RX 18940ac6dfecSJack F Vogel * Pause ONLY, we will advertise that we support both 18950ac6dfecSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 18960ac6dfecSJack F Vogel * disable the adapter's ability to send PAUSE frames. 18970ac6dfecSJack F Vogel */ 18980ac6dfecSJack F Vogel reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 18990ac6dfecSJack F Vogel break; 19000ac6dfecSJack F Vogel case ixgbe_fc_tx_pause: 19010ac6dfecSJack F Vogel /* 19020ac6dfecSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 19030ac6dfecSJack F Vogel * disabled by software override. 19040ac6dfecSJack F Vogel */ 19050ac6dfecSJack F Vogel reg |= (IXGBE_PCS1GANA_ASM_PAUSE); 19060ac6dfecSJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE); 19070ac6dfecSJack F Vogel break; 19080ac6dfecSJack F Vogel case ixgbe_fc_full: 19090ac6dfecSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 19100ac6dfecSJack F Vogel reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 19110ac6dfecSJack F Vogel break; 19120ac6dfecSJack F Vogel default: 19130ac6dfecSJack F Vogel DEBUGOUT("Flow control param set incorrectly\n"); 19140ac6dfecSJack F Vogel ret_val = -IXGBE_ERR_CONFIG; 19150ac6dfecSJack F Vogel goto out; 19160ac6dfecSJack F Vogel break; 19170ac6dfecSJack F Vogel } 19180ac6dfecSJack F Vogel 19190ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 19200ac6dfecSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 19210ac6dfecSJack F Vogel 19220ac6dfecSJack F Vogel /* Enable and restart autoneg to inform the link partner */ 19230ac6dfecSJack F Vogel reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART; 19240ac6dfecSJack F Vogel 19250ac6dfecSJack F Vogel /* Disable AN timeout */ 19260ac6dfecSJack F Vogel if (hw->fc.strict_ieee) 19270ac6dfecSJack F Vogel reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 19280ac6dfecSJack F Vogel 19290ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 19300ac6dfecSJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 19310ac6dfecSJack F Vogel 19320ac6dfecSJack F Vogel out: 19330ac6dfecSJack F Vogel return ret_val; 19340ac6dfecSJack F Vogel } 19351b6e0dbaSJack F Vogel 193613705f88SJack F Vogel /** 193713705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 193813705f88SJack F Vogel * @hw: pointer to hardware structure 193913705f88SJack F Vogel * 194013705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 194113705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 194213705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 194313705f88SJack F Vogel * is returned signifying master requests disabled. 194413705f88SJack F Vogel **/ 194513705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 194613705f88SJack F Vogel { 19475b7f4cedSJack F Vogel u32 i; 19485b7f4cedSJack F Vogel u32 reg_val; 19495b7f4cedSJack F Vogel u32 number_of_queues; 195013705f88SJack F Vogel s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 195113705f88SJack F Vogel 19525b7f4cedSJack F Vogel /* Disable the receive unit by stopping each queue */ 19535b7f4cedSJack F Vogel number_of_queues = hw->mac.max_rx_queues; 19545b7f4cedSJack F Vogel for (i = 0; i < number_of_queues; i++) { 19555b7f4cedSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 19565b7f4cedSJack F Vogel if (reg_val & IXGBE_RXDCTL_ENABLE) { 19575b7f4cedSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 19585b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 19595b7f4cedSJack F Vogel } 19605b7f4cedSJack F Vogel } 19615b7f4cedSJack F Vogel 19625b7f4cedSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL); 19635b7f4cedSJack F Vogel reg_val |= IXGBE_CTRL_GIO_DIS; 19645b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); 196513705f88SJack F Vogel 196613705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 196713705f88SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { 196813705f88SJack F Vogel status = IXGBE_SUCCESS; 196913705f88SJack F Vogel break; 197013705f88SJack F Vogel } 197113705f88SJack F Vogel usec_delay(100); 197213705f88SJack F Vogel } 197313705f88SJack F Vogel 197413705f88SJack F Vogel return status; 197513705f88SJack F Vogel } 197613705f88SJack F Vogel 197713705f88SJack F Vogel 197813705f88SJack F Vogel /** 19799ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 198013705f88SJack F Vogel * @hw: pointer to hardware structure 19819ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 198213705f88SJack F Vogel * 19839ca4041bSJack F Vogel * Acquires the SWFW semaphore thought the GSSR register for the specified 198413705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 198513705f88SJack F Vogel **/ 198613705f88SJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) 198713705f88SJack F Vogel { 198813705f88SJack F Vogel u32 gssr; 198913705f88SJack F Vogel u32 swmask = mask; 199013705f88SJack F Vogel u32 fwmask = mask << 5; 199113705f88SJack F Vogel s32 timeout = 200; 199213705f88SJack F Vogel 199313705f88SJack F Vogel while (timeout) { 19940ac6dfecSJack F Vogel /* 19950ac6dfecSJack F Vogel * SW EEPROM semaphore bit is used for access to all 19960ac6dfecSJack F Vogel * SW_FW_SYNC/GSSR bits (not just EEPROM) 19970ac6dfecSJack F Vogel */ 199813705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 199913705f88SJack F Vogel return -IXGBE_ERR_SWFW_SYNC; 200013705f88SJack F Vogel 200113705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 200213705f88SJack F Vogel if (!(gssr & (fwmask | swmask))) 200313705f88SJack F Vogel break; 200413705f88SJack F Vogel 200513705f88SJack F Vogel /* 200613705f88SJack F Vogel * Firmware currently using resource (fwmask) or other software 200713705f88SJack F Vogel * thread currently using resource (swmask) 200813705f88SJack F Vogel */ 200913705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 201013705f88SJack F Vogel msec_delay(5); 201113705f88SJack F Vogel timeout--; 201213705f88SJack F Vogel } 201313705f88SJack F Vogel 201413705f88SJack F Vogel if (!timeout) { 20150ac6dfecSJack F Vogel DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); 201613705f88SJack F Vogel return -IXGBE_ERR_SWFW_SYNC; 201713705f88SJack F Vogel } 201813705f88SJack F Vogel 201913705f88SJack F Vogel gssr |= swmask; 202013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 202113705f88SJack F Vogel 202213705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 202313705f88SJack F Vogel return IXGBE_SUCCESS; 202413705f88SJack F Vogel } 202513705f88SJack F Vogel 202613705f88SJack F Vogel /** 202713705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 202813705f88SJack F Vogel * @hw: pointer to hardware structure 20299ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 203013705f88SJack F Vogel * 20319ca4041bSJack F Vogel * Releases the SWFW semaphore thought the GSSR register for the specified 203213705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 203313705f88SJack F Vogel **/ 203413705f88SJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) 203513705f88SJack F Vogel { 203613705f88SJack F Vogel u32 gssr; 203713705f88SJack F Vogel u32 swmask = mask; 203813705f88SJack F Vogel 203913705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 204013705f88SJack F Vogel 204113705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 204213705f88SJack F Vogel gssr &= ~swmask; 204313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 204413705f88SJack F Vogel 204513705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 20460ac6dfecSJack F Vogel 20470ac6dfecSJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 20480ac6dfecSJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 20490ac6dfecSJack F Vogel } 20500ac6dfecSJack F Vogel 20510ac6dfecSJack F Vogel /** 20520ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 20530ac6dfecSJack F Vogel * @hw: pointer to hardware structure 20540ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 20550ac6dfecSJack F Vogel * 20560ac6dfecSJack F Vogel * Enables the Rx DMA unit 20570ac6dfecSJack F Vogel **/ 20580ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 20590ac6dfecSJack F Vogel { 20600ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); 20610ac6dfecSJack F Vogel 20620ac6dfecSJack F Vogel return IXGBE_SUCCESS; 20630ac6dfecSJack F Vogel } 20640ac6dfecSJack F Vogel 20650ac6dfecSJack F Vogel /** 20660ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 20670ac6dfecSJack F Vogel * @hw: pointer to hardware structure 20680ac6dfecSJack F Vogel * @index: led number to blink 20690ac6dfecSJack F Vogel **/ 20700ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 20710ac6dfecSJack F Vogel { 20720ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 20730ac6dfecSJack F Vogel bool link_up = 0; 20740ac6dfecSJack F Vogel u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 20750ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 20760ac6dfecSJack F Vogel 20770ac6dfecSJack F Vogel /* 20780ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 20790ac6dfecSJack F Vogel * Force it if link is down. 20800ac6dfecSJack F Vogel */ 20810ac6dfecSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 20820ac6dfecSJack F Vogel 20830ac6dfecSJack F Vogel if (!link_up) { 20840ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 20850ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); 20860ac6dfecSJack F Vogel msec_delay(10); 20870ac6dfecSJack F Vogel } 20880ac6dfecSJack F Vogel 20890ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 20900ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 20910ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 20920ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 20930ac6dfecSJack F Vogel 20940ac6dfecSJack F Vogel return IXGBE_SUCCESS; 20950ac6dfecSJack F Vogel } 20960ac6dfecSJack F Vogel 20970ac6dfecSJack F Vogel /** 20980ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 20990ac6dfecSJack F Vogel * @hw: pointer to hardware structure 21000ac6dfecSJack F Vogel * @index: led number to stop blinking 21010ac6dfecSJack F Vogel **/ 21020ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 21030ac6dfecSJack F Vogel { 21040ac6dfecSJack F Vogel u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 21050ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 21060ac6dfecSJack F Vogel 21070ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 21080ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 21090ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); 21100ac6dfecSJack F Vogel 21110ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 21120ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 21130ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 21140ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 21150ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 21160ac6dfecSJack F Vogel 21170ac6dfecSJack F Vogel return IXGBE_SUCCESS; 211813705f88SJack F Vogel } 211913705f88SJack F Vogel 2120