16a14ee0cSDon Skidmore /******************************************************************************* 26a14ee0cSDon Skidmore * 36a14ee0cSDon Skidmore * Intel 10 Gigabit PCI Express Linux driver 4d5ec98a0SDon Skidmore * Copyright(c) 1999 - 2015 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 29b5529ef5SDon Skidmore static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) 30b5529ef5SDon Skidmore { 31b5529ef5SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 32b5529ef5SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 33b5529ef5SDon Skidmore 34b5529ef5SDon Skidmore /* Start with X540 invariants, since so simular */ 35b5529ef5SDon Skidmore ixgbe_get_invariants_X540(hw); 36b5529ef5SDon Skidmore 37b5529ef5SDon Skidmore if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) 38b5529ef5SDon Skidmore phy->ops.set_phy_power = NULL; 39b5529ef5SDon Skidmore 40b5529ef5SDon Skidmore return 0; 41b5529ef5SDon Skidmore } 42b5529ef5SDon Skidmore 43ab5fe0c5SDon Skidmore /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control 44ab5fe0c5SDon Skidmore * @hw: pointer to hardware structure 45ab5fe0c5SDon Skidmore **/ 46ab5fe0c5SDon Skidmore static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) 47ab5fe0c5SDon Skidmore { 48ab5fe0c5SDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 49ab5fe0c5SDon Skidmore 50ab5fe0c5SDon Skidmore if (hw->bus.lan_id) { 51ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 52ab5fe0c5SDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 53ab5fe0c5SDon Skidmore } 54ab5fe0c5SDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 55ab5fe0c5SDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 56ab5fe0c5SDon Skidmore IXGBE_WRITE_FLUSH(hw); 57ab5fe0c5SDon Skidmore } 58ab5fe0c5SDon Skidmore 596a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 606a14ee0cSDon Skidmore * @hw: pointer to hardware structure 616a14ee0cSDon Skidmore * 626a14ee0cSDon Skidmore * Returns error code 636a14ee0cSDon Skidmore */ 646a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 656a14ee0cSDon Skidmore { 666a14ee0cSDon Skidmore switch (hw->device_id) { 676a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 686a14ee0cSDon Skidmore /* set up for CS4227 usage */ 696a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 70ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 716a14ee0cSDon Skidmore 726a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 736a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 746a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 756a14ee0cSDon Skidmore break; 766a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 776a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 786a14ee0cSDon Skidmore break; 796a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 806a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 816a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 826a14ee0cSDon Skidmore default: 836a14ee0cSDon Skidmore break; 846a14ee0cSDon Skidmore } 856a14ee0cSDon Skidmore return 0; 866a14ee0cSDon Skidmore } 876a14ee0cSDon Skidmore 886a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 896a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 906a14ee0cSDon Skidmore { 916a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 926a14ee0cSDon Skidmore } 936a14ee0cSDon Skidmore 946a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 956a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 966a14ee0cSDon Skidmore { 976a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 986a14ee0cSDon Skidmore } 996a14ee0cSDon Skidmore 1006a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 1016a14ee0cSDon Skidmore * @hw: pointer to hardware structure 1026a14ee0cSDon Skidmore * 1036a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 1046a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 1056a14ee0cSDon Skidmore **/ 1067ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 1076a14ee0cSDon Skidmore { 1086a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 1096a14ee0cSDon Skidmore u32 eec; 1106a14ee0cSDon Skidmore u16 eeprom_size; 1116a14ee0cSDon Skidmore 1126a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 1136a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 1146a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 1156a14ee0cSDon Skidmore 1169a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 1176a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 1186a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 1196a14ee0cSDon Skidmore eeprom->word_size = 1 << (eeprom_size + 1206a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 1216a14ee0cSDon Skidmore 1226a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 1236a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 1246a14ee0cSDon Skidmore } 1256a14ee0cSDon Skidmore 1266a14ee0cSDon Skidmore return 0; 1276a14ee0cSDon Skidmore } 1286a14ee0cSDon Skidmore 129ae14a1d8SMark Rustad /** 130ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 131ae14a1d8SMark Rustad * @hw: pointer to hardware structure 132ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 133ae14a1d8SMark Rustad * 134ae14a1d8SMark Rustad * Return: failing status on timeout 135ae14a1d8SMark Rustad * 136ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 137ae14a1d8SMark Rustad */ 138ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 139ae14a1d8SMark Rustad { 140ae14a1d8SMark Rustad u32 i, command; 141ae14a1d8SMark Rustad 142ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 143ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 144ae14a1d8SMark Rustad * complete. 145ae14a1d8SMark Rustad */ 146ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 147ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 148ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 149ae14a1d8SMark Rustad break; 150ae14a1d8SMark Rustad usleep_range(10, 20); 151ae14a1d8SMark Rustad } 152ae14a1d8SMark Rustad if (ctrl) 153ae14a1d8SMark Rustad *ctrl = command; 154ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 155ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 156ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 157ae14a1d8SMark Rustad } 158ae14a1d8SMark Rustad 159ae14a1d8SMark Rustad return 0; 160ae14a1d8SMark Rustad } 161ae14a1d8SMark Rustad 1626a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 1636a14ee0cSDon Skidmore * IOSF device 1646a14ee0cSDon Skidmore * @hw: pointer to hardware structure 1656a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 1666a14ee0cSDon Skidmore * @device_type: 3 bit device type 1676a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 1686a14ee0cSDon Skidmore **/ 1697ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 1706a14ee0cSDon Skidmore u32 device_type, u32 *data) 1716a14ee0cSDon Skidmore { 172ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 173ae14a1d8SMark Rustad u32 command, error; 174ae14a1d8SMark Rustad s32 ret; 175ae14a1d8SMark Rustad 176ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 177ae14a1d8SMark Rustad if (ret) 178ae14a1d8SMark Rustad return ret; 179ae14a1d8SMark Rustad 180ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 181ae14a1d8SMark Rustad if (ret) 182ae14a1d8SMark Rustad goto out; 1836a14ee0cSDon Skidmore 1846a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 1856a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 1866a14ee0cSDon Skidmore 1876a14ee0cSDon Skidmore /* Write IOSF control register */ 1886a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 1896a14ee0cSDon Skidmore 190ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 1916a14ee0cSDon Skidmore 1926a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 1936a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 1946a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 1956a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 1966a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 1976a14ee0cSDon Skidmore } 1986a14ee0cSDon Skidmore 199ae14a1d8SMark Rustad if (!ret) 2006a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 2016a14ee0cSDon Skidmore 202ae14a1d8SMark Rustad out: 203ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 204ae14a1d8SMark Rustad return ret; 2056a14ee0cSDon Skidmore } 2066a14ee0cSDon Skidmore 2076a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 2086a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 2096a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2106a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 2116a14ee0cSDon Skidmore * @data: word read from the EEPROM 2126a14ee0cSDon Skidmore * 2136a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 2146a14ee0cSDon Skidmore **/ 2157ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 2167ddbde3fSDon Skidmore u16 *data) 2176a14ee0cSDon Skidmore { 2186a14ee0cSDon Skidmore s32 status; 2196a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 2206a14ee0cSDon Skidmore 2216a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 2226a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 2236a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2246a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2256a14ee0cSDon Skidmore 2266a14ee0cSDon Skidmore /* convert offset from words to bytes */ 2276a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 2286a14ee0cSDon Skidmore /* one word */ 2296a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 2306a14ee0cSDon Skidmore 2316a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 2326a14ee0cSDon Skidmore sizeof(buffer), 2336a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 2346a14ee0cSDon Skidmore if (status) 2356a14ee0cSDon Skidmore return status; 2366a14ee0cSDon Skidmore 2376a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 2386a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 2396a14ee0cSDon Skidmore 2406a14ee0cSDon Skidmore return 0; 2416a14ee0cSDon Skidmore } 2426a14ee0cSDon Skidmore 2436a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 2446a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2456a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 2466a14ee0cSDon Skidmore * @words: number of words 2476a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 2486a14ee0cSDon Skidmore * 2496a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 2506a14ee0cSDon Skidmore **/ 2517ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 2526a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 2536a14ee0cSDon Skidmore { 2546a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 2556a14ee0cSDon Skidmore u32 current_word = 0; 2566a14ee0cSDon Skidmore u16 words_to_read; 2576a14ee0cSDon Skidmore s32 status; 2586a14ee0cSDon Skidmore u32 i; 2596a14ee0cSDon Skidmore 2606a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 2616a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2626a14ee0cSDon Skidmore if (status) { 2636a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 2646a14ee0cSDon Skidmore return status; 2656a14ee0cSDon Skidmore } 2666a14ee0cSDon Skidmore 2676a14ee0cSDon Skidmore while (words) { 2686a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 2696a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 2706a14ee0cSDon Skidmore else 2716a14ee0cSDon Skidmore words_to_read = words; 2726a14ee0cSDon Skidmore 2736a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 2746a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 2756a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2766a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2776a14ee0cSDon Skidmore 2786a14ee0cSDon Skidmore /* convert offset from words to bytes */ 2796a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 2806a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 2816a14ee0cSDon Skidmore 2826a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 2836a14ee0cSDon Skidmore sizeof(buffer), 2846a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 2856a14ee0cSDon Skidmore false); 2866a14ee0cSDon Skidmore if (status) { 2876a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 2886a14ee0cSDon Skidmore goto out; 2896a14ee0cSDon Skidmore } 2906a14ee0cSDon Skidmore 2916a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 2926a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 2936a14ee0cSDon Skidmore 2 * i; 2946a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 2956a14ee0cSDon Skidmore 2966a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 2976a14ee0cSDon Skidmore current_word++; 2986a14ee0cSDon Skidmore i++; 2996a14ee0cSDon Skidmore if (i < words_to_read) { 3006a14ee0cSDon Skidmore value >>= 16; 3016a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 3026a14ee0cSDon Skidmore current_word++; 3036a14ee0cSDon Skidmore } 3046a14ee0cSDon Skidmore } 3056a14ee0cSDon Skidmore words -= words_to_read; 3066a14ee0cSDon Skidmore } 3076a14ee0cSDon Skidmore 3086a14ee0cSDon Skidmore out: 3096a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 3106a14ee0cSDon Skidmore return status; 3116a14ee0cSDon Skidmore } 3126a14ee0cSDon Skidmore 3136a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 3146a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3156a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 3166a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 3176a14ee0cSDon Skidmore * @csum: address of checksum to update 3186a14ee0cSDon Skidmore * 3196a14ee0cSDon Skidmore * Returns error status for any failure 3206a14ee0cSDon Skidmore **/ 3216a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 3226a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 3236a14ee0cSDon Skidmore u32 buffer_size) 3246a14ee0cSDon Skidmore { 3256a14ee0cSDon Skidmore u16 buf[256]; 3266a14ee0cSDon Skidmore s32 status; 3276a14ee0cSDon Skidmore u16 length, bufsz, i, start; 3286a14ee0cSDon Skidmore u16 *local_buffer; 3296a14ee0cSDon Skidmore 3306a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 3316a14ee0cSDon Skidmore 3326a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 3336a14ee0cSDon Skidmore if (!buffer) { 3346a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 3356a14ee0cSDon Skidmore if (status) { 3366a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3376a14ee0cSDon Skidmore return status; 3386a14ee0cSDon Skidmore } 3396a14ee0cSDon Skidmore local_buffer = buf; 3406a14ee0cSDon Skidmore } else { 3416a14ee0cSDon Skidmore if (buffer_size < ptr) 3426a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3436a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 3446a14ee0cSDon Skidmore } 3456a14ee0cSDon Skidmore 3466a14ee0cSDon Skidmore if (size) { 3476a14ee0cSDon Skidmore start = 0; 3486a14ee0cSDon Skidmore length = size; 3496a14ee0cSDon Skidmore } else { 3506a14ee0cSDon Skidmore start = 1; 3516a14ee0cSDon Skidmore length = local_buffer[0]; 3526a14ee0cSDon Skidmore 3536a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 3546a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 3556a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 3566a14ee0cSDon Skidmore return 0; 3576a14ee0cSDon Skidmore } 3586a14ee0cSDon Skidmore 3596a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 3606a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3616a14ee0cSDon Skidmore 3626a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 3636a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 3646a14ee0cSDon Skidmore ptr += bufsz; 3656a14ee0cSDon Skidmore i = 0; 3666a14ee0cSDon Skidmore if (length < bufsz) 3676a14ee0cSDon Skidmore bufsz = length; 3686a14ee0cSDon Skidmore 3696a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 3706a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 3716a14ee0cSDon Skidmore bufsz, buf); 3726a14ee0cSDon Skidmore if (status) { 3736a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3746a14ee0cSDon Skidmore return status; 3756a14ee0cSDon Skidmore } 3766a14ee0cSDon Skidmore } 3776a14ee0cSDon Skidmore *csum += local_buffer[i]; 3786a14ee0cSDon Skidmore } 3796a14ee0cSDon Skidmore return 0; 3806a14ee0cSDon Skidmore } 3816a14ee0cSDon Skidmore 3826a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 3836a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3846a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 3856a14ee0cSDon Skidmore * @buffer_size: size of buffer 3866a14ee0cSDon Skidmore * 3876a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 3886a14ee0cSDon Skidmore **/ 3897ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 3907ddbde3fSDon Skidmore u32 buffer_size) 3916a14ee0cSDon Skidmore { 3926a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 3936a14ee0cSDon Skidmore u16 *local_buffer; 3946a14ee0cSDon Skidmore s32 status; 3956a14ee0cSDon Skidmore u16 checksum = 0; 3966a14ee0cSDon Skidmore u16 pointer, i, size; 3976a14ee0cSDon Skidmore 3986a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 3996a14ee0cSDon Skidmore 4006a14ee0cSDon Skidmore if (!buffer) { 4016a14ee0cSDon Skidmore /* Read pointer area */ 4026a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 4036a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 4046a14ee0cSDon Skidmore eeprom_ptrs); 4056a14ee0cSDon Skidmore if (status) { 4066a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 4076a14ee0cSDon Skidmore return status; 4086a14ee0cSDon Skidmore } 4096a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 4106a14ee0cSDon Skidmore } else { 4116a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 4126a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 4136a14ee0cSDon Skidmore local_buffer = buffer; 4146a14ee0cSDon Skidmore } 4156a14ee0cSDon Skidmore 4166a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 4176a14ee0cSDon Skidmore * checksum word itself 4186a14ee0cSDon Skidmore */ 4196a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 4206a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 4216a14ee0cSDon Skidmore checksum += local_buffer[i]; 4226a14ee0cSDon Skidmore 4236a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 4246a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 4256a14ee0cSDon Skidmore */ 4266a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 4276a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 4286a14ee0cSDon Skidmore continue; 4296a14ee0cSDon Skidmore 4306a14ee0cSDon Skidmore pointer = local_buffer[i]; 4316a14ee0cSDon Skidmore 4326a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 4336a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 4346a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 4356a14ee0cSDon Skidmore continue; 4366a14ee0cSDon Skidmore 4376a14ee0cSDon Skidmore switch (i) { 4386a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 4396a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 4406a14ee0cSDon Skidmore break; 4416a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 4426a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 4436a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 4446a14ee0cSDon Skidmore break; 4456a14ee0cSDon Skidmore default: 4466a14ee0cSDon Skidmore size = 0; 4476a14ee0cSDon Skidmore break; 4486a14ee0cSDon Skidmore } 4496a14ee0cSDon Skidmore 4506a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 4516a14ee0cSDon Skidmore buffer, buffer_size); 4526a14ee0cSDon Skidmore if (status) 4536a14ee0cSDon Skidmore return status; 4546a14ee0cSDon Skidmore } 4556a14ee0cSDon Skidmore 4566a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 4576a14ee0cSDon Skidmore 4586a14ee0cSDon Skidmore return (s32)checksum; 4596a14ee0cSDon Skidmore } 4606a14ee0cSDon Skidmore 4616a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 4626a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4636a14ee0cSDon Skidmore * 4646a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 4656a14ee0cSDon Skidmore **/ 4667ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 4676a14ee0cSDon Skidmore { 4686a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 4696a14ee0cSDon Skidmore } 4706a14ee0cSDon Skidmore 4716a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 4726a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4736a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 4746a14ee0cSDon Skidmore * @data: word read from the EEPROM 4756a14ee0cSDon Skidmore * 4766a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 4776a14ee0cSDon Skidmore **/ 4787ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 4796a14ee0cSDon Skidmore { 4806a14ee0cSDon Skidmore s32 status = 0; 4816a14ee0cSDon Skidmore 4826a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 4836a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 4846a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 4856a14ee0cSDon Skidmore } else { 4866a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 4876a14ee0cSDon Skidmore } 4886a14ee0cSDon Skidmore 4896a14ee0cSDon Skidmore return status; 4906a14ee0cSDon Skidmore } 4916a14ee0cSDon Skidmore 4926a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 4936a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4946a14ee0cSDon Skidmore * @checksum_val: calculated checksum 4956a14ee0cSDon Skidmore * 4966a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 4976a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 4986a14ee0cSDon Skidmore **/ 4997ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 5007ddbde3fSDon Skidmore u16 *checksum_val) 5016a14ee0cSDon Skidmore { 5026a14ee0cSDon Skidmore s32 status; 5036a14ee0cSDon Skidmore u16 checksum; 5046a14ee0cSDon Skidmore u16 read_checksum = 0; 5056a14ee0cSDon Skidmore 5066a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 5076a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 5086a14ee0cSDon Skidmore * EEPROM read fails 5096a14ee0cSDon Skidmore */ 5106a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 5116a14ee0cSDon Skidmore if (status) { 5126a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 5136a14ee0cSDon Skidmore return status; 5146a14ee0cSDon Skidmore } 5156a14ee0cSDon Skidmore 5166a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 5176a14ee0cSDon Skidmore if (status < 0) 5186a14ee0cSDon Skidmore return status; 5196a14ee0cSDon Skidmore 5206a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 5216a14ee0cSDon Skidmore 5226a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 5236a14ee0cSDon Skidmore &read_checksum); 5246a14ee0cSDon Skidmore if (status) 5256a14ee0cSDon Skidmore return status; 5266a14ee0cSDon Skidmore 5276a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 5286a14ee0cSDon Skidmore * calculated checksum 5296a14ee0cSDon Skidmore */ 5306a14ee0cSDon Skidmore if (read_checksum != checksum) { 5316a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 5326a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 5336a14ee0cSDon Skidmore } 5346a14ee0cSDon Skidmore 5356a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 5366a14ee0cSDon Skidmore if (checksum_val) 5376a14ee0cSDon Skidmore *checksum_val = checksum; 5386a14ee0cSDon Skidmore 5396a14ee0cSDon Skidmore return status; 5406a14ee0cSDon Skidmore } 5416a14ee0cSDon Skidmore 5426a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 5436a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5446a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 5456a14ee0cSDon Skidmore * @data: word write to the EEPROM 5466a14ee0cSDon Skidmore * 5476a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 5486a14ee0cSDon Skidmore **/ 5497ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 5507ddbde3fSDon Skidmore u16 data) 5516a14ee0cSDon Skidmore { 5526a14ee0cSDon Skidmore s32 status; 5536a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 5546a14ee0cSDon Skidmore 5556a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 5566a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 5576a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 5586a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 5596a14ee0cSDon Skidmore 5606a14ee0cSDon Skidmore /* one word */ 5616a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 5626a14ee0cSDon Skidmore buffer.data = data; 5636a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 5646a14ee0cSDon Skidmore 5656a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 5666a14ee0cSDon Skidmore sizeof(buffer), 5676a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5686a14ee0cSDon Skidmore return status; 5696a14ee0cSDon Skidmore } 5706a14ee0cSDon Skidmore 5716a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 5726a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5736a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 5746a14ee0cSDon Skidmore * @data: word write to the EEPROM 5756a14ee0cSDon Skidmore * 5766a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 5776a14ee0cSDon Skidmore **/ 5787ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 5796a14ee0cSDon Skidmore { 5806a14ee0cSDon Skidmore s32 status = 0; 5816a14ee0cSDon Skidmore 5826a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 5836a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 5846a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 5856a14ee0cSDon Skidmore } else { 5866a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 5876a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 5886a14ee0cSDon Skidmore } 5896a14ee0cSDon Skidmore 5906a14ee0cSDon Skidmore return status; 5916a14ee0cSDon Skidmore } 5926a14ee0cSDon Skidmore 5936a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 5946a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5956a14ee0cSDon Skidmore * 5966a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 5976a14ee0cSDon Skidmore **/ 5987ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 5996a14ee0cSDon Skidmore { 6006a14ee0cSDon Skidmore s32 status = 0; 6016a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 6026a14ee0cSDon Skidmore 6036a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 6046a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 6056a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 6066a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 6076a14ee0cSDon Skidmore 6086a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 6096a14ee0cSDon Skidmore sizeof(buffer), 6106a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 6116a14ee0cSDon Skidmore return status; 6126a14ee0cSDon Skidmore } 6136a14ee0cSDon Skidmore 6141f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 6151f9ac57cSDon Skidmore * 6161f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 6171f9ac57cSDon Skidmore **/ 6181f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 6191f9ac57cSDon Skidmore { 6201f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 6211f9ac57cSDon Skidmore s32 status; 6221f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 6231f9ac57cSDon Skidmore 6241f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 6251f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 6261f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 6271f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 6281f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 6291f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 6301f9ac57cSDon Skidmore hw->mac.set_lben = true; 6311f9ac57cSDon Skidmore } else { 6321f9ac57cSDon Skidmore hw->mac.set_lben = false; 6331f9ac57cSDon Skidmore } 6341f9ac57cSDon Skidmore 6351f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 6361f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 6371f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 6381f9ac57cSDon Skidmore fw_cmd.port_number = (u8)hw->bus.lan_id; 6391f9ac57cSDon Skidmore 6401f9ac57cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 6411f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 6421f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 6431f9ac57cSDon Skidmore 6441f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 6451f9ac57cSDon Skidmore if (status) { 6461f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 6471f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 6481f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 6491f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 6501f9ac57cSDon Skidmore } 6511f9ac57cSDon Skidmore } 6521f9ac57cSDon Skidmore } 6531f9ac57cSDon Skidmore } 6541f9ac57cSDon Skidmore 6556a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 6566a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6576a14ee0cSDon Skidmore * 6586a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 6596a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 6606a14ee0cSDon Skidmore * the flash. 6616a14ee0cSDon Skidmore **/ 6627ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 6636a14ee0cSDon Skidmore { 6646a14ee0cSDon Skidmore s32 status; 6656a14ee0cSDon Skidmore u16 checksum = 0; 6666a14ee0cSDon Skidmore 6676a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 6686a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 6696a14ee0cSDon Skidmore * EEPROM read fails 6706a14ee0cSDon Skidmore */ 6716a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 6726a14ee0cSDon Skidmore if (status) { 6736a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 6746a14ee0cSDon Skidmore return status; 6756a14ee0cSDon Skidmore } 6766a14ee0cSDon Skidmore 6776a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 6786a14ee0cSDon Skidmore if (status < 0) 6796a14ee0cSDon Skidmore return status; 6806a14ee0cSDon Skidmore 6816a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 6826a14ee0cSDon Skidmore 6836a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 6846a14ee0cSDon Skidmore checksum); 6856a14ee0cSDon Skidmore if (status) 6866a14ee0cSDon Skidmore return status; 6876a14ee0cSDon Skidmore 6886a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 6896a14ee0cSDon Skidmore 6906a14ee0cSDon Skidmore return status; 6916a14ee0cSDon Skidmore } 6926a14ee0cSDon Skidmore 6936a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 6946a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6956a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 6966a14ee0cSDon Skidmore * @words: number of words 6976a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 6986a14ee0cSDon Skidmore * 6996a14ee0cSDon Skidmore * 7006a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 7016a14ee0cSDon Skidmore **/ 7027ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 7037ddbde3fSDon Skidmore u16 offset, u16 words, 7047ddbde3fSDon Skidmore u16 *data) 7056a14ee0cSDon Skidmore { 7066a14ee0cSDon Skidmore s32 status = 0; 7076a14ee0cSDon Skidmore u32 i = 0; 7086a14ee0cSDon Skidmore 7096a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 7106a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 7116a14ee0cSDon Skidmore if (status) { 7126a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 7136a14ee0cSDon Skidmore return status; 7146a14ee0cSDon Skidmore } 7156a14ee0cSDon Skidmore 7166a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 7176a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 7186a14ee0cSDon Skidmore data[i]); 7196a14ee0cSDon Skidmore if (status) { 7206a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 7216a14ee0cSDon Skidmore break; 7226a14ee0cSDon Skidmore } 7236a14ee0cSDon Skidmore } 7246a14ee0cSDon Skidmore 7256a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 7266a14ee0cSDon Skidmore 7276a14ee0cSDon Skidmore return status; 7286a14ee0cSDon Skidmore } 7296a14ee0cSDon Skidmore 7306a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 7316a14ee0cSDon Skidmore * IOSF device 7326a14ee0cSDon Skidmore * 7336a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7346a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 7356a14ee0cSDon Skidmore * @device_type: 3 bit device type 7366a14ee0cSDon Skidmore * @data: Data to write to the register 7376a14ee0cSDon Skidmore **/ 7387ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 7396a14ee0cSDon Skidmore u32 device_type, u32 data) 7406a14ee0cSDon Skidmore { 741ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 742ae14a1d8SMark Rustad u32 command, error; 743ae14a1d8SMark Rustad s32 ret; 744ae14a1d8SMark Rustad 745ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 746ae14a1d8SMark Rustad if (ret) 747ae14a1d8SMark Rustad return ret; 748ae14a1d8SMark Rustad 749ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 750ae14a1d8SMark Rustad if (ret) 751ae14a1d8SMark Rustad goto out; 7526a14ee0cSDon Skidmore 7536a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 7546a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 7556a14ee0cSDon Skidmore 7566a14ee0cSDon Skidmore /* Write IOSF control register */ 7576a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 7586a14ee0cSDon Skidmore 7596a14ee0cSDon Skidmore /* Write IOSF data register */ 7606a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 7616a14ee0cSDon Skidmore 762ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 7636a14ee0cSDon Skidmore 7646a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 7656a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 7666a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 7676a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 7686a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 7696a14ee0cSDon Skidmore } 7706a14ee0cSDon Skidmore 771ae14a1d8SMark Rustad out: 772ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 773ae14a1d8SMark Rustad return ret; 7746a14ee0cSDon Skidmore } 7756a14ee0cSDon Skidmore 7766a14ee0cSDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 7776a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7786a14ee0cSDon Skidmore * @speed: the link speed to force 7796a14ee0cSDon Skidmore * 7806a14ee0cSDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 7816a14ee0cSDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 7826a14ee0cSDon Skidmore **/ 7836a14ee0cSDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 7846a14ee0cSDon Skidmore { 7856a14ee0cSDon Skidmore s32 status; 7866a14ee0cSDon Skidmore u32 reg_val; 7876a14ee0cSDon Skidmore 7886a14ee0cSDon Skidmore /* Disable AN and force speed to 10G Serial. */ 7896a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 7906a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 7916a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 7926a14ee0cSDon Skidmore if (status) 7936a14ee0cSDon Skidmore return status; 7946a14ee0cSDon Skidmore 7956a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 7966a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 7976a14ee0cSDon Skidmore 7986a14ee0cSDon Skidmore /* Select forced link speed for internal PHY. */ 7996a14ee0cSDon Skidmore switch (*speed) { 8006a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 8016a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 8026a14ee0cSDon Skidmore break; 8036a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 8046a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 8056a14ee0cSDon Skidmore break; 8066a14ee0cSDon Skidmore default: 8076a14ee0cSDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 8086a14ee0cSDon Skidmore return IXGBE_ERR_LINK_SETUP; 8096a14ee0cSDon Skidmore } 8106a14ee0cSDon Skidmore 8116a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 812bec4e68eSDon Skidmore IXGBE_KRM_LINK_CTRL_1(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 training protocol FSM. */ 8186a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8196a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(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_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 8256a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8266a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 8276a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8286a14ee0cSDon Skidmore if (status) 8296a14ee0cSDon Skidmore return status; 8306a14ee0cSDon Skidmore 8316a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 8326a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8336a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 8346a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8356a14ee0cSDon Skidmore if (status) 8366a14ee0cSDon Skidmore return status; 8376a14ee0cSDon Skidmore 8386a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 8396a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 8406a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 8416a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8426a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 8436a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8446a14ee0cSDon Skidmore if (status) 8456a14ee0cSDon Skidmore return status; 8466a14ee0cSDon Skidmore 8476a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8486a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 8496a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8506a14ee0cSDon Skidmore if (status) 8516a14ee0cSDon Skidmore return status; 8526a14ee0cSDon Skidmore 8536a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 8546a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 8556a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 8566a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8576a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 8586a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8596a14ee0cSDon Skidmore if (status) 8606a14ee0cSDon Skidmore return status; 8616a14ee0cSDon Skidmore 8626a14ee0cSDon Skidmore /* Enable override for coefficients. */ 8636a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8646a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 8656a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8666a14ee0cSDon Skidmore if (status) 8676a14ee0cSDon Skidmore return status; 8686a14ee0cSDon Skidmore 8696a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 8706a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 8716a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 8726a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 8736a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8746a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 8756a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8766a14ee0cSDon Skidmore if (status) 8776a14ee0cSDon Skidmore return status; 8786a14ee0cSDon Skidmore 8796a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 8806a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8816a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 8826a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8836a14ee0cSDon Skidmore if (status) 8846a14ee0cSDon Skidmore return status; 8856a14ee0cSDon Skidmore 8866a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 8876a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8886a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 8896a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8906a14ee0cSDon Skidmore 8916a14ee0cSDon Skidmore return status; 8926a14ee0cSDon Skidmore } 8936a14ee0cSDon Skidmore 894c3dc4c09SDon Skidmore /** 895c3dc4c09SDon Skidmore * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed 896c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 897c3dc4c09SDon Skidmore * @speed: new link speed 898c3dc4c09SDon Skidmore * @autoneg_wait_to_complete: true when waiting for completion is needed 899c3dc4c09SDon Skidmore * 900c3dc4c09SDon Skidmore * Setup internal/external PHY link speed based on link speed, then set 901c3dc4c09SDon Skidmore * external PHY auto advertised link speed. 902c3dc4c09SDon Skidmore * 903c3dc4c09SDon Skidmore * Returns error status for any failure 904c3dc4c09SDon Skidmore **/ 905c3dc4c09SDon Skidmore static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, 906c3dc4c09SDon Skidmore ixgbe_link_speed speed, 907c3dc4c09SDon Skidmore bool autoneg_wait) 908c3dc4c09SDon Skidmore { 909c3dc4c09SDon Skidmore s32 status; 910c3dc4c09SDon Skidmore ixgbe_link_speed force_speed; 911c3dc4c09SDon Skidmore 912c3dc4c09SDon Skidmore /* Setup internal/external PHY link speed to iXFI (10G), unless 913c3dc4c09SDon Skidmore * only 1G is auto advertised then setup KX link. 914c3dc4c09SDon Skidmore */ 915c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 916c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 917c3dc4c09SDon Skidmore else 918c3dc4c09SDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 919c3dc4c09SDon Skidmore 920c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup XFI internal link. */ 921c3dc4c09SDon Skidmore if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 922c3dc4c09SDon Skidmore status = ixgbe_setup_ixfi_x550em(hw, &force_speed); 923c3dc4c09SDon Skidmore 924c3dc4c09SDon Skidmore if (status) 925c3dc4c09SDon Skidmore return status; 926c3dc4c09SDon Skidmore } 927c3dc4c09SDon Skidmore 928c3dc4c09SDon Skidmore return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); 929c3dc4c09SDon Skidmore } 930c3dc4c09SDon Skidmore 931a4e293a5SDon Skidmore /** ixgbe_check_link_t_X550em - Determine link and speed status 932a4e293a5SDon Skidmore * @hw: pointer to hardware structure 933a4e293a5SDon Skidmore * @speed: pointer to link speed 934a4e293a5SDon Skidmore * @link_up: true when link is up 935a4e293a5SDon Skidmore * @link_up_wait_to_complete: bool used to wait for link up or not 936a4e293a5SDon Skidmore * 937a4e293a5SDon Skidmore * Check that both the MAC and X557 external PHY have link. 938a4e293a5SDon Skidmore **/ 939a4e293a5SDon Skidmore static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, 940a4e293a5SDon Skidmore ixgbe_link_speed *speed, 941a4e293a5SDon Skidmore bool *link_up, 942a4e293a5SDon Skidmore bool link_up_wait_to_complete) 943a4e293a5SDon Skidmore { 944a4e293a5SDon Skidmore u32 status; 945a4e293a5SDon Skidmore u16 autoneg_status; 946a4e293a5SDon Skidmore 947a4e293a5SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 948a4e293a5SDon Skidmore return IXGBE_ERR_CONFIG; 949a4e293a5SDon Skidmore 950a4e293a5SDon Skidmore status = ixgbe_check_mac_link_generic(hw, speed, link_up, 951a4e293a5SDon Skidmore link_up_wait_to_complete); 952a4e293a5SDon Skidmore 953a4e293a5SDon Skidmore /* If check link fails or MAC link is not up, then return */ 954a4e293a5SDon Skidmore if (status || !(*link_up)) 955a4e293a5SDon Skidmore return status; 956a4e293a5SDon Skidmore 957a4e293a5SDon Skidmore /* MAC link is up, so check external PHY link. 958a4e293a5SDon Skidmore * Read this twice back to back to indicate current status. 959a4e293a5SDon Skidmore */ 960a4e293a5SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 961a4e293a5SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 962a4e293a5SDon Skidmore &autoneg_status); 963a4e293a5SDon Skidmore if (status) 964a4e293a5SDon Skidmore return status; 965a4e293a5SDon Skidmore 966a4e293a5SDon Skidmore /* If external PHY link is not up, then indicate link not up */ 967a4e293a5SDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 968a4e293a5SDon Skidmore *link_up = false; 969a4e293a5SDon Skidmore 970a4e293a5SDon Skidmore return 0; 971a4e293a5SDon Skidmore } 972a4e293a5SDon Skidmore 973c3dc4c09SDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 974c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 975c3dc4c09SDon Skidmore **/ 976c3dc4c09SDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 977c3dc4c09SDon Skidmore { 978c3dc4c09SDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 979c3dc4c09SDon Skidmore 980c3dc4c09SDon Skidmore switch (mac->ops.get_media_type(hw)) { 981c3dc4c09SDon Skidmore case ixgbe_media_type_fiber: 982c3dc4c09SDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 983c3dc4c09SDon Skidmore * functions for SFP+ fiber 984c3dc4c09SDon Skidmore */ 985c3dc4c09SDon Skidmore mac->ops.disable_tx_laser = NULL; 986c3dc4c09SDon Skidmore mac->ops.enable_tx_laser = NULL; 987c3dc4c09SDon Skidmore mac->ops.flap_tx_laser = NULL; 988c3dc4c09SDon Skidmore break; 989c3dc4c09SDon Skidmore case ixgbe_media_type_copper: 990c3dc4c09SDon Skidmore mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; 991a4e293a5SDon Skidmore mac->ops.check_link = ixgbe_check_link_t_X550em; 992c3dc4c09SDon Skidmore break; 993c3dc4c09SDon Skidmore default: 994c3dc4c09SDon Skidmore break; 995c3dc4c09SDon Skidmore } 996c3dc4c09SDon Skidmore } 997c3dc4c09SDon Skidmore 998c3dc4c09SDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 999c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1000c3dc4c09SDon Skidmore */ 1001c3dc4c09SDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 1002c3dc4c09SDon Skidmore { 1003c3dc4c09SDon Skidmore bool setup_linear; 1004c3dc4c09SDon Skidmore u16 reg_slice, edc_mode; 1005c3dc4c09SDon Skidmore s32 ret_val; 1006c3dc4c09SDon Skidmore 1007c3dc4c09SDon Skidmore switch (hw->phy.sfp_type) { 1008c3dc4c09SDon Skidmore case ixgbe_sfp_type_unknown: 1009c3dc4c09SDon Skidmore return 0; 1010c3dc4c09SDon Skidmore case ixgbe_sfp_type_not_present: 1011c3dc4c09SDon Skidmore return IXGBE_ERR_SFP_NOT_PRESENT; 1012c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_cu_core0: 1013c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_cu_core1: 1014c3dc4c09SDon Skidmore setup_linear = true; 1015c3dc4c09SDon Skidmore break; 1016c3dc4c09SDon Skidmore case ixgbe_sfp_type_srlr_core0: 1017c3dc4c09SDon Skidmore case ixgbe_sfp_type_srlr_core1: 1018c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_act_lmt_core0: 1019c3dc4c09SDon Skidmore case ixgbe_sfp_type_da_act_lmt_core1: 1020c3dc4c09SDon Skidmore case ixgbe_sfp_type_1g_sx_core0: 1021c3dc4c09SDon Skidmore case ixgbe_sfp_type_1g_sx_core1: 1022c3dc4c09SDon Skidmore setup_linear = false; 1023c3dc4c09SDon Skidmore break; 1024c3dc4c09SDon Skidmore default: 1025c3dc4c09SDon Skidmore return IXGBE_ERR_SFP_NOT_SUPPORTED; 1026c3dc4c09SDon Skidmore } 1027c3dc4c09SDon Skidmore 1028c3dc4c09SDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 1029c3dc4c09SDon Skidmore hw->phy.ops.reset = NULL; 1030c3dc4c09SDon Skidmore 1031c3dc4c09SDon Skidmore /* The CS4227 slice address is the base address + the port-pair reg 1032c3dc4c09SDon Skidmore * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0. 1033c3dc4c09SDon Skidmore */ 1034c3dc4c09SDon Skidmore reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12); 1035c3dc4c09SDon Skidmore 1036c3dc4c09SDon Skidmore if (setup_linear) 1037c3dc4c09SDon Skidmore edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 1038c3dc4c09SDon Skidmore else 1039c3dc4c09SDon Skidmore edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 1040c3dc4c09SDon Skidmore 1041c3dc4c09SDon Skidmore /* Configure CS4227 for connection type. */ 1042c3dc4c09SDon Skidmore ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice, 1043c3dc4c09SDon Skidmore edc_mode); 1044c3dc4c09SDon Skidmore 1045c3dc4c09SDon Skidmore if (ret_val) 1046c3dc4c09SDon Skidmore ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice, 1047c3dc4c09SDon Skidmore edc_mode); 1048c3dc4c09SDon Skidmore 1049c3dc4c09SDon Skidmore return ret_val; 1050c3dc4c09SDon Skidmore } 1051c3dc4c09SDon Skidmore 1052c3dc4c09SDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 1053c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1054c3dc4c09SDon Skidmore * @speed: pointer to link speed 1055c3dc4c09SDon Skidmore * @autoneg: true when autoneg or autotry is enabled 1056c3dc4c09SDon Skidmore **/ 1057c3dc4c09SDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 1058c3dc4c09SDon Skidmore ixgbe_link_speed *speed, 1059c3dc4c09SDon Skidmore bool *autoneg) 1060c3dc4c09SDon Skidmore { 1061c3dc4c09SDon Skidmore /* SFP */ 1062c3dc4c09SDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 1063c3dc4c09SDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 1064c3dc4c09SDon Skidmore *autoneg = false; 1065c3dc4c09SDon Skidmore 1066c3dc4c09SDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 1067c3dc4c09SDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 1068c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 1069c3dc4c09SDon Skidmore return 0; 1070c3dc4c09SDon Skidmore } 1071c3dc4c09SDon Skidmore 1072c3dc4c09SDon Skidmore /* Link capabilities are based on SFP */ 1073c3dc4c09SDon Skidmore if (hw->phy.multispeed_fiber) 1074c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1075c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1076c3dc4c09SDon Skidmore else 1077c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 1078c3dc4c09SDon Skidmore } else { 1079c3dc4c09SDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 1080c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1081c3dc4c09SDon Skidmore *autoneg = true; 1082c3dc4c09SDon Skidmore } 1083c3dc4c09SDon Skidmore return 0; 1084c3dc4c09SDon Skidmore } 1085c3dc4c09SDon Skidmore 1086c3dc4c09SDon Skidmore /** 1087c3dc4c09SDon Skidmore * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause 1088c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1089c3dc4c09SDon Skidmore * @lsc: pointer to boolean flag which indicates whether external Base T 1090c3dc4c09SDon Skidmore * PHY interrupt is lsc 1091c3dc4c09SDon Skidmore * 1092c3dc4c09SDon Skidmore * Determime if external Base T PHY interrupt cause is high temperature 1093c3dc4c09SDon Skidmore * failure alarm or link status change. 1094c3dc4c09SDon Skidmore * 1095c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1096c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1097c3dc4c09SDon Skidmore **/ 1098c3dc4c09SDon Skidmore static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) 1099c3dc4c09SDon Skidmore { 1100c3dc4c09SDon Skidmore u32 status; 1101c3dc4c09SDon Skidmore u16 reg; 1102c3dc4c09SDon Skidmore 1103c3dc4c09SDon Skidmore *lsc = false; 1104c3dc4c09SDon Skidmore 1105c3dc4c09SDon Skidmore /* Vendor alarm triggered */ 1106c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1107c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1108c3dc4c09SDon Skidmore ®); 1109c3dc4c09SDon Skidmore 1110c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) 1111c3dc4c09SDon Skidmore return status; 1112c3dc4c09SDon Skidmore 1113c3dc4c09SDon Skidmore /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ 1114c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, 1115c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1116c3dc4c09SDon Skidmore ®); 1117c3dc4c09SDon Skidmore 1118c3dc4c09SDon Skidmore if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1119c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT))) 1120c3dc4c09SDon Skidmore return status; 1121c3dc4c09SDon Skidmore 1122c3dc4c09SDon Skidmore /* High temperature failure alarm triggered */ 1123c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, 1124c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1125c3dc4c09SDon Skidmore ®); 1126c3dc4c09SDon Skidmore 1127c3dc4c09SDon Skidmore if (status) 1128c3dc4c09SDon Skidmore return status; 1129c3dc4c09SDon Skidmore 1130c3dc4c09SDon Skidmore /* If high temperature failure, then return over temp error and exit */ 1131c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { 1132c3dc4c09SDon Skidmore /* power down the PHY in case the PHY FW didn't already */ 1133c3dc4c09SDon Skidmore ixgbe_set_copper_phy_power(hw, false); 1134c3dc4c09SDon Skidmore return IXGBE_ERR_OVERTEMP; 1135c3dc4c09SDon Skidmore } 1136c3dc4c09SDon Skidmore 1137c3dc4c09SDon Skidmore /* Vendor alarm 2 triggered */ 1138c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, 1139c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1140c3dc4c09SDon Skidmore 1141c3dc4c09SDon Skidmore if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) 1142c3dc4c09SDon Skidmore return status; 1143c3dc4c09SDon Skidmore 1144c3dc4c09SDon Skidmore /* link connect/disconnect event occurred */ 1145c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, 1146c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1147c3dc4c09SDon Skidmore 1148c3dc4c09SDon Skidmore if (status) 1149c3dc4c09SDon Skidmore return status; 1150c3dc4c09SDon Skidmore 1151c3dc4c09SDon Skidmore /* Indicate LSC */ 1152c3dc4c09SDon Skidmore if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) 1153c3dc4c09SDon Skidmore *lsc = true; 1154c3dc4c09SDon Skidmore 1155c3dc4c09SDon Skidmore return 0; 1156c3dc4c09SDon Skidmore } 1157c3dc4c09SDon Skidmore 1158c3dc4c09SDon Skidmore /** 1159c3dc4c09SDon Skidmore * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts 1160c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1161c3dc4c09SDon Skidmore * 1162c3dc4c09SDon Skidmore * Enable link status change and temperature failure alarm for the external 1163c3dc4c09SDon Skidmore * Base T PHY 1164c3dc4c09SDon Skidmore * 1165c3dc4c09SDon Skidmore * Returns PHY access status 1166c3dc4c09SDon Skidmore **/ 1167c3dc4c09SDon Skidmore static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1168c3dc4c09SDon Skidmore { 1169c3dc4c09SDon Skidmore u32 status; 1170c3dc4c09SDon Skidmore u16 reg; 1171c3dc4c09SDon Skidmore bool lsc; 1172c3dc4c09SDon Skidmore 1173c3dc4c09SDon Skidmore /* Clear interrupt flags */ 1174c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1175c3dc4c09SDon Skidmore 1176c3dc4c09SDon Skidmore /* Enable link status change alarm */ 1177c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1178c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); 1179c3dc4c09SDon Skidmore if (status) 1180c3dc4c09SDon Skidmore return status; 1181c3dc4c09SDon Skidmore 1182c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; 1183c3dc4c09SDon Skidmore 1184c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, 1185c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); 1186c3dc4c09SDon Skidmore if (status) 1187c3dc4c09SDon Skidmore return status; 1188c3dc4c09SDon Skidmore 1189c3dc4c09SDon Skidmore /* Enables high temperature failure alarm */ 1190c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1191c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1192c3dc4c09SDon Skidmore ®); 1193c3dc4c09SDon Skidmore if (status) 1194c3dc4c09SDon Skidmore return status; 1195c3dc4c09SDon Skidmore 1196c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN; 1197c3dc4c09SDon Skidmore 1198c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, 1199c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1200c3dc4c09SDon Skidmore reg); 1201c3dc4c09SDon Skidmore if (status) 1202c3dc4c09SDon Skidmore return status; 1203c3dc4c09SDon Skidmore 1204c3dc4c09SDon Skidmore /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ 1205c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1206c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1207c3dc4c09SDon Skidmore ®); 1208c3dc4c09SDon Skidmore if (status) 1209c3dc4c09SDon Skidmore return status; 1210c3dc4c09SDon Skidmore 1211c3dc4c09SDon Skidmore reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | 1212c3dc4c09SDon Skidmore IXGBE_MDIO_GLOBAL_ALARM_1_INT); 1213c3dc4c09SDon Skidmore 1214c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, 1215c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1216c3dc4c09SDon Skidmore reg); 1217c3dc4c09SDon Skidmore if (status) 1218c3dc4c09SDon Skidmore return status; 1219c3dc4c09SDon Skidmore 1220c3dc4c09SDon Skidmore /* Enable chip-wide vendor alarm */ 1221c3dc4c09SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1222c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1223c3dc4c09SDon Skidmore ®); 1224c3dc4c09SDon Skidmore if (status) 1225c3dc4c09SDon Skidmore return status; 1226c3dc4c09SDon Skidmore 1227c3dc4c09SDon Skidmore reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; 1228c3dc4c09SDon Skidmore 1229c3dc4c09SDon Skidmore status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, 1230c3dc4c09SDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 1231c3dc4c09SDon Skidmore reg); 1232c3dc4c09SDon Skidmore 1233c3dc4c09SDon Skidmore return status; 1234c3dc4c09SDon Skidmore } 1235c3dc4c09SDon Skidmore 1236c3dc4c09SDon Skidmore /** 1237c3dc4c09SDon Skidmore * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt 1238c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1239c3dc4c09SDon Skidmore * 1240c3dc4c09SDon Skidmore * Handle external Base T PHY interrupt. If high temperature 1241c3dc4c09SDon Skidmore * failure alarm then return error, else if link status change 1242c3dc4c09SDon Skidmore * then setup internal/external PHY link 1243c3dc4c09SDon Skidmore * 1244c3dc4c09SDon Skidmore * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature 1245c3dc4c09SDon Skidmore * failure alarm, else return PHY access status. 1246c3dc4c09SDon Skidmore **/ 1247c3dc4c09SDon Skidmore static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) 1248c3dc4c09SDon Skidmore { 1249c3dc4c09SDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1250c3dc4c09SDon Skidmore bool lsc; 1251c3dc4c09SDon Skidmore u32 status; 1252c3dc4c09SDon Skidmore 1253c3dc4c09SDon Skidmore status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); 1254c3dc4c09SDon Skidmore if (status) 1255c3dc4c09SDon Skidmore return status; 1256c3dc4c09SDon Skidmore 1257c3dc4c09SDon Skidmore if (lsc) 1258c3dc4c09SDon Skidmore return phy->ops.setup_internal_link(hw); 1259c3dc4c09SDon Skidmore 1260c3dc4c09SDon Skidmore return 0; 1261c3dc4c09SDon Skidmore } 1262c3dc4c09SDon Skidmore 1263c3dc4c09SDon Skidmore /** 1264c3dc4c09SDon Skidmore * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. 1265c3dc4c09SDon Skidmore * @hw: pointer to hardware structure 1266c3dc4c09SDon Skidmore * @speed: link speed 1267c3dc4c09SDon Skidmore * 1268c3dc4c09SDon Skidmore * Configures the integrated KR PHY. 1269c3dc4c09SDon Skidmore **/ 1270c3dc4c09SDon Skidmore static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, 1271c3dc4c09SDon Skidmore ixgbe_link_speed speed) 1272c3dc4c09SDon Skidmore { 1273c3dc4c09SDon Skidmore s32 status; 1274c3dc4c09SDon Skidmore u32 reg_val; 1275c3dc4c09SDon Skidmore 1276c3dc4c09SDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 1277c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1278c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 1279c3dc4c09SDon Skidmore if (status) 1280c3dc4c09SDon Skidmore return status; 1281c3dc4c09SDon Skidmore 1282c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 1283c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | 1284c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); 1285c3dc4c09SDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 1286c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 1287c3dc4c09SDon Skidmore 1288c3dc4c09SDon Skidmore /* Advertise 10G support. */ 1289c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_10GB_FULL) 1290c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 1291c3dc4c09SDon Skidmore 1292c3dc4c09SDon Skidmore /* Advertise 1G support. */ 1293c3dc4c09SDon Skidmore if (speed & IXGBE_LINK_SPEED_1GB_FULL) 1294c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 1295c3dc4c09SDon Skidmore 1296c3dc4c09SDon Skidmore /* Restart auto-negotiation. */ 1297c3dc4c09SDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 1298c3dc4c09SDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 1299c3dc4c09SDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 1300c3dc4c09SDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 1301c3dc4c09SDon Skidmore 1302c3dc4c09SDon Skidmore return status; 1303c3dc4c09SDon Skidmore } 1304c3dc4c09SDon Skidmore 13056a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 13066a14ee0cSDon Skidmore * @hw: pointer to hardware structure 13076a14ee0cSDon Skidmore * 13086a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 13096a14ee0cSDon Skidmore **/ 13107ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 13116a14ee0cSDon Skidmore { 13126a14ee0cSDon Skidmore s32 status; 13136a14ee0cSDon Skidmore u32 reg_val; 13146a14ee0cSDon Skidmore 13156a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 13166a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 13176a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 13186a14ee0cSDon Skidmore if (status) 13196a14ee0cSDon Skidmore return status; 13206a14ee0cSDon Skidmore 13216a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 13226a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 13236a14ee0cSDon Skidmore 13246a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 13256a14ee0cSDon Skidmore 13266a14ee0cSDon Skidmore /* Advertise 10G support. */ 13276a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 13286a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 13296a14ee0cSDon Skidmore 13306a14ee0cSDon Skidmore /* Advertise 1G support. */ 13316a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 13326a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 13336a14ee0cSDon Skidmore 13346a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 13356a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 13366a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 13376a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 13386a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 13396a14ee0cSDon Skidmore 13406a14ee0cSDon Skidmore return status; 13416a14ee0cSDon Skidmore } 13426a14ee0cSDon Skidmore 13436a14ee0cSDon Skidmore /** ixgbe_setup_kr_x550em - Configure the KR PHY. 13446a14ee0cSDon Skidmore * @hw: pointer to hardware structure 13456a14ee0cSDon Skidmore * 13466a14ee0cSDon Skidmore * Configures the integrated KR PHY. 13476a14ee0cSDon Skidmore **/ 13487ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 13496a14ee0cSDon Skidmore { 1350c3dc4c09SDon Skidmore return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); 13516a14ee0cSDon Skidmore } 13526a14ee0cSDon Skidmore 1353c3dc4c09SDon Skidmore /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status 1354c3dc4c09SDon Skidmore * @hw: address of hardware structure 1355c3dc4c09SDon Skidmore * @link_up: address of boolean to indicate link status 1356c3dc4c09SDon Skidmore * 1357c3dc4c09SDon Skidmore * Returns error code if unable to get link status. 1358c3dc4c09SDon Skidmore **/ 1359c3dc4c09SDon Skidmore static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) 1360c3dc4c09SDon Skidmore { 1361c3dc4c09SDon Skidmore u32 ret; 1362c3dc4c09SDon Skidmore u16 autoneg_status; 1363c3dc4c09SDon Skidmore 1364c3dc4c09SDon Skidmore *link_up = false; 1365c3dc4c09SDon Skidmore 1366c3dc4c09SDon Skidmore /* read this twice back to back to indicate current status */ 1367c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1368c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1369c3dc4c09SDon Skidmore &autoneg_status); 1370c3dc4c09SDon Skidmore if (ret) 1371c3dc4c09SDon Skidmore return ret; 1372c3dc4c09SDon Skidmore 1373c3dc4c09SDon Skidmore ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 1374c3dc4c09SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 1375c3dc4c09SDon Skidmore &autoneg_status); 1376c3dc4c09SDon Skidmore if (ret) 1377c3dc4c09SDon Skidmore return ret; 1378c3dc4c09SDon Skidmore 1379c3dc4c09SDon Skidmore *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); 1380c3dc4c09SDon Skidmore 1381c3dc4c09SDon Skidmore return 0; 1382c3dc4c09SDon Skidmore } 1383c3dc4c09SDon Skidmore 1384c3dc4c09SDon Skidmore /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link 13856a14ee0cSDon Skidmore * @hw: point to hardware structure 13866a14ee0cSDon Skidmore * 1387c3dc4c09SDon Skidmore * Configures the link between the integrated KR PHY and the external X557 PHY 1388c3dc4c09SDon Skidmore * The driver will call this function when it gets a link status change 1389c3dc4c09SDon Skidmore * interrupt from the X557 PHY. This function configures the link speed 1390c3dc4c09SDon Skidmore * between the PHYs to match the link speed of the BASE-T link. 13916a14ee0cSDon Skidmore * 13926a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 13936a14ee0cSDon Skidmore * not report link up. 13946a14ee0cSDon Skidmore **/ 1395c3dc4c09SDon Skidmore static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) 13966a14ee0cSDon Skidmore { 13976a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 1398c3dc4c09SDon Skidmore bool link_up; 1399c3dc4c09SDon Skidmore u32 status; 1400c3dc4c09SDon Skidmore u16 speed; 14016a14ee0cSDon Skidmore 1402c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) 1403c3dc4c09SDon Skidmore return IXGBE_ERR_CONFIG; 1404c3dc4c09SDon Skidmore 1405c3dc4c09SDon Skidmore /* If link is not up, then there is no setup necessary so return */ 1406c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 14076a14ee0cSDon Skidmore if (status) 14086a14ee0cSDon Skidmore return status; 14096a14ee0cSDon Skidmore 1410c3dc4c09SDon Skidmore if (!link_up) 14116a14ee0cSDon Skidmore return 0; 14126a14ee0cSDon Skidmore 14136a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 14146a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 14156a14ee0cSDon Skidmore &speed); 1416c3dc4c09SDon Skidmore if (status) 1417c3dc4c09SDon Skidmore return status; 1418c3dc4c09SDon Skidmore 1419c3dc4c09SDon Skidmore /* If link is not still up, then no setup is necessary so return */ 1420c3dc4c09SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 1421c3dc4c09SDon Skidmore if (status) 1422c3dc4c09SDon Skidmore return status; 1423c3dc4c09SDon Skidmore 1424c3dc4c09SDon Skidmore if (!link_up) 1425c3dc4c09SDon Skidmore return 0; 14266a14ee0cSDon Skidmore 14276a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 14286a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 14296a14ee0cSDon Skidmore 14306a14ee0cSDon Skidmore switch (speed) { 14316a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 14326a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 14336a14ee0cSDon Skidmore break; 14346a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 14356a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 14366a14ee0cSDon Skidmore break; 14376a14ee0cSDon Skidmore default: 14386a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 14396a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 14406a14ee0cSDon Skidmore } 14416a14ee0cSDon Skidmore 14426a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 14436a14ee0cSDon Skidmore } 14446a14ee0cSDon Skidmore 1445f4410d2cSDon Skidmore /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI 1446f4410d2cSDon Skidmore * @hw: pointer to hardware structure 1447f4410d2cSDon Skidmore **/ 1448f4410d2cSDon Skidmore static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) 1449f4410d2cSDon Skidmore { 1450f4410d2cSDon Skidmore s32 status; 1451f4410d2cSDon Skidmore 1452f4410d2cSDon Skidmore status = ixgbe_reset_phy_generic(hw); 1453f4410d2cSDon Skidmore 1454f4410d2cSDon Skidmore if (status) 1455f4410d2cSDon Skidmore return status; 1456f4410d2cSDon Skidmore 1457f4410d2cSDon Skidmore /* Configure Link Status Alarm and Temperature Threshold interrupts */ 1458f4410d2cSDon Skidmore return ixgbe_enable_lasi_ext_t_x550em(hw); 1459f4410d2cSDon Skidmore } 1460f4410d2cSDon Skidmore 14616ac74394SDon Skidmore /** ixgbe_get_lcd_x550em - Determine lowest common denominator 14626ac74394SDon Skidmore * @hw: pointer to hardware structure 14636ac74394SDon Skidmore * @lcd_speed: pointer to lowest common link speed 14646ac74394SDon Skidmore * 14656ac74394SDon Skidmore * Determine lowest common link speed with link partner. 14666ac74394SDon Skidmore **/ 14676ac74394SDon Skidmore static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, 14686ac74394SDon Skidmore ixgbe_link_speed *lcd_speed) 14696ac74394SDon Skidmore { 14706ac74394SDon Skidmore u16 an_lp_status; 14716ac74394SDon Skidmore s32 status; 14726ac74394SDon Skidmore u16 word = hw->eeprom.ctrl_word_3; 14736ac74394SDon Skidmore 14746ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; 14756ac74394SDon Skidmore 14766ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, 14776ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 14786ac74394SDon Skidmore &an_lp_status); 14796ac74394SDon Skidmore if (status) 14806ac74394SDon Skidmore return status; 14816ac74394SDon Skidmore 14826ac74394SDon Skidmore /* If link partner advertised 1G, return 1G */ 14836ac74394SDon Skidmore if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { 14846ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; 14856ac74394SDon Skidmore return status; 14866ac74394SDon Skidmore } 14876ac74394SDon Skidmore 14886ac74394SDon Skidmore /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ 14896ac74394SDon Skidmore if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || 14906ac74394SDon Skidmore (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) 14916ac74394SDon Skidmore return status; 14926ac74394SDon Skidmore 14936ac74394SDon Skidmore /* Link partner not capable of lower speeds, return 10G */ 14946ac74394SDon Skidmore *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; 14956ac74394SDon Skidmore return status; 14966ac74394SDon Skidmore } 14976ac74394SDon Skidmore 14986ac74394SDon Skidmore /** ixgbe_enter_lplu_x550em - Transition to low power states 14996ac74394SDon Skidmore * @hw: pointer to hardware structure 15006ac74394SDon Skidmore * 15016ac74394SDon Skidmore * Configures Low Power Link Up on transition to low power states 15026ac74394SDon Skidmore * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting 15036ac74394SDon Skidmore * the X557 PHY immediately prior to entering LPLU. 15046ac74394SDon Skidmore **/ 15056ac74394SDon Skidmore static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) 15066ac74394SDon Skidmore { 15076ac74394SDon Skidmore u16 an_10g_cntl_reg, autoneg_reg, speed; 15086ac74394SDon Skidmore s32 status; 15096ac74394SDon Skidmore ixgbe_link_speed lcd_speed; 15106ac74394SDon Skidmore u32 save_autoneg; 15116ac74394SDon Skidmore bool link_up; 15126ac74394SDon Skidmore 15136ac74394SDon Skidmore /* SW LPLU not required on later HW revisions. */ 15146ac74394SDon Skidmore if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))) 15156ac74394SDon Skidmore return 0; 15166ac74394SDon Skidmore 15176ac74394SDon Skidmore /* If blocked by MNG FW, then don't restart AN */ 15186ac74394SDon Skidmore if (ixgbe_check_reset_blocked(hw)) 15196ac74394SDon Skidmore return 0; 15206ac74394SDon Skidmore 15216ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 15226ac74394SDon Skidmore if (status) 15236ac74394SDon Skidmore return status; 15246ac74394SDon Skidmore 15256ac74394SDon Skidmore status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, 15266ac74394SDon Skidmore &hw->eeprom.ctrl_word_3); 15276ac74394SDon Skidmore if (status) 15286ac74394SDon Skidmore return status; 15296ac74394SDon Skidmore 15306ac74394SDon Skidmore /* If link is down, LPLU disabled in NVM, WoL disabled, or 15316ac74394SDon Skidmore * manageability disabled, then force link down by entering 15326ac74394SDon Skidmore * low power mode. 15336ac74394SDon Skidmore */ 15346ac74394SDon Skidmore if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || 15356ac74394SDon Skidmore !(hw->wol_enabled || ixgbe_mng_present(hw))) 15366ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 15376ac74394SDon Skidmore 15386ac74394SDon Skidmore /* Determine LCD */ 15396ac74394SDon Skidmore status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); 15406ac74394SDon Skidmore if (status) 15416ac74394SDon Skidmore return status; 15426ac74394SDon Skidmore 15436ac74394SDon Skidmore /* If no valid LCD link speed, then force link down and exit. */ 15446ac74394SDon Skidmore if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) 15456ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 15466ac74394SDon Skidmore 15476ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 15486ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 15496ac74394SDon Skidmore &speed); 15506ac74394SDon Skidmore if (status) 15516ac74394SDon Skidmore return status; 15526ac74394SDon Skidmore 15536ac74394SDon Skidmore /* If no link now, speed is invalid so take link down */ 15546ac74394SDon Skidmore status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); 15556ac74394SDon Skidmore if (status) 15566ac74394SDon Skidmore return ixgbe_set_copper_phy_power(hw, false); 15576ac74394SDon Skidmore 15586ac74394SDon Skidmore /* clear everything but the speed bits */ 15596ac74394SDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; 15606ac74394SDon Skidmore 15616ac74394SDon Skidmore /* If current speed is already LCD, then exit. */ 15626ac74394SDon Skidmore if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && 15636ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || 15646ac74394SDon Skidmore ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && 15656ac74394SDon Skidmore (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) 15666ac74394SDon Skidmore return status; 15676ac74394SDon Skidmore 15686ac74394SDon Skidmore /* Clear AN completed indication */ 15696ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, 15706ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 15716ac74394SDon Skidmore &autoneg_reg); 15726ac74394SDon Skidmore if (status) 15736ac74394SDon Skidmore return status; 15746ac74394SDon Skidmore 15756ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, 15766ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 15776ac74394SDon Skidmore &an_10g_cntl_reg); 15786ac74394SDon Skidmore if (status) 15796ac74394SDon Skidmore return status; 15806ac74394SDon Skidmore 15816ac74394SDon Skidmore status = hw->phy.ops.read_reg(hw, 15826ac74394SDon Skidmore IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, 15836ac74394SDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 15846ac74394SDon Skidmore &autoneg_reg); 15856ac74394SDon Skidmore if (status) 15866ac74394SDon Skidmore return status; 15876ac74394SDon Skidmore 15886ac74394SDon Skidmore save_autoneg = hw->phy.autoneg_advertised; 15896ac74394SDon Skidmore 15906ac74394SDon Skidmore /* Setup link at least common link speed */ 15916ac74394SDon Skidmore status = hw->mac.ops.setup_link(hw, lcd_speed, false); 15926ac74394SDon Skidmore 15936ac74394SDon Skidmore /* restore autoneg from before setting lplu speed */ 15946ac74394SDon Skidmore hw->phy.autoneg_advertised = save_autoneg; 15956ac74394SDon Skidmore 15966ac74394SDon Skidmore return status; 15976ac74394SDon Skidmore } 15986ac74394SDon Skidmore 15996a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 16006a14ee0cSDon Skidmore * @hw: pointer to hardware structure 16016a14ee0cSDon Skidmore * 16026a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 16036a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 16046a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 16056a14ee0cSDon Skidmore **/ 16067ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 16076a14ee0cSDon Skidmore { 16086a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 1609c3dc4c09SDon Skidmore ixgbe_link_speed speed; 16106a14ee0cSDon Skidmore s32 ret_val; 16116a14ee0cSDon Skidmore 16127e49d616SDon Skidmore hw->mac.ops.set_lan_id(hw); 16137e49d616SDon Skidmore 1614c3dc4c09SDon Skidmore if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { 16156a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 1616ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 1617c3dc4c09SDon Skidmore 1618c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 1619c3dc4c09SDon Skidmore * to determine internal PHY mode. 1620c3dc4c09SDon Skidmore */ 1621c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 1622c3dc4c09SDon Skidmore 1623c3dc4c09SDon Skidmore /* If internal PHY mode is KR, then initialize KR link */ 1624c3dc4c09SDon Skidmore if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { 1625c3dc4c09SDon Skidmore speed = IXGBE_LINK_SPEED_10GB_FULL | 1626c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1627c3dc4c09SDon Skidmore ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); 1628c3dc4c09SDon Skidmore } 16296a14ee0cSDon Skidmore } 16306a14ee0cSDon Skidmore 16316a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 16326a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 16336a14ee0cSDon Skidmore 1634c3dc4c09SDon Skidmore /* Setup function pointers based on detected hardware */ 16356a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 16366a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 16376a14ee0cSDon Skidmore phy->ops.reset = NULL; 16386a14ee0cSDon Skidmore 16396a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 16406a14ee0cSDon Skidmore switch (hw->phy.type) { 16416a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 16426a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 16436a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 16446a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 16456a14ee0cSDon Skidmore break; 16466a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 16476a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 16486a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 16496a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 16506a14ee0cSDon Skidmore break; 16516a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 1652c3dc4c09SDon Skidmore /* Save NW management interface connected on board. This is used 1653c3dc4c09SDon Skidmore * to determine internal PHY mode 1654c3dc4c09SDon Skidmore */ 1655c3dc4c09SDon Skidmore phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); 1656c3dc4c09SDon Skidmore 1657c3dc4c09SDon Skidmore /* If internal link mode is XFI, then setup iXFI internal link, 1658c3dc4c09SDon Skidmore * else setup KR now. 1659c3dc4c09SDon Skidmore */ 1660c3dc4c09SDon Skidmore if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { 1661c3dc4c09SDon Skidmore phy->ops.setup_internal_link = 1662c3dc4c09SDon Skidmore ixgbe_setup_internal_phy_t_x550em; 1663c3dc4c09SDon Skidmore } else { 1664c3dc4c09SDon Skidmore speed = IXGBE_LINK_SPEED_10GB_FULL | 1665c3dc4c09SDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 1666c3dc4c09SDon Skidmore ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); 1667c3dc4c09SDon Skidmore } 1668c3dc4c09SDon Skidmore 16696ac74394SDon Skidmore /* setup SW LPLU only for first revision */ 16706ac74394SDon Skidmore if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, 16716ac74394SDon Skidmore IXGBE_FUSES0_GROUP(0)))) 16726ac74394SDon Skidmore phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; 16736ac74394SDon Skidmore 1674c3dc4c09SDon Skidmore phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; 1675f4410d2cSDon Skidmore phy->ops.reset = ixgbe_reset_phy_t_X550em; 16766a14ee0cSDon Skidmore break; 16776a14ee0cSDon Skidmore default: 16786a14ee0cSDon Skidmore break; 16796a14ee0cSDon Skidmore } 1680c3dc4c09SDon Skidmore 16816a14ee0cSDon Skidmore return ret_val; 16826a14ee0cSDon Skidmore } 16836a14ee0cSDon Skidmore 16846a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 16856a14ee0cSDon Skidmore * @hw: pointer to hardware structure 16866a14ee0cSDon Skidmore * 16876a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 16886a14ee0cSDon Skidmore * 16896a14ee0cSDon Skidmore */ 16907ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 16916a14ee0cSDon Skidmore { 16926a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 16936a14ee0cSDon Skidmore 16946a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 16956a14ee0cSDon Skidmore switch (hw->device_id) { 16966a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 16976a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 16986a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 16996a14ee0cSDon Skidmore break; 17006a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 17016a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 17026a14ee0cSDon Skidmore break; 17036a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 17046a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 17056a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 17066a14ee0cSDon Skidmore break; 17076a14ee0cSDon Skidmore default: 17086a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 17096a14ee0cSDon Skidmore break; 17106a14ee0cSDon Skidmore } 17116a14ee0cSDon Skidmore return media_type; 17126a14ee0cSDon Skidmore } 17136a14ee0cSDon Skidmore 17146a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 17156a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 17166a14ee0cSDon Skidmore **/ 17177ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 17186a14ee0cSDon Skidmore { 1719a1e869deSMark Rustad s32 status; 17206a14ee0cSDon Skidmore u16 reg; 17216a14ee0cSDon Skidmore 17226a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 17236a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 17246a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 17256a14ee0cSDon Skidmore ®); 17266a14ee0cSDon Skidmore if (status) 17276a14ee0cSDon Skidmore return status; 17286a14ee0cSDon Skidmore 1729e2261bccSDon Skidmore /* If PHY FW reset completed bit is set then this is the first 1730e2261bccSDon Skidmore * SW instance after a power on so the PHY FW must be un-stalled. 1731e2261bccSDon Skidmore */ 1732e2261bccSDon Skidmore if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { 17336a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 17346a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 17356a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 17366a14ee0cSDon Skidmore ®); 17376a14ee0cSDon Skidmore if (status) 17386a14ee0cSDon Skidmore return status; 17396a14ee0cSDon Skidmore 17406a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 17416a14ee0cSDon Skidmore 17426a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 17436a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 17446a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 17456a14ee0cSDon Skidmore reg); 1746e2261bccSDon Skidmore if (status) 1747e2261bccSDon Skidmore return status; 1748e2261bccSDon Skidmore } 1749e2261bccSDon Skidmore 17506a14ee0cSDon Skidmore return status; 17516a14ee0cSDon Skidmore } 17526a14ee0cSDon Skidmore 17536a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 17546a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 17556a14ee0cSDon Skidmore ** 17566a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 17576a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 17586a14ee0cSDon Skidmore ** reset. 17596a14ee0cSDon Skidmore **/ 17607ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 17616a14ee0cSDon Skidmore { 17626a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 17636a14ee0cSDon Skidmore s32 status; 17646a14ee0cSDon Skidmore u32 ctrl = 0; 17656a14ee0cSDon Skidmore u32 i; 1766deda562aSDon Skidmore u32 hlreg0; 17676a14ee0cSDon Skidmore bool link_up = false; 17686a14ee0cSDon Skidmore 17696a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 17706a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 17716a14ee0cSDon Skidmore if (status) 17726a14ee0cSDon Skidmore return status; 17736a14ee0cSDon Skidmore 17746a14ee0cSDon Skidmore /* flush pending Tx transactions */ 17756a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 17766a14ee0cSDon Skidmore 17776a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 17786a14ee0cSDon Skidmore 17796a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 17806a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 17816a14ee0cSDon Skidmore 17826a14ee0cSDon Skidmore /* start the external PHY */ 17836a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 17846a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 17856a14ee0cSDon Skidmore if (status) 17866a14ee0cSDon Skidmore return status; 17876a14ee0cSDon Skidmore } 17886a14ee0cSDon Skidmore 17896a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 17906a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 17916a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 17926a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 17936a14ee0cSDon Skidmore } 17946a14ee0cSDon Skidmore 17956a14ee0cSDon Skidmore /* Reset PHY */ 17966a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 17976a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 17986a14ee0cSDon Skidmore 17996a14ee0cSDon Skidmore mac_reset_top: 18006a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 18016a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 18026a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 18036a14ee0cSDon Skidmore * reset is set, then perform link reset. 18046a14ee0cSDon Skidmore */ 18056a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 18066a14ee0cSDon Skidmore 18076a14ee0cSDon Skidmore if (!hw->force_full_reset) { 18086a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 18096a14ee0cSDon Skidmore if (link_up) 18106a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 18116a14ee0cSDon Skidmore } 18126a14ee0cSDon Skidmore 18136a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 18146a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 18156a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 18166a14ee0cSDon Skidmore 18176a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 18186a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 18196a14ee0cSDon Skidmore udelay(1); 18206a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 18216a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 18226a14ee0cSDon Skidmore break; 18236a14ee0cSDon Skidmore } 18246a14ee0cSDon Skidmore 18256a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 18266a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 18276a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 18286a14ee0cSDon Skidmore } 18296a14ee0cSDon Skidmore 18306a14ee0cSDon Skidmore msleep(50); 18316a14ee0cSDon Skidmore 18326a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 18336a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 18346a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 18356a14ee0cSDon Skidmore */ 18366a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 18376a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 18386a14ee0cSDon Skidmore goto mac_reset_top; 18396a14ee0cSDon Skidmore } 18406a14ee0cSDon Skidmore 18416a14ee0cSDon Skidmore /* Store the permanent mac address */ 18426a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 18436a14ee0cSDon Skidmore 18446a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 18456a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 18466a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 18476a14ee0cSDon Skidmore */ 18486a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 18496a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 18506a14ee0cSDon Skidmore 1851deda562aSDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { 1852deda562aSDon Skidmore hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 1853deda562aSDon Skidmore hlreg0 &= ~IXGBE_HLREG0_MDCSPD; 1854deda562aSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 1855deda562aSDon Skidmore } 1856deda562aSDon Skidmore 1857ab5fe0c5SDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) 1858ab5fe0c5SDon Skidmore ixgbe_setup_mux_ctl(hw); 1859ab5fe0c5SDon Skidmore 18606a14ee0cSDon Skidmore return status; 18616a14ee0cSDon Skidmore } 18626a14ee0cSDon Skidmore 18635b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 18645b7f000fSDon Skidmore * anti-spoofing 18655b7f000fSDon Skidmore * @hw: pointer to hardware structure 18665b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 18675b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 18685b7f000fSDon Skidmore **/ 1869bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 1870bc035fc5SDon Skidmore bool enable, int vf) 18715b7f000fSDon Skidmore { 18725b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 18735b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 18745b7f000fSDon Skidmore u32 pfvfspoof; 18755b7f000fSDon Skidmore 18765b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 18775b7f000fSDon Skidmore if (enable) 18785b7f000fSDon Skidmore pfvfspoof |= (1 << vf_target_shift); 18795b7f000fSDon Skidmore else 18805b7f000fSDon Skidmore pfvfspoof &= ~(1 << vf_target_shift); 18815b7f000fSDon Skidmore 18825b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 18835b7f000fSDon Skidmore } 18845b7f000fSDon Skidmore 18856d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 18866d4c96adSDon Skidmore * @hw: pointer to hardware structure 18876d4c96adSDon Skidmore * @enable: enable or disable source address pruning 18886d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 18896d4c96adSDon Skidmore **/ 18906d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 18916d4c96adSDon Skidmore bool enable, 18926d4c96adSDon Skidmore unsigned int pool) 18936d4c96adSDon Skidmore { 18946d4c96adSDon Skidmore u64 pfflp; 18956d4c96adSDon Skidmore 18966d4c96adSDon Skidmore /* max rx pool is 63 */ 18976d4c96adSDon Skidmore if (pool > 63) 18986d4c96adSDon Skidmore return; 18996d4c96adSDon Skidmore 19006d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 19016d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 19026d4c96adSDon Skidmore 19036d4c96adSDon Skidmore if (enable) 19046d4c96adSDon Skidmore pfflp |= (1ULL << pool); 19056d4c96adSDon Skidmore else 19066d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 19076d4c96adSDon Skidmore 19086d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 19096d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 19106d4c96adSDon Skidmore } 19116d4c96adSDon Skidmore 19126a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 19136a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 19146a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 19156a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 19166a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 19176a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 19186a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 19196a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 19206a14ee0cSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, \ 19216a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 19226a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 19236a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 19246a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 19256a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 19266a14ee0cSDon Skidmore .led_on = &ixgbe_led_on_generic, \ 19276a14ee0cSDon Skidmore .led_off = &ixgbe_led_off_generic, \ 19286a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 19296a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 19306a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 19316a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 19326a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 19336a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 19346a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 19356a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 19366a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 19376a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 19386a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 19396a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 19406a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 19416a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 19426a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 19436a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 19446a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 19456a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 19466d4c96adSDon Skidmore .set_source_address_pruning = \ 19476d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 19485b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 19495b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 19506a14ee0cSDon Skidmore .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, \ 19516a14ee0cSDon Skidmore .release_swfw_sync = &ixgbe_release_swfw_sync_X540, \ 19526a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 19536a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 19546a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 19556a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 19566a14ee0cSDon Skidmore .prot_autoc_read = &prot_autoc_read_generic, \ 19576a14ee0cSDon Skidmore .prot_autoc_write = &prot_autoc_write_generic, \ 19581f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 19591f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 19606a14ee0cSDon Skidmore 19616a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550 = { 19626a14ee0cSDon Skidmore X550_COMMON_MAC 19636a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 19646a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 19656a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 19666a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 19676a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 19686a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 19696a14ee0cSDon Skidmore .setup_sfp = NULL, 19706a14ee0cSDon Skidmore }; 19716a14ee0cSDon Skidmore 19726a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550EM_x = { 19736a14ee0cSDon Skidmore X550_COMMON_MAC 19746a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 19756a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 19766a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 19776a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 19786a14ee0cSDon Skidmore .setup_link = NULL, /* defined later */ 19796a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 19806a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 19816a14ee0cSDon Skidmore 19826a14ee0cSDon Skidmore }; 19836a14ee0cSDon Skidmore 19846a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 19856a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 19866a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 19876a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 19886a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 19896a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 19906a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 19916a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 19926a14ee0cSDon Skidmore 19936a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550 = { 19946a14ee0cSDon Skidmore X550_COMMON_EEP 19956a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 19966a14ee0cSDon Skidmore }; 19976a14ee0cSDon Skidmore 19986a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 19996a14ee0cSDon Skidmore X550_COMMON_EEP 20006a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 20016a14ee0cSDon Skidmore }; 20026a14ee0cSDon Skidmore 20036a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 20046a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 20056a14ee0cSDon Skidmore .reset = NULL, \ 20066a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 20076a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 20086a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 20096a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 20106a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 20116a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 2012bef23de1SDon Skidmore .read_reg = &ixgbe_read_phy_reg_generic, \ 2013bef23de1SDon Skidmore .write_reg = &ixgbe_write_phy_reg_generic, \ 2014bef23de1SDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, \ 2015b5529ef5SDon Skidmore .set_phy_power = NULL, \ 20166a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 20176a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 20186a14ee0cSDon Skidmore 20196a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550 = { 20206a14ee0cSDon Skidmore X550_COMMON_PHY 20216a14ee0cSDon Skidmore .init = NULL, 20226a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 20236a14ee0cSDon Skidmore .read_i2c_combined = &ixgbe_read_i2c_combined_generic, 20246a14ee0cSDon Skidmore .write_i2c_combined = &ixgbe_write_i2c_combined_generic, 20256a14ee0cSDon Skidmore }; 20266a14ee0cSDon Skidmore 20276a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550EM_x = { 20286a14ee0cSDon Skidmore X550_COMMON_PHY 20296a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 20306a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 20316a14ee0cSDon Skidmore }; 20326a14ee0cSDon Skidmore 20339a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 20349a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 20359a900ecaSDon Skidmore }; 20369a900ecaSDon Skidmore 20379a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 20389a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 20399a900ecaSDon Skidmore }; 20409a900ecaSDon Skidmore 20416a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550_info = { 20426a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 20436a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 20446a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 20456a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 20466a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 20476a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 20489a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 20496a14ee0cSDon Skidmore }; 20506a14ee0cSDon Skidmore 20516a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550EM_x_info = { 20526a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 2053b5529ef5SDon Skidmore .get_invariants = &ixgbe_get_invariants_X550_x, 20546a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 20556a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 20566a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 20576a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 20589a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 20596a14ee0cSDon Skidmore }; 2060