/******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" STATIC void ixgbe_i2c_start(struct ixgbe_hw *hw); STATIC void ixgbe_i2c_stop(struct ixgbe_hw *hw); STATIC s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data); STATIC s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data); STATIC s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw); STATIC s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data); STATIC s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data); STATIC void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); STATIC void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); STATIC s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data); STATIC bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl); STATIC s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); /** * ixgbe_out_i2c_byte_ack - Send I2C byte with ack * @hw: pointer to the hardware structure * @byte: byte to send * * Returns an error code on error. */ STATIC s32 ixgbe_out_i2c_byte_ack(struct ixgbe_hw *hw, u8 byte) { s32 status; status = ixgbe_clock_out_i2c_byte(hw, byte); if (status) return status; return ixgbe_get_i2c_ack(hw); } /** * ixgbe_in_i2c_byte_ack - Receive an I2C byte and send ack * @hw: pointer to the hardware structure * @byte: pointer to a u8 to receive the byte * * Returns an error code on error. */ STATIC s32 ixgbe_in_i2c_byte_ack(struct ixgbe_hw *hw, u8 *byte) { s32 status; status = ixgbe_clock_in_i2c_byte(hw, byte); if (status) return status; /* ACK */ return ixgbe_clock_out_i2c_bit(hw, false); } /** * ixgbe_ones_comp_byte_add - Perform one's complement addition * @add1 - addend 1 * @add2 - addend 2 * * Returns one's complement 8-bit sum. */ STATIC u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2) { u16 sum = add1 + add2; sum = (sum & 0xFF) + (sum >> 8); return sum & 0xFF; } /** * ixgbe_read_i2c_combined_generic_int - Perform I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value * @lock: true if to take and release semaphore * * Returns an error code on error. */ s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 10; int retry = 0; u8 csum_byte; u8 high_bits; u8 low_bits; u8 reg_high; u8 csum; if (hw->mac.type >= ixgbe_mac_X550) max_retry = 3; reg_high = ((reg >> 7) & 0xFE) | 1; /* Indicate read combined */ csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF); csum = ~csum; do { if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ if (ixgbe_out_i2c_byte_ack(hw, addr)) goto fail; /* Write bits 14:8 */ if (ixgbe_out_i2c_byte_ack(hw, reg_high)) goto fail; /* Write bits 7:0 */ if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF)) goto fail; /* Write csum */ if (ixgbe_out_i2c_byte_ack(hw, csum)) goto fail; /* Re-start condition */ ixgbe_i2c_start(hw); /* Device Address and read indication */ if (ixgbe_out_i2c_byte_ack(hw, addr | 1)) goto fail; /* Get upper bits */ if (ixgbe_in_i2c_byte_ack(hw, &high_bits)) goto fail; /* Get low bits */ if (ixgbe_in_i2c_byte_ack(hw, &low_bits)) goto fail; /* Get csum */ if (ixgbe_clock_in_i2c_byte(hw, &csum_byte)) goto fail; /* NACK */ if (ixgbe_clock_out_i2c_bit(hw, false)) goto fail; ixgbe_i2c_stop(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); *val = (high_bits << 8) | low_bits; return 0; fail: ixgbe_i2c_bus_clear(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); retry++; if (retry < max_retry) DEBUGOUT("I2C byte read combined error - Retrying.\n"); else DEBUGOUT("I2C byte read combined error.\n"); } while (retry < max_retry); return IXGBE_ERR_I2C; } /** * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write * @lock: true if to take and release semaphore * * Returns an error code on error. */ s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 1; int retry = 0; u8 reg_high; u8 csum; reg_high = (reg >> 7) & 0xFE; /* Indicate write combined */ csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF); csum = ixgbe_ones_comp_byte_add(csum, val >> 8); csum = ixgbe_ones_comp_byte_add(csum, val & 0xFF); csum = ~csum; do { if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ if (ixgbe_out_i2c_byte_ack(hw, addr)) goto fail; /* Write bits 14:8 */ if (ixgbe_out_i2c_byte_ack(hw, reg_high)) goto fail; /* Write bits 7:0 */ if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF)) goto fail; /* Write data 15:8 */ if (ixgbe_out_i2c_byte_ack(hw, val >> 8)) goto fail; /* Write data 7:0 */ if (ixgbe_out_i2c_byte_ack(hw, val & 0xFF)) goto fail; /* Write csum */ if (ixgbe_out_i2c_byte_ack(hw, csum)) goto fail; ixgbe_i2c_stop(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); return 0; fail: ixgbe_i2c_bus_clear(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); retry++; if (retry < max_retry) DEBUGOUT("I2C byte write combined error - Retrying.\n"); else DEBUGOUT("I2C byte write combined error.\n"); } while (retry < max_retry); return IXGBE_ERR_I2C; } /** * ixgbe_init_phy_ops_generic - Inits PHY function ptrs * @hw: pointer to the hardware structure * * Initialize the function pointers. **/ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_phy_info *phy = &hw->phy; DEBUGFUNC("ixgbe_init_phy_ops_generic"); /* PHY */ phy->ops.identify = ixgbe_identify_phy_generic; phy->ops.reset = ixgbe_reset_phy_generic; phy->ops.read_reg = ixgbe_read_phy_reg_generic; phy->ops.write_reg = ixgbe_write_phy_reg_generic; phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi; phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi; phy->ops.setup_link = ixgbe_setup_phy_link_generic; phy->ops.setup_link_speed = ixgbe_setup_phy_link_speed_generic; phy->ops.check_link = NULL; phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic; phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_generic; phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_generic; phy->ops.read_i2c_sff8472 = ixgbe_read_i2c_sff8472_generic; phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_generic; phy->ops.write_i2c_eeprom = ixgbe_write_i2c_eeprom_generic; phy->ops.i2c_bus_clear = ixgbe_i2c_bus_clear; phy->ops.identify_sfp = ixgbe_identify_module_generic; phy->sfp_type = ixgbe_sfp_type_unknown; phy->ops.read_i2c_byte_unlocked = ixgbe_read_i2c_byte_generic_unlocked; phy->ops.write_i2c_byte_unlocked = ixgbe_write_i2c_byte_generic_unlocked; phy->ops.check_overtemp = ixgbe_tn_check_overtemp; return IXGBE_SUCCESS; } /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 phy_addr; u16 ext_ability = 0; DEBUGFUNC("ixgbe_identify_phy_generic"); if (!hw->phy.phy_semaphore_mask) { if (hw->bus.lan_id) hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; else hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; } if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { if (ixgbe_validate_phy_addr(hw, phy_addr)) { hw->phy.addr = phy_addr; ixgbe_get_phy_id(hw); hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & (IXGBE_MDIO_PHY_10GBASET_ABILITY | IXGBE_MDIO_PHY_1000BASET_ABILITY)) hw->phy.type = ixgbe_phy_cu_unknown; else hw->phy.type = ixgbe_phy_generic; } status = IXGBE_SUCCESS; break; } } /* Certain media types do not have a phy so an address will not * be found and the code will take this path. Caller has to * decide if it is an error or not. */ if (status != IXGBE_SUCCESS) { hw->phy.addr = 0; } } else { status = IXGBE_SUCCESS; } return status; } /** * ixgbe_check_reset_blocked - check status of MNG FW veto bit * @hw: pointer to the hardware structure * * This function checks the MMNGC.MNG_VETO bit to see if there are * any constraints on link from manageability. For MAC's that don't * have this bit just return faluse since the link can not be blocked * via this method. **/ s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw) { u32 mmngc; DEBUGFUNC("ixgbe_check_reset_blocked"); /* If we don't have this bit, it can't be blocking */ if (hw->mac.type == ixgbe_mac_82598EB) return false; mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC); if (mmngc & IXGBE_MMNGC_MNG_VETO) { ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "MNG_VETO bit detected.\n"); return true; } return false; } /** * ixgbe_validate_phy_addr - Determines phy address is valid * @hw: pointer to hardware structure * **/ bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) { u16 phy_id = 0; bo
create_vhost_user_if socket {sock}