16a14ee0cSDon Skidmore /******************************************************************************* 26a14ee0cSDon Skidmore * 36a14ee0cSDon Skidmore * Intel 10 Gigabit PCI Express Linux driver 46a14ee0cSDon Skidmore * Copyright(c) 1999 - 2014 Intel Corporation. 56a14ee0cSDon Skidmore * 66a14ee0cSDon Skidmore * This program is free software; you can redistribute it and/or modify it 76a14ee0cSDon Skidmore * under the terms and conditions of the GNU General Public License, 86a14ee0cSDon Skidmore * version 2, as published by the Free Software Foundation. 96a14ee0cSDon Skidmore * 106a14ee0cSDon Skidmore * This program is distributed in the hope it will be useful, but WITHOUT 116a14ee0cSDon Skidmore * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 126a14ee0cSDon Skidmore * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 136a14ee0cSDon Skidmore * more details. 146a14ee0cSDon Skidmore * 156a14ee0cSDon Skidmore * The full GNU General Public License is included in this distribution in 166a14ee0cSDon Skidmore * the file called "COPYING". 176a14ee0cSDon Skidmore * 186a14ee0cSDon Skidmore * Contact Information: 196a14ee0cSDon Skidmore * Linux NICS <linux.nics@intel.com> 206a14ee0cSDon Skidmore * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 216a14ee0cSDon Skidmore * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 226a14ee0cSDon Skidmore * 236a14ee0cSDon Skidmore ******************************************************************************/ 246a14ee0cSDon Skidmore #include "ixgbe_x540.h" 256a14ee0cSDon Skidmore #include "ixgbe_type.h" 266a14ee0cSDon Skidmore #include "ixgbe_common.h" 276a14ee0cSDon Skidmore #include "ixgbe_phy.h" 286a14ee0cSDon Skidmore 29ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 30ab5fe0c5SDon Skidmore * @hw: pointer to hardware structure 31ab5fe0c5SDon Skidmore **/ 32ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 33ab5fe0c5SDon Skidmore { 34ab5fe0c5SDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 35ab5fe0c5SDon Skidmore 36ab5fe0c5SDon Skidmore if (hw->bus.lan_id) { 37ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 38ab5fe0c5SDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 39ab5fe0c5SDon Skidmore } 40ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 41ab5fe0c5SDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 42ab5fe0c5SDon Skidmore IXGBE_WRITE_FLUSH(hw); 43ab5fe0c5SDon Skidmore } 44ab5fe0c5SDon Skidmore 456a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 466a14ee0cSDon Skidmore * @hw: pointer to hardware structure 476a14ee0cSDon Skidmore * 486a14ee0cSDon Skidmore * Returns error code 496a14ee0cSDon Skidmore */ 506a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 516a14ee0cSDon Skidmore { 526a14ee0cSDon Skidmore switch (hw->device_id) { 536a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 546a14ee0cSDon Skidmore /* set up for CS4227 usage */ 556a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 56ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 576a14ee0cSDon Skidmore 586a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 596a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 606a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 616a14ee0cSDon Skidmore break; 626a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 636a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 646a14ee0cSDon Skidmore break; 656a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 666a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 676a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 686a14ee0cSDon Skidmore default: 696a14ee0cSDon Skidmore break; 706a14ee0cSDon Skidmore } 716a14ee0cSDon Skidmore return 0; 726a14ee0cSDon Skidmore } 736a14ee0cSDon Skidmore 746a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 756a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 766a14ee0cSDon Skidmore { 776a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 786a14ee0cSDon Skidmore } 796a14ee0cSDon Skidmore 806a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 816a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 826a14ee0cSDon Skidmore { 836a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 846a14ee0cSDon Skidmore } 856a14ee0cSDon Skidmore 866a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 876a14ee0cSDon Skidmore * @hw: pointer to hardware structure 886a14ee0cSDon Skidmore * 896a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 906a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 916a14ee0cSDon Skidmore **/ 927ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 936a14ee0cSDon Skidmore { 946a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 956a14ee0cSDon Skidmore u32 eec; 966a14ee0cSDon Skidmore u16 eeprom_size; 976a14ee0cSDon Skidmore 986a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 996a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 1006a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 1016a14ee0cSDon Skidmore 1029a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 1036a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 1046a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 1056a14ee0cSDon Skidmore eeprom->word_size = 1 << (eeprom_size + 1066a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 1076a14ee0cSDon Skidmore 1086a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 1096a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 1106a14ee0cSDon Skidmore } 1116a14ee0cSDon Skidmore 1126a14ee0cSDon Skidmore return 0; 1136a14ee0cSDon Skidmore } 1146a14ee0cSDon Skidmore 115ae14a1d8SMark Rustad /** 116ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 117ae14a1d8SMark Rustad * @hw: pointer to hardware structure 118ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 119ae14a1d8SMark Rustad * 120ae14a1d8SMark Rustad * Return: failing status on timeout 121ae14a1d8SMark Rustad * 122ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 123ae14a1d8SMark Rustad */ 124ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 125ae14a1d8SMark Rustad { 126ae14a1d8SMark Rustad u32 i, command; 127ae14a1d8SMark Rustad 128ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 129ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 130ae14a1d8SMark Rustad * complete. 131ae14a1d8SMark Rustad */ 132ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 133ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 134ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 135ae14a1d8SMark Rustad break; 136ae14a1d8SMark Rustad usleep_range(10, 20); 137ae14a1d8SMark Rustad } 138ae14a1d8SMark Rustad if (ctrl) 139ae14a1d8SMark Rustad *ctrl = command; 140ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 141ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 142ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 143ae14a1d8SMark Rustad } 144ae14a1d8SMark Rustad 145ae14a1d8SMark Rustad return 0; 146ae14a1d8SMark Rustad } 147ae14a1d8SMark Rustad 1486a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 1496a14ee0cSDon Skidmore * IOSF device 1506a14ee0cSDon Skidmore * @hw: pointer to hardware structure 1516a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 1526a14ee0cSDon Skidmore * @device_type: 3 bit device type 1536a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 1546a14ee0cSDon Skidmore **/ 1557ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 1566a14ee0cSDon Skidmore u32 device_type, u32 *data) 1576a14ee0cSDon Skidmore { 158ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 159ae14a1d8SMark Rustad u32 command, error; 160ae14a1d8SMark Rustad s32 ret; 161ae14a1d8SMark Rustad 162ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 163ae14a1d8SMark Rustad if (ret) 164ae14a1d8SMark Rustad return ret; 165ae14a1d8SMark Rustad 166ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 167ae14a1d8SMark Rustad if (ret) 168ae14a1d8SMark Rustad goto out; 1696a14ee0cSDon Skidmore 1706a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 1716a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 1726a14ee0cSDon Skidmore 1736a14ee0cSDon Skidmore /* Write IOSF control register */ 1746a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 1756a14ee0cSDon Skidmore 176ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 1776a14ee0cSDon Skidmore 1786a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 1796a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 1806a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 1816a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 1826a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 1836a14ee0cSDon Skidmore } 1846a14ee0cSDon Skidmore 185ae14a1d8SMark Rustad if (!ret) 1866a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 1876a14ee0cSDon Skidmore 188ae14a1d8SMark Rustad out: 189ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 190ae14a1d8SMark Rustad return ret; 1916a14ee0cSDon Skidmore } 1926a14ee0cSDon Skidmore 1936a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 1946a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 1956a14ee0cSDon Skidmore * @hw: pointer to hardware structure 1966a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 1976a14ee0cSDon Skidmore * @data: word read from the EEPROM 1986a14ee0cSDon Skidmore * 1996a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 2006a14ee0cSDon Skidmore **/ 2017ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 2027ddbde3fSDon Skidmore u16 *data) 2036a14ee0cSDon Skidmore { 2046a14ee0cSDon Skidmore s32 status; 2056a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 2066a14ee0cSDon Skidmore 2076a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 2086a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 2096a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2106a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2116a14ee0cSDon Skidmore 2126a14ee0cSDon Skidmore /* convert offset from words to bytes */ 2136a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 2146a14ee0cSDon Skidmore /* one word */ 2156a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 2166a14ee0cSDon Skidmore 2176a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 2186a14ee0cSDon Skidmore sizeof(buffer), 2196a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 2206a14ee0cSDon Skidmore if (status) 2216a14ee0cSDon Skidmore return status; 2226a14ee0cSDon Skidmore 2236a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 2246a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 2256a14ee0cSDon Skidmore 2266a14ee0cSDon Skidmore return 0; 2276a14ee0cSDon Skidmore } 2286a14ee0cSDon Skidmore 2296a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 2306a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2316a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 2326a14ee0cSDon Skidmore * @words: number of words 2336a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 2346a14ee0cSDon Skidmore * 2356a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 2366a14ee0cSDon Skidmore **/ 2377ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 2386a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 2396a14ee0cSDon Skidmore { 2406a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 2416a14ee0cSDon Skidmore u32 current_word = 0; 2426a14ee0cSDon Skidmore u16 words_to_read; 2436a14ee0cSDon Skidmore s32 status; 2446a14ee0cSDon Skidmore u32 i; 2456a14ee0cSDon Skidmore 2466a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 2476a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2486a14ee0cSDon Skidmore if (status) { 2496a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 2506a14ee0cSDon Skidmore return status; 2516a14ee0cSDon Skidmore } 2526a14ee0cSDon Skidmore 2536a14ee0cSDon Skidmore while (words) { 2546a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 2556a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 2566a14ee0cSDon Skidmore else 2576a14ee0cSDon Skidmore words_to_read = words; 2586a14ee0cSDon Skidmore 2596a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 2606a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 2616a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2626a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2636a14ee0cSDon Skidmore 2646a14ee0cSDon Skidmore /* convert offset from words to bytes */ 2656a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 2666a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 2676a14ee0cSDon Skidmore 2686a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 2696a14ee0cSDon Skidmore sizeof(buffer), 2706a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 2716a14ee0cSDon Skidmore false); 2726a14ee0cSDon Skidmore if (status) { 2736a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 2746a14ee0cSDon Skidmore goto out; 2756a14ee0cSDon Skidmore } 2766a14ee0cSDon Skidmore 2776a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 2786a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 2796a14ee0cSDon Skidmore 2 * i; 2806a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 2816a14ee0cSDon Skidmore 2826a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 2836a14ee0cSDon Skidmore current_word++; 2846a14ee0cSDon Skidmore i++; 2856a14ee0cSDon Skidmore if (i < words_to_read) { 2866a14ee0cSDon Skidmore value >>= 16; 2876a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 2886a14ee0cSDon Skidmore current_word++; 2896a14ee0cSDon Skidmore } 2906a14ee0cSDon Skidmore } 2916a14ee0cSDon Skidmore words -= words_to_read; 2926a14ee0cSDon Skidmore } 2936a14ee0cSDon Skidmore 2946a14ee0cSDon Skidmore out: 2956a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2966a14ee0cSDon Skidmore return status; 2976a14ee0cSDon Skidmore } 2986a14ee0cSDon Skidmore 2996a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 3006a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3016a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 3026a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 3036a14ee0cSDon Skidmore * @csum: address of checksum to update 3046a14ee0cSDon Skidmore * 3056a14ee0cSDon Skidmore * Returns error status for any failure 3066a14ee0cSDon Skidmore **/ 3076a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 3086a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 3096a14ee0cSDon Skidmore u32 buffer_size) 3106a14ee0cSDon Skidmore { 3116a14ee0cSDon Skidmore u16 buf[256]; 3126a14ee0cSDon Skidmore s32 status; 3136a14ee0cSDon Skidmore u16 length, bufsz, i, start; 3146a14ee0cSDon Skidmore u16 *local_buffer; 3156a14ee0cSDon Skidmore 3166a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 3176a14ee0cSDon Skidmore 3186a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 3196a14ee0cSDon Skidmore if (!buffer) { 3206a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 3216a14ee0cSDon Skidmore if (status) { 3226a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3236a14ee0cSDon Skidmore return status; 3246a14ee0cSDon Skidmore } 3256a14ee0cSDon Skidmore local_buffer = buf; 3266a14ee0cSDon Skidmore } else { 3276a14ee0cSDon Skidmore if (buffer_size < ptr) 3286a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3296a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 3306a14ee0cSDon Skidmore } 3316a14ee0cSDon Skidmore 3326a14ee0cSDon Skidmore if (size) { 3336a14ee0cSDon Skidmore start = 0; 3346a14ee0cSDon Skidmore length = size; 3356a14ee0cSDon Skidmore } else { 3366a14ee0cSDon Skidmore start = 1; 3376a14ee0cSDon Skidmore length = local_buffer[0]; 3386a14ee0cSDon Skidmore 3396a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 3406a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 3416a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 3426a14ee0cSDon Skidmore return 0; 3436a14ee0cSDon Skidmore } 3446a14ee0cSDon Skidmore 3456a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 3466a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3476a14ee0cSDon Skidmore 3486a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 3496a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 3506a14ee0cSDon Skidmore ptr += bufsz; 3516a14ee0cSDon Skidmore i = 0; 3526a14ee0cSDon Skidmore if (length < bufsz) 3536a14ee0cSDon Skidmore bufsz = length; 3546a14ee0cSDon Skidmore 3556a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 3566a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 3576a14ee0cSDon Skidmore bufsz, buf); 3586a14ee0cSDon Skidmore if (status) { 3596a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3606a14ee0cSDon Skidmore return status; 3616a14ee0cSDon Skidmore } 3626a14ee0cSDon Skidmore } 3636a14ee0cSDon Skidmore *csum += local_buffer[i]; 3646a14ee0cSDon Skidmore } 3656a14ee0cSDon Skidmore return 0; 3666a14ee0cSDon Skidmore } 3676a14ee0cSDon Skidmore 3686a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 3696a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3706a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 3716a14ee0cSDon Skidmore * @buffer_size: size of buffer 3726a14ee0cSDon Skidmore * 3736a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 3746a14ee0cSDon Skidmore **/ 3757ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 3767ddbde3fSDon Skidmore u32 buffer_size) 3776a14ee0cSDon Skidmore { 3786a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 3796a14ee0cSDon Skidmore u16 *local_buffer; 3806a14ee0cSDon Skidmore s32 status; 3816a14ee0cSDon Skidmore u16 checksum = 0; 3826a14ee0cSDon Skidmore u16 pointer, i, size; 3836a14ee0cSDon Skidmore 3846a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 3856a14ee0cSDon Skidmore 3866a14ee0cSDon Skidmore if (!buffer) { 3876a14ee0cSDon Skidmore /* Read pointer area */ 3886a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 3896a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 3906a14ee0cSDon Skidmore eeprom_ptrs); 3916a14ee0cSDon Skidmore if (status) { 3926a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3936a14ee0cSDon Skidmore return status; 3946a14ee0cSDon Skidmore } 3956a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 3966a14ee0cSDon Skidmore } else { 3976a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 3986a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3996a14ee0cSDon Skidmore local_buffer = buffer; 4006a14ee0cSDon Skidmore } 4016a14ee0cSDon Skidmore 4026a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 4036a14ee0cSDon Skidmore * checksum word itself 4046a14ee0cSDon Skidmore */ 4056a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 4066a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 4076a14ee0cSDon Skidmore checksum += local_buffer[i]; 4086a14ee0cSDon Skidmore 4096a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 4106a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 4116a14ee0cSDon Skidmore */ 4126a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 4136a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 4146a14ee0cSDon Skidmore continue; 4156a14ee0cSDon Skidmore 4166a14ee0cSDon Skidmore pointer = local_buffer[i]; 4176a14ee0cSDon Skidmore 4186a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 4196a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 4206a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 4216a14ee0cSDon Skidmore continue; 4226a14ee0cSDon Skidmore 4236a14ee0cSDon Skidmore switch (i) { 4246a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 4256a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 4266a14ee0cSDon Skidmore break; 4276a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 4286a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 4296a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 4306a14ee0cSDon Skidmore break; 4316a14ee0cSDon Skidmore default: 4326a14ee0cSDon Skidmore size = 0; 4336a14ee0cSDon Skidmore break; 4346a14ee0cSDon Skidmore } 4356a14ee0cSDon Skidmore 4366a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 4376a14ee0cSDon Skidmore buffer, buffer_size); 4386a14ee0cSDon Skidmore if (status) 4396a14ee0cSDon Skidmore return status; 4406a14ee0cSDon Skidmore } 4416a14ee0cSDon Skidmore 4426a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 4436a14ee0cSDon Skidmore 4446a14ee0cSDon Skidmore return (s32)checksum; 4456a14ee0cSDon Skidmore } 4466a14ee0cSDon Skidmore 4476a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 4486a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4496a14ee0cSDon Skidmore * 4506a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 4516a14ee0cSDon Skidmore **/ 4527ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 4536a14ee0cSDon Skidmore { 4546a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 4556a14ee0cSDon Skidmore } 4566a14ee0cSDon Skidmore 4576a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 4586a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4596a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 4606a14ee0cSDon Skidmore * @data: word read from the EEPROM 4616a14ee0cSDon Skidmore * 4626a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 4636a14ee0cSDon Skidmore **/ 4647ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 4656a14ee0cSDon Skidmore { 4666a14ee0cSDon Skidmore s32 status = 0; 4676a14ee0cSDon Skidmore 4686a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 4696a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 4706a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 4716a14ee0cSDon Skidmore } else { 4726a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 4736a14ee0cSDon Skidmore } 4746a14ee0cSDon Skidmore 4756a14ee0cSDon Skidmore return status; 4766a14ee0cSDon Skidmore } 4776a14ee0cSDon Skidmore 4786a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 4796a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4806a14ee0cSDon Skidmore * @checksum_val: calculated checksum 4816a14ee0cSDon Skidmore * 4826a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 4836a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 4846a14ee0cSDon Skidmore **/ 4857ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 4867ddbde3fSDon Skidmore u16 *checksum_val) 4876a14ee0cSDon Skidmore { 4886a14ee0cSDon Skidmore s32 status; 4896a14ee0cSDon Skidmore u16 checksum; 4906a14ee0cSDon Skidmore u16 read_checksum = 0; 4916a14ee0cSDon Skidmore 4926a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 4936a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 4946a14ee0cSDon Skidmore * EEPROM read fails 4956a14ee0cSDon Skidmore */ 4966a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 4976a14ee0cSDon Skidmore if (status) { 4986a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 4996a14ee0cSDon Skidmore return status; 5006a14ee0cSDon Skidmore } 5016a14ee0cSDon Skidmore 5026a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 5036a14ee0cSDon Skidmore if (status < 0) 5046a14ee0cSDon Skidmore return status; 5056a14ee0cSDon Skidmore 5066a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 5076a14ee0cSDon Skidmore 5086a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 5096a14ee0cSDon Skidmore &read_checksum); 5106a14ee0cSDon Skidmore if (status) 5116a14ee0cSDon Skidmore return status; 5126a14ee0cSDon Skidmore 5136a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 5146a14ee0cSDon Skidmore * calculated checksum 5156a14ee0cSDon Skidmore */ 5166a14ee0cSDon Skidmore if (read_checksum != checksum) { 5176a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 5186a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 5196a14ee0cSDon Skidmore } 5206a14ee0cSDon Skidmore 5216a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 5226a14ee0cSDon Skidmore if (checksum_val) 5236a14ee0cSDon Skidmore *checksum_val = checksum; 5246a14ee0cSDon Skidmore 5256a14ee0cSDon Skidmore return status; 5266a14ee0cSDon Skidmore } 5276a14ee0cSDon Skidmore 5286a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 5296a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5306a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 5316a14ee0cSDon Skidmore * @data: word write to the EEPROM 5326a14ee0cSDon Skidmore * 5336a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 5346a14ee0cSDon Skidmore **/ 5357ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 5367ddbde3fSDon Skidmore u16 data) 5376a14ee0cSDon Skidmore { 5386a14ee0cSDon Skidmore s32 status; 5396a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 5406a14ee0cSDon Skidmore 5416a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 5426a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 5436a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 5446a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 5456a14ee0cSDon Skidmore 5466a14ee0cSDon Skidmore /* one word */ 5476a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 5486a14ee0cSDon Skidmore buffer.data = data; 5496a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 5506a14ee0cSDon Skidmore 5516a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 5526a14ee0cSDon Skidmore sizeof(buffer), 5536a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5546a14ee0cSDon Skidmore return status; 5556a14ee0cSDon Skidmore } 5566a14ee0cSDon Skidmore 5576a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 5586a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5596a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 5606a14ee0cSDon Skidmore * @data: word write to the EEPROM 5616a14ee0cSDon Skidmore * 5626a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 5636a14ee0cSDon Skidmore **/ 5647ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 5656a14ee0cSDon Skidmore { 5666a14ee0cSDon Skidmore s32 status = 0; 5676a14ee0cSDon Skidmore 5686a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 5696a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 5706a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 5716a14ee0cSDon Skidmore } else { 5726a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 5736a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 5746a14ee0cSDon Skidmore } 5756a14ee0cSDon Skidmore 5766a14ee0cSDon Skidmore return status; 5776a14ee0cSDon Skidmore } 5786a14ee0cSDon Skidmore 5796a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 5806a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5816a14ee0cSDon Skidmore * 5826a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 5836a14ee0cSDon Skidmore **/ 5847ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 5856a14ee0cSDon Skidmore { 5866a14ee0cSDon Skidmore s32 status = 0; 5876a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 5886a14ee0cSDon Skidmore 5896a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 5906a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 5916a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 5926a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 5936a14ee0cSDon Skidmore 5946a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 5956a14ee0cSDon Skidmore sizeof(buffer), 5966a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5976a14ee0cSDon Skidmore return status; 5986a14ee0cSDon Skidmore } 5996a14ee0cSDon Skidmore 6001f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 6011f9ac57cSDon Skidmore * 6021f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 6031f9ac57cSDon Skidmore **/ 6041f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 6051f9ac57cSDon Skidmore { 6061f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 6071f9ac57cSDon Skidmore s32 status; 6081f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 6091f9ac57cSDon Skidmore 6101f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 6111f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 6121f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 6131f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 6141f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 6151f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 6161f9ac57cSDon Skidmore hw->mac.set_lben = true; 6171f9ac57cSDon Skidmore } else { 6181f9ac57cSDon Skidmore hw->mac.set_lben = false; 6191f9ac57cSDon Skidmore } 6201f9ac57cSDon Skidmore 6211f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 6221f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 6231f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 6241f9ac57cSDon Skidmore fw_cmd.port_number = (u8)hw->bus.lan_id; 6251f9ac57cSDon Skidmore 6261f9ac57cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 6271f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 6281f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 6291f9ac57cSDon Skidmore 6301f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 6311f9ac57cSDon Skidmore if (status) { 6321f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 6331f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 6341f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 6351f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 6361f9ac57cSDon Skidmore } 6371f9ac57cSDon Skidmore } 6381f9ac57cSDon Skidmore } 6391f9ac57cSDon Skidmore } 6401f9ac57cSDon Skidmore 6416a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 6426a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6436a14ee0cSDon Skidmore * 6446a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 6456a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 6466a14ee0cSDon Skidmore * the flash. 6476a14ee0cSDon Skidmore **/ 6487ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 6496a14ee0cSDon Skidmore { 6506a14ee0cSDon Skidmore s32 status; 6516a14ee0cSDon Skidmore u16 checksum = 0; 6526a14ee0cSDon Skidmore 6536a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 6546a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 6556a14ee0cSDon Skidmore * EEPROM read fails 6566a14ee0cSDon Skidmore */ 6576a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 6586a14ee0cSDon Skidmore if (status) { 6596a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 6606a14ee0cSDon Skidmore return status; 6616a14ee0cSDon Skidmore } 6626a14ee0cSDon Skidmore 6636a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 6646a14ee0cSDon Skidmore if (status < 0) 6656a14ee0cSDon Skidmore return status; 6666a14ee0cSDon Skidmore 6676a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 6686a14ee0cSDon Skidmore 6696a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 6706a14ee0cSDon Skidmore checksum); 6716a14ee0cSDon Skidmore if (status) 6726a14ee0cSDon Skidmore return status; 6736a14ee0cSDon Skidmore 6746a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 6756a14ee0cSDon Skidmore 6766a14ee0cSDon Skidmore return status; 6776a14ee0cSDon Skidmore } 6786a14ee0cSDon Skidmore 6796a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 6806a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6816a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 6826a14ee0cSDon Skidmore * @words: number of words 6836a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 6846a14ee0cSDon Skidmore * 6856a14ee0cSDon Skidmore * 6866a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 6876a14ee0cSDon Skidmore **/ 6887ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 6897ddbde3fSDon Skidmore u16 offset, u16 words, 6907ddbde3fSDon Skidmore u16 *data) 6916a14ee0cSDon Skidmore { 6926a14ee0cSDon Skidmore s32 status = 0; 6936a14ee0cSDon Skidmore u32 i = 0; 6946a14ee0cSDon Skidmore 6956a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 6966a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6976a14ee0cSDon Skidmore if (status) { 6986a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 6996a14ee0cSDon Skidmore return status; 7006a14ee0cSDon Skidmore } 7016a14ee0cSDon Skidmore 7026a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 7036a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 7046a14ee0cSDon Skidmore data[i]); 7056a14ee0cSDon Skidmore if (status) { 7066a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 7076a14ee0cSDon Skidmore break; 7086a14ee0cSDon Skidmore } 7096a14ee0cSDon Skidmore } 7106a14ee0cSDon Skidmore 7116a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 7126a14ee0cSDon Skidmore 7136a14ee0cSDon Skidmore return status; 7146a14ee0cSDon Skidmore } 7156a14ee0cSDon Skidmore 7166a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 7176a14ee0cSDon Skidmore * IOSF device 7186a14ee0cSDon Skidmore * 7196a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7206a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 7216a14ee0cSDon Skidmore * @device_type: 3 bit device type 7226a14ee0cSDon Skidmore * @data: Data to write to the register 7236a14ee0cSDon Skidmore **/ 7247ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 7256a14ee0cSDon Skidmore u32 device_type, u32 data) 7266a14ee0cSDon Skidmore { 727ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 728ae14a1d8SMark Rustad u32 command, error; 729ae14a1d8SMark Rustad s32 ret; 730ae14a1d8SMark Rustad 731ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 732ae14a1d8SMark Rustad if (ret) 733ae14a1d8SMark Rustad return ret; 734ae14a1d8SMark Rustad 735ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 736ae14a1d8SMark Rustad if (ret) 737ae14a1d8SMark Rustad goto out; 7386a14ee0cSDon Skidmore 7396a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 7406a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 7416a14ee0cSDon Skidmore 7426a14ee0cSDon Skidmore /* Write IOSF control register */ 7436a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 7446a14ee0cSDon Skidmore 7456a14ee0cSDon Skidmore /* Write IOSF data register */ 7466a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 7476a14ee0cSDon Skidmore 748ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 7496a14ee0cSDon Skidmore 7506a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 7516a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 7526a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 7536a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 7546a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 7556a14ee0cSDon Skidmore } 7566a14ee0cSDon Skidmore 757ae14a1d8SMark Rustad out: 758ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 759ae14a1d8SMark Rustad return ret; 7606a14ee0cSDon Skidmore } 7616a14ee0cSDon Skidmore 7626a14ee0cSDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 7636a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7646a14ee0cSDon Skidmore * @speed: the link speed to force 7656a14ee0cSDon Skidmore * 7666a14ee0cSDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 7676a14ee0cSDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 7686a14ee0cSDon Skidmore **/ 7696a14ee0cSDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 7706a14ee0cSDon Skidmore { 7716a14ee0cSDon Skidmore s32 status; 7726a14ee0cSDon Skidmore u32 reg_val; 7736a14ee0cSDon Skidmore 7746a14ee0cSDon Skidmore /* Disable AN and force speed to 10G Serial. */ 7756a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 7766a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 7776a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 7786a14ee0cSDon Skidmore if (status) 7796a14ee0cSDon Skidmore return status; 7806a14ee0cSDon Skidmore 7816a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 7826a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 7836a14ee0cSDon Skidmore 7846a14ee0cSDon Skidmore /* Select forced link speed for internal PHY. */ 7856a14ee0cSDon Skidmore switch (*speed) { 7866a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 7876a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 7886a14ee0cSDon Skidmore break; 7896a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 7906a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 7916a14ee0cSDon Skidmore break; 7926a14ee0cSDon Skidmore default: 7936a14ee0cSDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 7946a14ee0cSDon Skidmore return IXGBE_ERR_LINK_SETUP; 7956a14ee0cSDon Skidmore } 7966a14ee0cSDon Skidmore 7976a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 7986a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 7996a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8006a14ee0cSDon Skidmore if (status) 8016a14ee0cSDon Skidmore return status; 8026a14ee0cSDon Skidmore 8036a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 8046a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8056a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 8066a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8076a14ee0cSDon Skidmore if (status) 8086a14ee0cSDon Skidmore return status; 8096a14ee0cSDon Skidmore 8106a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 8116a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8126a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 8136a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8146a14ee0cSDon Skidmore if (status) 8156a14ee0cSDon Skidmore return status; 8166a14ee0cSDon Skidmore 8176a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 8186a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8196a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 8206a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8216a14ee0cSDon Skidmore if (status) 8226a14ee0cSDon Skidmore return status; 8236a14ee0cSDon Skidmore 8246a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 8256a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 8266a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 8276a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8286a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 8296a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8306a14ee0cSDon Skidmore if (status) 8316a14ee0cSDon Skidmore return status; 8326a14ee0cSDon Skidmore 8336a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8346a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 8356a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8366a14ee0cSDon Skidmore if (status) 8376a14ee0cSDon Skidmore return status; 8386a14ee0cSDon Skidmore 8396a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 8406a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 8416a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 8426a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8436a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 8446a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8456a14ee0cSDon Skidmore if (status) 8466a14ee0cSDon Skidmore return status; 8476a14ee0cSDon Skidmore 8486a14ee0cSDon Skidmore /* Enable override for coefficients. */ 8496a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8506a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 8516a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8526a14ee0cSDon Skidmore if (status) 8536a14ee0cSDon Skidmore return status; 8546a14ee0cSDon Skidmore 8556a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 8566a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 8576a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 8586a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 8596a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8606a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 8616a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8626a14ee0cSDon Skidmore if (status) 8636a14ee0cSDon Skidmore return status; 8646a14ee0cSDon Skidmore 8656a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 8666a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8676a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 8686a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8696a14ee0cSDon Skidmore if (status) 8706a14ee0cSDon Skidmore return status; 8716a14ee0cSDon Skidmore 8726a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 8736a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8746a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 8756a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8766a14ee0cSDon Skidmore 8776a14ee0cSDon Skidmore return status; 8786a14ee0cSDon Skidmore } 8796a14ee0cSDon Skidmore 880c3dc4c09SDon Skidmore /** 881c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 882c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 883c3dc4c09SDon Skidmore * @speed: new link speed 884c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 885c3dc4c09SDon Skidmore * 886c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 887c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 888c3dc4c09SDon Skidmore * 889c3dc4c09SDon Skidmore * Returns error status for any failure 890c3dc4c09SDon Skidmore **/ 891c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 892c3dc4c09SDon Skidmore ixgbe_link_speed speed, 893c3dc4c09SDon Skidmore bool autoneg_wait) 894c3dc4c09SDon Skidmore { 895c3dc4c09SDon Skidmore s32 status; 896c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 897c3dc4c09SDon Skidmore 898c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 899c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 900c3dc4c09SDon Skidmore */ 901c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 902c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 903c3dc4c09SDon Skidmore else 904c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 905c3dc4c09SDon Skidmore 906c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 907c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 908c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 909c3dc4c09SDon Skidmore 910c3dc4c09SDon Skidmore if (status) 911c3dc4c09SDon Skidmore return status; 912c3dc4c09SDon Skidmore } 913c3dc4c09SDon Skidmore 914c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 915c3dc4c09SDon Skidmore } 916c3dc4c09SDon Skidmore 917c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 918c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 919c3dc4c09SDon Skidmore **/ 920c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 921c3dc4c09SDon Skidmore { 922c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 923c3dc4c09SDon Skidmore 924c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 925c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 926c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 927c3dc4c09SDon Skidmore * functions for SFP+ fiber 928c3dc4c09SDon Skidmore */ 929c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 930c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 931c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 932c3dc4c09SDon Skidmore break; 933c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 934c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 935c3dc4c09SDon Skidmore break; 936c3dc4c09SDon Skidmore default: 937c3dc4c09SDon Skidmore break; 938c3dc4c09SDon Skidmore } 939c3dc4c09SDon Skidmore } 940c3dc4c09SDon Skidmore 941c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 942c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 943c3dc4c09SDon Skidmore */ 944c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 945c3dc4c09SDon Skidmore { 946c3dc4c09SDon Skidmore bool setup_linear; 947c3dc4c09SDon Skidmore u16 reg_slice, edc_mode; 948c3dc4c09SDon Skidmore s32 ret_val; 949c3dc4c09SDon Skidmore 950c3dc4c09SDon Skidmore switch (hw->phy.sfp_type) { 951c3dc4c09SDon Skidmore case ixgbe_sfp_type_unknown: 952c3dc4c09SDon Skidmore return 0; 953c3dc4c09SDon Skidmore case ixgbe_sfp_type_not_present: 954c3dc4c09SDon Skidmore return IXGBE_ERR_SFP_NOT_PRESENT; 955c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_cu_core0: 956c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_cu_core1: 957c3dc4c09SDon Skidmore setup_linear = true; 958c3dc4c09SDon Skidmore break; 959c3dc4c09SDon Skidmore case ixgbe_sfp_type_srlr_core0: 960c3dc4c09SDon Skidmore case ixgbe_sfp_type_srlr_core1: 961c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_act_lmt_core0: 962c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_act_lmt_core1: 963c3dc4c09SDon Skidmore case ixgbe_sfp_type_1g_sx_core0: 964c3dc4c09SDon Skidmore case ixgbe_sfp_type_1g_sx_core1: 965c3dc4c09SDon Skidmore setup_linear = false; 966c3dc4c09SDon Skidmore break; 967c3dc4c09SDon Skidmore default: 968c3dc4c09SDon Skidmore return IXGBE_ERR_SFP_NOT_SUPPORTED; 969c3dc4c09SDon Skidmore } 970c3dc4c09SDon Skidmore 971c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 972c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 973c3dc4c09SDon Skidmore 974c3dc4c09SDon Skidmore /* The CS4227 slice address is the base address + the port-pair reg 975c3dc4c09SDon Skidmore * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0. 976c3dc4c09SDon Skidmore */ 977c3dc4c09SDon Skidmore reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12); 978c3dc4c09SDon Skidmore 979c3dc4c09SDon Skidmore if (setup_linear) 980c3dc4c09SDon Skidmore edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 981c3dc4c09SDon Skidmore else 982c3dc4c09SDon Skidmore edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 983c3dc4c09SDon Skidmore 984c3dc4c09SDon Skidmore /* Configure CS4227 for connection type. */ 985c3dc4c09SDon Skidmore ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice, 986c3dc4c09SDon Skidmore edc_mode); 987c3dc4c09SDon Skidmore 988c3dc4c09SDon Skidmore if (ret_val) 989c3dc4c09SDon Skidmore ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice, 990c3dc4c09SDon Skidmore edc_mode); 991c3dc4c09SDon Skidmore 992c3dc4c09SDon Skidmore return ret_val; 993c3dc4c09SDon Skidmore } 994c3dc4c09SDon Skidmore 995c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 996c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 997c3dc4c09SDon Skidmore * @speed: pointer to link speed 998c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 999c3dc4c09SDon Skidmore **/ 1000c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1001c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1002c3dc4c09SDon Skidmore bool *autoneg) 1003c3dc4c09SDon Skidmore { 1004c3dc4c09SDon Skidmore /* SFP */ 1005c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1006c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1007c3dc4c09SDon Skidmore *autoneg = false; 1008c3dc4c09SDon Skidmore 1009c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1010c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1011c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1012c3dc4c09SDon Skidmore return 0; 1013c3dc4c09SDon Skidmore } 1014c3dc4c09SDon Skidmore 1015c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1016c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1017c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1018c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1019c3dc4c09SDon Skidmore else 1020c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1021c3dc4c09SDon Skidmore } else { 1022c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1023c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1024c3dc4c09SDon Skidmore *autoneg = true; 1025c3dc4c09SDon Skidmore } 1026c3dc4c09SDon Skidmore return 0; 1027c3dc4c09SDon Skidmore } 1028c3dc4c09SDon Skidmore 1029c3dc4c09SDon Skidmore /** 1030c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1031c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1032c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1033c3dc4c09SDon Skidmore * PHY interrupt is lsc 1034c3dc4c09SDon Skidmore * 1035c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1036c3dc4c09SDon Skidmore * failure alarm or link status change. 1037c3dc4c09SDon Skidmore * 1038c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1039c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1040c3dc4c09SDon Skidmore **/ 1041c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1042c3dc4c09SDon Skidmore { 1043c3dc4c09SDon Skidmore u32 status; 1044c3dc4c09SDon Skidmore u16 reg; 1045c3dc4c09SDon Skidmore 1046c3dc4c09SDon Skidmore *lsc = false; 1047c3dc4c09SDon Skidmore 1048c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1049c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1050c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1051c3dc4c09SDon Skidmore ®); 1052c3dc4c09SDon Skidmore 1053c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1054c3dc4c09SDon Skidmore return status; 1055c3dc4c09SDon Skidmore 1056c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1057c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 1058c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1059c3dc4c09SDon Skidmore ®); 1060c3dc4c09SDon Skidmore 1061c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1062c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1063c3dc4c09SDon Skidmore return status; 1064c3dc4c09SDon Skidmore 1065c3dc4c09SDon Skidmore /* High temperature failure alarm triggered */ 1066c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 1067c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1068c3dc4c09SDon Skidmore ®); 1069c3dc4c09SDon Skidmore 1070c3dc4c09SDon Skidmore if (status) 1071c3dc4c09SDon Skidmore return status; 1072c3dc4c09SDon Skidmore 1073c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1074c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1075c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1076c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1077c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1078c3dc4c09SDon Skidmore } 1079c3dc4c09SDon Skidmore 1080c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1081c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1082c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1083c3dc4c09SDon Skidmore 1084c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1085c3dc4c09SDon Skidmore return status; 1086c3dc4c09SDon Skidmore 1087c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1088c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 1089c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1090c3dc4c09SDon Skidmore 1091c3dc4c09SDon Skidmore if (status) 1092c3dc4c09SDon Skidmore return status; 1093c3dc4c09SDon Skidmore 1094c3dc4c09SDon Skidmore /* Indicate LSC */ 1095c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1096c3dc4c09SDon Skidmore *lsc = true; 1097c3dc4c09SDon Skidmore 1098c3dc4c09SDon Skidmore return 0; 1099c3dc4c09SDon Skidmore } 1100c3dc4c09SDon Skidmore 1101c3dc4c09SDon Skidmore /** 1102c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1103c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1104c3dc4c09SDon Skidmore * 1105c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 1106c3dc4c09SDon Skidmore * Base T PHY 1107c3dc4c09SDon Skidmore * 1108c3dc4c09SDon Skidmore * Returns PHY access status 1109c3dc4c09SDon Skidmore **/ 1110c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1111c3dc4c09SDon Skidmore { 1112c3dc4c09SDon Skidmore u32 status; 1113c3dc4c09SDon Skidmore u16 reg; 1114c3dc4c09SDon Skidmore bool lsc; 1115c3dc4c09SDon Skidmore 1116c3dc4c09SDon Skidmore /* Clear interrupt flags */ 1117c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1118c3dc4c09SDon Skidmore 1119c3dc4c09SDon Skidmore /* Enable link status change alarm */ 1120c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1121c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1122c3dc4c09SDon Skidmore if (status) 1123c3dc4c09SDon Skidmore return status; 1124c3dc4c09SDon Skidmore 1125c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1126c3dc4c09SDon Skidmore 1127c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1128c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); 1129c3dc4c09SDon Skidmore if (status) 1130c3dc4c09SDon Skidmore return status; 1131c3dc4c09SDon Skidmore 1132c3dc4c09SDon Skidmore /* Enables high temperature failure alarm */ 1133c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1134c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1135c3dc4c09SDon Skidmore ®); 1136c3dc4c09SDon Skidmore if (status) 1137c3dc4c09SDon Skidmore return status; 1138c3dc4c09SDon Skidmore 1139c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN; 1140c3dc4c09SDon Skidmore 1141c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1142c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1143c3dc4c09SDon Skidmore reg); 1144c3dc4c09SDon Skidmore if (status) 1145c3dc4c09SDon Skidmore return status; 1146c3dc4c09SDon Skidmore 1147c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1148c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1149c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1150c3dc4c09SDon Skidmore ®); 1151c3dc4c09SDon Skidmore if (status) 1152c3dc4c09SDon Skidmore return status; 1153c3dc4c09SDon Skidmore 1154c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1155c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1156c3dc4c09SDon Skidmore 1157c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1158c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1159c3dc4c09SDon Skidmore reg); 1160c3dc4c09SDon Skidmore if (status) 1161c3dc4c09SDon Skidmore return status; 1162c3dc4c09SDon Skidmore 1163c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 1164c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1165c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1166c3dc4c09SDon Skidmore ®); 1167c3dc4c09SDon Skidmore if (status) 1168c3dc4c09SDon Skidmore return status; 1169c3dc4c09SDon Skidmore 1170c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1171c3dc4c09SDon Skidmore 1172c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1173c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1174c3dc4c09SDon Skidmore reg); 1175c3dc4c09SDon Skidmore 1176c3dc4c09SDon Skidmore return status; 1177c3dc4c09SDon Skidmore } 1178c3dc4c09SDon Skidmore 1179c3dc4c09SDon Skidmore /** 1180c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 1181c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1182c3dc4c09SDon Skidmore * 1183c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 1184c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 1185c3dc4c09SDon Skidmore * then setup internal/external PHY link 1186c3dc4c09SDon Skidmore * 1187c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1188c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1189c3dc4c09SDon Skidmore **/ 1190c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1191c3dc4c09SDon Skidmore { 1192c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1193c3dc4c09SDon Skidmore bool lsc; 1194c3dc4c09SDon Skidmore u32 status; 1195c3dc4c09SDon Skidmore 1196c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1197c3dc4c09SDon Skidmore if (status) 1198c3dc4c09SDon Skidmore return status; 1199c3dc4c09SDon Skidmore 1200c3dc4c09SDon Skidmore if (lsc) 1201c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 1202c3dc4c09SDon Skidmore 1203c3dc4c09SDon Skidmore return 0; 1204c3dc4c09SDon Skidmore } 1205c3dc4c09SDon Skidmore 1206c3dc4c09SDon Skidmore /** 1207c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1208c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1209c3dc4c09SDon Skidmore * @speed: link speed 1210c3dc4c09SDon Skidmore * 1211c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 1212c3dc4c09SDon Skidmore **/ 1213c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1214c3dc4c09SDon Skidmore ixgbe_link_speed speed) 1215c3dc4c09SDon Skidmore { 1216c3dc4c09SDon Skidmore s32 status; 1217c3dc4c09SDon Skidmore u32 reg_val; 1218c3dc4c09SDon Skidmore 1219c3dc4c09SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 1220c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1221c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1222c3dc4c09SDon Skidmore if (status) 1223c3dc4c09SDon Skidmore return status; 1224c3dc4c09SDon Skidmore 1225c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1226c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | 1227c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); 1228c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 1229c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 1230c3dc4c09SDon Skidmore 1231c3dc4c09SDon Skidmore /* Advertise 10G support. */ 1232c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1233c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 1234c3dc4c09SDon Skidmore 1235c3dc4c09SDon Skidmore /* Advertise 1G support. */ 1236c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 1237c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 1238c3dc4c09SDon Skidmore 1239c3dc4c09SDon Skidmore /* Restart auto-negotiation. */ 1240c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1241c3dc4c09SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 1242c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1243c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1244c3dc4c09SDon Skidmore 1245c3dc4c09SDon Skidmore return status; 1246c3dc4c09SDon Skidmore } 1247c3dc4c09SDon Skidmore 12486a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 12496a14ee0cSDon Skidmore * @hw: pointer to hardware structure 12506a14ee0cSDon Skidmore * 12516a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 12526a14ee0cSDon Skidmore **/ 12537ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 12546a14ee0cSDon Skidmore { 12556a14ee0cSDon Skidmore s32 status; 12566a14ee0cSDon Skidmore u32 reg_val; 12576a14ee0cSDon Skidmore 12586a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 12596a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 12606a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 12616a14ee0cSDon Skidmore if (status) 12626a14ee0cSDon Skidmore return status; 12636a14ee0cSDon Skidmore 12646a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 12656a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 12666a14ee0cSDon Skidmore 12676a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 12686a14ee0cSDon Skidmore 12696a14ee0cSDon Skidmore /* Advertise 10G support. */ 12706a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 12716a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 12726a14ee0cSDon Skidmore 12736a14ee0cSDon Skidmore /* Advertise 1G support. */ 12746a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 12756a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 12766a14ee0cSDon Skidmore 12776a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 12786a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 12796a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 12806a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 12816a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 12826a14ee0cSDon Skidmore 12836a14ee0cSDon Skidmore return status; 12846a14ee0cSDon Skidmore } 12856a14ee0cSDon Skidmore 12866a14ee0cSDon Skidmore /** ixgbe_setup_kr_x550em - Configure the KR PHY. 12876a14ee0cSDon Skidmore * @hw: pointer to hardware structure 12886a14ee0cSDon Skidmore * 12896a14ee0cSDon Skidmore * Configures the integrated KR PHY. 12906a14ee0cSDon Skidmore **/ 12917ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 12926a14ee0cSDon Skidmore { 1293c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 12946a14ee0cSDon Skidmore } 12956a14ee0cSDon Skidmore 1296c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 1297c3dc4c09SDon Skidmore * @hw: address of hardware structure 1298c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 1299c3dc4c09SDon Skidmore * 1300c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 1301c3dc4c09SDon Skidmore **/ 1302c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 1303c3dc4c09SDon Skidmore { 1304c3dc4c09SDon Skidmore u32 ret; 1305c3dc4c09SDon Skidmore u16 autoneg_status; 1306c3dc4c09SDon Skidmore 1307c3dc4c09SDon Skidmore *link_up = false; 1308c3dc4c09SDon Skidmore 1309c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 1310c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1311c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1312c3dc4c09SDon Skidmore &autoneg_status); 1313c3dc4c09SDon Skidmore if (ret) 1314c3dc4c09SDon Skidmore return ret; 1315c3dc4c09SDon Skidmore 1316c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1317c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1318c3dc4c09SDon Skidmore &autoneg_status); 1319c3dc4c09SDon Skidmore if (ret) 1320c3dc4c09SDon Skidmore return ret; 1321c3dc4c09SDon Skidmore 1322c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 1323c3dc4c09SDon Skidmore 1324c3dc4c09SDon Skidmore return 0; 1325c3dc4c09SDon Skidmore } 1326c3dc4c09SDon Skidmore 1327c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 13286a14ee0cSDon Skidmore * @hw: point to hardware structure 13296a14ee0cSDon Skidmore * 1330c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 1331c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 1332c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 1333c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 13346a14ee0cSDon Skidmore * 13356a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 13366a14ee0cSDon Skidmore * not report link up. 13376a14ee0cSDon Skidmore **/ 1338c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 13396a14ee0cSDon Skidmore { 13406a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 1341c3dc4c09SDon Skidmore bool link_up; 1342c3dc4c09SDon Skidmore u32 status; 1343c3dc4c09SDon Skidmore u16 speed; 13446a14ee0cSDon Skidmore 1345c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1346c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 1347c3dc4c09SDon Skidmore 1348c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 1349c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 13506a14ee0cSDon Skidmore if (status) 13516a14ee0cSDon Skidmore return status; 13526a14ee0cSDon Skidmore 1353c3dc4c09SDon Skidmore if (!link_up) 13546a14ee0cSDon Skidmore return 0; 13556a14ee0cSDon Skidmore 13566a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 13576a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 13586a14ee0cSDon Skidmore &speed); 1359c3dc4c09SDon Skidmore if (status) 1360c3dc4c09SDon Skidmore return status; 1361c3dc4c09SDon Skidmore 1362c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 1363c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 1364c3dc4c09SDon Skidmore if (status) 1365c3dc4c09SDon Skidmore return status; 1366c3dc4c09SDon Skidmore 1367c3dc4c09SDon Skidmore if (!link_up) 1368c3dc4c09SDon Skidmore return 0; 13696a14ee0cSDon Skidmore 13706a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 13716a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 13726a14ee0cSDon Skidmore 13736a14ee0cSDon Skidmore switch (speed) { 13746a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 13756a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 13766a14ee0cSDon Skidmore break; 13776a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 13786a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 13796a14ee0cSDon Skidmore break; 13806a14ee0cSDon Skidmore default: 13816a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 13826a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 13836a14ee0cSDon Skidmore } 13846a14ee0cSDon Skidmore 13856a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 13866a14ee0cSDon Skidmore } 13876a14ee0cSDon Skidmore 1388f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 1389f4410d2cSDon Skidmore * @hw: pointer to hardware structure 1390f4410d2cSDon Skidmore **/ 1391f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 1392f4410d2cSDon Skidmore { 1393f4410d2cSDon Skidmore s32 status; 1394f4410d2cSDon Skidmore 1395f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 1396f4410d2cSDon Skidmore 1397f4410d2cSDon Skidmore if (status) 1398f4410d2cSDon Skidmore return status; 1399f4410d2cSDon Skidmore 1400f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 1401f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 1402f4410d2cSDon Skidmore } 1403f4410d2cSDon Skidmore 14046a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 14056a14ee0cSDon Skidmore * @hw: pointer to hardware structure 14066a14ee0cSDon Skidmore * 14076a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 14086a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 14096a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 14106a14ee0cSDon Skidmore **/ 14117ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 14126a14ee0cSDon Skidmore { 14136a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1414c3dc4c09SDon Skidmore ixgbe_link_speed speed; 14156a14ee0cSDon Skidmore s32 ret_val; 14166a14ee0cSDon Skidmore 1417c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 14186a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 1419ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 1420c3dc4c09SDon Skidmore 1421c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 1422c3dc4c09SDon Skidmore * to determine internal PHY mode. 1423c3dc4c09SDon Skidmore */ 1424c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 1425c3dc4c09SDon Skidmore 1426c3dc4c09SDon Skidmore /* If internal PHY mode is KR, then initialize KR link */ 1427c3dc4c09SDon Skidmore if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 1428c3dc4c09SDon Skidmore speed = IXGBE_LINK_SPEED_10GB_FULL | 1429c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1430c3dc4c09SDon Skidmore ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); 1431c3dc4c09SDon Skidmore } 14326a14ee0cSDon Skidmore } 14336a14ee0cSDon Skidmore 14346a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 14356a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 14366a14ee0cSDon Skidmore 1437c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 14386a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 14396a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 14406a14ee0cSDon Skidmore phy->ops.reset = NULL; 14416a14ee0cSDon Skidmore 14426a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 14436a14ee0cSDon Skidmore switch (hw->phy.type) { 14446a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 14456a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 14466a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 14476a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 14486a14ee0cSDon Skidmore break; 14496a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 14506a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 14516a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 14526a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 14536a14ee0cSDon Skidmore break; 14546a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 1455c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 1456c3dc4c09SDon Skidmore * to determine internal PHY mode 1457c3dc4c09SDon Skidmore */ 1458c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 1459c3dc4c09SDon Skidmore 1460c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 1461c3dc4c09SDon Skidmore * else setup KR now. 1462c3dc4c09SDon Skidmore */ 1463c3dc4c09SDon Skidmore if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1464c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 1465c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 1466c3dc4c09SDon Skidmore } else { 1467c3dc4c09SDon Skidmore speed = IXGBE_LINK_SPEED_10GB_FULL | 1468c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1469c3dc4c09SDon Skidmore ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); 1470c3dc4c09SDon Skidmore } 1471c3dc4c09SDon Skidmore 1472c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 1473f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 14746a14ee0cSDon Skidmore break; 14756a14ee0cSDon Skidmore default: 14766a14ee0cSDon Skidmore break; 14776a14ee0cSDon Skidmore } 1478c3dc4c09SDon Skidmore 14796a14ee0cSDon Skidmore return ret_val; 14806a14ee0cSDon Skidmore } 14816a14ee0cSDon Skidmore 14826a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 14836a14ee0cSDon Skidmore * @hw: pointer to hardware structure 14846a14ee0cSDon Skidmore * 14856a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 14866a14ee0cSDon Skidmore * 14876a14ee0cSDon Skidmore */ 14887ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 14896a14ee0cSDon Skidmore { 14906a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 14916a14ee0cSDon Skidmore 14926a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 14936a14ee0cSDon Skidmore switch (hw->device_id) { 14946a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 14956a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 14966a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 14976a14ee0cSDon Skidmore break; 14986a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 14996a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 15006a14ee0cSDon Skidmore break; 15016a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 15026a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 15036a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 15046a14ee0cSDon Skidmore break; 15056a14ee0cSDon Skidmore default: 15066a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 15076a14ee0cSDon Skidmore break; 15086a14ee0cSDon Skidmore } 15096a14ee0cSDon Skidmore return media_type; 15106a14ee0cSDon Skidmore } 15116a14ee0cSDon Skidmore 15126a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 15136a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 15146a14ee0cSDon Skidmore **/ 15157ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 15166a14ee0cSDon Skidmore { 1517a1e869deSMark Rustad s32 status; 15186a14ee0cSDon Skidmore u16 reg; 15196a14ee0cSDon Skidmore 15206a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 15216a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 15226a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 15236a14ee0cSDon Skidmore ®); 15246a14ee0cSDon Skidmore if (status) 15256a14ee0cSDon Skidmore return status; 15266a14ee0cSDon Skidmore 1527e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 1528e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 1529e2261bccSDon Skidmore */ 1530e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 15316a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 15326a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 15336a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 15346a14ee0cSDon Skidmore ®); 15356a14ee0cSDon Skidmore if (status) 15366a14ee0cSDon Skidmore return status; 15376a14ee0cSDon Skidmore 15386a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 15396a14ee0cSDon Skidmore 15406a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 15416a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 15426a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 15436a14ee0cSDon Skidmore reg); 1544e2261bccSDon Skidmore if (status) 1545e2261bccSDon Skidmore return status; 1546e2261bccSDon Skidmore } 1547e2261bccSDon Skidmore 15486a14ee0cSDon Skidmore return status; 15496a14ee0cSDon Skidmore } 15506a14ee0cSDon Skidmore 15516a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 15526a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 15536a14ee0cSDon Skidmore ** 15546a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 15556a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 15566a14ee0cSDon Skidmore ** reset. 15576a14ee0cSDon Skidmore **/ 15587ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 15596a14ee0cSDon Skidmore { 15606a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 15616a14ee0cSDon Skidmore s32 status; 15626a14ee0cSDon Skidmore u32 ctrl = 0; 15636a14ee0cSDon Skidmore u32 i; 15646a14ee0cSDon Skidmore bool link_up = false; 15656a14ee0cSDon Skidmore 15666a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 15676a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 15686a14ee0cSDon Skidmore if (status) 15696a14ee0cSDon Skidmore return status; 15706a14ee0cSDon Skidmore 15716a14ee0cSDon Skidmore /* flush pending Tx transactions */ 15726a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 15736a14ee0cSDon Skidmore 15746a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 15756a14ee0cSDon Skidmore 15766a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 15776a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 15786a14ee0cSDon Skidmore 15796a14ee0cSDon Skidmore /* start the external PHY */ 15806a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 15816a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 15826a14ee0cSDon Skidmore if (status) 15836a14ee0cSDon Skidmore return status; 15846a14ee0cSDon Skidmore } 15856a14ee0cSDon Skidmore 15866a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 15876a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 15886a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 15896a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 15906a14ee0cSDon Skidmore } 15916a14ee0cSDon Skidmore 15926a14ee0cSDon Skidmore /* Reset PHY */ 15936a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 15946a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 15956a14ee0cSDon Skidmore 15966a14ee0cSDon Skidmore mac_reset_top: 15976a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 15986a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 15996a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 16006a14ee0cSDon Skidmore * reset is set, then perform link reset. 16016a14ee0cSDon Skidmore */ 16026a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 16036a14ee0cSDon Skidmore 16046a14ee0cSDon Skidmore if (!hw->force_full_reset) { 16056a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 16066a14ee0cSDon Skidmore if (link_up) 16076a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 16086a14ee0cSDon Skidmore } 16096a14ee0cSDon Skidmore 16106a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 16116a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 16126a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 16136a14ee0cSDon Skidmore 16146a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 16156a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 16166a14ee0cSDon Skidmore udelay(1); 16176a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 16186a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 16196a14ee0cSDon Skidmore break; 16206a14ee0cSDon Skidmore } 16216a14ee0cSDon Skidmore 16226a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 16236a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 16246a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 16256a14ee0cSDon Skidmore } 16266a14ee0cSDon Skidmore 16276a14ee0cSDon Skidmore msleep(50); 16286a14ee0cSDon Skidmore 16296a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 16306a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 16316a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 16326a14ee0cSDon Skidmore */ 16336a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 16346a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 16356a14ee0cSDon Skidmore goto mac_reset_top; 16366a14ee0cSDon Skidmore } 16376a14ee0cSDon Skidmore 16386a14ee0cSDon Skidmore /* Store the permanent mac address */ 16396a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 16406a14ee0cSDon Skidmore 16416a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 16426a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 16436a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 16446a14ee0cSDon Skidmore */ 16456a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 16466a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 16476a14ee0cSDon Skidmore 1648ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 1649ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 1650ab5fe0c5SDon Skidmore 16516a14ee0cSDon Skidmore return status; 16526a14ee0cSDon Skidmore } 16536a14ee0cSDon Skidmore 16545b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 16555b7f000fSDon Skidmore * anti-spoofing 16565b7f000fSDon Skidmore * @hw: pointer to hardware structure 16575b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 16585b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 16595b7f000fSDon Skidmore **/ 1660bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 1661bc035fc5SDon Skidmore bool enable, int vf) 16625b7f000fSDon Skidmore { 16635b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 16645b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 16655b7f000fSDon Skidmore u32 pfvfspoof; 16665b7f000fSDon Skidmore 16675b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 16685b7f000fSDon Skidmore if (enable) 16695b7f000fSDon Skidmore pfvfspoof |= (1 << vf_target_shift); 16705b7f000fSDon Skidmore else 16715b7f000fSDon Skidmore pfvfspoof &= ~(1 << vf_target_shift); 16725b7f000fSDon Skidmore 16735b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 16745b7f000fSDon Skidmore } 16755b7f000fSDon Skidmore 16766d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 16776d4c96adSDon Skidmore * @hw: pointer to hardware structure 16786d4c96adSDon Skidmore * @enable: enable or disable source address pruning 16796d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 16806d4c96adSDon Skidmore **/ 16816d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 16826d4c96adSDon Skidmore bool enable, 16836d4c96adSDon Skidmore unsigned int pool) 16846d4c96adSDon Skidmore { 16856d4c96adSDon Skidmore u64 pfflp; 16866d4c96adSDon Skidmore 16876d4c96adSDon Skidmore /* max rx pool is 63 */ 16886d4c96adSDon Skidmore if (pool > 63) 16896d4c96adSDon Skidmore return; 16906d4c96adSDon Skidmore 16916d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 16926d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 16936d4c96adSDon Skidmore 16946d4c96adSDon Skidmore if (enable) 16956d4c96adSDon Skidmore pfflp |= (1ULL << pool); 16966d4c96adSDon Skidmore else 16976d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 16986d4c96adSDon Skidmore 16996d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 17006d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 17016d4c96adSDon Skidmore } 17026d4c96adSDon Skidmore 17036a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 17046a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 17056a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 17066a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 17076a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 17086a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 17096a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 17106a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 17116a14ee0cSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, \ 17126a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 17136a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 17146a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 17156a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 17166a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 17176a14ee0cSDon Skidmore .led_on = &ixgbe_led_on_generic, \ 17186a14ee0cSDon Skidmore .led_off = &ixgbe_led_off_generic, \ 17196a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 17206a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 17216a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 17226a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 17236a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 17246a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 17256a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 17266a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 17276a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 17286a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 17296a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 17306a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 17316a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 17326a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 17336a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 17346a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 17356a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 17366a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 17376d4c96adSDon Skidmore .set_source_address_pruning = \ 17386d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 17395b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 17405b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 17416a14ee0cSDon Skidmore .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, \ 17426a14ee0cSDon Skidmore .release_swfw_sync = &ixgbe_release_swfw_sync_X540, \ 17436a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 17446a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 17456a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 17466a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 17476a14ee0cSDon Skidmore .prot_autoc_read = &prot_autoc_read_generic, \ 17486a14ee0cSDon Skidmore .prot_autoc_write = &prot_autoc_write_generic, \ 17491f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 17501f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 17516a14ee0cSDon Skidmore 17526a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550 = { 17536a14ee0cSDon Skidmore X550_COMMON_MAC 17546a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 17556a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 17566a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 17576a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 17586a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 17596a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 17606a14ee0cSDon Skidmore .setup_sfp = NULL, 17616a14ee0cSDon Skidmore }; 17626a14ee0cSDon Skidmore 17636a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550EM_x = { 17646a14ee0cSDon Skidmore X550_COMMON_MAC 17656a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 17666a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 17676a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 17686a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 17696a14ee0cSDon Skidmore .setup_link = NULL, /* defined later */ 17706a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 17716a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 17726a14ee0cSDon Skidmore 17736a14ee0cSDon Skidmore }; 17746a14ee0cSDon Skidmore 17756a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 17766a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 17776a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 17786a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 17796a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 17806a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 17816a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 17826a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 17836a14ee0cSDon Skidmore 17846a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550 = { 17856a14ee0cSDon Skidmore X550_COMMON_EEP 17866a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 17876a14ee0cSDon Skidmore }; 17886a14ee0cSDon Skidmore 17896a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 17906a14ee0cSDon Skidmore X550_COMMON_EEP 17916a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 17926a14ee0cSDon Skidmore }; 17936a14ee0cSDon Skidmore 17946a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 17956a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 17966a14ee0cSDon Skidmore .reset = NULL, \ 17976a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 17986a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 17996a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 18006a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 18016a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 18026a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 18036a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 18046a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 18056a14ee0cSDon Skidmore 18066a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550 = { 18076a14ee0cSDon Skidmore X550_COMMON_PHY 18086a14ee0cSDon Skidmore .init = NULL, 18096a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 18106a14ee0cSDon Skidmore .read_reg = &ixgbe_read_phy_reg_generic, 18116a14ee0cSDon Skidmore .write_reg = &ixgbe_write_phy_reg_generic, 18126a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, 18136a14ee0cSDon Skidmore .read_i2c_combined = &ixgbe_read_i2c_combined_generic, 18146a14ee0cSDon Skidmore .write_i2c_combined = &ixgbe_write_i2c_combined_generic, 1815961fac88SDon Skidmore .set_phy_power = &ixgbe_set_copper_phy_power, 18166a14ee0cSDon Skidmore }; 18176a14ee0cSDon Skidmore 18186a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550EM_x = { 18196a14ee0cSDon Skidmore X550_COMMON_PHY 18206a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 18216a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 18226a14ee0cSDon Skidmore .read_reg = NULL, /* defined later */ 18236a14ee0cSDon Skidmore .write_reg = NULL, /* defined later */ 18246a14ee0cSDon Skidmore .setup_link = NULL, /* defined later */ 18256a14ee0cSDon Skidmore }; 18266a14ee0cSDon Skidmore 18279a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 18289a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 18299a900ecaSDon Skidmore }; 18309a900ecaSDon Skidmore 18319a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 18329a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 18339a900ecaSDon Skidmore }; 18349a900ecaSDon Skidmore 18356a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550_info = { 18366a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 18376a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 18386a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 18396a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 18406a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 18416a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 18429a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 18436a14ee0cSDon Skidmore }; 18446a14ee0cSDon Skidmore 18456a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550EM_x_info = { 18466a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 18476a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 18486a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 18496a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 18506a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 18516a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 18529a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 18536a14ee0cSDon Skidmore }; 1854