19ca4041bSJack F Vogel /****************************************************************************** 213705f88SJack F Vogel 39ca4041bSJack F Vogel Copyright (c) 2001-2008, 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 void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); 5313705f88SJack F Vogel static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); 5413705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 5513705f88SJack F Vogel void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); 569ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); 5713705f88SJack F Vogel 5813705f88SJack F Vogel /** 599ca4041bSJack F Vogel * ixgbe_init_ops_generic - Inits function ptrs 609ca4041bSJack F Vogel * @hw: pointer to the hardware structure 6113705f88SJack F Vogel * 629ca4041bSJack F Vogel * Initialize the function pointers. 6313705f88SJack F Vogel **/ 649ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 6513705f88SJack F Vogel { 669ca4041bSJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 679ca4041bSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 689ca4041bSJack F Vogel u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 6913705f88SJack F Vogel 7013705f88SJack F Vogel /* EEPROM */ 719ca4041bSJack F Vogel eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; 729ca4041bSJack F Vogel /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 739ca4041bSJack F Vogel if (eec & (1 << 8)) 749ca4041bSJack F Vogel eeprom->ops.read = &ixgbe_read_eeprom_generic; 759ca4041bSJack F Vogel else 769ca4041bSJack F Vogel eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; 779ca4041bSJack F Vogel eeprom->ops.write = &ixgbe_write_eeprom_generic; 789ca4041bSJack F Vogel eeprom->ops.validate_checksum = 7913705f88SJack F Vogel &ixgbe_validate_eeprom_checksum_generic; 809ca4041bSJack F Vogel eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; 819ca4041bSJack F Vogel 829ca4041bSJack F Vogel /* MAC */ 839ca4041bSJack F Vogel mac->ops.init_hw = &ixgbe_init_hw_generic; 849ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 859ca4041bSJack F Vogel mac->ops.start_hw = &ixgbe_start_hw_generic; 869ca4041bSJack F Vogel mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; 879ca4041bSJack F Vogel mac->ops.get_media_type = NULL; 889ca4041bSJack F Vogel mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic; 899ca4041bSJack F Vogel mac->ops.stop_adapter = &ixgbe_stop_adapter_generic; 909ca4041bSJack F Vogel mac->ops.get_bus_info = &ixgbe_get_bus_info_generic; 919ca4041bSJack F Vogel mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_generic; 929ca4041bSJack F Vogel mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_generic; 939ca4041bSJack F Vogel 949ca4041bSJack F Vogel /* LEDs */ 959ca4041bSJack F Vogel mac->ops.led_on = &ixgbe_led_on_generic; 969ca4041bSJack F Vogel mac->ops.led_off = &ixgbe_led_off_generic; 979ca4041bSJack F Vogel mac->ops.blink_led_start = NULL; 989ca4041bSJack F Vogel mac->ops.blink_led_stop = NULL; 999ca4041bSJack F Vogel 10013705f88SJack F Vogel /* RAR, Multicast, VLAN */ 1019ca4041bSJack F Vogel mac->ops.set_rar = &ixgbe_set_rar_generic; 1029ca4041bSJack F Vogel mac->ops.set_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; 1089ca4041bSJack F Vogel mac->ops.clear_vfta = &ixgbe_clear_vfta_generic; 1099ca4041bSJack F Vogel mac->ops.set_vfta = &ixgbe_set_vfta_generic; 1109ca4041bSJack F Vogel 1119ca4041bSJack F Vogel /* Flow Control */ 1129ca4041bSJack F Vogel mac->ops.setup_fc = NULL; 1139ca4041bSJack F Vogel 1149ca4041bSJack F Vogel /* Link */ 1159ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1169ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1179ca4041bSJack F Vogel mac->ops.setup_link_speed = NULL; 1189ca4041bSJack F Vogel mac->ops.check_link = NULL; 11913705f88SJack F Vogel 12013705f88SJack F Vogel return IXGBE_SUCCESS; 12113705f88SJack F Vogel } 12213705f88SJack F Vogel 12313705f88SJack F Vogel /** 1249ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 12513705f88SJack F Vogel * @hw: pointer to hardware structure 12613705f88SJack F Vogel * 12713705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 12813705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 12913705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 13013705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 13113705f88SJack F Vogel **/ 13213705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 13313705f88SJack F Vogel { 13413705f88SJack F Vogel u32 ctrl_ext; 13513705f88SJack F Vogel 13613705f88SJack F Vogel /* Set the media type */ 1379ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 13813705f88SJack F Vogel 13913705f88SJack F Vogel /* Set bus info */ 1409ca4041bSJack F Vogel hw->mac.ops.get_bus_info(hw); 14113705f88SJack F Vogel 14213705f88SJack F Vogel /* Identify the PHY */ 1439ca4041bSJack F Vogel hw->phy.ops.identify(hw); 14413705f88SJack F Vogel 14513705f88SJack F Vogel /* 14613705f88SJack F Vogel * Store MAC address from RAR0, clear receive address registers, and 14713705f88SJack F Vogel * clear the multicast table 14813705f88SJack F Vogel */ 1499ca4041bSJack F Vogel hw->mac.ops.init_rx_addrs(hw); 15013705f88SJack F Vogel 15113705f88SJack F Vogel /* Clear the VLAN filter table */ 1529ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 15313705f88SJack F Vogel 15413705f88SJack F Vogel /* Set up link */ 1559ca4041bSJack F Vogel hw->mac.ops.setup_link(hw); 15613705f88SJack F Vogel 15713705f88SJack F Vogel /* Clear statistics registers */ 1589ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 15913705f88SJack F Vogel 16013705f88SJack F Vogel /* Set No Snoop Disable */ 16113705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 16213705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 16313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 1649ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 16513705f88SJack F Vogel 16613705f88SJack F Vogel /* Clear adapter stopped flag */ 16713705f88SJack F Vogel hw->adapter_stopped = FALSE; 16813705f88SJack F Vogel 16913705f88SJack F Vogel return IXGBE_SUCCESS; 17013705f88SJack F Vogel } 17113705f88SJack F Vogel 17213705f88SJack F Vogel /** 17313705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 17413705f88SJack F Vogel * @hw: pointer to hardware structure 17513705f88SJack F Vogel * 1769ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 17713705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 17813705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 17913705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 18013705f88SJack F Vogel * disabled and uninitialized 18113705f88SJack F Vogel **/ 18213705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 18313705f88SJack F Vogel { 18413705f88SJack F Vogel /* Reset the hardware */ 1859ca4041bSJack F Vogel hw->mac.ops.reset_hw(hw); 18613705f88SJack F Vogel 18713705f88SJack F Vogel /* Start the HW */ 1889ca4041bSJack F Vogel hw->mac.ops.start_hw(hw); 18913705f88SJack F Vogel 19013705f88SJack F Vogel return IXGBE_SUCCESS; 19113705f88SJack F Vogel } 19213705f88SJack F Vogel 19313705f88SJack F Vogel /** 19413705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 19513705f88SJack F Vogel * @hw: pointer to hardware structure 19613705f88SJack F Vogel * 19713705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 19813705f88SJack F Vogel * Statistics counters are clear on read. 19913705f88SJack F Vogel **/ 20013705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 20113705f88SJack F Vogel { 20213705f88SJack F Vogel u16 i = 0; 20313705f88SJack F Vogel 20413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 20513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 20613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 20713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 20813705f88SJack F Vogel for (i = 0; i < 8; i++) 20913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 21013705f88SJack F Vogel 21113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 21213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 21313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 21413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 21513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 21613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 21713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 21813705f88SJack F Vogel 21913705f88SJack F Vogel for (i = 0; i < 8; i++) { 22013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 22113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 22213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 22313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 22413705f88SJack F Vogel } 22513705f88SJack F Vogel 22613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 22713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 22813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 22913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 23013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 23113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 23213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 23313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 23413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 23513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 23613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 23713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 23813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 23913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 24013705f88SJack F Vogel for (i = 0; i < 8; i++) 24113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 24213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 24313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 24413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 24513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 24613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 24713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 24813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 24913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 25013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 25113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 25213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 25313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 25413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 25513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 25613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 25713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 25813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 25913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 26013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 26113705f88SJack F Vogel for (i = 0; i < 16; i++) { 26213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 26313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 26413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 26513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 26613705f88SJack F Vogel } 26713705f88SJack F Vogel 26813705f88SJack F Vogel return IXGBE_SUCCESS; 26913705f88SJack F Vogel } 27013705f88SJack F Vogel 27113705f88SJack F Vogel /** 2729ca4041bSJack F Vogel * ixgbe_read_pba_num - Reads part number from EEPROM 2739ca4041bSJack F Vogel * @hw: pointer to hardware structure 2749ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 2759ca4041bSJack F Vogel * 2769ca4041bSJack F Vogel * Reads the part number from the EEPROM. 2779ca4041bSJack F Vogel **/ 2789ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 2799ca4041bSJack F Vogel { 2809ca4041bSJack F Vogel s32 ret_val; 2819ca4041bSJack F Vogel u16 data; 2829ca4041bSJack F Vogel 2839ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 2849ca4041bSJack F Vogel 2859ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 2869ca4041bSJack F Vogel if (ret_val) { 2879ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2889ca4041bSJack F Vogel return ret_val; 2899ca4041bSJack F Vogel } 2909ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 2919ca4041bSJack F Vogel 2929ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 2939ca4041bSJack F Vogel if (ret_val) { 2949ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2959ca4041bSJack F Vogel return ret_val; 2969ca4041bSJack F Vogel } 2979ca4041bSJack F Vogel *pba_num |= data; 2989ca4041bSJack F Vogel 2999ca4041bSJack F Vogel return IXGBE_SUCCESS; 3009ca4041bSJack F Vogel } 3019ca4041bSJack F Vogel 3029ca4041bSJack F Vogel /** 30313705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 30413705f88SJack F Vogel * @hw: pointer to hardware structure 30513705f88SJack F Vogel * @mac_addr: Adapter MAC address 30613705f88SJack F Vogel * 30713705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 30813705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 30913705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 31013705f88SJack F Vogel **/ 31113705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 31213705f88SJack F Vogel { 31313705f88SJack F Vogel u32 rar_high; 31413705f88SJack F Vogel u32 rar_low; 31513705f88SJack F Vogel u16 i; 31613705f88SJack F Vogel 31713705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 31813705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 31913705f88SJack F Vogel 32013705f88SJack F Vogel for (i = 0; i < 4; i++) 32113705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 32213705f88SJack F Vogel 32313705f88SJack F Vogel for (i = 0; i < 2; i++) 32413705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 32513705f88SJack F Vogel 32613705f88SJack F Vogel return IXGBE_SUCCESS; 32713705f88SJack F Vogel } 32813705f88SJack F Vogel 32913705f88SJack F Vogel /** 33013705f88SJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 33113705f88SJack F Vogel * @hw: pointer to hardware structure 33213705f88SJack F Vogel * 33313705f88SJack F Vogel * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure 33413705f88SJack F Vogel **/ 33513705f88SJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 33613705f88SJack F Vogel { 33713705f88SJack F Vogel u16 link_status; 33813705f88SJack F Vogel 33913705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 34013705f88SJack F Vogel 34113705f88SJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 34213705f88SJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 34313705f88SJack F Vogel 34413705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 34513705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 34613705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 34713705f88SJack F Vogel break; 34813705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 34913705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 35013705f88SJack F Vogel break; 35113705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 35213705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 35313705f88SJack F Vogel break; 35413705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 35513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 35613705f88SJack F Vogel break; 35713705f88SJack F Vogel default: 35813705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 35913705f88SJack F Vogel break; 36013705f88SJack F Vogel } 36113705f88SJack F Vogel 36213705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 36313705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 36413705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 36513705f88SJack F Vogel break; 36613705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 36713705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 36813705f88SJack F Vogel break; 36913705f88SJack F Vogel default: 37013705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 37113705f88SJack F Vogel break; 37213705f88SJack F Vogel } 37313705f88SJack F Vogel 37413705f88SJack F Vogel return IXGBE_SUCCESS; 37513705f88SJack F Vogel } 37613705f88SJack F Vogel 37713705f88SJack F Vogel /** 3789ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 37913705f88SJack F Vogel * @hw: pointer to hardware structure 38013705f88SJack F Vogel * 38113705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 38213705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 38313705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 38413705f88SJack F Vogel * state and should not touch the hardware. 38513705f88SJack F Vogel **/ 38613705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 38713705f88SJack F Vogel { 38813705f88SJack F Vogel u32 number_of_queues; 38913705f88SJack F Vogel u32 reg_val; 39013705f88SJack F Vogel u16 i; 39113705f88SJack F Vogel 39213705f88SJack F Vogel /* 39313705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 39413705f88SJack F Vogel * the hardware 39513705f88SJack F Vogel */ 39613705f88SJack F Vogel hw->adapter_stopped = TRUE; 39713705f88SJack F Vogel 39813705f88SJack F Vogel /* Disable the receive unit */ 39913705f88SJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 40013705f88SJack F Vogel reg_val &= ~(IXGBE_RXCTRL_RXEN); 40113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); 4029ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 40313705f88SJack F Vogel msec_delay(2); 40413705f88SJack F Vogel 40513705f88SJack F Vogel /* Clear interrupt mask to stop from interrupts being generated */ 40613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 40713705f88SJack F Vogel 40813705f88SJack F Vogel /* Clear any pending interrupts */ 40913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 41013705f88SJack F Vogel 41113705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 4129ca4041bSJack F Vogel number_of_queues = hw->mac.max_tx_queues; 41313705f88SJack F Vogel for (i = 0; i < number_of_queues; i++) { 41413705f88SJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); 41513705f88SJack F Vogel if (reg_val & IXGBE_TXDCTL_ENABLE) { 41613705f88SJack F Vogel reg_val &= ~IXGBE_TXDCTL_ENABLE; 41713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val); 41813705f88SJack F Vogel } 41913705f88SJack F Vogel } 42013705f88SJack F Vogel 4219ca4041bSJack F Vogel /* 4229ca4041bSJack F Vogel * Prevent the PCI-E bus from from hanging by disabling PCI-E master 4239ca4041bSJack F Vogel * access and verify no pending requests 4249ca4041bSJack F Vogel */ 4259ca4041bSJack F Vogel if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) { 4269ca4041bSJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 4279ca4041bSJack F Vogel } 4289ca4041bSJack F Vogel 42913705f88SJack F Vogel return IXGBE_SUCCESS; 43013705f88SJack F Vogel } 43113705f88SJack F Vogel 43213705f88SJack F Vogel /** 43313705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 43413705f88SJack F Vogel * @hw: pointer to hardware structure 43513705f88SJack F Vogel * @index: led number to turn on 43613705f88SJack F Vogel **/ 43713705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 43813705f88SJack F Vogel { 43913705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 44013705f88SJack F Vogel 44113705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 44213705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 44313705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 44413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 4459ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 44613705f88SJack F Vogel 44713705f88SJack F Vogel return IXGBE_SUCCESS; 44813705f88SJack F Vogel } 44913705f88SJack F Vogel 45013705f88SJack F Vogel /** 45113705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 45213705f88SJack F Vogel * @hw: pointer to hardware structure 45313705f88SJack F Vogel * @index: led number to turn off 45413705f88SJack F Vogel **/ 45513705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 45613705f88SJack F Vogel { 45713705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 45813705f88SJack F Vogel 45913705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 46013705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 46113705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 46213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 4639ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 46413705f88SJack F Vogel 46513705f88SJack F Vogel return IXGBE_SUCCESS; 46613705f88SJack F Vogel } 46713705f88SJack F Vogel 46813705f88SJack F Vogel /** 46913705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 47013705f88SJack F Vogel * @hw: pointer to hardware structure 47113705f88SJack F Vogel * 47213705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 47313705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 47413705f88SJack F Vogel **/ 47513705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 47613705f88SJack F Vogel { 47713705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 47813705f88SJack F Vogel u32 eec; 47913705f88SJack F Vogel u16 eeprom_size; 48013705f88SJack F Vogel 48113705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 48213705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 48313705f88SJack F Vogel 48413705f88SJack F Vogel /* 48513705f88SJack F Vogel * Check for EEPROM present first. 48613705f88SJack F Vogel * If not present leave as none 48713705f88SJack F Vogel */ 48813705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 48913705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 49013705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 49113705f88SJack F Vogel 49213705f88SJack F Vogel /* 49313705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 49413705f88SJack F Vogel * change if a future EEPROM is not SPI. 49513705f88SJack F Vogel */ 49613705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 49713705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 49813705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 49913705f88SJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 50013705f88SJack F Vogel } 50113705f88SJack F Vogel 50213705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 50313705f88SJack F Vogel eeprom->address_bits = 16; 50413705f88SJack F Vogel else 50513705f88SJack F Vogel eeprom->address_bits = 8; 50613705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 50713705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 50813705f88SJack F Vogel eeprom->address_bits); 50913705f88SJack F Vogel } 51013705f88SJack F Vogel 51113705f88SJack F Vogel return IXGBE_SUCCESS; 51213705f88SJack F Vogel } 51313705f88SJack F Vogel 51413705f88SJack F Vogel /** 51513705f88SJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 51613705f88SJack F Vogel * @hw: pointer to hardware structure 51713705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 51813705f88SJack F Vogel * @data: 16 bit word to be written to the EEPROM 51913705f88SJack F Vogel * 52013705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 52113705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 52213705f88SJack F Vogel **/ 52313705f88SJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 52413705f88SJack F Vogel { 52513705f88SJack F Vogel s32 status; 52613705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 52713705f88SJack F Vogel 5289ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 5299ca4041bSJack F Vogel 5309ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 5319ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 5329ca4041bSJack F Vogel goto out; 5339ca4041bSJack F Vogel } 5349ca4041bSJack F Vogel 53513705f88SJack F Vogel /* Prepare the EEPROM for writing */ 53613705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 53713705f88SJack F Vogel 53813705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 53913705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 54013705f88SJack F Vogel ixgbe_release_eeprom(hw); 54113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 54213705f88SJack F Vogel } 54313705f88SJack F Vogel } 54413705f88SJack F Vogel 54513705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 54613705f88SJack F Vogel ixgbe_standby_eeprom(hw); 54713705f88SJack F Vogel 54813705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 54913705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, 55013705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 55113705f88SJack F Vogel 55213705f88SJack F Vogel ixgbe_standby_eeprom(hw); 55313705f88SJack F Vogel 55413705f88SJack F Vogel /* 55513705f88SJack F Vogel * Some SPI eeproms use the 8th address bit embedded in the 55613705f88SJack F Vogel * opcode 55713705f88SJack F Vogel */ 55813705f88SJack F Vogel if ((hw->eeprom.address_bits == 8) && (offset >= 128)) 55913705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 56013705f88SJack F Vogel 56113705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 56213705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 56313705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 56413705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), 56513705f88SJack F Vogel hw->eeprom.address_bits); 56613705f88SJack F Vogel 56713705f88SJack F Vogel /* Send the data */ 56813705f88SJack F Vogel data = (data >> 8) | (data << 8); 56913705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, data, 16); 57013705f88SJack F Vogel ixgbe_standby_eeprom(hw); 57113705f88SJack F Vogel 57213705f88SJack F Vogel msec_delay(10); 57313705f88SJack F Vogel 57413705f88SJack F Vogel /* Done with writing - release the EEPROM */ 57513705f88SJack F Vogel ixgbe_release_eeprom(hw); 57613705f88SJack F Vogel } 57713705f88SJack F Vogel 5789ca4041bSJack F Vogel out: 57913705f88SJack F Vogel return status; 58013705f88SJack F Vogel } 58113705f88SJack F Vogel 58213705f88SJack F Vogel /** 58313705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 58413705f88SJack F Vogel * @hw: pointer to hardware structure 58513705f88SJack F Vogel * @offset: offset within the EEPROM to be read 58613705f88SJack F Vogel * @data: read 16 bit value from EEPROM 58713705f88SJack F Vogel * 58813705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 58913705f88SJack F Vogel **/ 59013705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 59113705f88SJack F Vogel u16 *data) 59213705f88SJack F Vogel { 59313705f88SJack F Vogel s32 status; 59413705f88SJack F Vogel u16 word_in; 59513705f88SJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 59613705f88SJack F Vogel 5979ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 5989ca4041bSJack F Vogel 5999ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 6009ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 6019ca4041bSJack F Vogel goto out; 6029ca4041bSJack F Vogel } 6039ca4041bSJack F Vogel 60413705f88SJack F Vogel /* Prepare the EEPROM for reading */ 60513705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 60613705f88SJack F Vogel 60713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 60813705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 60913705f88SJack F Vogel ixgbe_release_eeprom(hw); 61013705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 61113705f88SJack F Vogel } 61213705f88SJack F Vogel } 61313705f88SJack F Vogel 61413705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 61513705f88SJack F Vogel ixgbe_standby_eeprom(hw); 61613705f88SJack F Vogel 61713705f88SJack F Vogel /* 61813705f88SJack F Vogel * Some SPI eeproms use the 8th address bit embedded in the 61913705f88SJack F Vogel * opcode 62013705f88SJack F Vogel */ 62113705f88SJack F Vogel if ((hw->eeprom.address_bits == 8) && (offset >= 128)) 62213705f88SJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 62313705f88SJack F Vogel 62413705f88SJack F Vogel /* Send the READ command (opcode + addr) */ 62513705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 62613705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 62713705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), 62813705f88SJack F Vogel hw->eeprom.address_bits); 62913705f88SJack F Vogel 63013705f88SJack F Vogel /* Read the data. */ 63113705f88SJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 63213705f88SJack F Vogel *data = (word_in >> 8) | (word_in << 8); 63313705f88SJack F Vogel 63413705f88SJack F Vogel /* End this read operation */ 63513705f88SJack F Vogel ixgbe_release_eeprom(hw); 63613705f88SJack F Vogel } 63713705f88SJack F Vogel 6389ca4041bSJack F Vogel out: 63913705f88SJack F Vogel return status; 64013705f88SJack F Vogel } 64113705f88SJack F Vogel 64213705f88SJack F Vogel /** 64313705f88SJack F Vogel * ixgbe_read_eeprom_generic - Read EEPROM word using EERD 64413705f88SJack F Vogel * @hw: pointer to hardware structure 64513705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 64613705f88SJack F Vogel * @data: word read from the EEPROM 64713705f88SJack F Vogel * 64813705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 64913705f88SJack F Vogel **/ 65013705f88SJack F Vogel s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 65113705f88SJack F Vogel { 65213705f88SJack F Vogel u32 eerd; 65313705f88SJack F Vogel s32 status; 65413705f88SJack F Vogel 6559ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 6569ca4041bSJack F Vogel 6579ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 6589ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 6599ca4041bSJack F Vogel goto out; 6609ca4041bSJack F Vogel } 6619ca4041bSJack F Vogel 66213705f88SJack F Vogel eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + 66313705f88SJack F Vogel IXGBE_EEPROM_READ_REG_START; 66413705f88SJack F Vogel 66513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 66613705f88SJack F Vogel status = ixgbe_poll_eeprom_eerd_done(hw); 66713705f88SJack F Vogel 66813705f88SJack F Vogel if (status == IXGBE_SUCCESS) 66913705f88SJack F Vogel *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 67013705f88SJack F Vogel IXGBE_EEPROM_READ_REG_DATA); 67113705f88SJack F Vogel else 67213705f88SJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 67313705f88SJack F Vogel 6749ca4041bSJack F Vogel out: 67513705f88SJack F Vogel return status; 67613705f88SJack F Vogel } 67713705f88SJack F Vogel 67813705f88SJack F Vogel /** 67913705f88SJack F Vogel * ixgbe_poll_eeprom_eerd_done - Poll EERD status 68013705f88SJack F Vogel * @hw: pointer to hardware structure 68113705f88SJack F Vogel * 68213705f88SJack F Vogel * Polls the status bit (bit 1) of the EERD to determine when the read is done. 68313705f88SJack F Vogel **/ 68413705f88SJack F Vogel static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw) 68513705f88SJack F Vogel { 68613705f88SJack F Vogel u32 i; 68713705f88SJack F Vogel u32 reg; 68813705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 68913705f88SJack F Vogel 69013705f88SJack F Vogel for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) { 69113705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 69213705f88SJack F Vogel if (reg & IXGBE_EEPROM_READ_REG_DONE) { 69313705f88SJack F Vogel status = IXGBE_SUCCESS; 69413705f88SJack F Vogel break; 69513705f88SJack F Vogel } 69613705f88SJack F Vogel usec_delay(5); 69713705f88SJack F Vogel } 69813705f88SJack F Vogel return status; 69913705f88SJack F Vogel } 70013705f88SJack F Vogel 70113705f88SJack F Vogel /** 70213705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 70313705f88SJack F Vogel * @hw: pointer to hardware structure 70413705f88SJack F Vogel * 70513705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 70613705f88SJack F Vogel * be called before issuing a command to the EEPROM. 70713705f88SJack F Vogel **/ 70813705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 70913705f88SJack F Vogel { 71013705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 71113705f88SJack F Vogel u32 eec; 71213705f88SJack F Vogel u32 i; 71313705f88SJack F Vogel 71413705f88SJack F Vogel if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS) 71513705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 71613705f88SJack F Vogel 71713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 71813705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 71913705f88SJack F Vogel 72013705f88SJack F Vogel /* Request EEPROM Access */ 72113705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 72213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 72313705f88SJack F Vogel 72413705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 72513705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 72613705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 72713705f88SJack F Vogel break; 72813705f88SJack F Vogel usec_delay(5); 72913705f88SJack F Vogel } 73013705f88SJack F Vogel 7319ca4041bSJack F Vogel /* Release if grant not acquired */ 73213705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 73313705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 73413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 73513705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 73613705f88SJack F Vogel 73713705f88SJack F Vogel ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 73813705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 73913705f88SJack F Vogel } 74013705f88SJack F Vogel } 74113705f88SJack F Vogel 74213705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 74313705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 74413705f88SJack F Vogel /* Clear CS and SK */ 74513705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 74613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 74713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 74813705f88SJack F Vogel usec_delay(1); 74913705f88SJack F Vogel } 75013705f88SJack F Vogel return status; 75113705f88SJack F Vogel } 75213705f88SJack F Vogel 75313705f88SJack F Vogel /** 75413705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 75513705f88SJack F Vogel * @hw: pointer to hardware structure 75613705f88SJack F Vogel * 75713705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 75813705f88SJack F Vogel **/ 75913705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 76013705f88SJack F Vogel { 76113705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 76213705f88SJack F Vogel u32 timeout; 76313705f88SJack F Vogel u32 i; 76413705f88SJack F Vogel u32 swsm; 76513705f88SJack F Vogel 76613705f88SJack F Vogel /* Set timeout value based on size of EEPROM */ 76713705f88SJack F Vogel timeout = hw->eeprom.word_size + 1; 76813705f88SJack F Vogel 76913705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 77013705f88SJack F Vogel for (i = 0; i < timeout; i++) { 77113705f88SJack F Vogel /* 77213705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 77313705f88SJack F Vogel * set and we have the semaphore 77413705f88SJack F Vogel */ 77513705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 77613705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 77713705f88SJack F Vogel status = IXGBE_SUCCESS; 77813705f88SJack F Vogel break; 77913705f88SJack F Vogel } 78013705f88SJack F Vogel msec_delay(1); 78113705f88SJack F Vogel } 78213705f88SJack F Vogel 78313705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 78413705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 78513705f88SJack F Vogel for (i = 0; i < timeout; i++) { 78613705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 78713705f88SJack F Vogel 78813705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 78913705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 79013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 79113705f88SJack F Vogel 79213705f88SJack F Vogel /* 79313705f88SJack F Vogel * If we set the bit successfully then we got the 79413705f88SJack F Vogel * semaphore. 79513705f88SJack F Vogel */ 79613705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 79713705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 79813705f88SJack F Vogel break; 79913705f88SJack F Vogel 80013705f88SJack F Vogel usec_delay(50); 80113705f88SJack F Vogel } 80213705f88SJack F Vogel 80313705f88SJack F Vogel /* 80413705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 80513705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 80613705f88SJack F Vogel */ 80713705f88SJack F Vogel if (i >= timeout) { 80813705f88SJack F Vogel DEBUGOUT("Driver can't access the Eeprom - Semaphore " 80913705f88SJack F Vogel "not granted.\n"); 81013705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 81113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 81213705f88SJack F Vogel } 81313705f88SJack F Vogel } 81413705f88SJack F Vogel 81513705f88SJack F Vogel return status; 81613705f88SJack F Vogel } 81713705f88SJack F Vogel 81813705f88SJack F Vogel /** 81913705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 82013705f88SJack F Vogel * @hw: pointer to hardware structure 82113705f88SJack F Vogel * 82213705f88SJack F Vogel * This function clears hardware semaphore bits. 82313705f88SJack F Vogel **/ 82413705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 82513705f88SJack F Vogel { 82613705f88SJack F Vogel u32 swsm; 82713705f88SJack F Vogel 82813705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 82913705f88SJack F Vogel 83013705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 83113705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 83213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 8339ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 83413705f88SJack F Vogel } 83513705f88SJack F Vogel 83613705f88SJack F Vogel /** 83713705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 83813705f88SJack F Vogel * @hw: pointer to hardware structure 83913705f88SJack F Vogel **/ 84013705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 84113705f88SJack F Vogel { 84213705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 84313705f88SJack F Vogel u16 i; 84413705f88SJack F Vogel u8 spi_stat_reg; 84513705f88SJack F Vogel 84613705f88SJack F Vogel /* 84713705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 84813705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 84913705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 85013705f88SJack F Vogel * 5 milliseconds, then error out. 85113705f88SJack F Vogel */ 85213705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 85313705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 85413705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 85513705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 85613705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 85713705f88SJack F Vogel break; 85813705f88SJack F Vogel 85913705f88SJack F Vogel usec_delay(5); 86013705f88SJack F Vogel ixgbe_standby_eeprom(hw); 86113705f88SJack F Vogel }; 86213705f88SJack F Vogel 86313705f88SJack F Vogel /* 86413705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 86513705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 86613705f88SJack F Vogel */ 86713705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 86813705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 86913705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 87013705f88SJack F Vogel } 87113705f88SJack F Vogel 87213705f88SJack F Vogel return status; 87313705f88SJack F Vogel } 87413705f88SJack F Vogel 87513705f88SJack F Vogel /** 87613705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 87713705f88SJack F Vogel * @hw: pointer to hardware structure 87813705f88SJack F Vogel **/ 87913705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 88013705f88SJack F Vogel { 88113705f88SJack F Vogel u32 eec; 88213705f88SJack F Vogel 88313705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 88413705f88SJack F Vogel 88513705f88SJack F Vogel /* Toggle CS to flush commands */ 88613705f88SJack F Vogel eec |= IXGBE_EEC_CS; 88713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 88813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 88913705f88SJack F Vogel usec_delay(1); 89013705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 89113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 89213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 89313705f88SJack F Vogel usec_delay(1); 89413705f88SJack F Vogel } 89513705f88SJack F Vogel 89613705f88SJack F Vogel /** 89713705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 89813705f88SJack F Vogel * @hw: pointer to hardware structure 89913705f88SJack F Vogel * @data: data to send to the EEPROM 90013705f88SJack F Vogel * @count: number of bits to shift out 90113705f88SJack F Vogel **/ 90213705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 90313705f88SJack F Vogel u16 count) 90413705f88SJack F Vogel { 90513705f88SJack F Vogel u32 eec; 90613705f88SJack F Vogel u32 mask; 90713705f88SJack F Vogel u32 i; 90813705f88SJack F Vogel 90913705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 91013705f88SJack F Vogel 91113705f88SJack F Vogel /* 91213705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 91313705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 91413705f88SJack F Vogel */ 91513705f88SJack F Vogel mask = 0x01 << (count - 1); 91613705f88SJack F Vogel 91713705f88SJack F Vogel for (i = 0; i < count; i++) { 91813705f88SJack F Vogel /* 91913705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 92013705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 92113705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 92213705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 92313705f88SJack F Vogel * raising and then lowering the clock. 92413705f88SJack F Vogel */ 92513705f88SJack F Vogel if (data & mask) 92613705f88SJack F Vogel eec |= IXGBE_EEC_DI; 92713705f88SJack F Vogel else 92813705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 92913705f88SJack F Vogel 93013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 93113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 93213705f88SJack F Vogel 93313705f88SJack F Vogel usec_delay(1); 93413705f88SJack F Vogel 93513705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 93613705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 93713705f88SJack F Vogel 93813705f88SJack F Vogel /* 93913705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 94013705f88SJack F Vogel * EEPROM 94113705f88SJack F Vogel */ 94213705f88SJack F Vogel mask = mask >> 1; 94313705f88SJack F Vogel }; 94413705f88SJack F Vogel 94513705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 94613705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 94713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 94813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 94913705f88SJack F Vogel } 95013705f88SJack F Vogel 95113705f88SJack F Vogel /** 95213705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 95313705f88SJack F Vogel * @hw: pointer to hardware structure 95413705f88SJack F Vogel **/ 95513705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 95613705f88SJack F Vogel { 95713705f88SJack F Vogel u32 eec; 95813705f88SJack F Vogel u32 i; 95913705f88SJack F Vogel u16 data = 0; 96013705f88SJack F Vogel 96113705f88SJack F Vogel /* 96213705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 96313705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 96413705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 96513705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 96613705f88SJack F Vogel * "DI" bit should always be clear. 96713705f88SJack F Vogel */ 96813705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 96913705f88SJack F Vogel 97013705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 97113705f88SJack F Vogel 97213705f88SJack F Vogel for (i = 0; i < count; i++) { 97313705f88SJack F Vogel data = data << 1; 97413705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 97513705f88SJack F Vogel 97613705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 97713705f88SJack F Vogel 97813705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 97913705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 98013705f88SJack F Vogel data |= 1; 98113705f88SJack F Vogel 98213705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 98313705f88SJack F Vogel } 98413705f88SJack F Vogel 98513705f88SJack F Vogel return data; 98613705f88SJack F Vogel } 98713705f88SJack F Vogel 98813705f88SJack F Vogel /** 98913705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 99013705f88SJack F Vogel * @hw: pointer to hardware structure 99113705f88SJack F Vogel * @eec: EEC register's current value 99213705f88SJack F Vogel **/ 99313705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 99413705f88SJack F Vogel { 99513705f88SJack F Vogel /* 99613705f88SJack F Vogel * Raise the clock input to the EEPROM 99713705f88SJack F Vogel * (setting the SK bit), then delay 99813705f88SJack F Vogel */ 99913705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 100013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 100113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 100213705f88SJack F Vogel usec_delay(1); 100313705f88SJack F Vogel } 100413705f88SJack F Vogel 100513705f88SJack F Vogel /** 100613705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 100713705f88SJack F Vogel * @hw: pointer to hardware structure 100813705f88SJack F Vogel * @eecd: EECD's current value 100913705f88SJack F Vogel **/ 101013705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 101113705f88SJack F Vogel { 101213705f88SJack F Vogel /* 101313705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 101413705f88SJack F Vogel * delay 101513705f88SJack F Vogel */ 101613705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 101713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 101813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 101913705f88SJack F Vogel usec_delay(1); 102013705f88SJack F Vogel } 102113705f88SJack F Vogel 102213705f88SJack F Vogel /** 102313705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 102413705f88SJack F Vogel * @hw: pointer to hardware structure 102513705f88SJack F Vogel **/ 102613705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 102713705f88SJack F Vogel { 102813705f88SJack F Vogel u32 eec; 102913705f88SJack F Vogel 103013705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 103113705f88SJack F Vogel 103213705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 103313705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 103413705f88SJack F Vogel 103513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 103613705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 103713705f88SJack F Vogel 103813705f88SJack F Vogel usec_delay(1); 103913705f88SJack F Vogel 104013705f88SJack F Vogel /* Stop requesting EEPROM access */ 104113705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 104213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 104313705f88SJack F Vogel 104413705f88SJack F Vogel ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 104513705f88SJack F Vogel } 104613705f88SJack F Vogel 104713705f88SJack F Vogel /** 104813705f88SJack F Vogel * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum 104913705f88SJack F Vogel * @hw: pointer to hardware structure 105013705f88SJack F Vogel **/ 105113705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) 105213705f88SJack F Vogel { 105313705f88SJack F Vogel u16 i; 105413705f88SJack F Vogel u16 j; 105513705f88SJack F Vogel u16 checksum = 0; 105613705f88SJack F Vogel u16 length = 0; 105713705f88SJack F Vogel u16 pointer = 0; 105813705f88SJack F Vogel u16 word = 0; 105913705f88SJack F Vogel 106013705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 106113705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 10629ca4041bSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { 106313705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 106413705f88SJack F Vogel break; 106513705f88SJack F Vogel } 106613705f88SJack F Vogel checksum += word; 106713705f88SJack F Vogel } 106813705f88SJack F Vogel 106913705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 107013705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 10719ca4041bSJack F Vogel hw->eeprom.ops.read(hw, i, &pointer); 107213705f88SJack F Vogel 107313705f88SJack F Vogel /* Make sure the pointer seems valid */ 107413705f88SJack F Vogel if (pointer != 0xFFFF && pointer != 0) { 10759ca4041bSJack F Vogel hw->eeprom.ops.read(hw, pointer, &length); 107613705f88SJack F Vogel 107713705f88SJack F Vogel if (length != 0xFFFF && length != 0) { 107813705f88SJack F Vogel for (j = pointer+1; j <= pointer+length; j++) { 10799ca4041bSJack F Vogel hw->eeprom.ops.read(hw, j, &word); 108013705f88SJack F Vogel checksum += word; 108113705f88SJack F Vogel } 108213705f88SJack F Vogel } 108313705f88SJack F Vogel } 108413705f88SJack F Vogel } 108513705f88SJack F Vogel 108613705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 108713705f88SJack F Vogel 108813705f88SJack F Vogel return checksum; 108913705f88SJack F Vogel } 109013705f88SJack F Vogel 109113705f88SJack F Vogel /** 109213705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 109313705f88SJack F Vogel * @hw: pointer to hardware structure 109413705f88SJack F Vogel * @checksum_val: calculated checksum 109513705f88SJack F Vogel * 109613705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 109713705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 109813705f88SJack F Vogel **/ 109913705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 110013705f88SJack F Vogel u16 *checksum_val) 110113705f88SJack F Vogel { 110213705f88SJack F Vogel s32 status; 110313705f88SJack F Vogel u16 checksum; 110413705f88SJack F Vogel u16 read_checksum = 0; 110513705f88SJack F Vogel 110613705f88SJack F Vogel /* 110713705f88SJack F Vogel * Read the first word from the EEPROM. If this times out or fails, do 110813705f88SJack F Vogel * not continue or we could be in for a very long wait while every 110913705f88SJack F Vogel * EEPROM read fails 111013705f88SJack F Vogel */ 11119ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 111213705f88SJack F Vogel 111313705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 111413705f88SJack F Vogel checksum = ixgbe_calc_eeprom_checksum(hw); 111513705f88SJack F Vogel 11169ca4041bSJack F Vogel hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 111713705f88SJack F Vogel 111813705f88SJack F Vogel /* 111913705f88SJack F Vogel * Verify read checksum from EEPROM is the same as 112013705f88SJack F Vogel * calculated checksum 112113705f88SJack F Vogel */ 11229ca4041bSJack F Vogel if (read_checksum != checksum) 112313705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 112413705f88SJack F Vogel 112513705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 11269ca4041bSJack F Vogel if (checksum_val) 112713705f88SJack F Vogel *checksum_val = checksum; 112813705f88SJack F Vogel } else { 112913705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 113013705f88SJack F Vogel } 113113705f88SJack F Vogel 113213705f88SJack F Vogel return status; 113313705f88SJack F Vogel } 113413705f88SJack F Vogel 113513705f88SJack F Vogel /** 11369ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 113713705f88SJack F Vogel * @hw: pointer to hardware structure 113813705f88SJack F Vogel **/ 113913705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 114013705f88SJack F Vogel { 114113705f88SJack F Vogel s32 status; 114213705f88SJack F Vogel u16 checksum; 114313705f88SJack F Vogel 114413705f88SJack F Vogel /* 114513705f88SJack F Vogel * Read the first word from the EEPROM. If this times out or fails, do 114613705f88SJack F Vogel * not continue or we could be in for a very long wait while every 114713705f88SJack F Vogel * EEPROM read fails 114813705f88SJack F Vogel */ 11499ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 115013705f88SJack F Vogel 115113705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 115213705f88SJack F Vogel checksum = ixgbe_calc_eeprom_checksum(hw); 11539ca4041bSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, 115413705f88SJack F Vogel checksum); 115513705f88SJack F Vogel } else { 115613705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 115713705f88SJack F Vogel } 115813705f88SJack F Vogel 115913705f88SJack F Vogel return status; 116013705f88SJack F Vogel } 116113705f88SJack F Vogel 116213705f88SJack F Vogel /** 116313705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 116413705f88SJack F Vogel * @mac_addr: pointer to MAC address. 116513705f88SJack F Vogel * 116613705f88SJack F Vogel * Tests a MAC address to ensure it is a valid Individual Address 116713705f88SJack F Vogel **/ 116813705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 116913705f88SJack F Vogel { 117013705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 117113705f88SJack F Vogel 117213705f88SJack F Vogel /* Make sure it is not a multicast address */ 117313705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 117413705f88SJack F Vogel DEBUGOUT("MAC address is multicast\n"); 117513705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 117613705f88SJack F Vogel /* Not a broadcast address */ 117713705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 117813705f88SJack F Vogel DEBUGOUT("MAC address is broadcast\n"); 117913705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 118013705f88SJack F Vogel /* Reject the zero address */ 118113705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 118213705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 118313705f88SJack F Vogel DEBUGOUT("MAC address is all zeros\n"); 118413705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 118513705f88SJack F Vogel } 118613705f88SJack F Vogel return status; 118713705f88SJack F Vogel } 118813705f88SJack F Vogel 118913705f88SJack F Vogel /** 11909ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 119113705f88SJack F Vogel * @hw: pointer to hardware structure 119213705f88SJack F Vogel * @index: Receive address register to write 11939ca4041bSJack F Vogel * @addr: Address to put into receive address register 11949ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 119513705f88SJack F Vogel * @enable_addr: set flag that address is active 119613705f88SJack F Vogel * 119713705f88SJack F Vogel * Puts an ethernet address into a receive address register. 119813705f88SJack F Vogel **/ 11999ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 120013705f88SJack F Vogel u32 enable_addr) 120113705f88SJack F Vogel { 120213705f88SJack F Vogel u32 rar_low, rar_high; 12039ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 120413705f88SJack F Vogel 12059ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 12069ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 12079ca4041bSJack F Vogel 12089ca4041bSJack F Vogel /* Make sure we are using a valid rar index range */ 12099ca4041bSJack F Vogel if (index < rar_entries) { 121013705f88SJack F Vogel /* 12119ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 12129ca4041bSJack F Vogel * order from network order (big endian) to little endian 121313705f88SJack F Vogel */ 121413705f88SJack F Vogel rar_low = ((u32)addr[0] | 121513705f88SJack F Vogel ((u32)addr[1] << 8) | 121613705f88SJack F Vogel ((u32)addr[2] << 16) | 121713705f88SJack F Vogel ((u32)addr[3] << 24)); 12189ca4041bSJack F Vogel /* 12199ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 12209ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 12219ca4041bSJack F Vogel * of the address and the address valid bit. 12229ca4041bSJack F Vogel */ 12239ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 12249ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 12259ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 122613705f88SJack F Vogel 122713705f88SJack F Vogel if (enable_addr != 0) 122813705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 122913705f88SJack F Vogel 123013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 123113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 12329ca4041bSJack F Vogel } else { 12339ca4041bSJack F Vogel DEBUGOUT("Current RAR index is out of range."); 12349ca4041bSJack F Vogel } 123513705f88SJack F Vogel 123613705f88SJack F Vogel return IXGBE_SUCCESS; 123713705f88SJack F Vogel } 123813705f88SJack F Vogel 123913705f88SJack F Vogel /** 12409ca4041bSJack F Vogel * ixgbe_enable_rar - Enable Rx address register 124113705f88SJack F Vogel * @hw: pointer to hardware structure 124213705f88SJack F Vogel * @index: index into the RAR table 124313705f88SJack F Vogel * 124413705f88SJack F Vogel * Enables the select receive address register. 124513705f88SJack F Vogel **/ 124613705f88SJack F Vogel static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index) 124713705f88SJack F Vogel { 124813705f88SJack F Vogel u32 rar_high; 124913705f88SJack F Vogel 125013705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 125113705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 125213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 125313705f88SJack F Vogel } 125413705f88SJack F Vogel 125513705f88SJack F Vogel /** 12569ca4041bSJack F Vogel * ixgbe_disable_rar - Disable Rx address register 125713705f88SJack F Vogel * @hw: pointer to hardware structure 125813705f88SJack F Vogel * @index: index into the RAR table 125913705f88SJack F Vogel * 126013705f88SJack F Vogel * Disables the select receive address register. 126113705f88SJack F Vogel **/ 126213705f88SJack F Vogel static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index) 126313705f88SJack F Vogel { 126413705f88SJack F Vogel u32 rar_high; 126513705f88SJack F Vogel 126613705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 126713705f88SJack F Vogel rar_high &= (~IXGBE_RAH_AV); 126813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 126913705f88SJack F Vogel } 127013705f88SJack F Vogel 127113705f88SJack F Vogel /** 127213705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 127313705f88SJack F Vogel * @hw: pointer to hardware structure 127413705f88SJack F Vogel * 127513705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 12769ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 127713705f88SJack F Vogel * the receiver is in reset when the routine is called. 127813705f88SJack F Vogel **/ 127913705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 128013705f88SJack F Vogel { 128113705f88SJack F Vogel u32 i; 12829ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 128313705f88SJack F Vogel 128413705f88SJack F Vogel /* 128513705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 128613705f88SJack F Vogel * to the permanent address. 128713705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 128813705f88SJack F Vogel */ 128913705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 129013705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 129113705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 12929ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 129313705f88SJack F Vogel 129413705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 129513705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 129613705f88SJack F Vogel hw->mac.addr[2]); 129713705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 129813705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 129913705f88SJack F Vogel } else { 130013705f88SJack F Vogel /* Setup the receive address. */ 130113705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 130213705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 130313705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 130413705f88SJack F Vogel hw->mac.addr[2]); 130513705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 130613705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 130713705f88SJack F Vogel 13089ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 130913705f88SJack F Vogel } 13109ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 131113705f88SJack F Vogel 131213705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 131313705f88SJack F Vogel 131413705f88SJack F Vogel /* Zero out the other receive addresses. */ 13159ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 131613705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 131713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 131813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 131913705f88SJack F Vogel } 132013705f88SJack F Vogel 132113705f88SJack F Vogel /* Clear the MTA */ 132213705f88SJack F Vogel hw->addr_ctrl.mc_addr_in_rar_count = 0; 132313705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 132413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 132513705f88SJack F Vogel 132613705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 13279ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 132813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 132913705f88SJack F Vogel 133013705f88SJack F Vogel return IXGBE_SUCCESS; 133113705f88SJack F Vogel } 133213705f88SJack F Vogel 133313705f88SJack F Vogel /** 13349ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 13359ca4041bSJack F Vogel * @hw: pointer to hardware structure 13369ca4041bSJack F Vogel * @addr: new address 13379ca4041bSJack F Vogel * 13389ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 13399ca4041bSJack F Vogel **/ 13409ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 13419ca4041bSJack F Vogel { 13429ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 13439ca4041bSJack F Vogel u32 rar; 13449ca4041bSJack F Vogel 13459ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 13469ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 13479ca4041bSJack F Vogel 13489ca4041bSJack F Vogel /* 13499ca4041bSJack F Vogel * Place this address in the RAR if there is room, 13509ca4041bSJack F Vogel * else put the controller into promiscuous mode 13519ca4041bSJack F Vogel */ 13529ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 13539ca4041bSJack F Vogel rar = hw->addr_ctrl.rar_used_count - 13549ca4041bSJack F Vogel hw->addr_ctrl.mc_addr_in_rar_count; 13559ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 13569ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 13579ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 13589ca4041bSJack F Vogel } else { 13599ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 13609ca4041bSJack F Vogel } 13619ca4041bSJack F Vogel 13629ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 13639ca4041bSJack F Vogel } 13649ca4041bSJack F Vogel 13659ca4041bSJack F Vogel /** 13669ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 13679ca4041bSJack F Vogel * @hw: pointer to hardware structure 13689ca4041bSJack F Vogel * @addr_list: the list of new addresses 13699ca4041bSJack F Vogel * @addr_count: number of addresses 13709ca4041bSJack F Vogel * @next: iterator function to walk the address list 13719ca4041bSJack F Vogel * 13729ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 13739ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 13749ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 13759ca4041bSJack F Vogel * 13769ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 13779ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 13789ca4041bSJack F Vogel **/ 13799ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 13809ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 13819ca4041bSJack F Vogel { 13829ca4041bSJack F Vogel u8 *addr; 13839ca4041bSJack F Vogel u32 i; 13849ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 13859ca4041bSJack F Vogel u32 uc_addr_in_use; 13869ca4041bSJack F Vogel u32 fctrl; 13879ca4041bSJack F Vogel u32 vmdq; 13889ca4041bSJack F Vogel 13899ca4041bSJack F Vogel /* 13909ca4041bSJack F Vogel * Clear accounting of old secondary address list, 13919ca4041bSJack F Vogel * don't count RAR[0] 13929ca4041bSJack F Vogel */ 13939ca4041bSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 13949ca4041bSJack F Vogel hw->addr_ctrl.mc_addr_in_rar_count - 1; 13959ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 13969ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 13979ca4041bSJack F Vogel 13989ca4041bSJack F Vogel /* Zero out the other receive addresses */ 13999ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use); 14009ca4041bSJack F Vogel for (i = 1; i <= uc_addr_in_use; i++) { 14019ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 14029ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 14039ca4041bSJack F Vogel } 14049ca4041bSJack F Vogel 14059ca4041bSJack F Vogel /* Add the new addresses */ 14069ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 14079ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 14089ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 14099ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 14109ca4041bSJack F Vogel } 14119ca4041bSJack F Vogel 14129ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 14139ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 14149ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 14159ca4041bSJack F Vogel DEBUGOUT( " Entering address overflow promisc mode\n"); 14169ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 14179ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 14189ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 14199ca4041bSJack F Vogel } 14209ca4041bSJack F Vogel } else { 14219ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 14229ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 14239ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 14249ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 14259ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 14269ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 14279ca4041bSJack F Vogel } 14289ca4041bSJack F Vogel } 14299ca4041bSJack F Vogel 14309ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 14319ca4041bSJack F Vogel return IXGBE_SUCCESS; 14329ca4041bSJack F Vogel } 14339ca4041bSJack F Vogel 14349ca4041bSJack F Vogel /** 143513705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 143613705f88SJack F Vogel * @hw: pointer to hardware structure 143713705f88SJack F Vogel * @mc_addr: the multicast address 143813705f88SJack F Vogel * 143913705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 144013705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 144113705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 144213705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 14439ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 144413705f88SJack F Vogel * to mc_filter_type. 144513705f88SJack F Vogel **/ 144613705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 144713705f88SJack F Vogel { 144813705f88SJack F Vogel u32 vector = 0; 144913705f88SJack F Vogel 145013705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 145113705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 145213705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 145313705f88SJack F Vogel break; 145413705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 145513705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 145613705f88SJack F Vogel break; 145713705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 145813705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 145913705f88SJack F Vogel break; 146013705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 146113705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 146213705f88SJack F Vogel break; 146313705f88SJack F Vogel default: /* Invalid mc_filter_type */ 146413705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 146513705f88SJack F Vogel ASSERT(0); 146613705f88SJack F Vogel break; 146713705f88SJack F Vogel } 146813705f88SJack F Vogel 146913705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 147013705f88SJack F Vogel vector &= 0xFFF; 147113705f88SJack F Vogel return vector; 147213705f88SJack F Vogel } 147313705f88SJack F Vogel 147413705f88SJack F Vogel /** 147513705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 147613705f88SJack F Vogel * @hw: pointer to hardware structure 147713705f88SJack F Vogel * @hash_value: Multicast address hash value 147813705f88SJack F Vogel * 147913705f88SJack F Vogel * Sets the bit-vector in the multicast table. 148013705f88SJack F Vogel **/ 148113705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 148213705f88SJack F Vogel { 148313705f88SJack F Vogel u32 vector; 148413705f88SJack F Vogel u32 vector_bit; 148513705f88SJack F Vogel u32 vector_reg; 148613705f88SJack F Vogel u32 mta_reg; 148713705f88SJack F Vogel 148813705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 148913705f88SJack F Vogel 149013705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 149113705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 149213705f88SJack F Vogel 149313705f88SJack F Vogel /* 149413705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 149513705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 149613705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 149713705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 149813705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 149913705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 150013705f88SJack F Vogel * the value. 150113705f88SJack F Vogel */ 150213705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 150313705f88SJack F Vogel vector_bit = vector & 0x1F; 150413705f88SJack F Vogel mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); 150513705f88SJack F Vogel mta_reg |= (1 << vector_bit); 150613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); 150713705f88SJack F Vogel } 150813705f88SJack F Vogel 150913705f88SJack F Vogel /** 151013705f88SJack F Vogel * ixgbe_add_mc_addr - Adds a multicast address. 151113705f88SJack F Vogel * @hw: pointer to hardware structure 151213705f88SJack F Vogel * @mc_addr: new multicast address 151313705f88SJack F Vogel * 151413705f88SJack F Vogel * Adds it to unused receive address register or to the multicast table. 151513705f88SJack F Vogel **/ 151613705f88SJack F Vogel void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) 151713705f88SJack F Vogel { 15189ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 15199ca4041bSJack F Vogel u32 rar; 152013705f88SJack F Vogel 152113705f88SJack F Vogel DEBUGOUT6(" MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", 152213705f88SJack F Vogel mc_addr[0], mc_addr[1], mc_addr[2], 152313705f88SJack F Vogel mc_addr[3], mc_addr[4], mc_addr[5]); 152413705f88SJack F Vogel 152513705f88SJack F Vogel /* 152613705f88SJack F Vogel * Place this multicast address in the RAR if there is room, 152713705f88SJack F Vogel * else put it in the MTA 152813705f88SJack F Vogel */ 152913705f88SJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 15309ca4041bSJack F Vogel /* use RAR from the end up for multicast */ 15319ca4041bSJack F Vogel rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; 15329ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); 15339ca4041bSJack F Vogel DEBUGOUT1("Added a multicast address to RAR[%d]\n", rar); 153413705f88SJack F Vogel hw->addr_ctrl.rar_used_count++; 153513705f88SJack F Vogel hw->addr_ctrl.mc_addr_in_rar_count++; 153613705f88SJack F Vogel } else { 153713705f88SJack F Vogel ixgbe_set_mta(hw, mc_addr); 153813705f88SJack F Vogel } 153913705f88SJack F Vogel 154013705f88SJack F Vogel DEBUGOUT("ixgbe_add_mc_addr Complete\n"); 154113705f88SJack F Vogel } 154213705f88SJack F Vogel 154313705f88SJack F Vogel /** 154413705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 154513705f88SJack F Vogel * @hw: pointer to hardware structure 154613705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 154713705f88SJack F Vogel * @mc_addr_count: number of addresses 15489ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 154913705f88SJack F Vogel * 155013705f88SJack F Vogel * The given list replaces any existing list. Clears the MC addrs from receive 15519ca4041bSJack F Vogel * address registers and the multicast table. Uses unused receive address 155213705f88SJack F Vogel * registers for the first multicast addresses, and hashes the rest into the 155313705f88SJack F Vogel * multicast table. 155413705f88SJack F Vogel **/ 155513705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 15569ca4041bSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next) 155713705f88SJack F Vogel { 155813705f88SJack F Vogel u32 i; 15599ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 15609ca4041bSJack F Vogel u32 vmdq; 156113705f88SJack F Vogel 156213705f88SJack F Vogel /* 156313705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 156413705f88SJack F Vogel * use. 156513705f88SJack F Vogel */ 156613705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 156713705f88SJack F Vogel hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count; 156813705f88SJack F Vogel hw->addr_ctrl.mc_addr_in_rar_count = 0; 156913705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 157013705f88SJack F Vogel 157113705f88SJack F Vogel /* Zero out the other receive addresses. */ 15729ca4041bSJack F Vogel DEBUGOUT2("Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count, 15739ca4041bSJack F Vogel rar_entries - 1); 157413705f88SJack F Vogel for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { 157513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 157613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 157713705f88SJack F Vogel } 157813705f88SJack F Vogel 157913705f88SJack F Vogel /* Clear the MTA */ 158013705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 15819ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 158213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 158313705f88SJack F Vogel 158413705f88SJack F Vogel /* Add the new addresses */ 158513705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 158613705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 15879ca4041bSJack F Vogel ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq)); 158813705f88SJack F Vogel } 158913705f88SJack F Vogel 159013705f88SJack F Vogel /* Enable mta */ 159113705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 159213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 159313705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 159413705f88SJack F Vogel 159513705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 159613705f88SJack F Vogel return IXGBE_SUCCESS; 159713705f88SJack F Vogel } 159813705f88SJack F Vogel 159913705f88SJack F Vogel /** 160013705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 160113705f88SJack F Vogel * @hw: pointer to hardware structure 160213705f88SJack F Vogel * 160313705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 160413705f88SJack F Vogel **/ 160513705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 160613705f88SJack F Vogel { 160713705f88SJack F Vogel u32 i; 16089ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 160913705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 161013705f88SJack F Vogel 161113705f88SJack F Vogel if (a->mc_addr_in_rar_count > 0) 16129ca4041bSJack F Vogel for (i = (rar_entries - a->mc_addr_in_rar_count); 16139ca4041bSJack F Vogel i < rar_entries; i++) 161413705f88SJack F Vogel ixgbe_enable_rar(hw, i); 161513705f88SJack F Vogel 161613705f88SJack F Vogel if (a->mta_in_use > 0) 161713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 161813705f88SJack F Vogel hw->mac.mc_filter_type); 161913705f88SJack F Vogel 162013705f88SJack F Vogel return IXGBE_SUCCESS; 162113705f88SJack F Vogel } 162213705f88SJack F Vogel 162313705f88SJack F Vogel /** 16249ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 162513705f88SJack F Vogel * @hw: pointer to hardware structure 162613705f88SJack F Vogel * 162713705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 162813705f88SJack F Vogel **/ 162913705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 163013705f88SJack F Vogel { 163113705f88SJack F Vogel u32 i; 16329ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 163313705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 163413705f88SJack F Vogel 163513705f88SJack F Vogel if (a->mc_addr_in_rar_count > 0) 16369ca4041bSJack F Vogel for (i = (rar_entries - a->mc_addr_in_rar_count); 16379ca4041bSJack F Vogel i < rar_entries; i++) 163813705f88SJack F Vogel ixgbe_disable_rar(hw, i); 163913705f88SJack F Vogel 164013705f88SJack F Vogel if (a->mta_in_use > 0) 164113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 164213705f88SJack F Vogel 164313705f88SJack F Vogel return IXGBE_SUCCESS; 164413705f88SJack F Vogel } 164513705f88SJack F Vogel 164613705f88SJack F Vogel /** 164713705f88SJack F Vogel * ixgbe_clear_vfta_generic - Clear VLAN filter table 164813705f88SJack F Vogel * @hw: pointer to hardware structure 164913705f88SJack F Vogel * 165013705f88SJack F Vogel * Clears the VLAN filer table, and the VMDq index associated with the filter 165113705f88SJack F Vogel **/ 165213705f88SJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 165313705f88SJack F Vogel { 165413705f88SJack F Vogel u32 offset; 165513705f88SJack F Vogel u32 vlanbyte; 165613705f88SJack F Vogel 16579ca4041bSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 165813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 165913705f88SJack F Vogel 166013705f88SJack F Vogel for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) 16619ca4041bSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 166213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), 166313705f88SJack F Vogel 0); 166413705f88SJack F Vogel 166513705f88SJack F Vogel return IXGBE_SUCCESS; 166613705f88SJack F Vogel } 166713705f88SJack F Vogel 166813705f88SJack F Vogel /** 166913705f88SJack F Vogel * ixgbe_set_vfta_generic - Set VLAN filter table 167013705f88SJack F Vogel * @hw: pointer to hardware structure 167113705f88SJack F Vogel * @vlan: VLAN id to write to VLAN filter 167213705f88SJack F Vogel * @vind: VMDq output index that maps queue to VLAN id in VFTA 167313705f88SJack F Vogel * @vlan_on: boolean flag to turn on/off VLAN in VFTA 167413705f88SJack F Vogel * 167513705f88SJack F Vogel * Turn on/off specified VLAN in the VLAN filter table. 167613705f88SJack F Vogel **/ 167713705f88SJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 167813705f88SJack F Vogel bool vlan_on) 167913705f88SJack F Vogel { 168013705f88SJack F Vogel u32 VftaIndex; 168113705f88SJack F Vogel u32 BitOffset; 168213705f88SJack F Vogel u32 VftaReg; 168313705f88SJack F Vogel u32 VftaByte; 168413705f88SJack F Vogel 168513705f88SJack F Vogel /* Determine 32-bit word position in array */ 168613705f88SJack F Vogel VftaIndex = (vlan >> 5) & 0x7F; /* upper seven bits */ 168713705f88SJack F Vogel 168813705f88SJack F Vogel /* Determine the location of the (VMD) queue index */ 168913705f88SJack F Vogel VftaByte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ 169013705f88SJack F Vogel BitOffset = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ 169113705f88SJack F Vogel 169213705f88SJack F Vogel /* Set the nibble for VMD queue index */ 169313705f88SJack F Vogel VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex)); 169413705f88SJack F Vogel VftaReg &= (~(0x0F << BitOffset)); 169513705f88SJack F Vogel VftaReg |= (vind << BitOffset); 169613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg); 169713705f88SJack F Vogel 169813705f88SJack F Vogel /* Determine the location of the bit for this VLAN id */ 169913705f88SJack F Vogel BitOffset = vlan & 0x1F; /* lower five bits */ 170013705f88SJack F Vogel 170113705f88SJack F Vogel VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex)); 170213705f88SJack F Vogel if (vlan_on) 170313705f88SJack F Vogel /* Turn on this VLAN id */ 170413705f88SJack F Vogel VftaReg |= (1 << BitOffset); 170513705f88SJack F Vogel else 170613705f88SJack F Vogel /* Turn off this VLAN id */ 170713705f88SJack F Vogel VftaReg &= ~(1 << BitOffset); 170813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(VftaIndex), VftaReg); 170913705f88SJack F Vogel 171013705f88SJack F Vogel return IXGBE_SUCCESS; 171113705f88SJack F Vogel } 171213705f88SJack F Vogel 171313705f88SJack F Vogel /** 171413705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 171513705f88SJack F Vogel * @hw: pointer to hardware structure 171613705f88SJack F Vogel * 171713705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 171813705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 171913705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 172013705f88SJack F Vogel * is returned signifying master requests disabled. 172113705f88SJack F Vogel **/ 172213705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 172313705f88SJack F Vogel { 172413705f88SJack F Vogel u32 ctrl; 172513705f88SJack F Vogel s32 i; 172613705f88SJack F Vogel s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 172713705f88SJack F Vogel 172813705f88SJack F Vogel ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 172913705f88SJack F Vogel ctrl |= IXGBE_CTRL_GIO_DIS; 173013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 173113705f88SJack F Vogel 173213705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 173313705f88SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { 173413705f88SJack F Vogel status = IXGBE_SUCCESS; 173513705f88SJack F Vogel break; 173613705f88SJack F Vogel } 173713705f88SJack F Vogel usec_delay(100); 173813705f88SJack F Vogel } 173913705f88SJack F Vogel 174013705f88SJack F Vogel return status; 174113705f88SJack F Vogel } 174213705f88SJack F Vogel 174313705f88SJack F Vogel 174413705f88SJack F Vogel /** 17459ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 174613705f88SJack F Vogel * @hw: pointer to hardware structure 17479ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 174813705f88SJack F Vogel * 17499ca4041bSJack F Vogel * Acquires the SWFW semaphore thought the GSSR register for the specified 175013705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 175113705f88SJack F Vogel **/ 175213705f88SJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) 175313705f88SJack F Vogel { 175413705f88SJack F Vogel u32 gssr; 175513705f88SJack F Vogel u32 swmask = mask; 175613705f88SJack F Vogel u32 fwmask = mask << 5; 175713705f88SJack F Vogel s32 timeout = 200; 175813705f88SJack F Vogel 175913705f88SJack F Vogel while (timeout) { 176013705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 176113705f88SJack F Vogel return -IXGBE_ERR_SWFW_SYNC; 176213705f88SJack F Vogel 176313705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 176413705f88SJack F Vogel if (!(gssr & (fwmask | swmask))) 176513705f88SJack F Vogel break; 176613705f88SJack F Vogel 176713705f88SJack F Vogel /* 176813705f88SJack F Vogel * Firmware currently using resource (fwmask) or other software 176913705f88SJack F Vogel * thread currently using resource (swmask) 177013705f88SJack F Vogel */ 177113705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 177213705f88SJack F Vogel msec_delay(5); 177313705f88SJack F Vogel timeout--; 177413705f88SJack F Vogel } 177513705f88SJack F Vogel 177613705f88SJack F Vogel if (!timeout) { 177713705f88SJack F Vogel DEBUGOUT("Driver can't access resource, GSSR timeout.\n"); 177813705f88SJack F Vogel return -IXGBE_ERR_SWFW_SYNC; 177913705f88SJack F Vogel } 178013705f88SJack F Vogel 178113705f88SJack F Vogel gssr |= swmask; 178213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 178313705f88SJack F Vogel 178413705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 178513705f88SJack F Vogel return IXGBE_SUCCESS; 178613705f88SJack F Vogel } 178713705f88SJack F Vogel 178813705f88SJack F Vogel /** 178913705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 179013705f88SJack F Vogel * @hw: pointer to hardware structure 17919ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 179213705f88SJack F Vogel * 17939ca4041bSJack F Vogel * Releases the SWFW semaphore thought the GSSR register for the specified 179413705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 179513705f88SJack F Vogel **/ 179613705f88SJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) 179713705f88SJack F Vogel { 179813705f88SJack F Vogel u32 gssr; 179913705f88SJack F Vogel u32 swmask = mask; 180013705f88SJack F Vogel 180113705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 180213705f88SJack F Vogel 180313705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 180413705f88SJack F Vogel gssr &= ~swmask; 180513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 180613705f88SJack F Vogel 180713705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 180813705f88SJack F Vogel } 180913705f88SJack F Vogel 18109ca4041bSJack F Vogel /** 18119ca4041bSJack F Vogel * ixgbe_read_analog_reg8_generic - Reads 8 bit Atlas analog register 18129ca4041bSJack F Vogel * @hw: pointer to hardware structure 18139ca4041bSJack F Vogel * @reg: analog register to read 18149ca4041bSJack F Vogel * @val: read value 18159ca4041bSJack F Vogel * 18169ca4041bSJack F Vogel * Performs read operation to Atlas analog register specified. 18179ca4041bSJack F Vogel **/ 18189ca4041bSJack F Vogel s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val) 18199ca4041bSJack F Vogel { 18209ca4041bSJack F Vogel u32 atlas_ctl; 18219ca4041bSJack F Vogel 18229ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); 18239ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 18249ca4041bSJack F Vogel usec_delay(10); 18259ca4041bSJack F Vogel atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); 18269ca4041bSJack F Vogel *val = (u8)atlas_ctl; 18279ca4041bSJack F Vogel 18289ca4041bSJack F Vogel return IXGBE_SUCCESS; 18299ca4041bSJack F Vogel } 18309ca4041bSJack F Vogel 18319ca4041bSJack F Vogel /** 18329ca4041bSJack F Vogel * ixgbe_write_analog_reg8_generic - Writes 8 bit Atlas analog register 18339ca4041bSJack F Vogel * @hw: pointer to hardware structure 18349ca4041bSJack F Vogel * @reg: atlas register to write 18359ca4041bSJack F Vogel * @val: value to write 18369ca4041bSJack F Vogel * 18379ca4041bSJack F Vogel * Performs write operation to Atlas analog register specified. 18389ca4041bSJack F Vogel **/ 18399ca4041bSJack F Vogel s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val) 18409ca4041bSJack F Vogel { 18419ca4041bSJack F Vogel u32 atlas_ctl; 18429ca4041bSJack F Vogel 18439ca4041bSJack F Vogel atlas_ctl = (reg << 8) | val; 18449ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); 18459ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 18469ca4041bSJack F Vogel usec_delay(10); 18479ca4041bSJack F Vogel 18489ca4041bSJack F Vogel return IXGBE_SUCCESS; 18499ca4041bSJack F Vogel } 18509ca4041bSJack F Vogel 1851