📄 ixgb_ee.c
字号:
/******************************************************************************* Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: Linux NICS <linux.nics@intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************/#include "ixgb_hw.h"#include "ixgb_ee.h"/* Local prototypes */static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);static void ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count);static void ixgb_standby_eeprom(struct ixgb_hw *hw);static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);/****************************************************************************** * Raises the EEPROM's clock input. * * hw - Struct containing variables accessed by shared code * eecd_reg - EECD's current value *****************************************************************************/static voidixgb_raise_clock(struct ixgb_hw *hw, uint32_t *eecd_reg){ /* Raise the clock input to the EEPROM (by setting the SK bit), and then * wait 50 microseconds. */ *eecd_reg = *eecd_reg | IXGB_EECD_SK; IXGB_WRITE_REG(hw, EECD, *eecd_reg); udelay(50); return;}/****************************************************************************** * Lowers the EEPROM's clock input. * * hw - Struct containing variables accessed by shared code * eecd_reg - EECD's current value *****************************************************************************/static voidixgb_lower_clock(struct ixgb_hw *hw, uint32_t *eecd_reg){ /* Lower the clock input to the EEPROM (by clearing the SK bit), and then * wait 50 microseconds. */ *eecd_reg = *eecd_reg & ~IXGB_EECD_SK; IXGB_WRITE_REG(hw, EECD, *eecd_reg); udelay(50); return;}/****************************************************************************** * Shift data bits out to the EEPROM. * * hw - Struct containing variables accessed by shared code * data - data to send to the EEPROM * count - number of bits to shift out *****************************************************************************/static voidixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count){ uint32_t eecd_reg; uint32_t mask; /* We need to shift "count" bits out to the EEPROM. So, value in the * "data" parameter will be shifted out to the EEPROM one bit at a time. * In order to do this, "data" must be broken down into bits. */ mask = 0x01 << (count - 1); eecd_reg = IXGB_READ_REG(hw, EECD); eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI); do { /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", * and then raising and then lowering the clock (the SK bit controls * the clock input to the EEPROM). A "0" is shifted out to the EEPROM * by setting "DI" to "0" and then raising and then lowering the clock. */ eecd_reg &= ~IXGB_EECD_DI; if(data & mask) eecd_reg |= IXGB_EECD_DI; IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); ixgb_raise_clock(hw, &eecd_reg); ixgb_lower_clock(hw, &eecd_reg); mask = mask >> 1; } while(mask); /* We leave the "DI" bit set to "0" when we leave this routine. */ eecd_reg &= ~IXGB_EECD_DI; IXGB_WRITE_REG(hw, EECD, eecd_reg); return;}/****************************************************************************** * Shift data bits in from the EEPROM * * hw - Struct containing variables accessed by shared code *****************************************************************************/static uint16_tixgb_shift_in_bits(struct ixgb_hw *hw){ uint32_t eecd_reg; uint32_t i; uint16_t data; /* In order to read a register from the EEPROM, we need to shift 16 bits * in from the EEPROM. Bits are "shifted in" by raising the clock input to * the EEPROM (setting the SK bit), and then reading the value of the "DO" * bit. During this "shifting in" process the "DI" bit should always be * clear.. */ eecd_reg = IXGB_READ_REG(hw, EECD); eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI); data = 0; for(i = 0; i < 16; i++) { data = data << 1; ixgb_raise_clock(hw, &eecd_reg); eecd_reg = IXGB_READ_REG(hw, EECD); eecd_reg &= ~(IXGB_EECD_DI); if(eecd_reg & IXGB_EECD_DO) data |= 1; ixgb_lower_clock(hw, &eecd_reg); } return data;}/****************************************************************************** * Prepares EEPROM for access * * hw - Struct containing variables accessed by shared code * * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This * function should be called before issuing a command to the EEPROM. *****************************************************************************/static voidixgb_setup_eeprom(struct ixgb_hw *hw){ uint32_t eecd_reg; eecd_reg = IXGB_READ_REG(hw, EECD); /* Clear SK and DI */ eecd_reg &= ~(IXGB_EECD_SK | IXGB_EECD_DI); IXGB_WRITE_REG(hw, EECD, eecd_reg); /* Set CS */ eecd_reg |= IXGB_EECD_CS; IXGB_WRITE_REG(hw, EECD, eecd_reg); return;}/****************************************************************************** * Returns EEPROM to a "standby" state * * hw - Struct containing variables accessed by shared code *****************************************************************************/static voidixgb_standby_eeprom(struct ixgb_hw *hw){ uint32_t eecd_reg; eecd_reg = IXGB_READ_REG(hw, EECD); /* Deselct EEPROM */ eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_SK); IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); /* Clock high */ eecd_reg |= IXGB_EECD_SK; IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); /* Select EEPROM */ eecd_reg |= IXGB_EECD_CS; IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); /* Clock low */ eecd_reg &= ~IXGB_EECD_SK; IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); return;}/****************************************************************************** * Raises then lowers the EEPROM's clock pin * * hw - Struct containing variables accessed by shared code *****************************************************************************/static voidixgb_clock_eeprom(struct ixgb_hw *hw){ uint32_t eecd_reg; eecd_reg = IXGB_READ_REG(hw, EECD); /* Rising edge of clock */ eecd_reg |= IXGB_EECD_SK; IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); /* Falling edge of clock */ eecd_reg &= ~IXGB_EECD_SK; IXGB_WRITE_REG(hw, EECD, eecd_reg); udelay(50); return;}/****************************************************************************** * Terminates a command by lowering the EEPROM's chip select pin * * hw - Struct containing variables accessed by shared code *****************************************************************************/static voidixgb_cleanup_eeprom(struct ixgb_hw *hw){ uint32_t eecd_reg; eecd_reg = IXGB_READ_REG(hw, EECD); eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_DI); IXGB_WRITE_REG(hw, EECD, eecd_reg); ixgb_clock_eeprom(hw); return;}/****************************************************************************** * Waits for the EEPROM to finish the current command. * * hw - Struct containing variables accessed by shared code * * The command is done when the EEPROM's data out pin goes high. * * Returns: * TRUE: EEPROM data pin is high before timeout. * FALSE: Time expired. *****************************************************************************/static boolean_tixgb_wait_eeprom_command(struct ixgb_hw *hw){ uint32_t eecd_reg; uint32_t i; /* Toggle the CS line. This in effect tells to EEPROM to actually execute * the command in question. */ ixgb_standby_eeprom(hw); /* Now read DO repeatedly until is high (equal to '1'). The EEEPROM will * signal that the command has been completed by raising the DO signal. * If DO does not go high in 10 milliseconds, then error out. */ for(i = 0; i < 200; i++) { eecd_reg = IXGB_READ_REG(hw, EECD); if(eecd_reg & IXGB_EECD_DO) return (TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -