// SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 1999 - 2018 Intel Corporation. */ #include <linux/pci.h> #include <linux/delay.h> #include <linux/iopoll.h> #include <linux/sched.h> #include "ixgbe.h" #include "ixgbe_phy.h" static void ixgbe_i2c_start(struct ixgbe_hw *hw); static void ixgbe_i2c_stop(struct ixgbe_hw *hw); static int ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data); static int ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data); static int ixgbe_get_i2c_ack(struct ixgbe_hw *hw); static int ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data); static int 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 int 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 void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw); static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); static int ixgbe_get_phy_id(struct ixgbe_hw *hw); static int ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw); /** * 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 int ixgbe_out_i2c_byte_ack(struct ixgbe_hw *hw, u8 byte) { … } /** * 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 int ixgbe_in_i2c_byte_ack(struct ixgbe_hw *hw, u8 *byte) { … } /** * 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) { … } /** * 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. */ int ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val, bool lock) { … } /** * 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. */ int ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val, bool lock) { … } /** * ixgbe_probe_phy - Probe a single address for a PHY * @hw: pointer to hardware structure * @phy_addr: PHY address to probe * * Returns true if PHY found **/ static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr) { … } /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ int ixgbe_identify_phy_generic(struct ixgbe_hw *hw) { … } /** * 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 false since the link can not be blocked * via this method. **/ bool ixgbe_check_reset_blocked(struct ixgbe_hw *hw) { … } /** * ixgbe_get_phy_id - Get the phy type * @hw: pointer to hardware structure * **/ static int ixgbe_get_phy_id(struct ixgbe_hw *hw) { … } /** * ixgbe_get_phy_type_from_id - Get the phy type * @phy_id: hardware phy id * **/ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) { … } /** * ixgbe_reset_phy_generic - Performs a PHY reset * @hw: pointer to hardware structure **/ int ixgbe_reset_phy_generic(struct ixgbe_hw *hw) { … } /** * ixgbe_read_phy_reg_mdi - read PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @device_type: 5 bit device type * @phy_data: Pointer to read data from PHY register * * Reads a value from a specified PHY register without the SWFW lock **/ int ixgbe_read_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { … } /** * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register * using the SWFW lock - this function is needed in most cases * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @device_type: 5 bit device type * @phy_data: Pointer to read data from PHY register **/ int ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { … } /** * ixgbe_write_phy_reg_mdi - Writes a value to specified PHY register * without SWFW lock * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 5 bit device type * @phy_data: Data to write to the PHY register **/ int ixgbe_write_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { … } /** * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register * using SWFW lock- this function is needed in most cases * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 5 bit device type * @phy_data: Data to write to the PHY register **/ int ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { … } #define IXGBE_HW_READ_REG(addr) … /** * ixgbe_msca_cmd - Write the command register and poll for completion/timeout * @hw: pointer to hardware structure * @cmd: command register value to write **/ static int ixgbe_msca_cmd(struct ixgbe_hw *hw, u32 cmd) { … } /** * ixgbe_mii_bus_read_generic_c22 - Read a clause 22 register with gssr flags * @hw: pointer to hardware structure * @addr: address * @regnum: register number * @gssr: semaphore flags to acquire **/ static int ixgbe_mii_bus_read_generic_c22(struct ixgbe_hw *hw, int addr, int regnum, u32 gssr) { … } /** * ixgbe_mii_bus_read_generic_c45 - Read a clause 45 register with gssr flags * @hw: pointer to hardware structure * @addr: address * @devad: device address to read * @regnum: register number * @gssr: semaphore flags to acquire **/ static int ixgbe_mii_bus_read_generic_c45(struct ixgbe_hw *hw, int addr, int devad, int regnum, u32 gssr) { … } /** * ixgbe_mii_bus_write_generic_c22 - Write a clause 22 register with gssr flags * @hw: pointer to hardware structure * @addr: address * @regnum: register number * @val: value to write * @gssr: semaphore flags to acquire **/ static int ixgbe_mii_bus_write_generic_c22(struct ixgbe_hw *hw, int addr, int regnum, u16 val, u32 gssr) { … } /** * ixgbe_mii_bus_write_generic_c45 - Write a clause 45 register with gssr flags * @hw: pointer to hardware structure * @addr: address * @devad: device address to read * @regnum: register number * @val: value to write * @gssr: semaphore flags to acquire **/ static int ixgbe_mii_bus_write_generic_c45(struct ixgbe_hw *hw, int addr, int devad, int regnum, u16 val, u32 gssr) { … } /** * ixgbe_mii_bus_read_c22 - Read a clause 22 register * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @regnum: register number **/ static int ixgbe_mii_bus_read_c22(struct mii_bus *bus, int addr, int regnum) { … } /** * ixgbe_mii_bus_read_c45 - Read a clause 45 register * @bus: pointer to mii_bus structure which points to our driver private * @devad: device address to read * @addr: address * @regnum: register number **/ static int ixgbe_mii_bus_read_c45(struct mii_bus *bus, int devad, int addr, int regnum) { … } /** * ixgbe_mii_bus_write_c22 - Write a clause 22 register * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @regnum: register number * @val: value to write **/ static int ixgbe_mii_bus_write_c22(struct mii_bus *bus, int addr, int regnum, u16 val) { … } /** * ixgbe_mii_bus_write_c45 - Write a clause 45 register * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @devad: device address to read * @regnum: register number * @val: value to write **/ static int ixgbe_mii_bus_write_c45(struct mii_bus *bus, int addr, int devad, int regnum, u16 val) { … } /** * ixgbe_x550em_a_mii_bus_read_c22 - Read a clause 22 register on x550em_a * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @regnum: register number **/ static int ixgbe_x550em_a_mii_bus_read_c22(struct mii_bus *bus, int addr, int regnum) { … } /** * ixgbe_x550em_a_mii_bus_read_c45 - Read a clause 45 register on x550em_a * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @devad: device address to read * @regnum: register number **/ static int ixgbe_x550em_a_mii_bus_read_c45(struct mii_bus *bus, int addr, int devad, int regnum) { … } /** * ixgbe_x550em_a_mii_bus_write_c22 - Write a clause 22 register on x550em_a * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @regnum: register number * @val: value to write **/ static int ixgbe_x550em_a_mii_bus_write_c22(struct mii_bus *bus, int addr, int regnum, u16 val) { … } /** * ixgbe_x550em_a_mii_bus_write_c45 - Write a clause 45 register on x550em_a * @bus: pointer to mii_bus structure which points to our driver private * @addr: address * @devad: device address to read * @regnum: register number * @val: value to write **/ static int ixgbe_x550em_a_mii_bus_write_c45(struct mii_bus *bus, int addr, int devad, int regnum, u16 val) { … } /** * ixgbe_get_first_secondary_devfn - get first device downstream of root port * @devfn: PCI_DEVFN of root port on domain 0, bus 0 * * Returns pci_dev pointer to PCI_DEVFN(0, 0) on subordinate side of root * on domain 0, bus 0, devfn = 'devfn' **/ static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn) { … } /** * ixgbe_x550em_a_has_mii - is this the first ixgbe x550em_a PCI function? * @hw: pointer to hardware structure * * Returns true if hw points to lowest numbered PCI B:D.F x550_em_a device in * the SoC. There are up to 4 MACs sharing a single MDIO bus on the x550em_a, * but we only want to register one MDIO bus. **/ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw) { … } /** * ixgbe_mii_bus_init - mii_bus structure setup * @hw: pointer to hardware structure * * Returns 0 on success, negative on failure * * ixgbe_mii_bus_init initializes a mii_bus structure in adapter **/ int ixgbe_mii_bus_init(struct ixgbe_hw *hw) { … } /** * ixgbe_setup_phy_link_generic - Set and restart autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. **/ int ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) { … } /** * ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: unused **/ int ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { … } /** * ixgbe_get_copper_speeds_supported - Get copper link speed from phy * @hw: pointer to hardware structure * * Determines the supported link capabilities by reading the PHY auto * negotiation register. */ static int ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw) { … } /** * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value */ int ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { … } /** * ixgbe_check_phy_link_tnx - Determine link and speed status * @hw: pointer to hardware structure * @speed: link speed * @link_up: status of link * * Reads the VS1 register to determine if link is up and the current speed for * the PHY. **/ int ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up) { … } /** * ixgbe_setup_phy_link_tnx - Set and restart autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. * This function always returns success, this is nessary since * it is called via a function pointer that could call other * functions that could return an error. **/ int ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) { … } /** * ixgbe_reset_phy_nl - Performs a PHY reset * @hw: pointer to hardware structure **/ int ixgbe_reset_phy_nl(struct ixgbe_hw *hw) { … } /** * ixgbe_identify_module_generic - Identifies module type * @hw: pointer to hardware structure * * Determines HW type and calls appropriate function. **/ int ixgbe_identify_module_generic(struct ixgbe_hw *hw) { … } /** * ixgbe_identify_sfp_module_generic - Identifies SFP modules * @hw: pointer to hardware structure * * Searches for and identifies the SFP module and assigns appropriate PHY type. **/ int ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) { … } /** * ixgbe_identify_qsfp_module_generic - Identifies QSFP modules * @hw: pointer to hardware structure * * Searches for and identifies the QSFP module and assigns appropriate PHY type **/ static int ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw) { … } /** * ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence * @hw: pointer to hardware structure * @list_offset: offset to the SFP ID list * @data_offset: offset to the SFP data block * * Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if * so it returns the offsets to the phy init sequence block. **/ int ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *list_offset, u16 *data_offset) { … } /** * ixgbe_read_i2c_eeprom_generic - Reads 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ int ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { … } /** * ixgbe_read_i2c_sff8472_generic - Reads 8 bit word over I2C interface * @hw: pointer to hardware structure * @byte_offset: byte offset at address 0xA2 * @sff8472_data: value read * * Performs byte read operation to SFP module's SFF-8472 data over I2C **/ int ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data) { … } /** * ixgbe_write_i2c_eeprom_generic - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to write * @eeprom_data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface. **/ int ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data) { … } /** * ixgbe_is_sfp_probe - Returns true if SFP is being detected * @hw: pointer to hardware structure * @offset: eeprom offset to be read * @addr: I2C address to be read */ static bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, u8 offset, u8 addr) { … } /** * ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: device address * @data: value read * @lock: true if to take and release semaphore * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. */ static int ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data, bool lock) { … } /** * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: device address * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. */ int ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { … } /** * ixgbe_read_i2c_byte_generic_unlocked - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: device address * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. */ int ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { … } /** * ixgbe_write_i2c_byte_generic_int - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: value to write * @lock: true if to take and release semaphore * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. */ static int ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data, bool lock) { … } /** * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. */ int ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { … } /** * ixgbe_write_i2c_byte_generic_unlocked - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. */ int ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { … } /** * ixgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure * * Sets I2C start condition (High -> Low on SDA while SCL is High) * Set bit-bang mode on X550 hardware. **/ static void ixgbe_i2c_start(struct ixgbe_hw *hw) { … } /** * ixgbe_i2c_stop - Sets I2C stop condition * @hw: pointer to hardware structure * * Sets I2C stop condition (Low -> High on SDA while SCL is High) * Disables bit-bang mode and negates data output enable on X550 * hardware. **/ static void ixgbe_i2c_stop(struct ixgbe_hw *hw) { … } /** * ixgbe_clock_in_i2c_byte - Clocks in one byte via I2C * @hw: pointer to hardware structure * @data: data byte to clock in * * Clocks in one byte data via I2C data/clock **/ static int ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data) { … } /** * ixgbe_clock_out_i2c_byte - Clocks out one byte via I2C * @hw: pointer to hardware structure * @data: data byte clocked out * * Clocks out one byte data via I2C data/clock **/ static int ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data) { … } /** * ixgbe_get_i2c_ack - Polls for I2C ACK * @hw: pointer to hardware structure * * Clocks in/out one bit via I2C data/clock **/ static int ixgbe_get_i2c_ack(struct ixgbe_hw *hw) { … } /** * ixgbe_clock_in_i2c_bit - Clocks in one bit via I2C data/clock * @hw: pointer to hardware structure * @data: read data value * * Clocks in one bit via I2C data/clock **/ static int ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) { … } /** * ixgbe_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock * @hw: pointer to hardware structure * @data: data value to write * * Clocks out one bit via I2C data/clock **/ static int ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data) { … } /** * ixgbe_raise_i2c_clk - Raises the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Raises the I2C clock line '0'->'1' * Negates the I2C clock output enable on X550 hardware. **/ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { … } /** * ixgbe_lower_i2c_clk - Lowers the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Lowers the I2C clock line '1'->'0' * Asserts the I2C clock output enable on X550 hardware. **/ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { … } /** * ixgbe_set_i2c_data - Sets the I2C data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * @data: I2C data value (0 or 1) to set * * Sets the I2C data bit * Asserts the I2C data output enable on X550 hardware. **/ static int ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) { … } /** * ixgbe_get_i2c_data - Reads the I2C SDA data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value * Negates the I2C data output enable on X550 hardware. **/ static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl) { … } /** * ixgbe_i2c_bus_clear - Clears the I2C bus * @hw: pointer to hardware structure * * Clears the I2C bus by sending nine clock pulses. * Used when data line is stuck low. **/ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) { … } /** * ixgbe_tn_check_overtemp - Checks if an overtemp occurred. * @hw: pointer to hardware structure * * Checks if the LASI temp alarm status was triggered due to overtemp * * Return true when an overtemp event detected, otherwise false. **/ bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw) { … } /** ixgbe_set_copper_phy_power - Control power for copper phy * @hw: pointer to hardware structure * @on: true for on, false for off **/ int ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) { … }