16a14ee0cSDon Skidmore /******************************************************************************* 26a14ee0cSDon Skidmore * 36a14ee0cSDon Skidmore * Intel 10 Gigabit PCI Express Linux driver 46a14ee0cSDon Skidmore * Copyright(c) 1999 - 2014 Intel Corporation. 56a14ee0cSDon Skidmore * 66a14ee0cSDon Skidmore * This program is free software; you can redistribute it and/or modify it 76a14ee0cSDon Skidmore * under the terms and conditions of the GNU General Public License, 86a14ee0cSDon Skidmore * version 2, as published by the Free Software Foundation. 96a14ee0cSDon Skidmore * 106a14ee0cSDon Skidmore * This program is distributed in the hope it will be useful, but WITHOUT 116a14ee0cSDon Skidmore * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 126a14ee0cSDon Skidmore * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 136a14ee0cSDon Skidmore * more details. 146a14ee0cSDon Skidmore * 156a14ee0cSDon Skidmore * The full GNU General Public License is included in this distribution in 166a14ee0cSDon Skidmore * the file called "COPYING". 176a14ee0cSDon Skidmore * 186a14ee0cSDon Skidmore * Contact Information: 196a14ee0cSDon Skidmore * Linux NICS <linux.nics@intel.com> 206a14ee0cSDon Skidmore * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 216a14ee0cSDon Skidmore * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 226a14ee0cSDon Skidmore * 236a14ee0cSDon Skidmore ******************************************************************************/ 246a14ee0cSDon Skidmore #include "ixgbe_x540.h" 256a14ee0cSDon Skidmore #include "ixgbe_type.h" 266a14ee0cSDon Skidmore #include "ixgbe_common.h" 276a14ee0cSDon Skidmore #include "ixgbe_phy.h" 286a14ee0cSDon Skidmore 296a14ee0cSDon Skidmore /** ixgbe_identify_phy_x550em - Get PHY type based on device id 306a14ee0cSDon Skidmore * @hw: pointer to hardware structure 316a14ee0cSDon Skidmore * 326a14ee0cSDon Skidmore * Returns error code 336a14ee0cSDon Skidmore */ 346a14ee0cSDon Skidmore static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) 356a14ee0cSDon Skidmore { 366a14ee0cSDon Skidmore u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 376a14ee0cSDon Skidmore 386a14ee0cSDon Skidmore switch (hw->device_id) { 396a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 406a14ee0cSDon Skidmore /* set up for CS4227 usage */ 416a14ee0cSDon Skidmore hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 426a14ee0cSDon Skidmore if (hw->bus.lan_id) { 436a14ee0cSDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 446a14ee0cSDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 456a14ee0cSDon Skidmore } 466a14ee0cSDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 476a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 486a14ee0cSDon Skidmore 496a14ee0cSDon Skidmore return ixgbe_identify_module_generic(hw); 506a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 516a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kx4; 526a14ee0cSDon Skidmore break; 536a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 546a14ee0cSDon Skidmore hw->phy.type = ixgbe_phy_x550em_kr; 556a14ee0cSDon Skidmore break; 566a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 576a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 586a14ee0cSDon Skidmore return ixgbe_identify_phy_generic(hw); 596a14ee0cSDon Skidmore default: 606a14ee0cSDon Skidmore break; 616a14ee0cSDon Skidmore } 626a14ee0cSDon Skidmore return 0; 636a14ee0cSDon Skidmore } 646a14ee0cSDon Skidmore 656a14ee0cSDon Skidmore static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 666a14ee0cSDon Skidmore u32 device_type, u16 *phy_data) 676a14ee0cSDon Skidmore { 686a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 696a14ee0cSDon Skidmore } 706a14ee0cSDon Skidmore 716a14ee0cSDon Skidmore static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, 726a14ee0cSDon Skidmore u32 device_type, u16 phy_data) 736a14ee0cSDon Skidmore { 746a14ee0cSDon Skidmore return IXGBE_NOT_IMPLEMENTED; 756a14ee0cSDon Skidmore } 766a14ee0cSDon Skidmore 776a14ee0cSDon Skidmore /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params 786a14ee0cSDon Skidmore * @hw: pointer to hardware structure 796a14ee0cSDon Skidmore * 806a14ee0cSDon Skidmore * Initializes the EEPROM parameters ixgbe_eeprom_info within the 816a14ee0cSDon Skidmore * ixgbe_hw struct in order to set up EEPROM access. 826a14ee0cSDon Skidmore **/ 837ddbde3fSDon Skidmore static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) 846a14ee0cSDon Skidmore { 856a14ee0cSDon Skidmore struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 866a14ee0cSDon Skidmore u32 eec; 876a14ee0cSDon Skidmore u16 eeprom_size; 886a14ee0cSDon Skidmore 896a14ee0cSDon Skidmore if (eeprom->type == ixgbe_eeprom_uninitialized) { 906a14ee0cSDon Skidmore eeprom->semaphore_delay = 10; 916a14ee0cSDon Skidmore eeprom->type = ixgbe_flash; 926a14ee0cSDon Skidmore 939a900ecaSDon Skidmore eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 946a14ee0cSDon Skidmore eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 956a14ee0cSDon Skidmore IXGBE_EEC_SIZE_SHIFT); 966a14ee0cSDon Skidmore eeprom->word_size = 1 << (eeprom_size + 976a14ee0cSDon Skidmore IXGBE_EEPROM_WORD_SIZE_SHIFT); 986a14ee0cSDon Skidmore 996a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", 1006a14ee0cSDon Skidmore eeprom->type, eeprom->word_size); 1016a14ee0cSDon Skidmore } 1026a14ee0cSDon Skidmore 1036a14ee0cSDon Skidmore return 0; 1046a14ee0cSDon Skidmore } 1056a14ee0cSDon Skidmore 106ae14a1d8SMark Rustad /** 107ae14a1d8SMark Rustad * ixgbe_iosf_wait - Wait for IOSF command completion 108ae14a1d8SMark Rustad * @hw: pointer to hardware structure 109ae14a1d8SMark Rustad * @ctrl: pointer to location to receive final IOSF control value 110ae14a1d8SMark Rustad * 111ae14a1d8SMark Rustad * Return: failing status on timeout 112ae14a1d8SMark Rustad * 113ae14a1d8SMark Rustad * Note: ctrl can be NULL if the IOSF control register value is not needed 114ae14a1d8SMark Rustad */ 115ae14a1d8SMark Rustad static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) 116ae14a1d8SMark Rustad { 117ae14a1d8SMark Rustad u32 i, command; 118ae14a1d8SMark Rustad 119ae14a1d8SMark Rustad /* Check every 10 usec to see if the address cycle completed. 120ae14a1d8SMark Rustad * The SB IOSF BUSY bit will clear when the operation is 121ae14a1d8SMark Rustad * complete. 122ae14a1d8SMark Rustad */ 123ae14a1d8SMark Rustad for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { 124ae14a1d8SMark Rustad command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); 125ae14a1d8SMark Rustad if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) 126ae14a1d8SMark Rustad break; 127ae14a1d8SMark Rustad usleep_range(10, 20); 128ae14a1d8SMark Rustad } 129ae14a1d8SMark Rustad if (ctrl) 130ae14a1d8SMark Rustad *ctrl = command; 131ae14a1d8SMark Rustad if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { 132ae14a1d8SMark Rustad hw_dbg(hw, "IOSF wait timed out\n"); 133ae14a1d8SMark Rustad return IXGBE_ERR_PHY; 134ae14a1d8SMark Rustad } 135ae14a1d8SMark Rustad 136ae14a1d8SMark Rustad return 0; 137ae14a1d8SMark Rustad } 138ae14a1d8SMark Rustad 1396a14ee0cSDon Skidmore /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the 1406a14ee0cSDon Skidmore * IOSF device 1416a14ee0cSDon Skidmore * @hw: pointer to hardware structure 1426a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 1436a14ee0cSDon Skidmore * @device_type: 3 bit device type 1446a14ee0cSDon Skidmore * @phy_data: Pointer to read data from the register 1456a14ee0cSDon Skidmore **/ 1467ddbde3fSDon Skidmore static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 1476a14ee0cSDon Skidmore u32 device_type, u32 *data) 1486a14ee0cSDon Skidmore { 149ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 150ae14a1d8SMark Rustad u32 command, error; 151ae14a1d8SMark Rustad s32 ret; 152ae14a1d8SMark Rustad 153ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 154ae14a1d8SMark Rustad if (ret) 155ae14a1d8SMark Rustad return ret; 156ae14a1d8SMark Rustad 157ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 158ae14a1d8SMark Rustad if (ret) 159ae14a1d8SMark Rustad goto out; 1606a14ee0cSDon Skidmore 1616a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 1626a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 1636a14ee0cSDon Skidmore 1646a14ee0cSDon Skidmore /* Write IOSF control register */ 1656a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 1666a14ee0cSDon Skidmore 167ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 1686a14ee0cSDon Skidmore 1696a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 1706a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 1716a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 1726a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read, error %x\n", error); 1736a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 1746a14ee0cSDon Skidmore } 1756a14ee0cSDon Skidmore 176ae14a1d8SMark Rustad if (!ret) 1776a14ee0cSDon Skidmore *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); 1786a14ee0cSDon Skidmore 179ae14a1d8SMark Rustad out: 180ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 181ae14a1d8SMark Rustad return ret; 1826a14ee0cSDon Skidmore } 1836a14ee0cSDon Skidmore 1846a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface 1856a14ee0cSDon Skidmore * command assuming that the semaphore is already obtained. 1866a14ee0cSDon Skidmore * @hw: pointer to hardware structure 1876a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 1886a14ee0cSDon Skidmore * @data: word read from the EEPROM 1896a14ee0cSDon Skidmore * 1906a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 1916a14ee0cSDon Skidmore **/ 1927ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 1937ddbde3fSDon Skidmore u16 *data) 1946a14ee0cSDon Skidmore { 1956a14ee0cSDon Skidmore s32 status; 1966a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 1976a14ee0cSDon Skidmore 1986a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 1996a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 2006a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2016a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2026a14ee0cSDon Skidmore 2036a14ee0cSDon Skidmore /* convert offset from words to bytes */ 2046a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 2056a14ee0cSDon Skidmore /* one word */ 2066a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 2076a14ee0cSDon Skidmore 2086a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 2096a14ee0cSDon Skidmore sizeof(buffer), 2106a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 2116a14ee0cSDon Skidmore if (status) 2126a14ee0cSDon Skidmore return status; 2136a14ee0cSDon Skidmore 2146a14ee0cSDon Skidmore *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 2156a14ee0cSDon Skidmore FW_NVM_DATA_OFFSET); 2166a14ee0cSDon Skidmore 2176a14ee0cSDon Skidmore return 0; 2186a14ee0cSDon Skidmore } 2196a14ee0cSDon Skidmore 2206a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif 2216a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2226a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 2236a14ee0cSDon Skidmore * @words: number of words 2246a14ee0cSDon Skidmore * @data: word(s) read from the EEPROM 2256a14ee0cSDon Skidmore * 2266a14ee0cSDon Skidmore * Reads a 16 bit word(s) from the EEPROM using the hostif. 2276a14ee0cSDon Skidmore **/ 2287ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 2296a14ee0cSDon Skidmore u16 offset, u16 words, u16 *data) 2306a14ee0cSDon Skidmore { 2316a14ee0cSDon Skidmore struct ixgbe_hic_read_shadow_ram buffer; 2326a14ee0cSDon Skidmore u32 current_word = 0; 2336a14ee0cSDon Skidmore u16 words_to_read; 2346a14ee0cSDon Skidmore s32 status; 2356a14ee0cSDon Skidmore u32 i; 2366a14ee0cSDon Skidmore 2376a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 2386a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2396a14ee0cSDon Skidmore if (status) { 2406a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); 2416a14ee0cSDon Skidmore return status; 2426a14ee0cSDon Skidmore } 2436a14ee0cSDon Skidmore 2446a14ee0cSDon Skidmore while (words) { 2456a14ee0cSDon Skidmore if (words > FW_MAX_READ_BUFFER_SIZE / 2) 2466a14ee0cSDon Skidmore words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; 2476a14ee0cSDon Skidmore else 2486a14ee0cSDon Skidmore words_to_read = words; 2496a14ee0cSDon Skidmore 2506a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 2516a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 2526a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 2536a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2546a14ee0cSDon Skidmore 2556a14ee0cSDon Skidmore /* convert offset from words to bytes */ 2566a14ee0cSDon Skidmore buffer.address = cpu_to_be32((offset + current_word) * 2); 2576a14ee0cSDon Skidmore buffer.length = cpu_to_be16(words_to_read * 2); 2586a14ee0cSDon Skidmore 2596a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 2606a14ee0cSDon Skidmore sizeof(buffer), 2616a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, 2626a14ee0cSDon Skidmore false); 2636a14ee0cSDon Skidmore if (status) { 2646a14ee0cSDon Skidmore hw_dbg(hw, "Host interface command failed\n"); 2656a14ee0cSDon Skidmore goto out; 2666a14ee0cSDon Skidmore } 2676a14ee0cSDon Skidmore 2686a14ee0cSDon Skidmore for (i = 0; i < words_to_read; i++) { 2696a14ee0cSDon Skidmore u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 2706a14ee0cSDon Skidmore 2 * i; 2716a14ee0cSDon Skidmore u32 value = IXGBE_READ_REG(hw, reg); 2726a14ee0cSDon Skidmore 2736a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 2746a14ee0cSDon Skidmore current_word++; 2756a14ee0cSDon Skidmore i++; 2766a14ee0cSDon Skidmore if (i < words_to_read) { 2776a14ee0cSDon Skidmore value >>= 16; 2786a14ee0cSDon Skidmore data[current_word] = (u16)(value & 0xffff); 2796a14ee0cSDon Skidmore current_word++; 2806a14ee0cSDon Skidmore } 2816a14ee0cSDon Skidmore } 2826a14ee0cSDon Skidmore words -= words_to_read; 2836a14ee0cSDon Skidmore } 2846a14ee0cSDon Skidmore 2856a14ee0cSDon Skidmore out: 2866a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2876a14ee0cSDon Skidmore return status; 2886a14ee0cSDon Skidmore } 2896a14ee0cSDon Skidmore 2906a14ee0cSDon Skidmore /** ixgbe_checksum_ptr_x550 - Checksum one pointer region 2916a14ee0cSDon Skidmore * @hw: pointer to hardware structure 2926a14ee0cSDon Skidmore * @ptr: pointer offset in eeprom 2936a14ee0cSDon Skidmore * @size: size of section pointed by ptr, if 0 first word will be used as size 2946a14ee0cSDon Skidmore * @csum: address of checksum to update 2956a14ee0cSDon Skidmore * 2966a14ee0cSDon Skidmore * Returns error status for any failure 2976a14ee0cSDon Skidmore **/ 2986a14ee0cSDon Skidmore static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, 2996a14ee0cSDon Skidmore u16 size, u16 *csum, u16 *buffer, 3006a14ee0cSDon Skidmore u32 buffer_size) 3016a14ee0cSDon Skidmore { 3026a14ee0cSDon Skidmore u16 buf[256]; 3036a14ee0cSDon Skidmore s32 status; 3046a14ee0cSDon Skidmore u16 length, bufsz, i, start; 3056a14ee0cSDon Skidmore u16 *local_buffer; 3066a14ee0cSDon Skidmore 3076a14ee0cSDon Skidmore bufsz = sizeof(buf) / sizeof(buf[0]); 3086a14ee0cSDon Skidmore 3096a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 3106a14ee0cSDon Skidmore if (!buffer) { 3116a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); 3126a14ee0cSDon Skidmore if (status) { 3136a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3146a14ee0cSDon Skidmore return status; 3156a14ee0cSDon Skidmore } 3166a14ee0cSDon Skidmore local_buffer = buf; 3176a14ee0cSDon Skidmore } else { 3186a14ee0cSDon Skidmore if (buffer_size < ptr) 3196a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3206a14ee0cSDon Skidmore local_buffer = &buffer[ptr]; 3216a14ee0cSDon Skidmore } 3226a14ee0cSDon Skidmore 3236a14ee0cSDon Skidmore if (size) { 3246a14ee0cSDon Skidmore start = 0; 3256a14ee0cSDon Skidmore length = size; 3266a14ee0cSDon Skidmore } else { 3276a14ee0cSDon Skidmore start = 1; 3286a14ee0cSDon Skidmore length = local_buffer[0]; 3296a14ee0cSDon Skidmore 3306a14ee0cSDon Skidmore /* Skip pointer section if length is invalid. */ 3316a14ee0cSDon Skidmore if (length == 0xFFFF || length == 0 || 3326a14ee0cSDon Skidmore (ptr + length) >= hw->eeprom.word_size) 3336a14ee0cSDon Skidmore return 0; 3346a14ee0cSDon Skidmore } 3356a14ee0cSDon Skidmore 3366a14ee0cSDon Skidmore if (buffer && ((u32)start + (u32)length > buffer_size)) 3376a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3386a14ee0cSDon Skidmore 3396a14ee0cSDon Skidmore for (i = start; length; i++, length--) { 3406a14ee0cSDon Skidmore if (i == bufsz && !buffer) { 3416a14ee0cSDon Skidmore ptr += bufsz; 3426a14ee0cSDon Skidmore i = 0; 3436a14ee0cSDon Skidmore if (length < bufsz) 3446a14ee0cSDon Skidmore bufsz = length; 3456a14ee0cSDon Skidmore 3466a14ee0cSDon Skidmore /* Read a chunk at the pointer location */ 3476a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, 3486a14ee0cSDon Skidmore bufsz, buf); 3496a14ee0cSDon Skidmore if (status) { 3506a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3516a14ee0cSDon Skidmore return status; 3526a14ee0cSDon Skidmore } 3536a14ee0cSDon Skidmore } 3546a14ee0cSDon Skidmore *csum += local_buffer[i]; 3556a14ee0cSDon Skidmore } 3566a14ee0cSDon Skidmore return 0; 3576a14ee0cSDon Skidmore } 3586a14ee0cSDon Skidmore 3596a14ee0cSDon Skidmore /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum 3606a14ee0cSDon Skidmore * @hw: pointer to hardware structure 3616a14ee0cSDon Skidmore * @buffer: pointer to buffer containing calculated checksum 3626a14ee0cSDon Skidmore * @buffer_size: size of buffer 3636a14ee0cSDon Skidmore * 3646a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 3656a14ee0cSDon Skidmore **/ 3667ddbde3fSDon Skidmore static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, 3677ddbde3fSDon Skidmore u32 buffer_size) 3686a14ee0cSDon Skidmore { 3696a14ee0cSDon Skidmore u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; 3706a14ee0cSDon Skidmore u16 *local_buffer; 3716a14ee0cSDon Skidmore s32 status; 3726a14ee0cSDon Skidmore u16 checksum = 0; 3736a14ee0cSDon Skidmore u16 pointer, i, size; 3746a14ee0cSDon Skidmore 3756a14ee0cSDon Skidmore hw->eeprom.ops.init_params(hw); 3766a14ee0cSDon Skidmore 3776a14ee0cSDon Skidmore if (!buffer) { 3786a14ee0cSDon Skidmore /* Read pointer area */ 3796a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, 3806a14ee0cSDon Skidmore IXGBE_EEPROM_LAST_WORD + 1, 3816a14ee0cSDon Skidmore eeprom_ptrs); 3826a14ee0cSDon Skidmore if (status) { 3836a14ee0cSDon Skidmore hw_dbg(hw, "Failed to read EEPROM image\n"); 3846a14ee0cSDon Skidmore return status; 3856a14ee0cSDon Skidmore } 3866a14ee0cSDon Skidmore local_buffer = eeprom_ptrs; 3876a14ee0cSDon Skidmore } else { 3886a14ee0cSDon Skidmore if (buffer_size < IXGBE_EEPROM_LAST_WORD) 3896a14ee0cSDon Skidmore return IXGBE_ERR_PARAM; 3906a14ee0cSDon Skidmore local_buffer = buffer; 3916a14ee0cSDon Skidmore } 3926a14ee0cSDon Skidmore 3936a14ee0cSDon Skidmore /* For X550 hardware include 0x0-0x41 in the checksum, skip the 3946a14ee0cSDon Skidmore * checksum word itself 3956a14ee0cSDon Skidmore */ 3966a14ee0cSDon Skidmore for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) 3976a14ee0cSDon Skidmore if (i != IXGBE_EEPROM_CHECKSUM) 3986a14ee0cSDon Skidmore checksum += local_buffer[i]; 3996a14ee0cSDon Skidmore 4006a14ee0cSDon Skidmore /* Include all data from pointers 0x3, 0x6-0xE. This excludes the 4016a14ee0cSDon Skidmore * FW, PHY module, and PCIe Expansion/Option ROM pointers. 4026a14ee0cSDon Skidmore */ 4036a14ee0cSDon Skidmore for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { 4046a14ee0cSDon Skidmore if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) 4056a14ee0cSDon Skidmore continue; 4066a14ee0cSDon Skidmore 4076a14ee0cSDon Skidmore pointer = local_buffer[i]; 4086a14ee0cSDon Skidmore 4096a14ee0cSDon Skidmore /* Skip pointer section if the pointer is invalid. */ 4106a14ee0cSDon Skidmore if (pointer == 0xFFFF || pointer == 0 || 4116a14ee0cSDon Skidmore pointer >= hw->eeprom.word_size) 4126a14ee0cSDon Skidmore continue; 4136a14ee0cSDon Skidmore 4146a14ee0cSDon Skidmore switch (i) { 4156a14ee0cSDon Skidmore case IXGBE_PCIE_GENERAL_PTR: 4166a14ee0cSDon Skidmore size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; 4176a14ee0cSDon Skidmore break; 4186a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG0_PTR: 4196a14ee0cSDon Skidmore case IXGBE_PCIE_CONFIG1_PTR: 4206a14ee0cSDon Skidmore size = IXGBE_PCIE_CONFIG_SIZE; 4216a14ee0cSDon Skidmore break; 4226a14ee0cSDon Skidmore default: 4236a14ee0cSDon Skidmore size = 0; 4246a14ee0cSDon Skidmore break; 4256a14ee0cSDon Skidmore } 4266a14ee0cSDon Skidmore 4276a14ee0cSDon Skidmore status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, 4286a14ee0cSDon Skidmore buffer, buffer_size); 4296a14ee0cSDon Skidmore if (status) 4306a14ee0cSDon Skidmore return status; 4316a14ee0cSDon Skidmore } 4326a14ee0cSDon Skidmore 4336a14ee0cSDon Skidmore checksum = (u16)IXGBE_EEPROM_SUM - checksum; 4346a14ee0cSDon Skidmore 4356a14ee0cSDon Skidmore return (s32)checksum; 4366a14ee0cSDon Skidmore } 4376a14ee0cSDon Skidmore 4386a14ee0cSDon Skidmore /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum 4396a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4406a14ee0cSDon Skidmore * 4416a14ee0cSDon Skidmore * Returns a negative error code on error, or the 16-bit checksum 4426a14ee0cSDon Skidmore **/ 4437ddbde3fSDon Skidmore static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) 4446a14ee0cSDon Skidmore { 4456a14ee0cSDon Skidmore return ixgbe_calc_checksum_X550(hw, NULL, 0); 4466a14ee0cSDon Skidmore } 4476a14ee0cSDon Skidmore 4486a14ee0cSDon Skidmore /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command 4496a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4506a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to read 4516a14ee0cSDon Skidmore * @data: word read from the EEPROM 4526a14ee0cSDon Skidmore * 4536a14ee0cSDon Skidmore * Reads a 16 bit word from the EEPROM using the hostif. 4546a14ee0cSDon Skidmore **/ 4557ddbde3fSDon Skidmore static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) 4566a14ee0cSDon Skidmore { 4576a14ee0cSDon Skidmore s32 status = 0; 4586a14ee0cSDon Skidmore 4596a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 4606a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); 4616a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 4626a14ee0cSDon Skidmore } else { 4636a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 4646a14ee0cSDon Skidmore } 4656a14ee0cSDon Skidmore 4666a14ee0cSDon Skidmore return status; 4676a14ee0cSDon Skidmore } 4686a14ee0cSDon Skidmore 4696a14ee0cSDon Skidmore /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum 4706a14ee0cSDon Skidmore * @hw: pointer to hardware structure 4716a14ee0cSDon Skidmore * @checksum_val: calculated checksum 4726a14ee0cSDon Skidmore * 4736a14ee0cSDon Skidmore * Performs checksum calculation and validates the EEPROM checksum. If the 4746a14ee0cSDon Skidmore * caller does not need checksum_val, the value can be NULL. 4756a14ee0cSDon Skidmore **/ 4767ddbde3fSDon Skidmore static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, 4777ddbde3fSDon Skidmore u16 *checksum_val) 4786a14ee0cSDon Skidmore { 4796a14ee0cSDon Skidmore s32 status; 4806a14ee0cSDon Skidmore u16 checksum; 4816a14ee0cSDon Skidmore u16 read_checksum = 0; 4826a14ee0cSDon Skidmore 4836a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 4846a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 4856a14ee0cSDon Skidmore * EEPROM read fails 4866a14ee0cSDon Skidmore */ 4876a14ee0cSDon Skidmore status = hw->eeprom.ops.read(hw, 0, &checksum); 4886a14ee0cSDon Skidmore if (status) { 4896a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 4906a14ee0cSDon Skidmore return status; 4916a14ee0cSDon Skidmore } 4926a14ee0cSDon Skidmore 4936a14ee0cSDon Skidmore status = hw->eeprom.ops.calc_checksum(hw); 4946a14ee0cSDon Skidmore if (status < 0) 4956a14ee0cSDon Skidmore return status; 4966a14ee0cSDon Skidmore 4976a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 4986a14ee0cSDon Skidmore 4996a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 5006a14ee0cSDon Skidmore &read_checksum); 5016a14ee0cSDon Skidmore if (status) 5026a14ee0cSDon Skidmore return status; 5036a14ee0cSDon Skidmore 5046a14ee0cSDon Skidmore /* Verify read checksum from EEPROM is the same as 5056a14ee0cSDon Skidmore * calculated checksum 5066a14ee0cSDon Skidmore */ 5076a14ee0cSDon Skidmore if (read_checksum != checksum) { 5086a14ee0cSDon Skidmore status = IXGBE_ERR_EEPROM_CHECKSUM; 5096a14ee0cSDon Skidmore hw_dbg(hw, "Invalid EEPROM checksum"); 5106a14ee0cSDon Skidmore } 5116a14ee0cSDon Skidmore 5126a14ee0cSDon Skidmore /* If the user cares, return the calculated checksum */ 5136a14ee0cSDon Skidmore if (checksum_val) 5146a14ee0cSDon Skidmore *checksum_val = checksum; 5156a14ee0cSDon Skidmore 5166a14ee0cSDon Skidmore return status; 5176a14ee0cSDon Skidmore } 5186a14ee0cSDon Skidmore 5196a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 5206a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5216a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 5226a14ee0cSDon Skidmore * @data: word write to the EEPROM 5236a14ee0cSDon Skidmore * 5246a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 5256a14ee0cSDon Skidmore **/ 5267ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, 5277ddbde3fSDon Skidmore u16 data) 5286a14ee0cSDon Skidmore { 5296a14ee0cSDon Skidmore s32 status; 5306a14ee0cSDon Skidmore struct ixgbe_hic_write_shadow_ram buffer; 5316a14ee0cSDon Skidmore 5326a14ee0cSDon Skidmore buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 5336a14ee0cSDon Skidmore buffer.hdr.req.buf_lenh = 0; 5346a14ee0cSDon Skidmore buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 5356a14ee0cSDon Skidmore buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 5366a14ee0cSDon Skidmore 5376a14ee0cSDon Skidmore /* one word */ 5386a14ee0cSDon Skidmore buffer.length = cpu_to_be16(sizeof(u16)); 5396a14ee0cSDon Skidmore buffer.data = data; 5406a14ee0cSDon Skidmore buffer.address = cpu_to_be32(offset * 2); 5416a14ee0cSDon Skidmore 5426a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 5436a14ee0cSDon Skidmore sizeof(buffer), 5446a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5456a14ee0cSDon Skidmore return status; 5466a14ee0cSDon Skidmore } 5476a14ee0cSDon Skidmore 5486a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif 5496a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5506a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 5516a14ee0cSDon Skidmore * @data: word write to the EEPROM 5526a14ee0cSDon Skidmore * 5536a14ee0cSDon Skidmore * Write a 16 bit word to the EEPROM using the hostif. 5546a14ee0cSDon Skidmore **/ 5557ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) 5566a14ee0cSDon Skidmore { 5576a14ee0cSDon Skidmore s32 status = 0; 5586a14ee0cSDon Skidmore 5596a14ee0cSDon Skidmore if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { 5606a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); 5616a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 5626a14ee0cSDon Skidmore } else { 5636a14ee0cSDon Skidmore hw_dbg(hw, "write ee hostif failed to get semaphore"); 5646a14ee0cSDon Skidmore status = IXGBE_ERR_SWFW_SYNC; 5656a14ee0cSDon Skidmore } 5666a14ee0cSDon Skidmore 5676a14ee0cSDon Skidmore return status; 5686a14ee0cSDon Skidmore } 5696a14ee0cSDon Skidmore 5706a14ee0cSDon Skidmore /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device 5716a14ee0cSDon Skidmore * @hw: pointer to hardware structure 5726a14ee0cSDon Skidmore * 5736a14ee0cSDon Skidmore * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. 5746a14ee0cSDon Skidmore **/ 5757ddbde3fSDon Skidmore static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) 5766a14ee0cSDon Skidmore { 5776a14ee0cSDon Skidmore s32 status = 0; 5786a14ee0cSDon Skidmore union ixgbe_hic_hdr2 buffer; 5796a14ee0cSDon Skidmore 5806a14ee0cSDon Skidmore buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; 5816a14ee0cSDon Skidmore buffer.req.buf_lenh = 0; 5826a14ee0cSDon Skidmore buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; 5836a14ee0cSDon Skidmore buffer.req.checksum = FW_DEFAULT_CHECKSUM; 5846a14ee0cSDon Skidmore 5856a14ee0cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&buffer, 5866a14ee0cSDon Skidmore sizeof(buffer), 5876a14ee0cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, false); 5886a14ee0cSDon Skidmore return status; 5896a14ee0cSDon Skidmore } 5906a14ee0cSDon Skidmore 5911f9ac57cSDon Skidmore /** ixgbe_disable_rx_x550 - Disable RX unit 5921f9ac57cSDon Skidmore * 5931f9ac57cSDon Skidmore * Enables the Rx DMA unit for x550 5941f9ac57cSDon Skidmore **/ 5951f9ac57cSDon Skidmore static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) 5961f9ac57cSDon Skidmore { 5971f9ac57cSDon Skidmore u32 rxctrl, pfdtxgswc; 5981f9ac57cSDon Skidmore s32 status; 5991f9ac57cSDon Skidmore struct ixgbe_hic_disable_rxen fw_cmd; 6001f9ac57cSDon Skidmore 6011f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 6021f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 6031f9ac57cSDon Skidmore pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 6041f9ac57cSDon Skidmore if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 6051f9ac57cSDon Skidmore pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 6061f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 6071f9ac57cSDon Skidmore hw->mac.set_lben = true; 6081f9ac57cSDon Skidmore } else { 6091f9ac57cSDon Skidmore hw->mac.set_lben = false; 6101f9ac57cSDon Skidmore } 6111f9ac57cSDon Skidmore 6121f9ac57cSDon Skidmore fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; 6131f9ac57cSDon Skidmore fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; 6141f9ac57cSDon Skidmore fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; 6151f9ac57cSDon Skidmore fw_cmd.port_number = (u8)hw->bus.lan_id; 6161f9ac57cSDon Skidmore 6171f9ac57cSDon Skidmore status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 6181f9ac57cSDon Skidmore sizeof(struct ixgbe_hic_disable_rxen), 6191f9ac57cSDon Skidmore IXGBE_HI_COMMAND_TIMEOUT, true); 6201f9ac57cSDon Skidmore 6211f9ac57cSDon Skidmore /* If we fail - disable RX using register write */ 6221f9ac57cSDon Skidmore if (status) { 6231f9ac57cSDon Skidmore rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 6241f9ac57cSDon Skidmore if (rxctrl & IXGBE_RXCTRL_RXEN) { 6251f9ac57cSDon Skidmore rxctrl &= ~IXGBE_RXCTRL_RXEN; 6261f9ac57cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 6271f9ac57cSDon Skidmore } 6281f9ac57cSDon Skidmore } 6291f9ac57cSDon Skidmore } 6301f9ac57cSDon Skidmore } 6311f9ac57cSDon Skidmore 6326a14ee0cSDon Skidmore /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash 6336a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6346a14ee0cSDon Skidmore * 6356a14ee0cSDon Skidmore * After writing EEPROM to shadow RAM using EEWR register, software calculates 6366a14ee0cSDon Skidmore * checksum and updates the EEPROM and instructs the hardware to update 6376a14ee0cSDon Skidmore * the flash. 6386a14ee0cSDon Skidmore **/ 6397ddbde3fSDon Skidmore static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) 6406a14ee0cSDon Skidmore { 6416a14ee0cSDon Skidmore s32 status; 6426a14ee0cSDon Skidmore u16 checksum = 0; 6436a14ee0cSDon Skidmore 6446a14ee0cSDon Skidmore /* Read the first word from the EEPROM. If this times out or fails, do 6456a14ee0cSDon Skidmore * not continue or we could be in for a very long wait while every 6466a14ee0cSDon Skidmore * EEPROM read fails 6476a14ee0cSDon Skidmore */ 6486a14ee0cSDon Skidmore status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); 6496a14ee0cSDon Skidmore if (status) { 6506a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM read failed\n"); 6516a14ee0cSDon Skidmore return status; 6526a14ee0cSDon Skidmore } 6536a14ee0cSDon Skidmore 6546a14ee0cSDon Skidmore status = ixgbe_calc_eeprom_checksum_X550(hw); 6556a14ee0cSDon Skidmore if (status < 0) 6566a14ee0cSDon Skidmore return status; 6576a14ee0cSDon Skidmore 6586a14ee0cSDon Skidmore checksum = (u16)(status & 0xffff); 6596a14ee0cSDon Skidmore 6606a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, 6616a14ee0cSDon Skidmore checksum); 6626a14ee0cSDon Skidmore if (status) 6636a14ee0cSDon Skidmore return status; 6646a14ee0cSDon Skidmore 6656a14ee0cSDon Skidmore status = ixgbe_update_flash_X550(hw); 6666a14ee0cSDon Skidmore 6676a14ee0cSDon Skidmore return status; 6686a14ee0cSDon Skidmore } 6696a14ee0cSDon Skidmore 6706a14ee0cSDon Skidmore /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif 6716a14ee0cSDon Skidmore * @hw: pointer to hardware structure 6726a14ee0cSDon Skidmore * @offset: offset of word in the EEPROM to write 6736a14ee0cSDon Skidmore * @words: number of words 6746a14ee0cSDon Skidmore * @data: word(s) write to the EEPROM 6756a14ee0cSDon Skidmore * 6766a14ee0cSDon Skidmore * 6776a14ee0cSDon Skidmore * Write a 16 bit word(s) to the EEPROM using the hostif. 6786a14ee0cSDon Skidmore **/ 6797ddbde3fSDon Skidmore static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, 6807ddbde3fSDon Skidmore u16 offset, u16 words, 6817ddbde3fSDon Skidmore u16 *data) 6826a14ee0cSDon Skidmore { 6836a14ee0cSDon Skidmore s32 status = 0; 6846a14ee0cSDon Skidmore u32 i = 0; 6856a14ee0cSDon Skidmore 6866a14ee0cSDon Skidmore /* Take semaphore for the entire operation. */ 6876a14ee0cSDon Skidmore status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 6886a14ee0cSDon Skidmore if (status) { 6896a14ee0cSDon Skidmore hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); 6906a14ee0cSDon Skidmore return status; 6916a14ee0cSDon Skidmore } 6926a14ee0cSDon Skidmore 6936a14ee0cSDon Skidmore for (i = 0; i < words; i++) { 6946a14ee0cSDon Skidmore status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, 6956a14ee0cSDon Skidmore data[i]); 6966a14ee0cSDon Skidmore if (status) { 6976a14ee0cSDon Skidmore hw_dbg(hw, "Eeprom buffered write failed\n"); 6986a14ee0cSDon Skidmore break; 6996a14ee0cSDon Skidmore } 7006a14ee0cSDon Skidmore } 7016a14ee0cSDon Skidmore 7026a14ee0cSDon Skidmore hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 7036a14ee0cSDon Skidmore 7046a14ee0cSDon Skidmore return status; 7056a14ee0cSDon Skidmore } 7066a14ee0cSDon Skidmore 7076a14ee0cSDon Skidmore /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers 7086a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7096a14ee0cSDon Skidmore **/ 7107ddbde3fSDon Skidmore static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) 7116a14ee0cSDon Skidmore { 7126a14ee0cSDon Skidmore struct ixgbe_mac_info *mac = &hw->mac; 7136a14ee0cSDon Skidmore 7146a14ee0cSDon Skidmore /* CS4227 does not support autoneg, so disable the laser control 7156a14ee0cSDon Skidmore * functions for SFP+ fiber 7166a14ee0cSDon Skidmore */ 7176a14ee0cSDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) { 7186a14ee0cSDon Skidmore mac->ops.disable_tx_laser = NULL; 7196a14ee0cSDon Skidmore mac->ops.enable_tx_laser = NULL; 7206a14ee0cSDon Skidmore mac->ops.flap_tx_laser = NULL; 7216a14ee0cSDon Skidmore } 7226a14ee0cSDon Skidmore } 7236a14ee0cSDon Skidmore 7246a14ee0cSDon Skidmore /** ixgbe_setup_sfp_modules_X550em - Setup SFP module 7256a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7266a14ee0cSDon Skidmore */ 7277ddbde3fSDon Skidmore static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) 7286a14ee0cSDon Skidmore { 7296a14ee0cSDon Skidmore bool setup_linear; 7306a14ee0cSDon Skidmore u16 reg_slice, edc_mode; 7316a14ee0cSDon Skidmore s32 ret_val; 7326a14ee0cSDon Skidmore 7336a14ee0cSDon Skidmore switch (hw->phy.sfp_type) { 7346a14ee0cSDon Skidmore case ixgbe_sfp_type_unknown: 7356a14ee0cSDon Skidmore return 0; 7366a14ee0cSDon Skidmore case ixgbe_sfp_type_not_present: 7376a14ee0cSDon Skidmore return IXGBE_ERR_SFP_NOT_PRESENT; 7386a14ee0cSDon Skidmore case ixgbe_sfp_type_da_cu_core0: 7396a14ee0cSDon Skidmore case ixgbe_sfp_type_da_cu_core1: 7406a14ee0cSDon Skidmore setup_linear = true; 7416a14ee0cSDon Skidmore break; 7426a14ee0cSDon Skidmore case ixgbe_sfp_type_srlr_core0: 7436a14ee0cSDon Skidmore case ixgbe_sfp_type_srlr_core1: 7446a14ee0cSDon Skidmore case ixgbe_sfp_type_da_act_lmt_core0: 7456a14ee0cSDon Skidmore case ixgbe_sfp_type_da_act_lmt_core1: 7466a14ee0cSDon Skidmore case ixgbe_sfp_type_1g_sx_core0: 7476a14ee0cSDon Skidmore case ixgbe_sfp_type_1g_sx_core1: 7486a14ee0cSDon Skidmore setup_linear = false; 7496a14ee0cSDon Skidmore break; 7506a14ee0cSDon Skidmore default: 7516a14ee0cSDon Skidmore return IXGBE_ERR_SFP_NOT_SUPPORTED; 7526a14ee0cSDon Skidmore } 7536a14ee0cSDon Skidmore 7546a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 7556a14ee0cSDon Skidmore hw->phy.ops.reset = NULL; 7566a14ee0cSDon Skidmore 7576a14ee0cSDon Skidmore /* The CS4227 slice address is the base address + the port-pair reg 7586a14ee0cSDon Skidmore * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0. 7596a14ee0cSDon Skidmore */ 7606a14ee0cSDon Skidmore reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12); 7616a14ee0cSDon Skidmore 7626a14ee0cSDon Skidmore if (setup_linear) 7636a14ee0cSDon Skidmore edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; 7646a14ee0cSDon Skidmore else 7656a14ee0cSDon Skidmore edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; 7666a14ee0cSDon Skidmore 7676a14ee0cSDon Skidmore /* Configure CS4227 for connection type. */ 7686a14ee0cSDon Skidmore ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice, 7696a14ee0cSDon Skidmore edc_mode); 7706a14ee0cSDon Skidmore 7716a14ee0cSDon Skidmore if (ret_val) 7726a14ee0cSDon Skidmore ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice, 7736a14ee0cSDon Skidmore edc_mode); 7746a14ee0cSDon Skidmore 7756a14ee0cSDon Skidmore return ret_val; 7766a14ee0cSDon Skidmore } 7776a14ee0cSDon Skidmore 7786a14ee0cSDon Skidmore /** ixgbe_get_link_capabilities_x550em - Determines link capabilities 7796a14ee0cSDon Skidmore * @hw: pointer to hardware structure 7806a14ee0cSDon Skidmore * @speed: pointer to link speed 7816a14ee0cSDon Skidmore * @autoneg: true when autoneg or autotry is enabled 7826a14ee0cSDon Skidmore **/ 7837ddbde3fSDon Skidmore static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, 7846a14ee0cSDon Skidmore ixgbe_link_speed *speed, 7856a14ee0cSDon Skidmore bool *autoneg) 7866a14ee0cSDon Skidmore { 7876a14ee0cSDon Skidmore /* SFP */ 7886a14ee0cSDon Skidmore if (hw->phy.media_type == ixgbe_media_type_fiber) { 7896a14ee0cSDon Skidmore /* CS4227 SFP must not enable auto-negotiation */ 7906a14ee0cSDon Skidmore *autoneg = false; 7916a14ee0cSDon Skidmore 7926a14ee0cSDon Skidmore if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || 7936a14ee0cSDon Skidmore hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { 7946a14ee0cSDon Skidmore *speed = IXGBE_LINK_SPEED_1GB_FULL; 7956a14ee0cSDon Skidmore return 0; 7966a14ee0cSDon Skidmore } 7976a14ee0cSDon Skidmore 7986a14ee0cSDon Skidmore /* Link capabilities are based on SFP */ 7996a14ee0cSDon Skidmore if (hw->phy.multispeed_fiber) 8006a14ee0cSDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 8016a14ee0cSDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 8026a14ee0cSDon Skidmore else 8036a14ee0cSDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL; 8046a14ee0cSDon Skidmore } else { 8056a14ee0cSDon Skidmore *speed = IXGBE_LINK_SPEED_10GB_FULL | 8066a14ee0cSDon Skidmore IXGBE_LINK_SPEED_1GB_FULL; 8076a14ee0cSDon Skidmore *autoneg = true; 8086a14ee0cSDon Skidmore } 8096a14ee0cSDon Skidmore return 0; 8106a14ee0cSDon Skidmore } 8116a14ee0cSDon Skidmore 8126a14ee0cSDon Skidmore /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the 8136a14ee0cSDon Skidmore * IOSF device 8146a14ee0cSDon Skidmore * 8156a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8166a14ee0cSDon Skidmore * @reg_addr: 32 bit PHY register to write 8176a14ee0cSDon Skidmore * @device_type: 3 bit device type 8186a14ee0cSDon Skidmore * @data: Data to write to the register 8196a14ee0cSDon Skidmore **/ 8207ddbde3fSDon Skidmore static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, 8216a14ee0cSDon Skidmore u32 device_type, u32 data) 8226a14ee0cSDon Skidmore { 823ae14a1d8SMark Rustad u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; 824ae14a1d8SMark Rustad u32 command, error; 825ae14a1d8SMark Rustad s32 ret; 826ae14a1d8SMark Rustad 827ae14a1d8SMark Rustad ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); 828ae14a1d8SMark Rustad if (ret) 829ae14a1d8SMark Rustad return ret; 830ae14a1d8SMark Rustad 831ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, NULL); 832ae14a1d8SMark Rustad if (ret) 833ae14a1d8SMark Rustad goto out; 8346a14ee0cSDon Skidmore 8356a14ee0cSDon Skidmore command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | 8366a14ee0cSDon Skidmore (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); 8376a14ee0cSDon Skidmore 8386a14ee0cSDon Skidmore /* Write IOSF control register */ 8396a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); 8406a14ee0cSDon Skidmore 8416a14ee0cSDon Skidmore /* Write IOSF data register */ 8426a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); 8436a14ee0cSDon Skidmore 844ae14a1d8SMark Rustad ret = ixgbe_iosf_wait(hw, &command); 8456a14ee0cSDon Skidmore 8466a14ee0cSDon Skidmore if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { 8476a14ee0cSDon Skidmore error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> 8486a14ee0cSDon Skidmore IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; 8496a14ee0cSDon Skidmore hw_dbg(hw, "Failed to write, error %x\n", error); 8506a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 8516a14ee0cSDon Skidmore } 8526a14ee0cSDon Skidmore 853ae14a1d8SMark Rustad out: 854ae14a1d8SMark Rustad hw->mac.ops.release_swfw_sync(hw, gssr); 855ae14a1d8SMark Rustad return ret; 8566a14ee0cSDon Skidmore } 8576a14ee0cSDon Skidmore 8586a14ee0cSDon Skidmore /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. 8596a14ee0cSDon Skidmore * @hw: pointer to hardware structure 8606a14ee0cSDon Skidmore * @speed: the link speed to force 8616a14ee0cSDon Skidmore * 8626a14ee0cSDon Skidmore * Configures the integrated KR PHY to use iXFI mode. Used to connect an 8636a14ee0cSDon Skidmore * internal and external PHY at a specific speed, without autonegotiation. 8646a14ee0cSDon Skidmore **/ 8656a14ee0cSDon Skidmore static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) 8666a14ee0cSDon Skidmore { 8676a14ee0cSDon Skidmore s32 status; 8686a14ee0cSDon Skidmore u32 reg_val; 8696a14ee0cSDon Skidmore 8706a14ee0cSDon Skidmore /* Disable AN and force speed to 10G Serial. */ 8716a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 8726a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 8736a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 8746a14ee0cSDon Skidmore if (status) 8756a14ee0cSDon Skidmore return status; 8766a14ee0cSDon Skidmore 8776a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 8786a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; 8796a14ee0cSDon Skidmore 8806a14ee0cSDon Skidmore /* Select forced link speed for internal PHY. */ 8816a14ee0cSDon Skidmore switch (*speed) { 8826a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_10GB_FULL: 8836a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; 8846a14ee0cSDon Skidmore break; 8856a14ee0cSDon Skidmore case IXGBE_LINK_SPEED_1GB_FULL: 8866a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; 8876a14ee0cSDon Skidmore break; 8886a14ee0cSDon Skidmore default: 8896a14ee0cSDon Skidmore /* Other link speeds are not supported by internal KR PHY. */ 8906a14ee0cSDon Skidmore return IXGBE_ERR_LINK_SETUP; 8916a14ee0cSDon Skidmore } 8926a14ee0cSDon Skidmore 8936a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 8946a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 8956a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 8966a14ee0cSDon Skidmore if (status) 8976a14ee0cSDon Skidmore return status; 8986a14ee0cSDon Skidmore 8996a14ee0cSDon Skidmore /* Disable training protocol FSM. */ 9006a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 9016a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 9026a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 9036a14ee0cSDon Skidmore if (status) 9046a14ee0cSDon Skidmore return status; 9056a14ee0cSDon Skidmore 9066a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; 9076a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 9086a14ee0cSDon Skidmore IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), 9096a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 9106a14ee0cSDon Skidmore if (status) 9116a14ee0cSDon Skidmore return status; 9126a14ee0cSDon Skidmore 9136a14ee0cSDon Skidmore /* Disable Flex from training TXFFE. */ 9146a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 9156a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 9166a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 9176a14ee0cSDon Skidmore if (status) 9186a14ee0cSDon Skidmore return status; 9196a14ee0cSDon Skidmore 9206a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 9216a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 9226a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 9236a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 9246a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), 9256a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 9266a14ee0cSDon Skidmore if (status) 9276a14ee0cSDon Skidmore return status; 9286a14ee0cSDon Skidmore 9296a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 9306a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 9316a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 9326a14ee0cSDon Skidmore if (status) 9336a14ee0cSDon Skidmore return status; 9346a14ee0cSDon Skidmore 9356a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; 9366a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; 9376a14ee0cSDon Skidmore reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; 9386a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 9396a14ee0cSDon Skidmore IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), 9406a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 9416a14ee0cSDon Skidmore if (status) 9426a14ee0cSDon Skidmore return status; 9436a14ee0cSDon Skidmore 9446a14ee0cSDon Skidmore /* Enable override for coefficients. */ 9456a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 9466a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 9476a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 9486a14ee0cSDon Skidmore if (status) 9496a14ee0cSDon Skidmore return status; 9506a14ee0cSDon Skidmore 9516a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; 9526a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; 9536a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; 9546a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; 9556a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 9566a14ee0cSDon Skidmore IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), 9576a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 9586a14ee0cSDon Skidmore if (status) 9596a14ee0cSDon Skidmore return status; 9606a14ee0cSDon Skidmore 9616a14ee0cSDon Skidmore /* Toggle port SW reset by AN reset. */ 9626a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 9636a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 9646a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 9656a14ee0cSDon Skidmore if (status) 9666a14ee0cSDon Skidmore return status; 9676a14ee0cSDon Skidmore 9686a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 9696a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 9706a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 9716a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 9726a14ee0cSDon Skidmore 9736a14ee0cSDon Skidmore return status; 9746a14ee0cSDon Skidmore } 9756a14ee0cSDon Skidmore 9766a14ee0cSDon Skidmore /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. 9776a14ee0cSDon Skidmore * @hw: pointer to hardware structure 9786a14ee0cSDon Skidmore * 9796a14ee0cSDon Skidmore * Configures the integrated KX4 PHY. 9806a14ee0cSDon Skidmore **/ 9817ddbde3fSDon Skidmore static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) 9826a14ee0cSDon Skidmore { 9836a14ee0cSDon Skidmore s32 status; 9846a14ee0cSDon Skidmore u32 reg_val; 9856a14ee0cSDon Skidmore 9866a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 9876a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 9886a14ee0cSDon Skidmore hw->bus.lan_id, ®_val); 9896a14ee0cSDon Skidmore if (status) 9906a14ee0cSDon Skidmore return status; 9916a14ee0cSDon Skidmore 9926a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | 9936a14ee0cSDon Skidmore IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); 9946a14ee0cSDon Skidmore 9956a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; 9966a14ee0cSDon Skidmore 9976a14ee0cSDon Skidmore /* Advertise 10G support. */ 9986a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 9996a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; 10006a14ee0cSDon Skidmore 10016a14ee0cSDon Skidmore /* Advertise 1G support. */ 10026a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 10036a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; 10046a14ee0cSDon Skidmore 10056a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 10066a14ee0cSDon Skidmore reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; 10076a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, 10086a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KX4_PCS0 + 10096a14ee0cSDon Skidmore hw->bus.lan_id, reg_val); 10106a14ee0cSDon Skidmore 10116a14ee0cSDon Skidmore return status; 10126a14ee0cSDon Skidmore } 10136a14ee0cSDon Skidmore 10146a14ee0cSDon Skidmore /** ixgbe_setup_kr_x550em - Configure the KR PHY. 10156a14ee0cSDon Skidmore * @hw: pointer to hardware structure 10166a14ee0cSDon Skidmore * 10176a14ee0cSDon Skidmore * Configures the integrated KR PHY. 10186a14ee0cSDon Skidmore **/ 10197ddbde3fSDon Skidmore static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) 10206a14ee0cSDon Skidmore { 10216a14ee0cSDon Skidmore s32 status; 10226a14ee0cSDon Skidmore u32 reg_val; 10236a14ee0cSDon Skidmore 10246a14ee0cSDon Skidmore status = ixgbe_read_iosf_sb_reg_x550(hw, 10256a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 10266a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); 10276a14ee0cSDon Skidmore if (status) 10286a14ee0cSDon Skidmore return status; 10296a14ee0cSDon Skidmore 10306a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; 10316a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ; 10326a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC; 10336a14ee0cSDon Skidmore reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | 10346a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); 10356a14ee0cSDon Skidmore 10366a14ee0cSDon Skidmore /* Advertise 10G support. */ 10376a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 10386a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; 10396a14ee0cSDon Skidmore 10406a14ee0cSDon Skidmore /* Advertise 1G support. */ 10416a14ee0cSDon Skidmore if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) 10426a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; 10436a14ee0cSDon Skidmore 10446a14ee0cSDon Skidmore /* Restart auto-negotiation. */ 10456a14ee0cSDon Skidmore reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; 10466a14ee0cSDon Skidmore status = ixgbe_write_iosf_sb_reg_x550(hw, 10476a14ee0cSDon Skidmore IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), 10486a14ee0cSDon Skidmore IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); 10496a14ee0cSDon Skidmore 10506a14ee0cSDon Skidmore return status; 10516a14ee0cSDon Skidmore } 10526a14ee0cSDon Skidmore 10536a14ee0cSDon Skidmore /** ixgbe_setup_internal_phy_x550em - Configure integrated KR PHY 10546a14ee0cSDon Skidmore * @hw: point to hardware structure 10556a14ee0cSDon Skidmore * 10566a14ee0cSDon Skidmore * Configures the integrated KR PHY to talk to the external PHY. The base 10576a14ee0cSDon Skidmore * driver will call this function when it gets notification via interrupt from 10586a14ee0cSDon Skidmore * the external PHY. This function forces the internal PHY into iXFI mode at 10596a14ee0cSDon Skidmore * the correct speed. 10606a14ee0cSDon Skidmore * 10616a14ee0cSDon Skidmore * A return of a non-zero value indicates an error, and the base driver should 10626a14ee0cSDon Skidmore * not report link up. 10636a14ee0cSDon Skidmore **/ 10647ddbde3fSDon Skidmore static s32 ixgbe_setup_internal_phy_x550em(struct ixgbe_hw *hw) 10656a14ee0cSDon Skidmore { 1066a1e869deSMark Rustad s32 status; 10676a14ee0cSDon Skidmore u16 lasi, autoneg_status, speed; 10686a14ee0cSDon Skidmore ixgbe_link_speed force_speed; 10696a14ee0cSDon Skidmore 10706a14ee0cSDon Skidmore /* Verify that the external link status has changed */ 10716a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_XENPAK_LASI_STATUS, 10726a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, &lasi); 10736a14ee0cSDon Skidmore if (status) 10746a14ee0cSDon Skidmore return status; 10756a14ee0cSDon Skidmore 10766a14ee0cSDon Skidmore /* If there was no change in link status, we can just exit */ 10776a14ee0cSDon Skidmore if (!(lasi & IXGBE_XENPAK_LASI_LINK_STATUS_ALARM)) 10786a14ee0cSDon Skidmore return 0; 10796a14ee0cSDon Skidmore 10806a14ee0cSDon Skidmore /* we read this twice back to back to indicate current status */ 10816a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 10826a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 10836a14ee0cSDon Skidmore &autoneg_status); 10846a14ee0cSDon Skidmore if (status) 10856a14ee0cSDon Skidmore return status; 10866a14ee0cSDon Skidmore 10876a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, 10886a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 10896a14ee0cSDon Skidmore &autoneg_status); 10906a14ee0cSDon Skidmore if (status) 10916a14ee0cSDon Skidmore return status; 10926a14ee0cSDon Skidmore 10936a14ee0cSDon Skidmore /* If link is not up return an error indicating treat link as down */ 10946a14ee0cSDon Skidmore if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) 10956a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 10966a14ee0cSDon Skidmore 10976a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, 10986a14ee0cSDon Skidmore IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 10996a14ee0cSDon Skidmore &speed); 11006a14ee0cSDon Skidmore 11016a14ee0cSDon Skidmore /* clear everything but the speed and duplex bits */ 11026a14ee0cSDon Skidmore speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; 11036a14ee0cSDon Skidmore 11046a14ee0cSDon Skidmore switch (speed) { 11056a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: 11066a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_10GB_FULL; 11076a14ee0cSDon Skidmore break; 11086a14ee0cSDon Skidmore case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: 11096a14ee0cSDon Skidmore force_speed = IXGBE_LINK_SPEED_1GB_FULL; 11106a14ee0cSDon Skidmore break; 11116a14ee0cSDon Skidmore default: 11126a14ee0cSDon Skidmore /* Internal PHY does not support anything else */ 11136a14ee0cSDon Skidmore return IXGBE_ERR_INVALID_LINK_SETTINGS; 11146a14ee0cSDon Skidmore } 11156a14ee0cSDon Skidmore 11166a14ee0cSDon Skidmore return ixgbe_setup_ixfi_x550em(hw, &force_speed); 11176a14ee0cSDon Skidmore } 11186a14ee0cSDon Skidmore 11196a14ee0cSDon Skidmore /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init 11206a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11216a14ee0cSDon Skidmore * 11226a14ee0cSDon Skidmore * Initialize any function pointers that were not able to be 11236a14ee0cSDon Skidmore * set during init_shared_code because the PHY/SFP type was 11246a14ee0cSDon Skidmore * not known. Perform the SFP init if necessary. 11256a14ee0cSDon Skidmore **/ 11267ddbde3fSDon Skidmore static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) 11276a14ee0cSDon Skidmore { 11286a14ee0cSDon Skidmore struct ixgbe_phy_info *phy = &hw->phy; 11296a14ee0cSDon Skidmore s32 ret_val; 11306a14ee0cSDon Skidmore u32 esdp; 11316a14ee0cSDon Skidmore 11326a14ee0cSDon Skidmore if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) { 11336a14ee0cSDon Skidmore esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 11346a14ee0cSDon Skidmore phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; 11356a14ee0cSDon Skidmore 11366a14ee0cSDon Skidmore if (hw->bus.lan_id) { 11376a14ee0cSDon Skidmore esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); 11386a14ee0cSDon Skidmore esdp |= IXGBE_ESDP_SDP1_DIR; 11396a14ee0cSDon Skidmore } 11406a14ee0cSDon Skidmore esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); 11416a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 11426a14ee0cSDon Skidmore } 11436a14ee0cSDon Skidmore 11446a14ee0cSDon Skidmore /* Identify the PHY or SFP module */ 11456a14ee0cSDon Skidmore ret_val = phy->ops.identify(hw); 11466a14ee0cSDon Skidmore 11476a14ee0cSDon Skidmore /* Setup function pointers based on detected SFP module and speeds */ 11486a14ee0cSDon Skidmore ixgbe_init_mac_link_ops_X550em(hw); 11496a14ee0cSDon Skidmore if (phy->sfp_type != ixgbe_sfp_type_unknown) 11506a14ee0cSDon Skidmore phy->ops.reset = NULL; 11516a14ee0cSDon Skidmore 11526a14ee0cSDon Skidmore /* Set functions pointers based on phy type */ 11536a14ee0cSDon Skidmore switch (hw->phy.type) { 11546a14ee0cSDon Skidmore case ixgbe_phy_x550em_kx4: 11556a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kx4_x550em; 11566a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 11576a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 11586a14ee0cSDon Skidmore break; 11596a14ee0cSDon Skidmore case ixgbe_phy_x550em_kr: 11606a14ee0cSDon Skidmore phy->ops.setup_link = ixgbe_setup_kr_x550em; 11616a14ee0cSDon Skidmore phy->ops.read_reg = ixgbe_read_phy_reg_x550em; 11626a14ee0cSDon Skidmore phy->ops.write_reg = ixgbe_write_phy_reg_x550em; 11636a14ee0cSDon Skidmore break; 11646a14ee0cSDon Skidmore case ixgbe_phy_x550em_ext_t: 11656a14ee0cSDon Skidmore phy->ops.setup_internal_link = ixgbe_setup_internal_phy_x550em; 11666a14ee0cSDon Skidmore break; 11676a14ee0cSDon Skidmore default: 11686a14ee0cSDon Skidmore break; 11696a14ee0cSDon Skidmore } 11706a14ee0cSDon Skidmore return ret_val; 11716a14ee0cSDon Skidmore } 11726a14ee0cSDon Skidmore 11736a14ee0cSDon Skidmore /** ixgbe_get_media_type_X550em - Get media type 11746a14ee0cSDon Skidmore * @hw: pointer to hardware structure 11756a14ee0cSDon Skidmore * 11766a14ee0cSDon Skidmore * Returns the media type (fiber, copper, backplane) 11776a14ee0cSDon Skidmore * 11786a14ee0cSDon Skidmore */ 11797ddbde3fSDon Skidmore static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) 11806a14ee0cSDon Skidmore { 11816a14ee0cSDon Skidmore enum ixgbe_media_type media_type; 11826a14ee0cSDon Skidmore 11836a14ee0cSDon Skidmore /* Detect if there is a copper PHY attached. */ 11846a14ee0cSDon Skidmore switch (hw->device_id) { 11856a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KR: 11866a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_KX4: 11876a14ee0cSDon Skidmore media_type = ixgbe_media_type_backplane; 11886a14ee0cSDon Skidmore break; 11896a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_SFP: 11906a14ee0cSDon Skidmore media_type = ixgbe_media_type_fiber; 11916a14ee0cSDon Skidmore break; 11926a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_1G_T: 11936a14ee0cSDon Skidmore case IXGBE_DEV_ID_X550EM_X_10G_T: 11946a14ee0cSDon Skidmore media_type = ixgbe_media_type_copper; 11956a14ee0cSDon Skidmore break; 11966a14ee0cSDon Skidmore default: 11976a14ee0cSDon Skidmore media_type = ixgbe_media_type_unknown; 11986a14ee0cSDon Skidmore break; 11996a14ee0cSDon Skidmore } 12006a14ee0cSDon Skidmore return media_type; 12016a14ee0cSDon Skidmore } 12026a14ee0cSDon Skidmore 12036a14ee0cSDon Skidmore /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. 12046a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 12056a14ee0cSDon Skidmore **/ 12067ddbde3fSDon Skidmore static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) 12076a14ee0cSDon Skidmore { 1208a1e869deSMark Rustad s32 status; 12096a14ee0cSDon Skidmore u16 reg; 12106a14ee0cSDon Skidmore u32 retries = 2; 12116a14ee0cSDon Skidmore 12126a14ee0cSDon Skidmore do { 12136a14ee0cSDon Skidmore /* decrement retries counter and exit if we hit 0 */ 12146a14ee0cSDon Skidmore if (retries < 1) { 12156a14ee0cSDon Skidmore hw_dbg(hw, "External PHY not yet finished resetting."); 12166a14ee0cSDon Skidmore return IXGBE_ERR_PHY; 12176a14ee0cSDon Skidmore } 12186a14ee0cSDon Skidmore retries--; 12196a14ee0cSDon Skidmore 12206a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 12216a14ee0cSDon Skidmore IXGBE_MDIO_TX_VENDOR_ALARMS_3, 12226a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 12236a14ee0cSDon Skidmore ®); 12246a14ee0cSDon Skidmore if (status) 12256a14ee0cSDon Skidmore return status; 12266a14ee0cSDon Skidmore 12276a14ee0cSDon Skidmore /* Verify PHY FW reset has completed */ 12286a14ee0cSDon Skidmore } while ((reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) != 1); 12296a14ee0cSDon Skidmore 12306a14ee0cSDon Skidmore /* Set port to low power mode */ 12316a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 12326a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, 12336a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 12346a14ee0cSDon Skidmore ®); 12356a14ee0cSDon Skidmore if (status) 12366a14ee0cSDon Skidmore return status; 12376a14ee0cSDon Skidmore 12386a14ee0cSDon Skidmore /* Enable the transmitter */ 12396a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 12406a14ee0cSDon Skidmore IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR, 12416a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 12426a14ee0cSDon Skidmore ®); 12436a14ee0cSDon Skidmore if (status) 12446a14ee0cSDon Skidmore return status; 12456a14ee0cSDon Skidmore 12466a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_PMD_GLOBAL_TX_DISABLE; 12476a14ee0cSDon Skidmore 12486a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 12496a14ee0cSDon Skidmore IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR, 12506a14ee0cSDon Skidmore IXGBE_MDIO_PMA_PMD_DEV_TYPE, 12516a14ee0cSDon Skidmore reg); 12526a14ee0cSDon Skidmore if (status) 12536a14ee0cSDon Skidmore return status; 12546a14ee0cSDon Skidmore 12556a14ee0cSDon Skidmore /* Un-stall the PHY FW */ 12566a14ee0cSDon Skidmore status = hw->phy.ops.read_reg(hw, 12576a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 12586a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 12596a14ee0cSDon Skidmore ®); 12606a14ee0cSDon Skidmore if (status) 12616a14ee0cSDon Skidmore return status; 12626a14ee0cSDon Skidmore 12636a14ee0cSDon Skidmore reg &= ~IXGBE_MDIO_POWER_UP_STALL; 12646a14ee0cSDon Skidmore 12656a14ee0cSDon Skidmore status = hw->phy.ops.write_reg(hw, 12666a14ee0cSDon Skidmore IXGBE_MDIO_GLOBAL_RES_PR_10, 12676a14ee0cSDon Skidmore IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, 12686a14ee0cSDon Skidmore reg); 12696a14ee0cSDon Skidmore return status; 12706a14ee0cSDon Skidmore } 12716a14ee0cSDon Skidmore 12726a14ee0cSDon Skidmore /** ixgbe_reset_hw_X550em - Perform hardware reset 12736a14ee0cSDon Skidmore ** @hw: pointer to hardware structure 12746a14ee0cSDon Skidmore ** 12756a14ee0cSDon Skidmore ** Resets the hardware by resetting the transmit and receive units, masks 12766a14ee0cSDon Skidmore ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) 12776a14ee0cSDon Skidmore ** reset. 12786a14ee0cSDon Skidmore **/ 12797ddbde3fSDon Skidmore static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) 12806a14ee0cSDon Skidmore { 12816a14ee0cSDon Skidmore ixgbe_link_speed link_speed; 12826a14ee0cSDon Skidmore s32 status; 12836a14ee0cSDon Skidmore u32 ctrl = 0; 12846a14ee0cSDon Skidmore u32 i; 12856a14ee0cSDon Skidmore bool link_up = false; 12866a14ee0cSDon Skidmore 12876a14ee0cSDon Skidmore /* Call adapter stop to disable Tx/Rx and clear interrupts */ 12886a14ee0cSDon Skidmore status = hw->mac.ops.stop_adapter(hw); 12896a14ee0cSDon Skidmore if (status) 12906a14ee0cSDon Skidmore return status; 12916a14ee0cSDon Skidmore 12926a14ee0cSDon Skidmore /* flush pending Tx transactions */ 12936a14ee0cSDon Skidmore ixgbe_clear_tx_pending(hw); 12946a14ee0cSDon Skidmore 12956a14ee0cSDon Skidmore /* PHY ops must be identified and initialized prior to reset */ 12966a14ee0cSDon Skidmore 12976a14ee0cSDon Skidmore /* Identify PHY and related function pointers */ 12986a14ee0cSDon Skidmore status = hw->phy.ops.init(hw); 12996a14ee0cSDon Skidmore 13006a14ee0cSDon Skidmore /* start the external PHY */ 13016a14ee0cSDon Skidmore if (hw->phy.type == ixgbe_phy_x550em_ext_t) { 13026a14ee0cSDon Skidmore status = ixgbe_init_ext_t_x550em(hw); 13036a14ee0cSDon Skidmore if (status) 13046a14ee0cSDon Skidmore return status; 13056a14ee0cSDon Skidmore } 13066a14ee0cSDon Skidmore 13076a14ee0cSDon Skidmore /* Setup SFP module if there is one present. */ 13086a14ee0cSDon Skidmore if (hw->phy.sfp_setup_needed) { 13096a14ee0cSDon Skidmore status = hw->mac.ops.setup_sfp(hw); 13106a14ee0cSDon Skidmore hw->phy.sfp_setup_needed = false; 13116a14ee0cSDon Skidmore } 13126a14ee0cSDon Skidmore 13136a14ee0cSDon Skidmore /* Reset PHY */ 13146a14ee0cSDon Skidmore if (!hw->phy.reset_disable && hw->phy.ops.reset) 13156a14ee0cSDon Skidmore hw->phy.ops.reset(hw); 13166a14ee0cSDon Skidmore 13176a14ee0cSDon Skidmore mac_reset_top: 13186a14ee0cSDon Skidmore /* Issue global reset to the MAC. Needs to be SW reset if link is up. 13196a14ee0cSDon Skidmore * If link reset is used when link is up, it might reset the PHY when 13206a14ee0cSDon Skidmore * mng is using it. If link is down or the flag to force full link 13216a14ee0cSDon Skidmore * reset is set, then perform link reset. 13226a14ee0cSDon Skidmore */ 13236a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_LNK_RST; 13246a14ee0cSDon Skidmore 13256a14ee0cSDon Skidmore if (!hw->force_full_reset) { 13266a14ee0cSDon Skidmore hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 13276a14ee0cSDon Skidmore if (link_up) 13286a14ee0cSDon Skidmore ctrl = IXGBE_CTRL_RST; 13296a14ee0cSDon Skidmore } 13306a14ee0cSDon Skidmore 13316a14ee0cSDon Skidmore ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); 13326a14ee0cSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); 13336a14ee0cSDon Skidmore IXGBE_WRITE_FLUSH(hw); 13346a14ee0cSDon Skidmore 13356a14ee0cSDon Skidmore /* Poll for reset bit to self-clear meaning reset is complete */ 13366a14ee0cSDon Skidmore for (i = 0; i < 10; i++) { 13376a14ee0cSDon Skidmore udelay(1); 13386a14ee0cSDon Skidmore ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); 13396a14ee0cSDon Skidmore if (!(ctrl & IXGBE_CTRL_RST_MASK)) 13406a14ee0cSDon Skidmore break; 13416a14ee0cSDon Skidmore } 13426a14ee0cSDon Skidmore 13436a14ee0cSDon Skidmore if (ctrl & IXGBE_CTRL_RST_MASK) { 13446a14ee0cSDon Skidmore status = IXGBE_ERR_RESET_FAILED; 13456a14ee0cSDon Skidmore hw_dbg(hw, "Reset polling failed to complete.\n"); 13466a14ee0cSDon Skidmore } 13476a14ee0cSDon Skidmore 13486a14ee0cSDon Skidmore msleep(50); 13496a14ee0cSDon Skidmore 13506a14ee0cSDon Skidmore /* Double resets are required for recovery from certain error 13516a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 13526a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 13536a14ee0cSDon Skidmore */ 13546a14ee0cSDon Skidmore if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { 13556a14ee0cSDon Skidmore hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 13566a14ee0cSDon Skidmore goto mac_reset_top; 13576a14ee0cSDon Skidmore } 13586a14ee0cSDon Skidmore 13596a14ee0cSDon Skidmore /* Store the permanent mac address */ 13606a14ee0cSDon Skidmore hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); 13616a14ee0cSDon Skidmore 13626a14ee0cSDon Skidmore /* Store MAC address from RAR0, clear receive address registers, and 13636a14ee0cSDon Skidmore * clear the multicast table. Also reset num_rar_entries to 128, 13646a14ee0cSDon Skidmore * since we modify this value when programming the SAN MAC address. 13656a14ee0cSDon Skidmore */ 13666a14ee0cSDon Skidmore hw->mac.num_rar_entries = 128; 13676a14ee0cSDon Skidmore hw->mac.ops.init_rx_addrs(hw); 13686a14ee0cSDon Skidmore 13696a14ee0cSDon Skidmore return status; 13706a14ee0cSDon Skidmore } 13716a14ee0cSDon Skidmore 13725b7f000fSDon Skidmore /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype 13735b7f000fSDon Skidmore * anti-spoofing 13745b7f000fSDon Skidmore * @hw: pointer to hardware structure 13755b7f000fSDon Skidmore * @enable: enable or disable switch for Ethertype anti-spoofing 13765b7f000fSDon Skidmore * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing 13775b7f000fSDon Skidmore **/ 1378bc035fc5SDon Skidmore static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, 1379bc035fc5SDon Skidmore bool enable, int vf) 13805b7f000fSDon Skidmore { 13815b7f000fSDon Skidmore int vf_target_reg = vf >> 3; 13825b7f000fSDon Skidmore int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; 13835b7f000fSDon Skidmore u32 pfvfspoof; 13845b7f000fSDon Skidmore 13855b7f000fSDon Skidmore pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 13865b7f000fSDon Skidmore if (enable) 13875b7f000fSDon Skidmore pfvfspoof |= (1 << vf_target_shift); 13885b7f000fSDon Skidmore else 13895b7f000fSDon Skidmore pfvfspoof &= ~(1 << vf_target_shift); 13905b7f000fSDon Skidmore 13915b7f000fSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 13925b7f000fSDon Skidmore } 13935b7f000fSDon Skidmore 13946d4c96adSDon Skidmore /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning 13956d4c96adSDon Skidmore * @hw: pointer to hardware structure 13966d4c96adSDon Skidmore * @enable: enable or disable source address pruning 13976d4c96adSDon Skidmore * @pool: Rx pool to set source address pruning for 13986d4c96adSDon Skidmore **/ 13996d4c96adSDon Skidmore static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, 14006d4c96adSDon Skidmore bool enable, 14016d4c96adSDon Skidmore unsigned int pool) 14026d4c96adSDon Skidmore { 14036d4c96adSDon Skidmore u64 pfflp; 14046d4c96adSDon Skidmore 14056d4c96adSDon Skidmore /* max rx pool is 63 */ 14066d4c96adSDon Skidmore if (pool > 63) 14076d4c96adSDon Skidmore return; 14086d4c96adSDon Skidmore 14096d4c96adSDon Skidmore pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); 14106d4c96adSDon Skidmore pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; 14116d4c96adSDon Skidmore 14126d4c96adSDon Skidmore if (enable) 14136d4c96adSDon Skidmore pfflp |= (1ULL << pool); 14146d4c96adSDon Skidmore else 14156d4c96adSDon Skidmore pfflp &= ~(1ULL << pool); 14166d4c96adSDon Skidmore 14176d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); 14186d4c96adSDon Skidmore IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); 14196d4c96adSDon Skidmore } 14206d4c96adSDon Skidmore 14216a14ee0cSDon Skidmore #define X550_COMMON_MAC \ 14226a14ee0cSDon Skidmore .init_hw = &ixgbe_init_hw_generic, \ 14236a14ee0cSDon Skidmore .start_hw = &ixgbe_start_hw_X540, \ 14246a14ee0cSDon Skidmore .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ 14256a14ee0cSDon Skidmore .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ 14266a14ee0cSDon Skidmore .get_mac_addr = &ixgbe_get_mac_addr_generic, \ 14276a14ee0cSDon Skidmore .get_device_caps = &ixgbe_get_device_caps_generic, \ 14286a14ee0cSDon Skidmore .stop_adapter = &ixgbe_stop_adapter_generic, \ 14296a14ee0cSDon Skidmore .get_bus_info = &ixgbe_get_bus_info_generic, \ 14306a14ee0cSDon Skidmore .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ 14316a14ee0cSDon Skidmore .read_analog_reg8 = NULL, \ 14326a14ee0cSDon Skidmore .write_analog_reg8 = NULL, \ 14336a14ee0cSDon Skidmore .set_rxpba = &ixgbe_set_rxpba_generic, \ 14346a14ee0cSDon Skidmore .check_link = &ixgbe_check_mac_link_generic, \ 14356a14ee0cSDon Skidmore .led_on = &ixgbe_led_on_generic, \ 14366a14ee0cSDon Skidmore .led_off = &ixgbe_led_off_generic, \ 14376a14ee0cSDon Skidmore .blink_led_start = &ixgbe_blink_led_start_X540, \ 14386a14ee0cSDon Skidmore .blink_led_stop = &ixgbe_blink_led_stop_X540, \ 14396a14ee0cSDon Skidmore .set_rar = &ixgbe_set_rar_generic, \ 14406a14ee0cSDon Skidmore .clear_rar = &ixgbe_clear_rar_generic, \ 14416a14ee0cSDon Skidmore .set_vmdq = &ixgbe_set_vmdq_generic, \ 14426a14ee0cSDon Skidmore .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ 14436a14ee0cSDon Skidmore .clear_vmdq = &ixgbe_clear_vmdq_generic, \ 14446a14ee0cSDon Skidmore .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ 14456a14ee0cSDon Skidmore .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ 14466a14ee0cSDon Skidmore .enable_mc = &ixgbe_enable_mc_generic, \ 14476a14ee0cSDon Skidmore .disable_mc = &ixgbe_disable_mc_generic, \ 14486a14ee0cSDon Skidmore .clear_vfta = &ixgbe_clear_vfta_generic, \ 14496a14ee0cSDon Skidmore .set_vfta = &ixgbe_set_vfta_generic, \ 14506a14ee0cSDon Skidmore .fc_enable = &ixgbe_fc_enable_generic, \ 14516a14ee0cSDon Skidmore .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic, \ 14526a14ee0cSDon Skidmore .init_uta_tables = &ixgbe_init_uta_tables_generic, \ 14536a14ee0cSDon Skidmore .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ 14546a14ee0cSDon Skidmore .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ 14556d4c96adSDon Skidmore .set_source_address_pruning = \ 14566d4c96adSDon Skidmore &ixgbe_set_source_address_pruning_X550, \ 14575b7f000fSDon Skidmore .set_ethertype_anti_spoofing = \ 14585b7f000fSDon Skidmore &ixgbe_set_ethertype_anti_spoofing_X550, \ 14596a14ee0cSDon Skidmore .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, \ 14606a14ee0cSDon Skidmore .release_swfw_sync = &ixgbe_release_swfw_sync_X540, \ 14616a14ee0cSDon Skidmore .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ 14626a14ee0cSDon Skidmore .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ 14636a14ee0cSDon Skidmore .get_thermal_sensor_data = NULL, \ 14646a14ee0cSDon Skidmore .init_thermal_sensor_thresh = NULL, \ 14656a14ee0cSDon Skidmore .prot_autoc_read = &prot_autoc_read_generic, \ 14666a14ee0cSDon Skidmore .prot_autoc_write = &prot_autoc_write_generic, \ 14671f9ac57cSDon Skidmore .enable_rx = &ixgbe_enable_rx_generic, \ 14681f9ac57cSDon Skidmore .disable_rx = &ixgbe_disable_rx_x550, \ 14696a14ee0cSDon Skidmore 14706a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550 = { 14716a14ee0cSDon Skidmore X550_COMMON_MAC 14726a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X540, 14736a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X540, 14746a14ee0cSDon Skidmore .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, 14756a14ee0cSDon Skidmore .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, 14766a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_mac_link_X540, 14776a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, 14786a14ee0cSDon Skidmore .setup_sfp = NULL, 14796a14ee0cSDon Skidmore }; 14806a14ee0cSDon Skidmore 14816a14ee0cSDon Skidmore static struct ixgbe_mac_operations mac_ops_X550EM_x = { 14826a14ee0cSDon Skidmore X550_COMMON_MAC 14836a14ee0cSDon Skidmore .reset_hw = &ixgbe_reset_hw_X550em, 14846a14ee0cSDon Skidmore .get_media_type = &ixgbe_get_media_type_X550em, 14856a14ee0cSDon Skidmore .get_san_mac_addr = NULL, 14866a14ee0cSDon Skidmore .get_wwn_prefix = NULL, 14876a14ee0cSDon Skidmore .setup_link = NULL, /* defined later */ 14886a14ee0cSDon Skidmore .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, 14896a14ee0cSDon Skidmore .setup_sfp = ixgbe_setup_sfp_modules_X550em, 14906a14ee0cSDon Skidmore 14916a14ee0cSDon Skidmore }; 14926a14ee0cSDon Skidmore 14936a14ee0cSDon Skidmore #define X550_COMMON_EEP \ 14946a14ee0cSDon Skidmore .read = &ixgbe_read_ee_hostif_X550, \ 14956a14ee0cSDon Skidmore .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ 14966a14ee0cSDon Skidmore .write = &ixgbe_write_ee_hostif_X550, \ 14976a14ee0cSDon Skidmore .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ 14986a14ee0cSDon Skidmore .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ 14996a14ee0cSDon Skidmore .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ 15006a14ee0cSDon Skidmore .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ 15016a14ee0cSDon Skidmore 15026a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550 = { 15036a14ee0cSDon Skidmore X550_COMMON_EEP 15046a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X550, 15056a14ee0cSDon Skidmore }; 15066a14ee0cSDon Skidmore 15076a14ee0cSDon Skidmore static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { 15086a14ee0cSDon Skidmore X550_COMMON_EEP 15096a14ee0cSDon Skidmore .init_params = &ixgbe_init_eeprom_params_X540, 15106a14ee0cSDon Skidmore }; 15116a14ee0cSDon Skidmore 15126a14ee0cSDon Skidmore #define X550_COMMON_PHY \ 15136a14ee0cSDon Skidmore .identify_sfp = &ixgbe_identify_module_generic, \ 15146a14ee0cSDon Skidmore .reset = NULL, \ 15156a14ee0cSDon Skidmore .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ 15166a14ee0cSDon Skidmore .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ 15176a14ee0cSDon Skidmore .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ 15186a14ee0cSDon Skidmore .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ 15196a14ee0cSDon Skidmore .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ 15206a14ee0cSDon Skidmore .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ 15216a14ee0cSDon Skidmore .check_overtemp = &ixgbe_tn_check_overtemp, \ 15226a14ee0cSDon Skidmore .get_firmware_version = &ixgbe_get_phy_firmware_version_generic, 15236a14ee0cSDon Skidmore 15246a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550 = { 15256a14ee0cSDon Skidmore X550_COMMON_PHY 15266a14ee0cSDon Skidmore .init = NULL, 15276a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_generic, 15286a14ee0cSDon Skidmore .read_reg = &ixgbe_read_phy_reg_generic, 15296a14ee0cSDon Skidmore .write_reg = &ixgbe_write_phy_reg_generic, 15306a14ee0cSDon Skidmore .setup_link = &ixgbe_setup_phy_link_generic, 15316a14ee0cSDon Skidmore .read_i2c_combined = &ixgbe_read_i2c_combined_generic, 15326a14ee0cSDon Skidmore .write_i2c_combined = &ixgbe_write_i2c_combined_generic, 1533961fac88SDon Skidmore .set_phy_power = &ixgbe_set_copper_phy_power, 15346a14ee0cSDon Skidmore }; 15356a14ee0cSDon Skidmore 15366a14ee0cSDon Skidmore static struct ixgbe_phy_operations phy_ops_X550EM_x = { 15376a14ee0cSDon Skidmore X550_COMMON_PHY 15386a14ee0cSDon Skidmore .init = &ixgbe_init_phy_ops_X550em, 15396a14ee0cSDon Skidmore .identify = &ixgbe_identify_phy_x550em, 15406a14ee0cSDon Skidmore .read_reg = NULL, /* defined later */ 15416a14ee0cSDon Skidmore .write_reg = NULL, /* defined later */ 15426a14ee0cSDon Skidmore .setup_link = NULL, /* defined later */ 15436a14ee0cSDon Skidmore }; 15446a14ee0cSDon Skidmore 15459a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { 15469a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550) 15479a900ecaSDon Skidmore }; 15489a900ecaSDon Skidmore 15499a900ecaSDon Skidmore static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { 15509a900ecaSDon Skidmore IXGBE_MVALS_INIT(X550EM_x) 15519a900ecaSDon Skidmore }; 15529a900ecaSDon Skidmore 15536a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550_info = { 15546a14ee0cSDon Skidmore .mac = ixgbe_mac_X550, 15556a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 15566a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550, 15576a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550, 15586a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550, 15596a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 15609a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550, 15616a14ee0cSDon Skidmore }; 15626a14ee0cSDon Skidmore 15636a14ee0cSDon Skidmore struct ixgbe_info ixgbe_X550EM_x_info = { 15646a14ee0cSDon Skidmore .mac = ixgbe_mac_X550EM_x, 15656a14ee0cSDon Skidmore .get_invariants = &ixgbe_get_invariants_X540, 15666a14ee0cSDon Skidmore .mac_ops = &mac_ops_X550EM_x, 15676a14ee0cSDon Skidmore .eeprom_ops = &eeprom_ops_X550EM_x, 15686a14ee0cSDon Skidmore .phy_ops = &phy_ops_X550EM_x, 15696a14ee0cSDon Skidmore .mbx_ops = &mbx_ops_generic, 15709a900ecaSDon Skidmore .mvals = ixgbe_mvals_X550EM_x, 15716a14ee0cSDon Skidmore }; 1572