igb-4.19 kernel driver
This commit is contained in:
parent
1846af4995
commit
260ae28310
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,264 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_82575_H_
|
||||
#define _E1000_82575_H_
|
||||
|
||||
void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
|
||||
void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
|
||||
s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 *data);
|
||||
s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 data);
|
||||
|
||||
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
|
||||
(ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
#define E1000_RAR_ENTRIES_82575 16
|
||||
#define E1000_RAR_ENTRIES_82576 24
|
||||
#define E1000_RAR_ENTRIES_82580 24
|
||||
#define E1000_RAR_ENTRIES_I350 32
|
||||
|
||||
#define E1000_SW_SYNCH_MB 0x00000100
|
||||
#define E1000_STAT_DEV_RST_SET 0x00100000
|
||||
#define E1000_CTRL_DEV_RST 0x20000000
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
#define E1000_SRRCTL_TIMESTAMP 0x40000000
|
||||
|
||||
|
||||
#define E1000_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define E1000_MRQC_ENABLE_VMDQ_RSS_MQ 0x00000005
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
|
||||
|
||||
#define E1000_EICR_TX_QUEUE ( \
|
||||
E1000_EICR_TX_QUEUE0 | \
|
||||
E1000_EICR_TX_QUEUE1 | \
|
||||
E1000_EICR_TX_QUEUE2 | \
|
||||
E1000_EICR_TX_QUEUE3)
|
||||
|
||||
#define E1000_EICR_RX_QUEUE ( \
|
||||
E1000_EICR_RX_QUEUE0 | \
|
||||
E1000_EICR_RX_QUEUE1 | \
|
||||
E1000_EICR_RX_QUEUE2 | \
|
||||
E1000_EICR_RX_QUEUE3)
|
||||
|
||||
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
|
||||
#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
__le16 pkt_info; /* RSS type, Packet type */
|
||||
__le16 hdr_info; /* Split Head, buf len */
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
|
||||
#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 seqnum_seed;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
/* IPSec Encrypt Enable for ESP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
/* Adv ctxt IPSec SA IDX mask */
|
||||
/* Adv ctxt IPSec ESP len mask */
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
/* Tx Queue Arbitration Priority 0=low, 1=high */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_DISABLE 0x01 /* DCA Disable */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
|
||||
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_DESC_DCA_EN BIT(5) /* DCA Rx Desc enable */
|
||||
#define E1000_DCA_RXCTRL_HEAD_DCA_EN BIT(6) /* DCA Rx Desc header enable */
|
||||
#define E1000_DCA_RXCTRL_DATA_DCA_EN BIT(7) /* DCA Rx Desc payload enable */
|
||||
#define E1000_DCA_RXCTRL_DESC_RRO_EN BIT(9) /* DCA Rx rd Desc Relax Order */
|
||||
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_DESC_DCA_EN BIT(5) /* DCA Tx Desc enable */
|
||||
#define E1000_DCA_TXCTRL_DESC_RRO_EN BIT(9) /* Tx rd Desc Relax Order */
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN BIT(11) /* Tx Desc writeback RO bit */
|
||||
#define E1000_DCA_TXCTRL_DATA_RRO_EN BIT(13) /* Tx rd data Relax Order */
|
||||
|
||||
/* Additional DCA related definitions, note change in position of CPUID */
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
|
||||
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */
|
||||
|
||||
/* ETQF register bit definitions */
|
||||
#define E1000_ETQF_FILTER_ENABLE BIT(26)
|
||||
#define E1000_ETQF_1588 BIT(30)
|
||||
#define E1000_ETQF_IMM_INT BIT(29)
|
||||
#define E1000_ETQF_QUEUE_ENABLE BIT(31)
|
||||
#define E1000_ETQF_QUEUE_SHIFT 16
|
||||
#define E1000_ETQF_QUEUE_MASK 0x00070000
|
||||
#define E1000_ETQF_ETYPE_MASK 0x0000FFFF
|
||||
|
||||
/* FTQF register bit definitions */
|
||||
#define E1000_FTQF_VF_BP 0x00008000
|
||||
#define E1000_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define E1000_FTQF_MASK 0xF0000000
|
||||
#define E1000_FTQF_MASK_PROTO_BP 0x10000000
|
||||
#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
|
||||
|
||||
#define E1000_NVM_APME_82575 0x0400
|
||||
#define MAX_NUM_VFS 8
|
||||
|
||||
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
|
||||
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN BIT(31) /* global VF LB enable */
|
||||
|
||||
/* Easy defines for setting default pool, would normally be left a zero */
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
|
||||
|
||||
/* Other useful VMD_CTL register defines */
|
||||
#define E1000_VT_CTL_IGNORE_MAC BIT(28)
|
||||
#define E1000_VT_CTL_DISABLE_DEF_POOL BIT(29)
|
||||
#define E1000_VT_CTL_VM_REPL_EN BIT(30)
|
||||
|
||||
/* Per VM Offload register setup */
|
||||
#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
|
||||
#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
|
||||
#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
|
||||
#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
|
||||
#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
|
||||
#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
|
||||
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
|
||||
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
|
||||
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_DVMOLR_HIDEVLAN 0x20000000 /* Hide vlan enable */
|
||||
#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_VLVF_ARRAY_SIZE 32
|
||||
#define E1000_VLVF_VLANID_MASK 0x00000FFF
|
||||
#define E1000_VLVF_POOLSEL_SHIFT 12
|
||||
#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
|
||||
#define E1000_VLVF_LVLAN 0x00100000
|
||||
#define E1000_VLVF_VLANID_ENABLE 0x80000000
|
||||
|
||||
#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
|
||||
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
|
||||
|
||||
#define E1000_IOVCTL 0x05BBC
|
||||
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
|
||||
|
||||
#define E1000_RPLOLR_STRVLAN 0x40000000
|
||||
#define E1000_RPLOLR_STRCRC 0x80000000
|
||||
|
||||
#define E1000_DTXCTL_8023LL 0x0004
|
||||
#define E1000_DTXCTL_VLAN_ADDED 0x0008
|
||||
#define E1000_DTXCTL_OOS_ENABLE 0x0010
|
||||
#define E1000_DTXCTL_MDP_EN 0x0020
|
||||
#define E1000_DTXCTL_SPOOF_INT 0x0040
|
||||
|
||||
#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT BIT(14)
|
||||
|
||||
#define ALL_QUEUES 0xFFFF
|
||||
|
||||
/* RX packet buffer size defines */
|
||||
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
|
||||
void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
|
||||
void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
|
||||
void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
|
||||
u16 igb_rxpbs_adjust_82580(u32 data);
|
||||
s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
|
||||
s32 igb_set_eee_i350(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_set_eee_i354(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status);
|
||||
|
||||
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
|
||||
#define E1000_EMC_INTERNAL_DATA 0x00
|
||||
#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20
|
||||
#define E1000_EMC_DIODE1_DATA 0x01
|
||||
#define E1000_EMC_DIODE1_THERM_LIMIT 0x19
|
||||
#define E1000_EMC_DIODE2_DATA 0x23
|
||||
#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A
|
||||
#define E1000_EMC_DIODE3_DATA 0x2A
|
||||
#define E1000_EMC_DIODE3_THERM_LIMIT 0x30
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,264 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_82575_H_
|
||||
#define _E1000_82575_H_
|
||||
|
||||
void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
|
||||
void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
|
||||
s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 *data);
|
||||
s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 data);
|
||||
|
||||
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
|
||||
(ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
#define E1000_RAR_ENTRIES_82575 16
|
||||
#define E1000_RAR_ENTRIES_82576 24
|
||||
#define E1000_RAR_ENTRIES_82580 24
|
||||
#define E1000_RAR_ENTRIES_I350 32
|
||||
|
||||
#define E1000_SW_SYNCH_MB 0x00000100
|
||||
#define E1000_STAT_DEV_RST_SET 0x00100000
|
||||
#define E1000_CTRL_DEV_RST 0x20000000
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
#define E1000_SRRCTL_TIMESTAMP 0x40000000
|
||||
|
||||
|
||||
#define E1000_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define E1000_MRQC_ENABLE_VMDQ_RSS_MQ 0x00000005
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
|
||||
|
||||
#define E1000_EICR_TX_QUEUE ( \
|
||||
E1000_EICR_TX_QUEUE0 | \
|
||||
E1000_EICR_TX_QUEUE1 | \
|
||||
E1000_EICR_TX_QUEUE2 | \
|
||||
E1000_EICR_TX_QUEUE3)
|
||||
|
||||
#define E1000_EICR_RX_QUEUE ( \
|
||||
E1000_EICR_RX_QUEUE0 | \
|
||||
E1000_EICR_RX_QUEUE1 | \
|
||||
E1000_EICR_RX_QUEUE2 | \
|
||||
E1000_EICR_RX_QUEUE3)
|
||||
|
||||
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
|
||||
#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
__le16 pkt_info; /* RSS type, Packet type */
|
||||
__le16 hdr_info; /* Split Head, buf len */
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
|
||||
#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 seqnum_seed;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
/* IPSec Encrypt Enable for ESP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
/* Adv ctxt IPSec SA IDX mask */
|
||||
/* Adv ctxt IPSec ESP len mask */
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
/* Tx Queue Arbitration Priority 0=low, 1=high */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_DISABLE 0x01 /* DCA Disable */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
|
||||
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_DESC_DCA_EN BIT(5) /* DCA Rx Desc enable */
|
||||
#define E1000_DCA_RXCTRL_HEAD_DCA_EN BIT(6) /* DCA Rx Desc header enable */
|
||||
#define E1000_DCA_RXCTRL_DATA_DCA_EN BIT(7) /* DCA Rx Desc payload enable */
|
||||
#define E1000_DCA_RXCTRL_DESC_RRO_EN BIT(9) /* DCA Rx rd Desc Relax Order */
|
||||
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_DESC_DCA_EN BIT(5) /* DCA Tx Desc enable */
|
||||
#define E1000_DCA_TXCTRL_DESC_RRO_EN BIT(9) /* Tx rd Desc Relax Order */
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN BIT(11) /* Tx Desc writeback RO bit */
|
||||
#define E1000_DCA_TXCTRL_DATA_RRO_EN BIT(13) /* Tx rd data Relax Order */
|
||||
|
||||
/* Additional DCA related definitions, note change in position of CPUID */
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
|
||||
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */
|
||||
|
||||
/* ETQF register bit definitions */
|
||||
#define E1000_ETQF_FILTER_ENABLE BIT(26)
|
||||
#define E1000_ETQF_1588 BIT(30)
|
||||
#define E1000_ETQF_IMM_INT BIT(29)
|
||||
#define E1000_ETQF_QUEUE_ENABLE BIT(31)
|
||||
#define E1000_ETQF_QUEUE_SHIFT 16
|
||||
#define E1000_ETQF_QUEUE_MASK 0x00070000
|
||||
#define E1000_ETQF_ETYPE_MASK 0x0000FFFF
|
||||
|
||||
/* FTQF register bit definitions */
|
||||
#define E1000_FTQF_VF_BP 0x00008000
|
||||
#define E1000_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define E1000_FTQF_MASK 0xF0000000
|
||||
#define E1000_FTQF_MASK_PROTO_BP 0x10000000
|
||||
#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
|
||||
|
||||
#define E1000_NVM_APME_82575 0x0400
|
||||
#define MAX_NUM_VFS 8
|
||||
|
||||
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
|
||||
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN BIT(31) /* global VF LB enable */
|
||||
|
||||
/* Easy defines for setting default pool, would normally be left a zero */
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
|
||||
|
||||
/* Other useful VMD_CTL register defines */
|
||||
#define E1000_VT_CTL_IGNORE_MAC BIT(28)
|
||||
#define E1000_VT_CTL_DISABLE_DEF_POOL BIT(29)
|
||||
#define E1000_VT_CTL_VM_REPL_EN BIT(30)
|
||||
|
||||
/* Per VM Offload register setup */
|
||||
#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
|
||||
#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
|
||||
#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
|
||||
#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
|
||||
#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
|
||||
#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
|
||||
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
|
||||
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
|
||||
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_DVMOLR_HIDEVLAN 0x20000000 /* Hide vlan enable */
|
||||
#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_VLVF_ARRAY_SIZE 32
|
||||
#define E1000_VLVF_VLANID_MASK 0x00000FFF
|
||||
#define E1000_VLVF_POOLSEL_SHIFT 12
|
||||
#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
|
||||
#define E1000_VLVF_LVLAN 0x00100000
|
||||
#define E1000_VLVF_VLANID_ENABLE 0x80000000
|
||||
|
||||
#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
|
||||
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
|
||||
|
||||
#define E1000_IOVCTL 0x05BBC
|
||||
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
|
||||
|
||||
#define E1000_RPLOLR_STRVLAN 0x40000000
|
||||
#define E1000_RPLOLR_STRCRC 0x80000000
|
||||
|
||||
#define E1000_DTXCTL_8023LL 0x0004
|
||||
#define E1000_DTXCTL_VLAN_ADDED 0x0008
|
||||
#define E1000_DTXCTL_OOS_ENABLE 0x0010
|
||||
#define E1000_DTXCTL_MDP_EN 0x0020
|
||||
#define E1000_DTXCTL_SPOOF_INT 0x0040
|
||||
|
||||
#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT BIT(14)
|
||||
|
||||
#define ALL_QUEUES 0xFFFF
|
||||
|
||||
/* RX packet buffer size defines */
|
||||
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
|
||||
void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
|
||||
void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
|
||||
void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
|
||||
u16 igb_rxpbs_adjust_82580(u32 data);
|
||||
s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
|
||||
s32 igb_set_eee_i350(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_set_eee_i354(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status);
|
||||
|
||||
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
|
||||
#define E1000_EMC_INTERNAL_DATA 0x00
|
||||
#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20
|
||||
#define E1000_EMC_DIODE1_DATA 0x01
|
||||
#define E1000_EMC_DIODE1_THERM_LIMIT 0x19
|
||||
#define E1000_EMC_DIODE2_DATA 0x23
|
||||
#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A
|
||||
#define E1000_EMC_DIODE3_DATA 0x2A
|
||||
#define E1000_EMC_DIODE3_THERM_LIMIT 0x30
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,554 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_HW_H_
|
||||
#define _E1000_HW_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "e1000_regs-4.19-ethercat.h"
|
||||
#include "e1000_defines-4.19-ethercat.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82576 0x10C9
|
||||
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
|
||||
#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
|
||||
#define E1000_DEV_ID_82576_NS 0x150A
|
||||
#define E1000_DEV_ID_82576_NS_SERDES 0x1518
|
||||
#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
|
||||
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
|
||||
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
|
||||
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
|
||||
#define E1000_DEV_ID_82580_COPPER 0x150E
|
||||
#define E1000_DEV_ID_82580_FIBER 0x150F
|
||||
#define E1000_DEV_ID_82580_SERDES 0x1510
|
||||
#define E1000_DEV_ID_82580_SGMII 0x1511
|
||||
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
|
||||
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
|
||||
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
|
||||
#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
|
||||
#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
|
||||
#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
|
||||
#define E1000_DEV_ID_I350_COPPER 0x1521
|
||||
#define E1000_DEV_ID_I350_FIBER 0x1522
|
||||
#define E1000_DEV_ID_I350_SERDES 0x1523
|
||||
#define E1000_DEV_ID_I350_SGMII 0x1524
|
||||
#define E1000_DEV_ID_I210_COPPER 0x1533
|
||||
#define E1000_DEV_ID_I210_FIBER 0x1536
|
||||
#define E1000_DEV_ID_I210_SERDES 0x1537
|
||||
#define E1000_DEV_ID_I210_SGMII 0x1538
|
||||
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
|
||||
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
|
||||
#define E1000_DEV_ID_I211_COPPER 0x1539
|
||||
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
|
||||
#define E1000_DEV_ID_I354_SGMII 0x1F41
|
||||
#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45
|
||||
|
||||
#define E1000_REVISION_2 2
|
||||
#define E1000_REVISION_4 4
|
||||
|
||||
#define E1000_FUNC_0 0
|
||||
#define E1000_FUNC_1 1
|
||||
#define E1000_FUNC_2 2
|
||||
#define E1000_FUNC_3 3
|
||||
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_82575,
|
||||
e1000_82576,
|
||||
e1000_82580,
|
||||
e1000_i350,
|
||||
e1000_i354,
|
||||
e1000_i210,
|
||||
e1000_i211,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
enum e1000_media_type {
|
||||
e1000_media_type_unknown = 0,
|
||||
e1000_media_type_copper = 1,
|
||||
e1000_media_type_fiber = 2,
|
||||
e1000_media_type_internal_serdes = 3,
|
||||
e1000_num_media_types
|
||||
};
|
||||
|
||||
enum e1000_nvm_type {
|
||||
e1000_nvm_unknown = 0,
|
||||
e1000_nvm_none,
|
||||
e1000_nvm_eeprom_spi,
|
||||
e1000_nvm_flash_hw,
|
||||
e1000_nvm_invm,
|
||||
e1000_nvm_flash_sw
|
||||
};
|
||||
|
||||
enum e1000_nvm_override {
|
||||
e1000_nvm_override_none = 0,
|
||||
e1000_nvm_override_spi_small,
|
||||
e1000_nvm_override_spi_large,
|
||||
};
|
||||
|
||||
enum e1000_phy_type {
|
||||
e1000_phy_unknown = 0,
|
||||
e1000_phy_none,
|
||||
e1000_phy_m88,
|
||||
e1000_phy_igp,
|
||||
e1000_phy_igp_2,
|
||||
e1000_phy_gg82563,
|
||||
e1000_phy_igp_3,
|
||||
e1000_phy_ife,
|
||||
e1000_phy_82580,
|
||||
e1000_phy_i210,
|
||||
e1000_phy_bcm54616,
|
||||
};
|
||||
|
||||
enum e1000_bus_type {
|
||||
e1000_bus_type_unknown = 0,
|
||||
e1000_bus_type_pci,
|
||||
e1000_bus_type_pcix,
|
||||
e1000_bus_type_pci_express,
|
||||
e1000_bus_type_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_speed {
|
||||
e1000_bus_speed_unknown = 0,
|
||||
e1000_bus_speed_33,
|
||||
e1000_bus_speed_66,
|
||||
e1000_bus_speed_100,
|
||||
e1000_bus_speed_120,
|
||||
e1000_bus_speed_133,
|
||||
e1000_bus_speed_2500,
|
||||
e1000_bus_speed_5000,
|
||||
e1000_bus_speed_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_width {
|
||||
e1000_bus_width_unknown = 0,
|
||||
e1000_bus_width_pcie_x1,
|
||||
e1000_bus_width_pcie_x2,
|
||||
e1000_bus_width_pcie_x4 = 4,
|
||||
e1000_bus_width_pcie_x8 = 8,
|
||||
e1000_bus_width_32,
|
||||
e1000_bus_width_64,
|
||||
e1000_bus_width_reserved
|
||||
};
|
||||
|
||||
enum e1000_1000t_rx_status {
|
||||
e1000_1000t_rx_status_not_ok = 0,
|
||||
e1000_1000t_rx_status_ok,
|
||||
e1000_1000t_rx_status_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_rev_polarity {
|
||||
e1000_rev_polarity_normal = 0,
|
||||
e1000_rev_polarity_reversed,
|
||||
e1000_rev_polarity_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_fc_mode {
|
||||
e1000_fc_none = 0,
|
||||
e1000_fc_rx_pause,
|
||||
e1000_fc_tx_pause,
|
||||
e1000_fc_full,
|
||||
e1000_fc_default = 0xFF
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct e1000_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 cexterr;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 tsctfc;
|
||||
u64 iac;
|
||||
u64 icrxptc;
|
||||
u64 icrxatc;
|
||||
u64 ictxptc;
|
||||
u64 ictxatc;
|
||||
u64 ictxqec;
|
||||
u64 ictxqmtc;
|
||||
u64 icrxdmtc;
|
||||
u64 icrxoc;
|
||||
u64 cbtmpc;
|
||||
u64 htdpmc;
|
||||
u64 cbrdpc;
|
||||
u64 cbrmpc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 htcbdpc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
u64 doosync;
|
||||
u64 o2bgptc;
|
||||
u64 o2bspc;
|
||||
u64 b2ospc;
|
||||
u64 b2ogprc;
|
||||
};
|
||||
|
||||
struct e1000_host_mng_dhcp_cookie {
|
||||
u32 signature;
|
||||
u8 status;
|
||||
u8 reserved0;
|
||||
u16 vlan_id;
|
||||
u32 reserved1;
|
||||
u16 reserved2;
|
||||
u8 reserved3;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 1" */
|
||||
struct e1000_host_command_header {
|
||||
u8 command_id;
|
||||
u8 command_length;
|
||||
u8 command_options;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_DATA_LENGTH 252
|
||||
struct e1000_host_command_info {
|
||||
struct e1000_host_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 2" */
|
||||
struct e1000_host_mng_command_header {
|
||||
u8 command_id;
|
||||
u8 checksum;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u16 command_length;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
|
||||
struct e1000_host_mng_command_info {
|
||||
struct e1000_host_mng_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
|
||||
};
|
||||
|
||||
#include "e1000_mac-4.19-ethercat.h"
|
||||
#include "e1000_phy-4.19-ethercat.h"
|
||||
#include "e1000_nvm-4.19-ethercat.h"
|
||||
#include "e1000_mbx-4.19-ethercat.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
bool (*check_mng_mode)(struct e1000_hw *);
|
||||
s32 (*setup_physical_interface)(struct e1000_hw *);
|
||||
void (*rar_set)(struct e1000_hw *, u8 *, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
|
||||
s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
|
||||
void (*release_swfw_sync)(struct e1000_hw *, u16);
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
|
||||
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
|
||||
#endif
|
||||
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||
};
|
||||
|
||||
struct e1000_phy_operations {
|
||||
s32 (*acquire)(struct e1000_hw *);
|
||||
s32 (*check_polarity)(struct e1000_hw *);
|
||||
s32 (*check_reset_block)(struct e1000_hw *);
|
||||
s32 (*force_speed_duplex)(struct e1000_hw *);
|
||||
s32 (*get_cfg_done)(struct e1000_hw *hw);
|
||||
s32 (*get_cable_length)(struct e1000_hw *);
|
||||
s32 (*get_phy_info)(struct e1000_hw *);
|
||||
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
|
||||
void (*release)(struct e1000_hw *);
|
||||
s32 (*reset)(struct e1000_hw *);
|
||||
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*write_reg)(struct e1000_hw *, u32, u16);
|
||||
s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
|
||||
s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
|
||||
};
|
||||
|
||||
struct e1000_nvm_operations {
|
||||
s32 (*acquire)(struct e1000_hw *);
|
||||
s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
|
||||
void (*release)(struct e1000_hw *);
|
||||
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
|
||||
s32 (*update)(struct e1000_hw *);
|
||||
s32 (*validate)(struct e1000_hw *);
|
||||
s32 (*valid_led_default)(struct e1000_hw *, u16 *);
|
||||
};
|
||||
|
||||
#define E1000_MAX_SENSORS 3
|
||||
|
||||
struct e1000_thermal_diode_data {
|
||||
u8 location;
|
||||
u8 temp;
|
||||
u8 caution_thresh;
|
||||
u8 max_op_thresh;
|
||||
};
|
||||
|
||||
struct e1000_thermal_sensor_data {
|
||||
struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS];
|
||||
};
|
||||
|
||||
struct e1000_info {
|
||||
s32 (*get_invariants)(struct e1000_hw *);
|
||||
struct e1000_mac_operations *mac_ops;
|
||||
const struct e1000_phy_operations *phy_ops;
|
||||
struct e1000_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct e1000_info e1000_82575_info;
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u32 ledctl_default;
|
||||
u32 ledctl_mode1;
|
||||
u32 ledctl_mode2;
|
||||
u32 mc_filter_type;
|
||||
u32 txcw;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 uta_reg_count;
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
u32 mta_shadow[MAX_MTA_REG];
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool adaptive_ifs;
|
||||
bool arc_subsystem_valid;
|
||||
bool asf_firmware_present;
|
||||
bool autoneg;
|
||||
bool autoneg_failed;
|
||||
bool disable_hw_init_bits;
|
||||
bool get_link_status;
|
||||
bool ifs_params_forced;
|
||||
bool in_ifs_mode;
|
||||
bool report_tx_early;
|
||||
bool serdes_has_link;
|
||||
bool tx_pkt_filtering;
|
||||
struct e1000_thermal_sensor_data thermal_sensor_data;
|
||||
};
|
||||
|
||||
struct e1000_phy_info {
|
||||
struct e1000_phy_operations ops;
|
||||
|
||||
enum e1000_phy_type type;
|
||||
|
||||
enum e1000_1000t_rx_status local_rx;
|
||||
enum e1000_1000t_rx_status remote_rx;
|
||||
enum e1000_ms_type ms_type;
|
||||
enum e1000_ms_type original_ms_type;
|
||||
enum e1000_rev_polarity cable_polarity;
|
||||
enum e1000_smart_speed smart_speed;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum e1000_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
u16 cable_length;
|
||||
u16 max_cable_length;
|
||||
u16 min_cable_length;
|
||||
u16 pair_length[4];
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool disable_polarity_correction;
|
||||
bool is_mdix;
|
||||
bool polarity_correction;
|
||||
bool reset_disable;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct e1000_nvm_info {
|
||||
struct e1000_nvm_operations ops;
|
||||
enum e1000_nvm_type type;
|
||||
enum e1000_nvm_override override;
|
||||
|
||||
u32 flash_bank_size;
|
||||
u32 flash_base_addr;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct e1000_bus_info {
|
||||
enum e1000_bus_type type;
|
||||
enum e1000_bus_speed speed;
|
||||
enum e1000_bus_width width;
|
||||
|
||||
u32 snoop;
|
||||
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
struct e1000_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum e1000_fc_mode current_mode; /* Type of flow control */
|
||||
enum e1000_fc_mode requested_mode;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock);
|
||||
s32 (*write)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 (*read_posted)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 (*write_posted)(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id);
|
||||
s32 (*check_for_msg)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*check_for_ack)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*check_for_rst)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*unlock)(struct e1000_hw *hw, u16 mbx_id);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_82575 {
|
||||
bool sgmii_active;
|
||||
bool global_device_reset;
|
||||
bool eee_disable;
|
||||
bool clear_semaphore_once;
|
||||
struct e1000_sfp_flags eth_flags;
|
||||
bool module_plugged;
|
||||
u8 media_port;
|
||||
bool media_changed;
|
||||
bool mas_capable;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_fc_info fc;
|
||||
struct e1000_phy_info phy;
|
||||
struct e1000_nvm_info nvm;
|
||||
struct e1000_bus_info bus;
|
||||
struct e1000_mbx_info mbx;
|
||||
struct e1000_host_mng_dhcp_cookie mng_cookie;
|
||||
|
||||
union {
|
||||
struct e1000_dev_spec_82575 _82575;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
struct net_device *igb_get_hw_dev(struct e1000_hw *hw);
|
||||
#define hw_dbg(format, arg...) \
|
||||
netdev_dbg(igb_get_hw_dev(hw), format, ##arg)
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
|
||||
void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
void igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
#endif /* _E1000_HW_H_ */
|
||||
|
|
@ -0,0 +1,554 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_HW_H_
|
||||
#define _E1000_HW_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "e1000_regs.h"
|
||||
#include "e1000_defines.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82576 0x10C9
|
||||
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
|
||||
#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
|
||||
#define E1000_DEV_ID_82576_NS 0x150A
|
||||
#define E1000_DEV_ID_82576_NS_SERDES 0x1518
|
||||
#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
|
||||
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
|
||||
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
|
||||
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
|
||||
#define E1000_DEV_ID_82580_COPPER 0x150E
|
||||
#define E1000_DEV_ID_82580_FIBER 0x150F
|
||||
#define E1000_DEV_ID_82580_SERDES 0x1510
|
||||
#define E1000_DEV_ID_82580_SGMII 0x1511
|
||||
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
|
||||
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
|
||||
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
|
||||
#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
|
||||
#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
|
||||
#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
|
||||
#define E1000_DEV_ID_I350_COPPER 0x1521
|
||||
#define E1000_DEV_ID_I350_FIBER 0x1522
|
||||
#define E1000_DEV_ID_I350_SERDES 0x1523
|
||||
#define E1000_DEV_ID_I350_SGMII 0x1524
|
||||
#define E1000_DEV_ID_I210_COPPER 0x1533
|
||||
#define E1000_DEV_ID_I210_FIBER 0x1536
|
||||
#define E1000_DEV_ID_I210_SERDES 0x1537
|
||||
#define E1000_DEV_ID_I210_SGMII 0x1538
|
||||
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
|
||||
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
|
||||
#define E1000_DEV_ID_I211_COPPER 0x1539
|
||||
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
|
||||
#define E1000_DEV_ID_I354_SGMII 0x1F41
|
||||
#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45
|
||||
|
||||
#define E1000_REVISION_2 2
|
||||
#define E1000_REVISION_4 4
|
||||
|
||||
#define E1000_FUNC_0 0
|
||||
#define E1000_FUNC_1 1
|
||||
#define E1000_FUNC_2 2
|
||||
#define E1000_FUNC_3 3
|
||||
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_82575,
|
||||
e1000_82576,
|
||||
e1000_82580,
|
||||
e1000_i350,
|
||||
e1000_i354,
|
||||
e1000_i210,
|
||||
e1000_i211,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
enum e1000_media_type {
|
||||
e1000_media_type_unknown = 0,
|
||||
e1000_media_type_copper = 1,
|
||||
e1000_media_type_fiber = 2,
|
||||
e1000_media_type_internal_serdes = 3,
|
||||
e1000_num_media_types
|
||||
};
|
||||
|
||||
enum e1000_nvm_type {
|
||||
e1000_nvm_unknown = 0,
|
||||
e1000_nvm_none,
|
||||
e1000_nvm_eeprom_spi,
|
||||
e1000_nvm_flash_hw,
|
||||
e1000_nvm_invm,
|
||||
e1000_nvm_flash_sw
|
||||
};
|
||||
|
||||
enum e1000_nvm_override {
|
||||
e1000_nvm_override_none = 0,
|
||||
e1000_nvm_override_spi_small,
|
||||
e1000_nvm_override_spi_large,
|
||||
};
|
||||
|
||||
enum e1000_phy_type {
|
||||
e1000_phy_unknown = 0,
|
||||
e1000_phy_none,
|
||||
e1000_phy_m88,
|
||||
e1000_phy_igp,
|
||||
e1000_phy_igp_2,
|
||||
e1000_phy_gg82563,
|
||||
e1000_phy_igp_3,
|
||||
e1000_phy_ife,
|
||||
e1000_phy_82580,
|
||||
e1000_phy_i210,
|
||||
e1000_phy_bcm54616,
|
||||
};
|
||||
|
||||
enum e1000_bus_type {
|
||||
e1000_bus_type_unknown = 0,
|
||||
e1000_bus_type_pci,
|
||||
e1000_bus_type_pcix,
|
||||
e1000_bus_type_pci_express,
|
||||
e1000_bus_type_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_speed {
|
||||
e1000_bus_speed_unknown = 0,
|
||||
e1000_bus_speed_33,
|
||||
e1000_bus_speed_66,
|
||||
e1000_bus_speed_100,
|
||||
e1000_bus_speed_120,
|
||||
e1000_bus_speed_133,
|
||||
e1000_bus_speed_2500,
|
||||
e1000_bus_speed_5000,
|
||||
e1000_bus_speed_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_width {
|
||||
e1000_bus_width_unknown = 0,
|
||||
e1000_bus_width_pcie_x1,
|
||||
e1000_bus_width_pcie_x2,
|
||||
e1000_bus_width_pcie_x4 = 4,
|
||||
e1000_bus_width_pcie_x8 = 8,
|
||||
e1000_bus_width_32,
|
||||
e1000_bus_width_64,
|
||||
e1000_bus_width_reserved
|
||||
};
|
||||
|
||||
enum e1000_1000t_rx_status {
|
||||
e1000_1000t_rx_status_not_ok = 0,
|
||||
e1000_1000t_rx_status_ok,
|
||||
e1000_1000t_rx_status_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_rev_polarity {
|
||||
e1000_rev_polarity_normal = 0,
|
||||
e1000_rev_polarity_reversed,
|
||||
e1000_rev_polarity_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_fc_mode {
|
||||
e1000_fc_none = 0,
|
||||
e1000_fc_rx_pause,
|
||||
e1000_fc_tx_pause,
|
||||
e1000_fc_full,
|
||||
e1000_fc_default = 0xFF
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct e1000_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 cexterr;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 tsctfc;
|
||||
u64 iac;
|
||||
u64 icrxptc;
|
||||
u64 icrxatc;
|
||||
u64 ictxptc;
|
||||
u64 ictxatc;
|
||||
u64 ictxqec;
|
||||
u64 ictxqmtc;
|
||||
u64 icrxdmtc;
|
||||
u64 icrxoc;
|
||||
u64 cbtmpc;
|
||||
u64 htdpmc;
|
||||
u64 cbrdpc;
|
||||
u64 cbrmpc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 htcbdpc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
u64 doosync;
|
||||
u64 o2bgptc;
|
||||
u64 o2bspc;
|
||||
u64 b2ospc;
|
||||
u64 b2ogprc;
|
||||
};
|
||||
|
||||
struct e1000_host_mng_dhcp_cookie {
|
||||
u32 signature;
|
||||
u8 status;
|
||||
u8 reserved0;
|
||||
u16 vlan_id;
|
||||
u32 reserved1;
|
||||
u16 reserved2;
|
||||
u8 reserved3;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 1" */
|
||||
struct e1000_host_command_header {
|
||||
u8 command_id;
|
||||
u8 command_length;
|
||||
u8 command_options;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_DATA_LENGTH 252
|
||||
struct e1000_host_command_info {
|
||||
struct e1000_host_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 2" */
|
||||
struct e1000_host_mng_command_header {
|
||||
u8 command_id;
|
||||
u8 checksum;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u16 command_length;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
|
||||
struct e1000_host_mng_command_info {
|
||||
struct e1000_host_mng_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
|
||||
};
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_phy.h"
|
||||
#include "e1000_nvm.h"
|
||||
#include "e1000_mbx.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
bool (*check_mng_mode)(struct e1000_hw *);
|
||||
s32 (*setup_physical_interface)(struct e1000_hw *);
|
||||
void (*rar_set)(struct e1000_hw *, u8 *, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
|
||||
s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
|
||||
void (*release_swfw_sync)(struct e1000_hw *, u16);
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
|
||||
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
|
||||
#endif
|
||||
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||
};
|
||||
|
||||
struct e1000_phy_operations {
|
||||
s32 (*acquire)(struct e1000_hw *);
|
||||
s32 (*check_polarity)(struct e1000_hw *);
|
||||
s32 (*check_reset_block)(struct e1000_hw *);
|
||||
s32 (*force_speed_duplex)(struct e1000_hw *);
|
||||
s32 (*get_cfg_done)(struct e1000_hw *hw);
|
||||
s32 (*get_cable_length)(struct e1000_hw *);
|
||||
s32 (*get_phy_info)(struct e1000_hw *);
|
||||
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
|
||||
void (*release)(struct e1000_hw *);
|
||||
s32 (*reset)(struct e1000_hw *);
|
||||
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*write_reg)(struct e1000_hw *, u32, u16);
|
||||
s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
|
||||
s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
|
||||
};
|
||||
|
||||
struct e1000_nvm_operations {
|
||||
s32 (*acquire)(struct e1000_hw *);
|
||||
s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
|
||||
void (*release)(struct e1000_hw *);
|
||||
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
|
||||
s32 (*update)(struct e1000_hw *);
|
||||
s32 (*validate)(struct e1000_hw *);
|
||||
s32 (*valid_led_default)(struct e1000_hw *, u16 *);
|
||||
};
|
||||
|
||||
#define E1000_MAX_SENSORS 3
|
||||
|
||||
struct e1000_thermal_diode_data {
|
||||
u8 location;
|
||||
u8 temp;
|
||||
u8 caution_thresh;
|
||||
u8 max_op_thresh;
|
||||
};
|
||||
|
||||
struct e1000_thermal_sensor_data {
|
||||
struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS];
|
||||
};
|
||||
|
||||
struct e1000_info {
|
||||
s32 (*get_invariants)(struct e1000_hw *);
|
||||
struct e1000_mac_operations *mac_ops;
|
||||
const struct e1000_phy_operations *phy_ops;
|
||||
struct e1000_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct e1000_info e1000_82575_info;
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u32 ledctl_default;
|
||||
u32 ledctl_mode1;
|
||||
u32 ledctl_mode2;
|
||||
u32 mc_filter_type;
|
||||
u32 txcw;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 uta_reg_count;
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
u32 mta_shadow[MAX_MTA_REG];
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool adaptive_ifs;
|
||||
bool arc_subsystem_valid;
|
||||
bool asf_firmware_present;
|
||||
bool autoneg;
|
||||
bool autoneg_failed;
|
||||
bool disable_hw_init_bits;
|
||||
bool get_link_status;
|
||||
bool ifs_params_forced;
|
||||
bool in_ifs_mode;
|
||||
bool report_tx_early;
|
||||
bool serdes_has_link;
|
||||
bool tx_pkt_filtering;
|
||||
struct e1000_thermal_sensor_data thermal_sensor_data;
|
||||
};
|
||||
|
||||
struct e1000_phy_info {
|
||||
struct e1000_phy_operations ops;
|
||||
|
||||
enum e1000_phy_type type;
|
||||
|
||||
enum e1000_1000t_rx_status local_rx;
|
||||
enum e1000_1000t_rx_status remote_rx;
|
||||
enum e1000_ms_type ms_type;
|
||||
enum e1000_ms_type original_ms_type;
|
||||
enum e1000_rev_polarity cable_polarity;
|
||||
enum e1000_smart_speed smart_speed;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum e1000_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
u16 cable_length;
|
||||
u16 max_cable_length;
|
||||
u16 min_cable_length;
|
||||
u16 pair_length[4];
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool disable_polarity_correction;
|
||||
bool is_mdix;
|
||||
bool polarity_correction;
|
||||
bool reset_disable;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct e1000_nvm_info {
|
||||
struct e1000_nvm_operations ops;
|
||||
enum e1000_nvm_type type;
|
||||
enum e1000_nvm_override override;
|
||||
|
||||
u32 flash_bank_size;
|
||||
u32 flash_base_addr;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct e1000_bus_info {
|
||||
enum e1000_bus_type type;
|
||||
enum e1000_bus_speed speed;
|
||||
enum e1000_bus_width width;
|
||||
|
||||
u32 snoop;
|
||||
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
struct e1000_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum e1000_fc_mode current_mode; /* Type of flow control */
|
||||
enum e1000_fc_mode requested_mode;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock);
|
||||
s32 (*write)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 (*read_posted)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 (*write_posted)(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id);
|
||||
s32 (*check_for_msg)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*check_for_ack)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*check_for_rst)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*unlock)(struct e1000_hw *hw, u16 mbx_id);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_82575 {
|
||||
bool sgmii_active;
|
||||
bool global_device_reset;
|
||||
bool eee_disable;
|
||||
bool clear_semaphore_once;
|
||||
struct e1000_sfp_flags eth_flags;
|
||||
bool module_plugged;
|
||||
u8 media_port;
|
||||
bool media_changed;
|
||||
bool mas_capable;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_fc_info fc;
|
||||
struct e1000_phy_info phy;
|
||||
struct e1000_nvm_info nvm;
|
||||
struct e1000_bus_info bus;
|
||||
struct e1000_mbx_info mbx;
|
||||
struct e1000_host_mng_dhcp_cookie mng_cookie;
|
||||
|
||||
union {
|
||||
struct e1000_dev_spec_82575 _82575;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
struct net_device *igb_get_hw_dev(struct e1000_hw *hw);
|
||||
#define hw_dbg(format, arg...) \
|
||||
netdev_dbg(igb_get_hw_dev(hw), format, ##arg)
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
|
||||
void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
void igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
#endif /* _E1000_HW_H_ */
|
||||
|
|
@ -0,0 +1,911 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
/* e1000_i210
|
||||
* e1000_i211
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "e1000_hw-4.19-ethercat.h"
|
||||
#include "e1000_i210-4.19-ethercat.h"
|
||||
|
||||
static s32 igb_update_flash_i210(struct e1000_hw *hw);
|
||||
|
||||
/**
|
||||
* igb_get_hw_semaphore_i210 - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM
|
||||
*/
|
||||
static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
s32 timeout = hw->nvm.word_size + 1;
|
||||
s32 i = 0;
|
||||
|
||||
/* Get the SW semaphore */
|
||||
while (i < timeout) {
|
||||
swsm = rd32(E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
udelay(50);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* In rare circumstances, the SW semaphore may already be held
|
||||
* unintentionally. Clear the semaphore once before giving up.
|
||||
*/
|
||||
if (hw->dev_spec._82575.clear_semaphore_once) {
|
||||
hw->dev_spec._82575.clear_semaphore_once = false;
|
||||
igb_put_hw_semaphore(hw);
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = rd32(E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
udelay(50);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we do not have the semaphore here, we have to give up. */
|
||||
if (i == timeout) {
|
||||
hw_dbg("Driver can't access device - SMBI bit is set.\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the FW semaphore. */
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = rd32(E1000_SWSM);
|
||||
wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
|
||||
|
||||
/* Semaphore acquired if bit latched */
|
||||
if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
|
||||
break;
|
||||
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* Release semaphores */
|
||||
igb_put_hw_semaphore(hw);
|
||||
hw_dbg("Driver can't access the NVM\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_acquire_nvm_i210 - Request for access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the necessary semaphores for exclusive access to the EEPROM.
|
||||
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
|
||||
* Return successful if access grant bit set, else clear the request for
|
||||
* EEPROM access and return -E1000_ERR_NVM (-1).
|
||||
**/
|
||||
static s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
|
||||
{
|
||||
return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_nvm_i210 - Release exclusive access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Stop any current commands to the EEPROM and clear the EEPROM request bit,
|
||||
* then release the semaphores acquired.
|
||||
**/
|
||||
static void igb_release_nvm_i210(struct e1000_hw *hw)
|
||||
{
|
||||
igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
|
||||
* will also specify which port we're acquiring the lock for.
|
||||
**/
|
||||
s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
u32 swmask = mask;
|
||||
u32 fwmask = mask << 16;
|
||||
s32 ret_val = 0;
|
||||
s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
|
||||
|
||||
while (i < timeout) {
|
||||
if (igb_get_hw_semaphore_i210(hw)) {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync = rd32(E1000_SW_FW_SYNC);
|
||||
if (!(swfw_sync & (fwmask | swmask)))
|
||||
break;
|
||||
|
||||
/* Firmware currently using resource (fwmask) */
|
||||
igb_put_hw_semaphore(hw);
|
||||
mdelay(5);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync |= swmask;
|
||||
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
igb_put_hw_semaphore(hw);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_swfw_sync_i210 - Release SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
|
||||
* will also specify which port we're releasing the lock for.
|
||||
**/
|
||||
void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
|
||||
while (igb_get_hw_semaphore_i210(hw))
|
||||
; /* Empty */
|
||||
|
||||
swfw_sync = rd32(E1000_SW_FW_SYNC);
|
||||
swfw_sync &= ~mask;
|
||||
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
igb_put_hw_semaphore(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the Shadow Ram to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the Shadow Ram
|
||||
*
|
||||
* Reads a 16 bit word from the Shadow Ram using the EERD register.
|
||||
* Uses necessary synchronization semaphores.
|
||||
**/
|
||||
static s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
s32 status = 0;
|
||||
u16 i, count;
|
||||
|
||||
/* We cannot hold synchronization semaphores for too long,
|
||||
* because of forceful takeover procedure. However it is more efficient
|
||||
* to read in bursts than synchronizing access for each word.
|
||||
*/
|
||||
for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
|
||||
count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
|
||||
E1000_EERD_EEWR_MAX_COUNT : (words - i);
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
status = igb_read_nvm_eerd(hw, offset, count,
|
||||
data + i);
|
||||
hw->nvm.ops.release(hw);
|
||||
} else {
|
||||
status = E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_nvm_srwr - Write to Shadow Ram using EEWR
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the Shadow Ram to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the Shadow Ram
|
||||
*
|
||||
* Writes data to Shadow Ram at offset using EEWR register.
|
||||
*
|
||||
* If igb_update_nvm_checksum is not called after this function , the
|
||||
* Shadow Ram will most likely contain an invalid checksum.
|
||||
**/
|
||||
static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i, k, eewr = 0;
|
||||
u32 attempts = 100000;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* too many words for the offset, and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
|
||||
(data[i] << E1000_NVM_RW_REG_DATA) |
|
||||
E1000_NVM_RW_REG_START;
|
||||
|
||||
wr32(E1000_SRWR, eewr);
|
||||
|
||||
for (k = 0; k < attempts; k++) {
|
||||
if (E1000_NVM_RW_REG_DONE &
|
||||
rd32(E1000_SRWR)) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
if (ret_val) {
|
||||
hw_dbg("Shadow RAM write EEWR timed out\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the Shadow RAM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the Shadow RAM
|
||||
*
|
||||
* Writes data to Shadow RAM at offset using EEWR register.
|
||||
*
|
||||
* If e1000_update_nvm_checksum is not called after this function , the
|
||||
* data will not be committed to FLASH and also Shadow RAM will most likely
|
||||
* contain an invalid checksum.
|
||||
*
|
||||
* If error code is returned, data and Shadow RAM may be inconsistent - buffer
|
||||
* partially written.
|
||||
**/
|
||||
static s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
s32 status = 0;
|
||||
u16 i, count;
|
||||
|
||||
/* We cannot hold synchronization semaphores for too long,
|
||||
* because of forceful takeover procedure. However it is more efficient
|
||||
* to write in bursts than synchronizing access for each word.
|
||||
*/
|
||||
for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
|
||||
count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
|
||||
E1000_EERD_EEWR_MAX_COUNT : (words - i);
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
status = igb_write_nvm_srwr(hw, offset, count,
|
||||
data + i);
|
||||
hw->nvm.ops.release(hw);
|
||||
} else {
|
||||
status = E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_invm_word_i210 - Reads OTP
|
||||
* @hw: pointer to the HW structure
|
||||
* @address: the word address (aka eeprom offset) to read
|
||||
* @data: pointer to the data read
|
||||
*
|
||||
* Reads 16-bit words from the OTP. Return error when the word is not
|
||||
* stored in OTP.
|
||||
**/
|
||||
static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
|
||||
{
|
||||
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
|
||||
u32 invm_dword;
|
||||
u16 i;
|
||||
u8 record_type, word_address;
|
||||
|
||||
for (i = 0; i < E1000_INVM_SIZE; i++) {
|
||||
invm_dword = rd32(E1000_INVM_DATA_REG(i));
|
||||
/* Get record type */
|
||||
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
|
||||
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
|
||||
break;
|
||||
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
|
||||
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
|
||||
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
|
||||
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
|
||||
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
|
||||
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
|
||||
if (word_address == address) {
|
||||
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
|
||||
hw_dbg("Read INVM Word 0x%02x = %x\n",
|
||||
address, *data);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status)
|
||||
hw_dbg("Requested word 0x%02x not found in OTP\n", address);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_invm_i210 - Read invm wrapper function for I210/I211
|
||||
* @hw: pointer to the HW structure
|
||||
* @words: number of words to read
|
||||
* @data: pointer to the data read
|
||||
*
|
||||
* Wrapper function to return data formerly found in the NVM.
|
||||
**/
|
||||
static s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset,
|
||||
u16 words __always_unused, u16 *data)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* Only the MAC addr is required to be present in the iNVM */
|
||||
switch (offset) {
|
||||
case NVM_MAC_ADDR:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]);
|
||||
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1,
|
||||
&data[1]);
|
||||
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2,
|
||||
&data[2]);
|
||||
if (ret_val)
|
||||
hw_dbg("MAC Addr not found in iNVM\n");
|
||||
break;
|
||||
case NVM_INIT_CTRL_2:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_INIT_CTRL_2_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_INIT_CTRL_4:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_INIT_CTRL_4_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_LED_1_CFG:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_LED_1_CFG_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_LED_0_2_CFG:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_LED_0_2_CFG_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_ID_LED_SETTINGS:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = ID_LED_RESERVED_FFFF;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_SUB_DEV_ID:
|
||||
*data = hw->subsystem_device_id;
|
||||
break;
|
||||
case NVM_SUB_VEN_ID:
|
||||
*data = hw->subsystem_vendor_id;
|
||||
break;
|
||||
case NVM_DEV_ID:
|
||||
*data = hw->device_id;
|
||||
break;
|
||||
case NVM_VEN_ID:
|
||||
*data = hw->vendor_id;
|
||||
break;
|
||||
default:
|
||||
hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
|
||||
*data = NVM_RESERVED_WORD;
|
||||
break;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_invm_version - Reads iNVM version and image type
|
||||
* @hw: pointer to the HW structure
|
||||
* @invm_ver: version structure for the version read
|
||||
*
|
||||
* Reads iNVM version and image type.
|
||||
**/
|
||||
s32 igb_read_invm_version(struct e1000_hw *hw,
|
||||
struct e1000_fw_version *invm_ver) {
|
||||
u32 *record = NULL;
|
||||
u32 *next_record = NULL;
|
||||
u32 i = 0;
|
||||
u32 invm_dword = 0;
|
||||
u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
|
||||
E1000_INVM_RECORD_SIZE_IN_BYTES);
|
||||
u32 buffer[E1000_INVM_SIZE];
|
||||
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
|
||||
u16 version = 0;
|
||||
|
||||
/* Read iNVM memory */
|
||||
for (i = 0; i < E1000_INVM_SIZE; i++) {
|
||||
invm_dword = rd32(E1000_INVM_DATA_REG(i));
|
||||
buffer[i] = invm_dword;
|
||||
}
|
||||
|
||||
/* Read version number */
|
||||
for (i = 1; i < invm_blocks; i++) {
|
||||
record = &buffer[invm_blocks - i];
|
||||
next_record = &buffer[invm_blocks - i + 1];
|
||||
|
||||
/* Check if we have first version location used */
|
||||
if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
|
||||
version = 0;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have second version location used */
|
||||
else if ((i == 1) &&
|
||||
((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
|
||||
version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have odd version location
|
||||
* used and it is the last one used
|
||||
*/
|
||||
else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
|
||||
((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
|
||||
(i != 1))) {
|
||||
version = (*next_record & E1000_INVM_VER_FIELD_TWO)
|
||||
>> 13;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have even version location
|
||||
* used and it is the last one used
|
||||
*/
|
||||
else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
|
||||
((*record & 0x3) == 0)) {
|
||||
version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
|
||||
>> E1000_INVM_MAJOR_SHIFT;
|
||||
invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
|
||||
}
|
||||
/* Read Image Type */
|
||||
for (i = 1; i < invm_blocks; i++) {
|
||||
record = &buffer[invm_blocks - i];
|
||||
next_record = &buffer[invm_blocks - i + 1];
|
||||
|
||||
/* Check if we have image type in first location used */
|
||||
if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
|
||||
invm_ver->invm_img_type = 0;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have image type in first location used */
|
||||
else if ((((*record & 0x3) == 0) &&
|
||||
((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
|
||||
((((*record & 0x3) != 0) && (i != 1)))) {
|
||||
invm_ver->invm_img_type =
|
||||
(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
|
||||
**/
|
||||
static s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 status = 0;
|
||||
s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
|
||||
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
|
||||
/* Replace the read function with semaphore grabbing with
|
||||
* the one that skips this for a while.
|
||||
* We have semaphore taken already here.
|
||||
*/
|
||||
read_op_ptr = hw->nvm.ops.read;
|
||||
hw->nvm.ops.read = igb_read_nvm_eerd;
|
||||
|
||||
status = igb_validate_nvm_checksum(hw);
|
||||
|
||||
/* Revert original read operation. */
|
||||
hw->nvm.ops.read = read_op_ptr;
|
||||
|
||||
hw->nvm.ops.release(hw);
|
||||
} else {
|
||||
status = E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_update_nvm_checksum_i210 - Update EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* up to the checksum. Then calculates the EEPROM checksum and writes the
|
||||
* value to the EEPROM. Next commit EEPROM data onto the Flash.
|
||||
**/
|
||||
static s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
/* Read the first word from the EEPROM. If this times out or fails, do
|
||||
* not continue or we could be in for a very long wait while every
|
||||
* EEPROM read fails
|
||||
*/
|
||||
ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("EEPROM read failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
/* Do not use hw->nvm.ops.write, hw->nvm.ops.read
|
||||
* because we do not want to take the synchronization
|
||||
* semaphores twice here.
|
||||
*/
|
||||
|
||||
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
|
||||
ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw->nvm.ops.release(hw);
|
||||
hw_dbg("NVM Read Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
checksum = (u16) NVM_SUM - checksum;
|
||||
ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
|
||||
&checksum);
|
||||
if (ret_val) {
|
||||
hw->nvm.ops.release(hw);
|
||||
hw_dbg("NVM Write Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
hw->nvm.ops.release(hw);
|
||||
|
||||
ret_val = igb_update_flash_i210(hw);
|
||||
} else {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_pool_flash_update_done_i210 - Pool FLUDONE status.
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
**/
|
||||
static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
u32 i, reg;
|
||||
|
||||
for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
|
||||
reg = rd32(E1000_EECD);
|
||||
if (reg & E1000_EECD_FLUDONE_I210) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_get_flash_presence_i210 - Check if flash device is detected.
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
**/
|
||||
bool igb_get_flash_presence_i210(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eec = 0;
|
||||
bool ret_val = false;
|
||||
|
||||
eec = rd32(E1000_EECD);
|
||||
if (eec & E1000_EECD_FLASH_DETECTED_I210)
|
||||
ret_val = true;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_update_flash_i210 - Commit EEPROM to the flash
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
**/
|
||||
static s32 igb_update_flash_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u32 flup;
|
||||
|
||||
ret_val = igb_pool_flash_update_done_i210(hw);
|
||||
if (ret_val == -E1000_ERR_NVM) {
|
||||
hw_dbg("Flash update time out\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
|
||||
wr32(E1000_EECD, flup);
|
||||
|
||||
ret_val = igb_pool_flash_update_done_i210(hw);
|
||||
if (ret_val)
|
||||
hw_dbg("Flash update time out\n");
|
||||
else
|
||||
hw_dbg("Flash update complete\n");
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_valid_led_default_i210 - Verify a valid default LED config
|
||||
* @hw: pointer to the HW structure
|
||||
* @data: pointer to the NVM (EEPROM)
|
||||
*
|
||||
* Read the EEPROM for the current default LED configuration. If the
|
||||
* LED configuration is not valid, set to a valid LED configuration.
|
||||
**/
|
||||
s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
|
||||
{
|
||||
s32 ret_val;
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
|
||||
switch (hw->phy.media_type) {
|
||||
case e1000_media_type_internal_serdes:
|
||||
*data = ID_LED_DEFAULT_I210_SERDES;
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
default:
|
||||
*data = ID_LED_DEFAULT_I210;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* __igb_access_xmdio_reg - Read/write XMDIO register
|
||||
* @hw: pointer to the HW structure
|
||||
* @address: XMDIO address to program
|
||||
* @dev_addr: device address to program
|
||||
* @data: pointer to value to read/write from/to the XMDIO address
|
||||
* @read: boolean flag to indicate read or write
|
||||
**/
|
||||
static s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address,
|
||||
u8 dev_addr, u16 *data, bool read)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
|
||||
dev_addr);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
if (read)
|
||||
ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
|
||||
else
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
/* Recalibrate the device back to 0 */
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_xmdio_reg - Read XMDIO register
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: XMDIO address to program
|
||||
* @dev_addr: device address to program
|
||||
* @data: value to be read from the EMI address
|
||||
**/
|
||||
s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
|
||||
{
|
||||
return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_xmdio_reg - Write XMDIO register
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: XMDIO address to program
|
||||
* @dev_addr: device address to program
|
||||
* @data: value to be written to the XMDIO address
|
||||
**/
|
||||
s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
|
||||
{
|
||||
return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_init_nvm_params_i210 - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 igb_init_nvm_params_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
|
||||
nvm->ops.acquire = igb_acquire_nvm_i210;
|
||||
nvm->ops.release = igb_release_nvm_i210;
|
||||
nvm->ops.valid_led_default = igb_valid_led_default_i210;
|
||||
|
||||
/* NVM Function Pointers */
|
||||
if (igb_get_flash_presence_i210(hw)) {
|
||||
hw->nvm.type = e1000_nvm_flash_hw;
|
||||
nvm->ops.read = igb_read_nvm_srrd_i210;
|
||||
nvm->ops.write = igb_write_nvm_srwr_i210;
|
||||
nvm->ops.validate = igb_validate_nvm_checksum_i210;
|
||||
nvm->ops.update = igb_update_nvm_checksum_i210;
|
||||
} else {
|
||||
hw->nvm.type = e1000_nvm_invm;
|
||||
nvm->ops.read = igb_read_invm_i210;
|
||||
nvm->ops.write = NULL;
|
||||
nvm->ops.validate = NULL;
|
||||
nvm->ops.update = NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_pll_workaround_i210
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Works around an errata in the PLL circuit where it occasionally
|
||||
* provides the wrong clock frequency after power up.
|
||||
**/
|
||||
s32 igb_pll_workaround_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
|
||||
u16 nvm_word, phy_word, pci_word, tmp_nvm;
|
||||
int i;
|
||||
|
||||
/* Get and set needed register values */
|
||||
wuc = rd32(E1000_WUC);
|
||||
mdicnfg = rd32(E1000_MDICNFG);
|
||||
reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;
|
||||
wr32(E1000_MDICNFG, reg_val);
|
||||
|
||||
/* Get data from NVM, or set default */
|
||||
ret_val = igb_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD,
|
||||
&nvm_word);
|
||||
if (ret_val)
|
||||
nvm_word = E1000_INVM_DEFAULT_AL;
|
||||
tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
|
||||
igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, E1000_PHY_PLL_FREQ_PAGE);
|
||||
phy_word = E1000_PHY_PLL_UNCONF;
|
||||
for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
|
||||
/* check current state directly from internal PHY */
|
||||
igb_read_phy_reg_82580(hw, E1000_PHY_PLL_FREQ_REG, &phy_word);
|
||||
if ((phy_word & E1000_PHY_PLL_UNCONF)
|
||||
!= E1000_PHY_PLL_UNCONF) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
} else {
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
}
|
||||
/* directly reset the internal PHY */
|
||||
ctrl = rd32(E1000_CTRL);
|
||||
wr32(E1000_CTRL, ctrl|E1000_CTRL_PHY_RST);
|
||||
|
||||
ctrl_ext = rd32(E1000_CTRL_EXT);
|
||||
ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);
|
||||
wr32(E1000_CTRL_EXT, ctrl_ext);
|
||||
|
||||
wr32(E1000_WUC, 0);
|
||||
reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
|
||||
wr32(E1000_EEARBC_I210, reg_val);
|
||||
|
||||
igb_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
|
||||
pci_word |= E1000_PCI_PMCSR_D3;
|
||||
igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
|
||||
usleep_range(1000, 2000);
|
||||
pci_word &= ~E1000_PCI_PMCSR_D3;
|
||||
igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
|
||||
reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);
|
||||
wr32(E1000_EEARBC_I210, reg_val);
|
||||
|
||||
/* restore WUC register */
|
||||
wr32(E1000_WUC, wuc);
|
||||
}
|
||||
igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, 0);
|
||||
/* restore MDICNFG setting */
|
||||
wr32(E1000_MDICNFG, mdicnfg);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_get_cfg_done_i210 - Read config done bit
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Read the management control register for the config done bit for
|
||||
* completion status. NOTE: silicon which is EEPROM-less will fail trying
|
||||
* to read the config done bit, so an error is *ONLY* logged and returns
|
||||
* 0. If we were to return with error, EEPROM-less silicon
|
||||
* would not be able to be reset or change link.
|
||||
**/
|
||||
s32 igb_get_cfg_done_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 timeout = PHY_CFG_TIMEOUT;
|
||||
u32 mask = E1000_NVM_CFG_DONE_PORT_0;
|
||||
|
||||
while (timeout) {
|
||||
if (rd32(E1000_EEMNGCTL_I210) & mask)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
timeout--;
|
||||
}
|
||||
if (!timeout)
|
||||
hw_dbg("MNG configuration cycle has not completed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_I210_H_
|
||||
#define _E1000_I210_H_
|
||||
|
||||
s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
|
||||
void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
|
||||
s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
|
||||
s32 igb_read_invm_version(struct e1000_hw *hw,
|
||||
struct e1000_fw_version *invm_ver);
|
||||
s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data);
|
||||
s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data);
|
||||
s32 igb_init_nvm_params_i210(struct e1000_hw *hw);
|
||||
bool igb_get_flash_presence_i210(struct e1000_hw *hw);
|
||||
s32 igb_pll_workaround_i210(struct e1000_hw *hw);
|
||||
s32 igb_get_cfg_done_i210(struct e1000_hw *hw);
|
||||
|
||||
#define E1000_STM_OPCODE 0xDB00
|
||||
#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
|
||||
|
||||
#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
|
||||
(u8)((invm_dword) & 0x7)
|
||||
#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
|
||||
(u8)(((invm_dword) & 0x0000FE00) >> 9)
|
||||
#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
|
||||
(u16)(((invm_dword) & 0xFFFF0000) >> 16)
|
||||
|
||||
enum E1000_INVM_STRUCTURE_TYPE {
|
||||
E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00,
|
||||
E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01,
|
||||
E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02,
|
||||
E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03,
|
||||
E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04,
|
||||
E1000_INVM_INVALIDATED_STRUCTURE = 0x0F,
|
||||
};
|
||||
|
||||
#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
|
||||
#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
|
||||
#define E1000_INVM_ULT_BYTES_SIZE 8
|
||||
#define E1000_INVM_RECORD_SIZE_IN_BYTES 4
|
||||
#define E1000_INVM_VER_FIELD_ONE 0x1FF8
|
||||
#define E1000_INVM_VER_FIELD_TWO 0x7FE000
|
||||
#define E1000_INVM_IMGTYPE_FIELD 0x1F800000
|
||||
|
||||
#define E1000_INVM_MAJOR_MASK 0x3F0
|
||||
#define E1000_INVM_MINOR_MASK 0xF
|
||||
#define E1000_INVM_MAJOR_SHIFT 4
|
||||
|
||||
#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_OFF2))
|
||||
#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
/* NVM offset defaults for i211 device */
|
||||
#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243
|
||||
#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1
|
||||
#define NVM_LED_1_CFG_DEFAULT_I211 0x0184
|
||||
#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C
|
||||
|
||||
/* PLL Defines */
|
||||
#define E1000_PCI_PMCSR 0x44
|
||||
#define E1000_PCI_PMCSR_D3 0x03
|
||||
#define E1000_MAX_PLL_TRIES 5
|
||||
#define E1000_PHY_PLL_UNCONF 0xFF
|
||||
#define E1000_PHY_PLL_FREQ_PAGE 0xFC
|
||||
#define E1000_PHY_PLL_FREQ_REG 0x000E
|
||||
#define E1000_INVM_DEFAULT_AL 0x202F
|
||||
#define E1000_INVM_AUTOLOAD 0x0A
|
||||
#define E1000_INVM_PLL_WO_VAL 0x0010
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,911 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
/* e1000_i210
|
||||
* e1000_i211
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "e1000_hw.h"
|
||||
#include "e1000_i210.h"
|
||||
|
||||
static s32 igb_update_flash_i210(struct e1000_hw *hw);
|
||||
|
||||
/**
|
||||
* igb_get_hw_semaphore_i210 - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM
|
||||
*/
|
||||
static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
s32 timeout = hw->nvm.word_size + 1;
|
||||
s32 i = 0;
|
||||
|
||||
/* Get the SW semaphore */
|
||||
while (i < timeout) {
|
||||
swsm = rd32(E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
udelay(50);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* In rare circumstances, the SW semaphore may already be held
|
||||
* unintentionally. Clear the semaphore once before giving up.
|
||||
*/
|
||||
if (hw->dev_spec._82575.clear_semaphore_once) {
|
||||
hw->dev_spec._82575.clear_semaphore_once = false;
|
||||
igb_put_hw_semaphore(hw);
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = rd32(E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
udelay(50);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we do not have the semaphore here, we have to give up. */
|
||||
if (i == timeout) {
|
||||
hw_dbg("Driver can't access device - SMBI bit is set.\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the FW semaphore. */
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = rd32(E1000_SWSM);
|
||||
wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
|
||||
|
||||
/* Semaphore acquired if bit latched */
|
||||
if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
|
||||
break;
|
||||
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* Release semaphores */
|
||||
igb_put_hw_semaphore(hw);
|
||||
hw_dbg("Driver can't access the NVM\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_acquire_nvm_i210 - Request for access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the necessary semaphores for exclusive access to the EEPROM.
|
||||
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
|
||||
* Return successful if access grant bit set, else clear the request for
|
||||
* EEPROM access and return -E1000_ERR_NVM (-1).
|
||||
**/
|
||||
static s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
|
||||
{
|
||||
return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_nvm_i210 - Release exclusive access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Stop any current commands to the EEPROM and clear the EEPROM request bit,
|
||||
* then release the semaphores acquired.
|
||||
**/
|
||||
static void igb_release_nvm_i210(struct e1000_hw *hw)
|
||||
{
|
||||
igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
|
||||
* will also specify which port we're acquiring the lock for.
|
||||
**/
|
||||
s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
u32 swmask = mask;
|
||||
u32 fwmask = mask << 16;
|
||||
s32 ret_val = 0;
|
||||
s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
|
||||
|
||||
while (i < timeout) {
|
||||
if (igb_get_hw_semaphore_i210(hw)) {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync = rd32(E1000_SW_FW_SYNC);
|
||||
if (!(swfw_sync & (fwmask | swmask)))
|
||||
break;
|
||||
|
||||
/* Firmware currently using resource (fwmask) */
|
||||
igb_put_hw_semaphore(hw);
|
||||
mdelay(5);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync |= swmask;
|
||||
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
igb_put_hw_semaphore(hw);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_swfw_sync_i210 - Release SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
|
||||
* will also specify which port we're releasing the lock for.
|
||||
**/
|
||||
void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
|
||||
while (igb_get_hw_semaphore_i210(hw))
|
||||
; /* Empty */
|
||||
|
||||
swfw_sync = rd32(E1000_SW_FW_SYNC);
|
||||
swfw_sync &= ~mask;
|
||||
wr32(E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
igb_put_hw_semaphore(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the Shadow Ram to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the Shadow Ram
|
||||
*
|
||||
* Reads a 16 bit word from the Shadow Ram using the EERD register.
|
||||
* Uses necessary synchronization semaphores.
|
||||
**/
|
||||
static s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
s32 status = 0;
|
||||
u16 i, count;
|
||||
|
||||
/* We cannot hold synchronization semaphores for too long,
|
||||
* because of forceful takeover procedure. However it is more efficient
|
||||
* to read in bursts than synchronizing access for each word.
|
||||
*/
|
||||
for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
|
||||
count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
|
||||
E1000_EERD_EEWR_MAX_COUNT : (words - i);
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
status = igb_read_nvm_eerd(hw, offset, count,
|
||||
data + i);
|
||||
hw->nvm.ops.release(hw);
|
||||
} else {
|
||||
status = E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_nvm_srwr - Write to Shadow Ram using EEWR
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the Shadow Ram to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the Shadow Ram
|
||||
*
|
||||
* Writes data to Shadow Ram at offset using EEWR register.
|
||||
*
|
||||
* If igb_update_nvm_checksum is not called after this function , the
|
||||
* Shadow Ram will most likely contain an invalid checksum.
|
||||
**/
|
||||
static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i, k, eewr = 0;
|
||||
u32 attempts = 100000;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* too many words for the offset, and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
|
||||
(data[i] << E1000_NVM_RW_REG_DATA) |
|
||||
E1000_NVM_RW_REG_START;
|
||||
|
||||
wr32(E1000_SRWR, eewr);
|
||||
|
||||
for (k = 0; k < attempts; k++) {
|
||||
if (E1000_NVM_RW_REG_DONE &
|
||||
rd32(E1000_SRWR)) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
if (ret_val) {
|
||||
hw_dbg("Shadow RAM write EEWR timed out\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the Shadow RAM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the Shadow RAM
|
||||
*
|
||||
* Writes data to Shadow RAM at offset using EEWR register.
|
||||
*
|
||||
* If e1000_update_nvm_checksum is not called after this function , the
|
||||
* data will not be committed to FLASH and also Shadow RAM will most likely
|
||||
* contain an invalid checksum.
|
||||
*
|
||||
* If error code is returned, data and Shadow RAM may be inconsistent - buffer
|
||||
* partially written.
|
||||
**/
|
||||
static s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data)
|
||||
{
|
||||
s32 status = 0;
|
||||
u16 i, count;
|
||||
|
||||
/* We cannot hold synchronization semaphores for too long,
|
||||
* because of forceful takeover procedure. However it is more efficient
|
||||
* to write in bursts than synchronizing access for each word.
|
||||
*/
|
||||
for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
|
||||
count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
|
||||
E1000_EERD_EEWR_MAX_COUNT : (words - i);
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
status = igb_write_nvm_srwr(hw, offset, count,
|
||||
data + i);
|
||||
hw->nvm.ops.release(hw);
|
||||
} else {
|
||||
status = E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_invm_word_i210 - Reads OTP
|
||||
* @hw: pointer to the HW structure
|
||||
* @address: the word address (aka eeprom offset) to read
|
||||
* @data: pointer to the data read
|
||||
*
|
||||
* Reads 16-bit words from the OTP. Return error when the word is not
|
||||
* stored in OTP.
|
||||
**/
|
||||
static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
|
||||
{
|
||||
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
|
||||
u32 invm_dword;
|
||||
u16 i;
|
||||
u8 record_type, word_address;
|
||||
|
||||
for (i = 0; i < E1000_INVM_SIZE; i++) {
|
||||
invm_dword = rd32(E1000_INVM_DATA_REG(i));
|
||||
/* Get record type */
|
||||
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
|
||||
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
|
||||
break;
|
||||
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
|
||||
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
|
||||
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
|
||||
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
|
||||
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
|
||||
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
|
||||
if (word_address == address) {
|
||||
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
|
||||
hw_dbg("Read INVM Word 0x%02x = %x\n",
|
||||
address, *data);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status)
|
||||
hw_dbg("Requested word 0x%02x not found in OTP\n", address);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_invm_i210 - Read invm wrapper function for I210/I211
|
||||
* @hw: pointer to the HW structure
|
||||
* @words: number of words to read
|
||||
* @data: pointer to the data read
|
||||
*
|
||||
* Wrapper function to return data formerly found in the NVM.
|
||||
**/
|
||||
static s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset,
|
||||
u16 words __always_unused, u16 *data)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* Only the MAC addr is required to be present in the iNVM */
|
||||
switch (offset) {
|
||||
case NVM_MAC_ADDR:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]);
|
||||
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1,
|
||||
&data[1]);
|
||||
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2,
|
||||
&data[2]);
|
||||
if (ret_val)
|
||||
hw_dbg("MAC Addr not found in iNVM\n");
|
||||
break;
|
||||
case NVM_INIT_CTRL_2:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_INIT_CTRL_2_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_INIT_CTRL_4:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_INIT_CTRL_4_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_LED_1_CFG:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_LED_1_CFG_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_LED_0_2_CFG:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = NVM_LED_0_2_CFG_DEFAULT_I211;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_ID_LED_SETTINGS:
|
||||
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
|
||||
if (ret_val) {
|
||||
*data = ID_LED_RESERVED_FFFF;
|
||||
ret_val = 0;
|
||||
}
|
||||
break;
|
||||
case NVM_SUB_DEV_ID:
|
||||
*data = hw->subsystem_device_id;
|
||||
break;
|
||||
case NVM_SUB_VEN_ID:
|
||||
*data = hw->subsystem_vendor_id;
|
||||
break;
|
||||
case NVM_DEV_ID:
|
||||
*data = hw->device_id;
|
||||
break;
|
||||
case NVM_VEN_ID:
|
||||
*data = hw->vendor_id;
|
||||
break;
|
||||
default:
|
||||
hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
|
||||
*data = NVM_RESERVED_WORD;
|
||||
break;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_invm_version - Reads iNVM version and image type
|
||||
* @hw: pointer to the HW structure
|
||||
* @invm_ver: version structure for the version read
|
||||
*
|
||||
* Reads iNVM version and image type.
|
||||
**/
|
||||
s32 igb_read_invm_version(struct e1000_hw *hw,
|
||||
struct e1000_fw_version *invm_ver) {
|
||||
u32 *record = NULL;
|
||||
u32 *next_record = NULL;
|
||||
u32 i = 0;
|
||||
u32 invm_dword = 0;
|
||||
u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
|
||||
E1000_INVM_RECORD_SIZE_IN_BYTES);
|
||||
u32 buffer[E1000_INVM_SIZE];
|
||||
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
|
||||
u16 version = 0;
|
||||
|
||||
/* Read iNVM memory */
|
||||
for (i = 0; i < E1000_INVM_SIZE; i++) {
|
||||
invm_dword = rd32(E1000_INVM_DATA_REG(i));
|
||||
buffer[i] = invm_dword;
|
||||
}
|
||||
|
||||
/* Read version number */
|
||||
for (i = 1; i < invm_blocks; i++) {
|
||||
record = &buffer[invm_blocks - i];
|
||||
next_record = &buffer[invm_blocks - i + 1];
|
||||
|
||||
/* Check if we have first version location used */
|
||||
if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
|
||||
version = 0;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have second version location used */
|
||||
else if ((i == 1) &&
|
||||
((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
|
||||
version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have odd version location
|
||||
* used and it is the last one used
|
||||
*/
|
||||
else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
|
||||
((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
|
||||
(i != 1))) {
|
||||
version = (*next_record & E1000_INVM_VER_FIELD_TWO)
|
||||
>> 13;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have even version location
|
||||
* used and it is the last one used
|
||||
*/
|
||||
else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
|
||||
((*record & 0x3) == 0)) {
|
||||
version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
|
||||
>> E1000_INVM_MAJOR_SHIFT;
|
||||
invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
|
||||
}
|
||||
/* Read Image Type */
|
||||
for (i = 1; i < invm_blocks; i++) {
|
||||
record = &buffer[invm_blocks - i];
|
||||
next_record = &buffer[invm_blocks - i + 1];
|
||||
|
||||
/* Check if we have image type in first location used */
|
||||
if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
|
||||
invm_ver->invm_img_type = 0;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
/* Check if we have image type in first location used */
|
||||
else if ((((*record & 0x3) == 0) &&
|
||||
((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
|
||||
((((*record & 0x3) != 0) && (i != 1)))) {
|
||||
invm_ver->invm_img_type =
|
||||
(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
|
||||
**/
|
||||
static s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 status = 0;
|
||||
s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
|
||||
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
|
||||
/* Replace the read function with semaphore grabbing with
|
||||
* the one that skips this for a while.
|
||||
* We have semaphore taken already here.
|
||||
*/
|
||||
read_op_ptr = hw->nvm.ops.read;
|
||||
hw->nvm.ops.read = igb_read_nvm_eerd;
|
||||
|
||||
status = igb_validate_nvm_checksum(hw);
|
||||
|
||||
/* Revert original read operation. */
|
||||
hw->nvm.ops.read = read_op_ptr;
|
||||
|
||||
hw->nvm.ops.release(hw);
|
||||
} else {
|
||||
status = E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_update_nvm_checksum_i210 - Update EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* up to the checksum. Then calculates the EEPROM checksum and writes the
|
||||
* value to the EEPROM. Next commit EEPROM data onto the Flash.
|
||||
**/
|
||||
static s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
/* Read the first word from the EEPROM. If this times out or fails, do
|
||||
* not continue or we could be in for a very long wait while every
|
||||
* EEPROM read fails
|
||||
*/
|
||||
ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("EEPROM read failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(hw->nvm.ops.acquire(hw))) {
|
||||
/* Do not use hw->nvm.ops.write, hw->nvm.ops.read
|
||||
* because we do not want to take the synchronization
|
||||
* semaphores twice here.
|
||||
*/
|
||||
|
||||
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
|
||||
ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw->nvm.ops.release(hw);
|
||||
hw_dbg("NVM Read Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
checksum = (u16) NVM_SUM - checksum;
|
||||
ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
|
||||
&checksum);
|
||||
if (ret_val) {
|
||||
hw->nvm.ops.release(hw);
|
||||
hw_dbg("NVM Write Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
hw->nvm.ops.release(hw);
|
||||
|
||||
ret_val = igb_update_flash_i210(hw);
|
||||
} else {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_pool_flash_update_done_i210 - Pool FLUDONE status.
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
**/
|
||||
static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
u32 i, reg;
|
||||
|
||||
for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
|
||||
reg = rd32(E1000_EECD);
|
||||
if (reg & E1000_EECD_FLUDONE_I210) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_get_flash_presence_i210 - Check if flash device is detected.
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
**/
|
||||
bool igb_get_flash_presence_i210(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eec = 0;
|
||||
bool ret_val = false;
|
||||
|
||||
eec = rd32(E1000_EECD);
|
||||
if (eec & E1000_EECD_FLASH_DETECTED_I210)
|
||||
ret_val = true;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_update_flash_i210 - Commit EEPROM to the flash
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
**/
|
||||
static s32 igb_update_flash_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u32 flup;
|
||||
|
||||
ret_val = igb_pool_flash_update_done_i210(hw);
|
||||
if (ret_val == -E1000_ERR_NVM) {
|
||||
hw_dbg("Flash update time out\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
|
||||
wr32(E1000_EECD, flup);
|
||||
|
||||
ret_val = igb_pool_flash_update_done_i210(hw);
|
||||
if (ret_val)
|
||||
hw_dbg("Flash update time out\n");
|
||||
else
|
||||
hw_dbg("Flash update complete\n");
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_valid_led_default_i210 - Verify a valid default LED config
|
||||
* @hw: pointer to the HW structure
|
||||
* @data: pointer to the NVM (EEPROM)
|
||||
*
|
||||
* Read the EEPROM for the current default LED configuration. If the
|
||||
* LED configuration is not valid, set to a valid LED configuration.
|
||||
**/
|
||||
s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
|
||||
{
|
||||
s32 ret_val;
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
|
||||
switch (hw->phy.media_type) {
|
||||
case e1000_media_type_internal_serdes:
|
||||
*data = ID_LED_DEFAULT_I210_SERDES;
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
default:
|
||||
*data = ID_LED_DEFAULT_I210;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* __igb_access_xmdio_reg - Read/write XMDIO register
|
||||
* @hw: pointer to the HW structure
|
||||
* @address: XMDIO address to program
|
||||
* @dev_addr: device address to program
|
||||
* @data: pointer to value to read/write from/to the XMDIO address
|
||||
* @read: boolean flag to indicate read or write
|
||||
**/
|
||||
static s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address,
|
||||
u8 dev_addr, u16 *data, bool read)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
|
||||
dev_addr);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
if (read)
|
||||
ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
|
||||
else
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
/* Recalibrate the device back to 0 */
|
||||
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_xmdio_reg - Read XMDIO register
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: XMDIO address to program
|
||||
* @dev_addr: device address to program
|
||||
* @data: value to be read from the EMI address
|
||||
**/
|
||||
s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
|
||||
{
|
||||
return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_xmdio_reg - Write XMDIO register
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: XMDIO address to program
|
||||
* @dev_addr: device address to program
|
||||
* @data: value to be written to the XMDIO address
|
||||
**/
|
||||
s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
|
||||
{
|
||||
return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_init_nvm_params_i210 - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 igb_init_nvm_params_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
|
||||
nvm->ops.acquire = igb_acquire_nvm_i210;
|
||||
nvm->ops.release = igb_release_nvm_i210;
|
||||
nvm->ops.valid_led_default = igb_valid_led_default_i210;
|
||||
|
||||
/* NVM Function Pointers */
|
||||
if (igb_get_flash_presence_i210(hw)) {
|
||||
hw->nvm.type = e1000_nvm_flash_hw;
|
||||
nvm->ops.read = igb_read_nvm_srrd_i210;
|
||||
nvm->ops.write = igb_write_nvm_srwr_i210;
|
||||
nvm->ops.validate = igb_validate_nvm_checksum_i210;
|
||||
nvm->ops.update = igb_update_nvm_checksum_i210;
|
||||
} else {
|
||||
hw->nvm.type = e1000_nvm_invm;
|
||||
nvm->ops.read = igb_read_invm_i210;
|
||||
nvm->ops.write = NULL;
|
||||
nvm->ops.validate = NULL;
|
||||
nvm->ops.update = NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_pll_workaround_i210
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Works around an errata in the PLL circuit where it occasionally
|
||||
* provides the wrong clock frequency after power up.
|
||||
**/
|
||||
s32 igb_pll_workaround_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
|
||||
u16 nvm_word, phy_word, pci_word, tmp_nvm;
|
||||
int i;
|
||||
|
||||
/* Get and set needed register values */
|
||||
wuc = rd32(E1000_WUC);
|
||||
mdicnfg = rd32(E1000_MDICNFG);
|
||||
reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO;
|
||||
wr32(E1000_MDICNFG, reg_val);
|
||||
|
||||
/* Get data from NVM, or set default */
|
||||
ret_val = igb_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD,
|
||||
&nvm_word);
|
||||
if (ret_val)
|
||||
nvm_word = E1000_INVM_DEFAULT_AL;
|
||||
tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
|
||||
igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, E1000_PHY_PLL_FREQ_PAGE);
|
||||
phy_word = E1000_PHY_PLL_UNCONF;
|
||||
for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
|
||||
/* check current state directly from internal PHY */
|
||||
igb_read_phy_reg_82580(hw, E1000_PHY_PLL_FREQ_REG, &phy_word);
|
||||
if ((phy_word & E1000_PHY_PLL_UNCONF)
|
||||
!= E1000_PHY_PLL_UNCONF) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
} else {
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
}
|
||||
/* directly reset the internal PHY */
|
||||
ctrl = rd32(E1000_CTRL);
|
||||
wr32(E1000_CTRL, ctrl|E1000_CTRL_PHY_RST);
|
||||
|
||||
ctrl_ext = rd32(E1000_CTRL_EXT);
|
||||
ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE);
|
||||
wr32(E1000_CTRL_EXT, ctrl_ext);
|
||||
|
||||
wr32(E1000_WUC, 0);
|
||||
reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
|
||||
wr32(E1000_EEARBC_I210, reg_val);
|
||||
|
||||
igb_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
|
||||
pci_word |= E1000_PCI_PMCSR_D3;
|
||||
igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
|
||||
usleep_range(1000, 2000);
|
||||
pci_word &= ~E1000_PCI_PMCSR_D3;
|
||||
igb_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word);
|
||||
reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16);
|
||||
wr32(E1000_EEARBC_I210, reg_val);
|
||||
|
||||
/* restore WUC register */
|
||||
wr32(E1000_WUC, wuc);
|
||||
}
|
||||
igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, 0);
|
||||
/* restore MDICNFG setting */
|
||||
wr32(E1000_MDICNFG, mdicnfg);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_get_cfg_done_i210 - Read config done bit
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Read the management control register for the config done bit for
|
||||
* completion status. NOTE: silicon which is EEPROM-less will fail trying
|
||||
* to read the config done bit, so an error is *ONLY* logged and returns
|
||||
* 0. If we were to return with error, EEPROM-less silicon
|
||||
* would not be able to be reset or change link.
|
||||
**/
|
||||
s32 igb_get_cfg_done_i210(struct e1000_hw *hw)
|
||||
{
|
||||
s32 timeout = PHY_CFG_TIMEOUT;
|
||||
u32 mask = E1000_NVM_CFG_DONE_PORT_0;
|
||||
|
||||
while (timeout) {
|
||||
if (rd32(E1000_EEMNGCTL_I210) & mask)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
timeout--;
|
||||
}
|
||||
if (!timeout)
|
||||
hw_dbg("MNG configuration cycle has not completed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_I210_H_
|
||||
#define _E1000_I210_H_
|
||||
|
||||
s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
|
||||
void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
|
||||
s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
|
||||
s32 igb_read_invm_version(struct e1000_hw *hw,
|
||||
struct e1000_fw_version *invm_ver);
|
||||
s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data);
|
||||
s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data);
|
||||
s32 igb_init_nvm_params_i210(struct e1000_hw *hw);
|
||||
bool igb_get_flash_presence_i210(struct e1000_hw *hw);
|
||||
s32 igb_pll_workaround_i210(struct e1000_hw *hw);
|
||||
s32 igb_get_cfg_done_i210(struct e1000_hw *hw);
|
||||
|
||||
#define E1000_STM_OPCODE 0xDB00
|
||||
#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
|
||||
|
||||
#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
|
||||
(u8)((invm_dword) & 0x7)
|
||||
#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
|
||||
(u8)(((invm_dword) & 0x0000FE00) >> 9)
|
||||
#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
|
||||
(u16)(((invm_dword) & 0xFFFF0000) >> 16)
|
||||
|
||||
enum E1000_INVM_STRUCTURE_TYPE {
|
||||
E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00,
|
||||
E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01,
|
||||
E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02,
|
||||
E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03,
|
||||
E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04,
|
||||
E1000_INVM_INVALIDATED_STRUCTURE = 0x0F,
|
||||
};
|
||||
|
||||
#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
|
||||
#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
|
||||
#define E1000_INVM_ULT_BYTES_SIZE 8
|
||||
#define E1000_INVM_RECORD_SIZE_IN_BYTES 4
|
||||
#define E1000_INVM_VER_FIELD_ONE 0x1FF8
|
||||
#define E1000_INVM_VER_FIELD_TWO 0x7FE000
|
||||
#define E1000_INVM_IMGTYPE_FIELD 0x1F800000
|
||||
|
||||
#define E1000_INVM_MAJOR_MASK 0x3F0
|
||||
#define E1000_INVM_MINOR_MASK 0xF
|
||||
#define E1000_INVM_MAJOR_SHIFT 4
|
||||
|
||||
#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_OFF2))
|
||||
#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
/* NVM offset defaults for i211 device */
|
||||
#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243
|
||||
#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1
|
||||
#define NVM_LED_1_CFG_DEFAULT_I211 0x0184
|
||||
#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C
|
||||
|
||||
/* PLL Defines */
|
||||
#define E1000_PCI_PMCSR 0x44
|
||||
#define E1000_PCI_PMCSR_D3 0x03
|
||||
#define E1000_MAX_PLL_TRIES 5
|
||||
#define E1000_PHY_PLL_UNCONF 0xFF
|
||||
#define E1000_PHY_PLL_FREQ_PAGE 0xFC
|
||||
#define E1000_PHY_PLL_FREQ_REG 0x000E
|
||||
#define E1000_INVM_DEFAULT_AL 0x202F
|
||||
#define E1000_INVM_AUTOLOAD 0x0A
|
||||
#define E1000_INVM_PLL_WO_VAL 0x0010
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_MAC_H_
|
||||
#define _E1000_MAC_H_
|
||||
|
||||
#include "e1000_hw-4.19-ethercat.h"
|
||||
|
||||
#include "e1000_phy-4.19-ethercat.h"
|
||||
#include "e1000_nvm-4.19-ethercat.h"
|
||||
#include "e1000_defines-4.19-ethercat.h"
|
||||
#include "e1000_i210-4.19-ethercat.h"
|
||||
|
||||
/* Functions that should not be called directly from drivers but can be used
|
||||
* by other files in this 'shared code'
|
||||
*/
|
||||
s32 igb_blink_led(struct e1000_hw *hw);
|
||||
s32 igb_check_for_copper_link(struct e1000_hw *hw);
|
||||
s32 igb_cleanup_led(struct e1000_hw *hw);
|
||||
s32 igb_config_fc_after_link_up(struct e1000_hw *hw);
|
||||
s32 igb_disable_pcie_master(struct e1000_hw *hw);
|
||||
s32 igb_force_mac_fc(struct e1000_hw *hw);
|
||||
s32 igb_get_auto_rd_done(struct e1000_hw *hw);
|
||||
s32 igb_get_bus_info_pcie(struct e1000_hw *hw);
|
||||
s32 igb_get_hw_semaphore(struct e1000_hw *hw);
|
||||
s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 igb_id_led_init(struct e1000_hw *hw);
|
||||
s32 igb_led_off(struct e1000_hw *hw);
|
||||
void igb_update_mc_addr_list(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count);
|
||||
s32 igb_setup_link(struct e1000_hw *hw);
|
||||
s32 igb_validate_mdi_setting(struct e1000_hw *hw);
|
||||
s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
|
||||
u32 offset, u8 data);
|
||||
|
||||
void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
|
||||
void igb_clear_vfta(struct e1000_hw *hw);
|
||||
void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, u32 vind,
|
||||
bool vlan_on, bool vlvf_bypass);
|
||||
void igb_config_collision_dist(struct e1000_hw *hw);
|
||||
void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
|
||||
void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
|
||||
void igb_put_hw_semaphore(struct e1000_hw *hw);
|
||||
void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
|
||||
s32 igb_check_alt_mac_addr(struct e1000_hw *hw);
|
||||
|
||||
bool igb_enable_mng_pass_thru(struct e1000_hw *hw);
|
||||
|
||||
enum e1000_mng_mode {
|
||||
e1000_mng_mode_none = 0,
|
||||
e1000_mng_mode_asf,
|
||||
e1000_mng_mode_pt,
|
||||
e1000_mng_mode_ipmi,
|
||||
e1000_mng_mode_host_if_only
|
||||
};
|
||||
|
||||
#define E1000_FACTPS_MNGCG 0x20000000
|
||||
|
||||
#define E1000_FWSM_MODE_MASK 0xE
|
||||
#define E1000_FWSM_MODE_SHIFT 1
|
||||
|
||||
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
|
||||
|
||||
void e1000_init_function_pointers_82575(struct e1000_hw *hw);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_MAC_H_
|
||||
#define _E1000_MAC_H_
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#include "e1000_phy.h"
|
||||
#include "e1000_nvm.h"
|
||||
#include "e1000_defines.h"
|
||||
#include "e1000_i210.h"
|
||||
|
||||
/* Functions that should not be called directly from drivers but can be used
|
||||
* by other files in this 'shared code'
|
||||
*/
|
||||
s32 igb_blink_led(struct e1000_hw *hw);
|
||||
s32 igb_check_for_copper_link(struct e1000_hw *hw);
|
||||
s32 igb_cleanup_led(struct e1000_hw *hw);
|
||||
s32 igb_config_fc_after_link_up(struct e1000_hw *hw);
|
||||
s32 igb_disable_pcie_master(struct e1000_hw *hw);
|
||||
s32 igb_force_mac_fc(struct e1000_hw *hw);
|
||||
s32 igb_get_auto_rd_done(struct e1000_hw *hw);
|
||||
s32 igb_get_bus_info_pcie(struct e1000_hw *hw);
|
||||
s32 igb_get_hw_semaphore(struct e1000_hw *hw);
|
||||
s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 igb_id_led_init(struct e1000_hw *hw);
|
||||
s32 igb_led_off(struct e1000_hw *hw);
|
||||
void igb_update_mc_addr_list(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count);
|
||||
s32 igb_setup_link(struct e1000_hw *hw);
|
||||
s32 igb_validate_mdi_setting(struct e1000_hw *hw);
|
||||
s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
|
||||
u32 offset, u8 data);
|
||||
|
||||
void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
|
||||
void igb_clear_vfta(struct e1000_hw *hw);
|
||||
void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, u32 vind,
|
||||
bool vlan_on, bool vlvf_bypass);
|
||||
void igb_config_collision_dist(struct e1000_hw *hw);
|
||||
void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
|
||||
void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
|
||||
void igb_put_hw_semaphore(struct e1000_hw *hw);
|
||||
void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
|
||||
s32 igb_check_alt_mac_addr(struct e1000_hw *hw);
|
||||
|
||||
bool igb_enable_mng_pass_thru(struct e1000_hw *hw);
|
||||
|
||||
enum e1000_mng_mode {
|
||||
e1000_mng_mode_none = 0,
|
||||
e1000_mng_mode_asf,
|
||||
e1000_mng_mode_pt,
|
||||
e1000_mng_mode_ipmi,
|
||||
e1000_mng_mode_host_if_only
|
||||
};
|
||||
|
||||
#define E1000_FACTPS_MNGCG 0x20000000
|
||||
|
||||
#define E1000_FWSM_MODE_MASK 0xE
|
||||
#define E1000_FWSM_MODE_SHIFT 1
|
||||
|
||||
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
|
||||
|
||||
void e1000_init_function_pointers_82575(struct e1000_hw *hw);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#include "e1000_mbx-4.19-ethercat.h"
|
||||
|
||||
/**
|
||||
* igb_read_mbx - Reads a message from the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to read
|
||||
*
|
||||
* returns SUCCESS if it successfully read message from buffer
|
||||
**/
|
||||
s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* limit read to size of mailbox */
|
||||
if (size > mbx->size)
|
||||
size = mbx->size;
|
||||
|
||||
if (mbx->ops.read)
|
||||
ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_mbx - Write a message to the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = 0;
|
||||
|
||||
if (size > mbx->size)
|
||||
ret_val = -E1000_ERR_MBX;
|
||||
|
||||
else if (mbx->ops.write)
|
||||
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_msg - checks to see if someone sent us mail
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the Status bit was found or else ERR_MBX
|
||||
**/
|
||||
s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_msg)
|
||||
ret_val = mbx->ops.check_for_msg(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_ack - checks to see if someone sent us ACK
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the Status bit was found or else ERR_MBX
|
||||
**/
|
||||
s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_ack)
|
||||
ret_val = mbx->ops.check_for_ack(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_rst - checks to see if other side has reset
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the Status bit was found or else ERR_MBX
|
||||
**/
|
||||
s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_rst)
|
||||
ret_val = mbx->ops.check_for_rst(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_unlock_mbx - unlock the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the mailbox was unlocked or else ERR_MBX
|
||||
**/
|
||||
s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.unlock)
|
||||
ret_val = mbx->ops.unlock(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_poll_for_msg - Wait for message notification
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification
|
||||
**/
|
||||
static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!countdown || !mbx->ops.check_for_msg)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
|
||||
countdown--;
|
||||
if (!countdown)
|
||||
break;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? 0 : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_poll_for_ack - Wait for message acknowledgement
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message acknowledgement
|
||||
**/
|
||||
static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!countdown || !mbx->ops.check_for_ack)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
|
||||
countdown--;
|
||||
if (!countdown)
|
||||
break;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? 0 : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_posted_mbx - Wait for message notification and receive message
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification and
|
||||
* copied it into the receive buffer.
|
||||
**/
|
||||
static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!mbx->ops.read)
|
||||
goto out;
|
||||
|
||||
ret_val = igb_poll_for_msg(hw, mbx_id);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read(hw, msg, size, mbx_id, true);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_posted_mbx - Write a message to the mailbox, wait for ack
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer and
|
||||
* received an ack to that message within delay * timeout period
|
||||
**/
|
||||
static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* exit if either we can't write or there isn't a defined timeout */
|
||||
if (!mbx->ops.write || !mbx->timeout)
|
||||
goto out;
|
||||
|
||||
/* send msg */
|
||||
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
|
||||
|
||||
/* if msg sent wait until we receive an ack */
|
||||
if (!ret_val)
|
||||
ret_val = igb_poll_for_ack(hw, mbx_id);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
|
||||
{
|
||||
u32 mbvficr = rd32(E1000_MBVFICR);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbvficr & mask) {
|
||||
ret_val = 0;
|
||||
wr32(E1000_MBVFICR, mask);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_msg_pf - checks to see if the VF has sent mail
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
hw->mbx.stats.reqs++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_ack_pf - checks to see if the VF has ACKed
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
hw->mbx.stats.acks++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_rst_pf - checks to see if the VF has reset
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
u32 vflre = rd32(E1000_VFLRE);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (vflre & BIT(vf_number)) {
|
||||
ret_val = 0;
|
||||
wr32(E1000_VFLRE, BIT(vf_number));
|
||||
hw->mbx.stats.rsts++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_obtain_mbx_lock_pf - obtain mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* return SUCCESS if we obtained the mailbox lock
|
||||
**/
|
||||
static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
u32 p2v_mailbox;
|
||||
int count = 10;
|
||||
|
||||
do {
|
||||
/* Take ownership of the buffer */
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
|
||||
|
||||
/* reserve mailbox for vf use */
|
||||
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
|
||||
if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
udelay(1000);
|
||||
} while (count-- > 0);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_mbx_lock_pf - release mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* return SUCCESS if we released the mailbox lock
|
||||
**/
|
||||
static s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
u32 p2v_mailbox;
|
||||
|
||||
/* drop PF lock of mailbox, if set */
|
||||
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
|
||||
if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
|
||||
wr32(E1000_P2VMAILBOX(vf_number),
|
||||
p2v_mailbox & ~E1000_P2VMAILBOX_PFU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_mbx_pf - Places a message in the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 vf_number)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
|
||||
if (ret_val)
|
||||
goto out_no_write;
|
||||
|
||||
/* flush msg and acks as we are overwriting the message buffer */
|
||||
igb_check_for_msg_pf(hw, vf_number);
|
||||
igb_check_for_ack_pf(hw, vf_number);
|
||||
|
||||
/* copy the caller specified message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
array_wr32(E1000_VMBMEM(vf_number), i, msg[i]);
|
||||
|
||||
/* Interrupt VF to tell it a message has been sent and release buffer*/
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_tx++;
|
||||
|
||||
out_no_write:
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_mbx_pf - Read a message from the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @vf_number: the VF index
|
||||
* @unlock: unlock the mailbox when done?
|
||||
*
|
||||
* This function copies a message from the mailbox buffer to the caller's
|
||||
* memory buffer. The presumption is that the caller knows that there was
|
||||
* a message due to a VF request so no polling for message is needed.
|
||||
**/
|
||||
static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 vf_number, bool unlock)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
|
||||
if (ret_val)
|
||||
goto out_no_read;
|
||||
|
||||
/* copy the message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
|
||||
|
||||
/* Acknowledge the message and release mailbox lock (or not) */
|
||||
if (unlock)
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
|
||||
else
|
||||
wr32(E1000_P2VMAILBOX(vf_number),
|
||||
E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_rx++;
|
||||
|
||||
out_no_read:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_mbx_params_pf - set initial values for pf mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Initializes the hw->mbx struct to correct values for pf mailbox
|
||||
*/
|
||||
s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
|
||||
mbx->timeout = 0;
|
||||
mbx->usec_delay = 0;
|
||||
|
||||
mbx->size = E1000_VFMAILBOX_SIZE;
|
||||
|
||||
mbx->ops.read = igb_read_mbx_pf;
|
||||
mbx->ops.write = igb_write_mbx_pf;
|
||||
mbx->ops.read_posted = igb_read_posted_mbx;
|
||||
mbx->ops.write_posted = igb_write_posted_mbx;
|
||||
mbx->ops.check_for_msg = igb_check_for_msg_pf;
|
||||
mbx->ops.check_for_ack = igb_check_for_ack_pf;
|
||||
mbx->ops.check_for_rst = igb_check_for_rst_pf;
|
||||
mbx->ops.unlock = igb_release_mbx_lock_pf;
|
||||
|
||||
mbx->stats.msgs_tx = 0;
|
||||
mbx->stats.msgs_rx = 0;
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_MBX_H_
|
||||
#define _E1000_MBX_H_
|
||||
|
||||
#include "e1000_hw-4.19-ethercat.h"
|
||||
|
||||
#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */
|
||||
#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
|
||||
#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
|
||||
#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
|
||||
#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
|
||||
|
||||
#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */
|
||||
#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */
|
||||
#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */
|
||||
#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
|
||||
|
||||
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
|
||||
|
||||
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
|
||||
* PF. The reverse is true if it is E1000_PF_*.
|
||||
* Message ACK's are the value or'd with 0xF0000000
|
||||
*/
|
||||
/* Messages below or'd with this are the ACK */
|
||||
#define E1000_VT_MSGTYPE_ACK 0x80000000
|
||||
/* Messages below or'd with this are the NACK */
|
||||
#define E1000_VT_MSGTYPE_NACK 0x40000000
|
||||
/* Indicates that VF is still clear to send requests */
|
||||
#define E1000_VT_MSGTYPE_CTS 0x20000000
|
||||
#define E1000_VT_MSGINFO_SHIFT 16
|
||||
/* bits 23:16 are used for exra info for certain messages */
|
||||
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_VF_RESET 0x01 /* VF requests reset */
|
||||
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */
|
||||
/* VF requests to clear all unicast MAC filters */
|
||||
#define E1000_VF_MAC_FILTER_CLR (0x01 << E1000_VT_MSGINFO_SHIFT)
|
||||
/* VF requests to add unicast MAC filter */
|
||||
#define E1000_VF_MAC_FILTER_ADD (0x02 << E1000_VT_MSGINFO_SHIFT)
|
||||
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */
|
||||
#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */
|
||||
#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */
|
||||
#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
|
||||
#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
|
||||
|
||||
s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock);
|
||||
s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_init_mbx_params_pf(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_MBX_H_ */
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#include "e1000_mbx.h"
|
||||
|
||||
/**
|
||||
* igb_read_mbx - Reads a message from the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to read
|
||||
*
|
||||
* returns SUCCESS if it successfully read message from buffer
|
||||
**/
|
||||
s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* limit read to size of mailbox */
|
||||
if (size > mbx->size)
|
||||
size = mbx->size;
|
||||
|
||||
if (mbx->ops.read)
|
||||
ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_mbx - Write a message to the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = 0;
|
||||
|
||||
if (size > mbx->size)
|
||||
ret_val = -E1000_ERR_MBX;
|
||||
|
||||
else if (mbx->ops.write)
|
||||
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_msg - checks to see if someone sent us mail
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the Status bit was found or else ERR_MBX
|
||||
**/
|
||||
s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_msg)
|
||||
ret_val = mbx->ops.check_for_msg(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_ack - checks to see if someone sent us ACK
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the Status bit was found or else ERR_MBX
|
||||
**/
|
||||
s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_ack)
|
||||
ret_val = mbx->ops.check_for_ack(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_rst - checks to see if other side has reset
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the Status bit was found or else ERR_MBX
|
||||
**/
|
||||
s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_rst)
|
||||
ret_val = mbx->ops.check_for_rst(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_unlock_mbx - unlock the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to check
|
||||
*
|
||||
* returns SUCCESS if the mailbox was unlocked or else ERR_MBX
|
||||
**/
|
||||
s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.unlock)
|
||||
ret_val = mbx->ops.unlock(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_poll_for_msg - Wait for message notification
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification
|
||||
**/
|
||||
static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!countdown || !mbx->ops.check_for_msg)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
|
||||
countdown--;
|
||||
if (!countdown)
|
||||
break;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? 0 : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_poll_for_ack - Wait for message acknowledgement
|
||||
* @hw: pointer to the HW structure
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message acknowledgement
|
||||
**/
|
||||
static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!countdown || !mbx->ops.check_for_ack)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
|
||||
countdown--;
|
||||
if (!countdown)
|
||||
break;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? 0 : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_posted_mbx - Wait for message notification and receive message
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification and
|
||||
* copied it into the receive buffer.
|
||||
**/
|
||||
static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!mbx->ops.read)
|
||||
goto out;
|
||||
|
||||
ret_val = igb_poll_for_msg(hw, mbx_id);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read(hw, msg, size, mbx_id, true);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_posted_mbx - Write a message to the mailbox, wait for ack
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @mbx_id: id of mailbox to write
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer and
|
||||
* received an ack to that message within delay * timeout period
|
||||
**/
|
||||
static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* exit if either we can't write or there isn't a defined timeout */
|
||||
if (!mbx->ops.write || !mbx->timeout)
|
||||
goto out;
|
||||
|
||||
/* send msg */
|
||||
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
|
||||
|
||||
/* if msg sent wait until we receive an ack */
|
||||
if (!ret_val)
|
||||
ret_val = igb_poll_for_ack(hw, mbx_id);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
|
||||
{
|
||||
u32 mbvficr = rd32(E1000_MBVFICR);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbvficr & mask) {
|
||||
ret_val = 0;
|
||||
wr32(E1000_MBVFICR, mask);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_msg_pf - checks to see if the VF has sent mail
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
hw->mbx.stats.reqs++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_ack_pf - checks to see if the VF has ACKed
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
hw->mbx.stats.acks++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_for_rst_pf - checks to see if the VF has reset
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if the VF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
u32 vflre = rd32(E1000_VFLRE);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (vflre & BIT(vf_number)) {
|
||||
ret_val = 0;
|
||||
wr32(E1000_VFLRE, BIT(vf_number));
|
||||
hw->mbx.stats.rsts++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_obtain_mbx_lock_pf - obtain mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* return SUCCESS if we obtained the mailbox lock
|
||||
**/
|
||||
static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
u32 p2v_mailbox;
|
||||
int count = 10;
|
||||
|
||||
do {
|
||||
/* Take ownership of the buffer */
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
|
||||
|
||||
/* reserve mailbox for vf use */
|
||||
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
|
||||
if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
udelay(1000);
|
||||
} while (count-- > 0);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_mbx_lock_pf - release mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* return SUCCESS if we released the mailbox lock
|
||||
**/
|
||||
static s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
u32 p2v_mailbox;
|
||||
|
||||
/* drop PF lock of mailbox, if set */
|
||||
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
|
||||
if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
|
||||
wr32(E1000_P2VMAILBOX(vf_number),
|
||||
p2v_mailbox & ~E1000_P2VMAILBOX_PFU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_mbx_pf - Places a message in the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @vf_number: the VF index
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 vf_number)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
|
||||
if (ret_val)
|
||||
goto out_no_write;
|
||||
|
||||
/* flush msg and acks as we are overwriting the message buffer */
|
||||
igb_check_for_msg_pf(hw, vf_number);
|
||||
igb_check_for_ack_pf(hw, vf_number);
|
||||
|
||||
/* copy the caller specified message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
array_wr32(E1000_VMBMEM(vf_number), i, msg[i]);
|
||||
|
||||
/* Interrupt VF to tell it a message has been sent and release buffer*/
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_tx++;
|
||||
|
||||
out_no_write:
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_mbx_pf - Read a message from the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
* @vf_number: the VF index
|
||||
* @unlock: unlock the mailbox when done?
|
||||
*
|
||||
* This function copies a message from the mailbox buffer to the caller's
|
||||
* memory buffer. The presumption is that the caller knows that there was
|
||||
* a message due to a VF request so no polling for message is needed.
|
||||
**/
|
||||
static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 vf_number, bool unlock)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
|
||||
if (ret_val)
|
||||
goto out_no_read;
|
||||
|
||||
/* copy the message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
|
||||
|
||||
/* Acknowledge the message and release mailbox lock (or not) */
|
||||
if (unlock)
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
|
||||
else
|
||||
wr32(E1000_P2VMAILBOX(vf_number),
|
||||
E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_rx++;
|
||||
|
||||
out_no_read:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_mbx_params_pf - set initial values for pf mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Initializes the hw->mbx struct to correct values for pf mailbox
|
||||
*/
|
||||
s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
|
||||
mbx->timeout = 0;
|
||||
mbx->usec_delay = 0;
|
||||
|
||||
mbx->size = E1000_VFMAILBOX_SIZE;
|
||||
|
||||
mbx->ops.read = igb_read_mbx_pf;
|
||||
mbx->ops.write = igb_write_mbx_pf;
|
||||
mbx->ops.read_posted = igb_read_posted_mbx;
|
||||
mbx->ops.write_posted = igb_write_posted_mbx;
|
||||
mbx->ops.check_for_msg = igb_check_for_msg_pf;
|
||||
mbx->ops.check_for_ack = igb_check_for_ack_pf;
|
||||
mbx->ops.check_for_rst = igb_check_for_rst_pf;
|
||||
mbx->ops.unlock = igb_release_mbx_lock_pf;
|
||||
|
||||
mbx->stats.msgs_tx = 0;
|
||||
mbx->stats.msgs_rx = 0;
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_MBX_H_
|
||||
#define _E1000_MBX_H_
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */
|
||||
#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
|
||||
#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
|
||||
#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
|
||||
#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
|
||||
|
||||
#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */
|
||||
#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */
|
||||
#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */
|
||||
#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
|
||||
|
||||
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
|
||||
|
||||
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
|
||||
* PF. The reverse is true if it is E1000_PF_*.
|
||||
* Message ACK's are the value or'd with 0xF0000000
|
||||
*/
|
||||
/* Messages below or'd with this are the ACK */
|
||||
#define E1000_VT_MSGTYPE_ACK 0x80000000
|
||||
/* Messages below or'd with this are the NACK */
|
||||
#define E1000_VT_MSGTYPE_NACK 0x40000000
|
||||
/* Indicates that VF is still clear to send requests */
|
||||
#define E1000_VT_MSGTYPE_CTS 0x20000000
|
||||
#define E1000_VT_MSGINFO_SHIFT 16
|
||||
/* bits 23:16 are used for exra info for certain messages */
|
||||
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_VF_RESET 0x01 /* VF requests reset */
|
||||
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */
|
||||
/* VF requests to clear all unicast MAC filters */
|
||||
#define E1000_VF_MAC_FILTER_CLR (0x01 << E1000_VT_MSGINFO_SHIFT)
|
||||
/* VF requests to add unicast MAC filter */
|
||||
#define E1000_VF_MAC_FILTER_ADD (0x02 << E1000_VT_MSGINFO_SHIFT)
|
||||
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */
|
||||
#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */
|
||||
#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */
|
||||
#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
|
||||
#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
|
||||
|
||||
s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock);
|
||||
s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 igb_init_mbx_params_pf(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_MBX_H_ */
|
||||
|
|
@ -0,0 +1,782 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "e1000_mac-4.19-ethercat.h"
|
||||
#include "e1000_nvm-4.19-ethercat.h"
|
||||
|
||||
/**
|
||||
* igb_raise_eec_clk - Raise EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Enable/Raise the EEPROM clock bit.
|
||||
**/
|
||||
static void igb_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd | E1000_EECD_SK;
|
||||
wr32(E1000_EECD, *eecd);
|
||||
wrfl();
|
||||
udelay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_lower_eec_clk - Lower EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Clear/Lower the EEPROM clock bit.
|
||||
**/
|
||||
static void igb_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd & ~E1000_EECD_SK;
|
||||
wr32(E1000_EECD, *eecd);
|
||||
wrfl();
|
||||
udelay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_shift_out_eec_bits - Shift data bits our to the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @data: data to send to the EEPROM
|
||||
* @count: number of bits to shift out
|
||||
*
|
||||
* We need to shift 'count' bits out to the EEPROM. So, the 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.
|
||||
**/
|
||||
static void igb_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
u32 mask;
|
||||
|
||||
mask = 1u << (count - 1);
|
||||
if (nvm->type == e1000_nvm_eeprom_spi)
|
||||
eecd |= E1000_EECD_DO;
|
||||
|
||||
do {
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
|
||||
if (data & mask)
|
||||
eecd |= E1000_EECD_DI;
|
||||
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
|
||||
udelay(nvm->delay_usec);
|
||||
|
||||
igb_raise_eec_clk(hw, &eecd);
|
||||
igb_lower_eec_clk(hw, &eecd);
|
||||
|
||||
mask >>= 1;
|
||||
} while (mask);
|
||||
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
wr32(E1000_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_shift_in_eec_bits - Shift data bits in from the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @count: number of bits to shift in
|
||||
*
|
||||
* In order to read a register from the EEPROM, we need to shift 'count' 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 data out
|
||||
* "DO" bit. During this "shifting in" process the data in "DI" bit should
|
||||
* always be clear.
|
||||
**/
|
||||
static u16 igb_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
|
||||
{
|
||||
u32 eecd;
|
||||
u32 i;
|
||||
u16 data;
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
|
||||
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
|
||||
data = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
data <<= 1;
|
||||
igb_raise_eec_clk(hw, &eecd);
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
if (eecd & E1000_EECD_DO)
|
||||
data |= 1;
|
||||
|
||||
igb_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_poll_eerd_eewr_done - Poll for EEPROM read/write completion
|
||||
* @hw: pointer to the HW structure
|
||||
* @ee_reg: EEPROM flag for polling
|
||||
*
|
||||
* Polls the EEPROM status bit for either read or write completion based
|
||||
* upon the value of 'ee_reg'.
|
||||
**/
|
||||
static s32 igb_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
|
||||
{
|
||||
u32 attempts = 100000;
|
||||
u32 i, reg = 0;
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
|
||||
for (i = 0; i < attempts; i++) {
|
||||
if (ee_reg == E1000_NVM_POLL_READ)
|
||||
reg = rd32(E1000_EERD);
|
||||
else
|
||||
reg = rd32(E1000_EEWR);
|
||||
|
||||
if (reg & E1000_NVM_RW_REG_DONE) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_acquire_nvm - Generic request for access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
|
||||
* Return successful if access grant bit set, else clear the request for
|
||||
* EEPROM access and return -E1000_ERR_NVM (-1).
|
||||
**/
|
||||
s32 igb_acquire_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
|
||||
s32 ret_val = 0;
|
||||
|
||||
|
||||
wr32(E1000_EECD, eecd | E1000_EECD_REQ);
|
||||
eecd = rd32(E1000_EECD);
|
||||
|
||||
while (timeout) {
|
||||
if (eecd & E1000_EECD_GNT)
|
||||
break;
|
||||
udelay(5);
|
||||
eecd = rd32(E1000_EECD);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
wr32(E1000_EECD, eecd);
|
||||
hw_dbg("Could not acquire NVM grant\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_standby_nvm - Return EEPROM to standby state
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Return the EEPROM to a standby state.
|
||||
**/
|
||||
static void igb_standby_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
|
||||
if (nvm->type == e1000_nvm_eeprom_spi) {
|
||||
/* Toggle CS to flush commands */
|
||||
eecd |= E1000_EECD_CS;
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
udelay(nvm->delay_usec);
|
||||
eecd &= ~E1000_EECD_CS;
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
udelay(nvm->delay_usec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_stop_nvm - Terminate EEPROM command
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Terminates the current command by inverting the EEPROM's chip select pin.
|
||||
**/
|
||||
static void e1000_stop_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
if (hw->nvm.type == e1000_nvm_eeprom_spi) {
|
||||
/* Pull CS high */
|
||||
eecd |= E1000_EECD_CS;
|
||||
igb_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_nvm - Release exclusive access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
|
||||
**/
|
||||
void igb_release_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
e1000_stop_nvm(hw);
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
wr32(E1000_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_ready_nvm_eeprom - Prepares EEPROM for read/write
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups the EEPROM for reading and writing.
|
||||
**/
|
||||
static s32 igb_ready_nvm_eeprom(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
s32 ret_val = 0;
|
||||
u16 timeout = 0;
|
||||
u8 spi_stat_reg;
|
||||
|
||||
|
||||
if (nvm->type == e1000_nvm_eeprom_spi) {
|
||||
/* Clear SK and CS */
|
||||
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
udelay(1);
|
||||
timeout = NVM_MAX_RETRY_SPI;
|
||||
|
||||
/* Read "Status Register" repeatedly until the LSB is cleared.
|
||||
* The EEPROM will signal that the command has been completed
|
||||
* by clearing bit 0 of the internal status register. If it's
|
||||
* not cleared within 'timeout', then error out.
|
||||
*/
|
||||
while (timeout) {
|
||||
igb_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
|
||||
hw->nvm.opcode_bits);
|
||||
spi_stat_reg = (u8)igb_shift_in_eec_bits(hw, 8);
|
||||
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
|
||||
break;
|
||||
|
||||
udelay(5);
|
||||
igb_standby_nvm(hw);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
hw_dbg("SPI NVM Status error\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_nvm_spi - Read EEPROM's using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM.
|
||||
**/
|
||||
s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i = 0;
|
||||
s32 ret_val;
|
||||
u16 word_in;
|
||||
u8 read_opcode = NVM_READ_OPCODE_SPI;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = igb_ready_nvm_eeprom(hw);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
|
||||
igb_standby_nvm(hw);
|
||||
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
read_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the READ command (opcode + addr) */
|
||||
igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
|
||||
igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
|
||||
|
||||
/* Read the data. SPI NVMs increment the address with each byte
|
||||
* read and will roll over if reading beyond the end. This allows
|
||||
* us to read the whole NVM from any offset
|
||||
*/
|
||||
for (i = 0; i < words; i++) {
|
||||
word_in = igb_shift_in_eec_bits(hw, 16);
|
||||
data[i] = (word_in >> 8) | (word_in << 8);
|
||||
}
|
||||
|
||||
release:
|
||||
nvm->ops.release(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_nvm_eerd - Reads EEPROM using EERD register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM using the EERD register.
|
||||
**/
|
||||
s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i, eerd = 0;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
|
||||
E1000_NVM_RW_REG_START;
|
||||
|
||||
wr32(E1000_EERD, eerd);
|
||||
ret_val = igb_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
|
||||
if (ret_val)
|
||||
break;
|
||||
|
||||
data[i] = (rd32(E1000_EERD) >>
|
||||
E1000_NVM_RW_REG_DATA);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_nvm_spi - Write to EEPROM using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the EEPROM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the EEPROM
|
||||
*
|
||||
* Writes data to EEPROM at offset using SPI interface.
|
||||
*
|
||||
* If e1000_update_nvm_checksum is not called after this function , the
|
||||
* EEPROM will most likley contain an invalid checksum.
|
||||
**/
|
||||
s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
u16 widx = 0;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
while (widx < words) {
|
||||
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = igb_ready_nvm_eeprom(hw);
|
||||
if (ret_val) {
|
||||
nvm->ops.release(hw);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
igb_standby_nvm(hw);
|
||||
|
||||
/* Send the WRITE ENABLE command (8 bit opcode) */
|
||||
igb_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
|
||||
nvm->opcode_bits);
|
||||
|
||||
igb_standby_nvm(hw);
|
||||
|
||||
/* Some SPI eeproms use the 8th address bit embedded in the
|
||||
* opcode
|
||||
*/
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
write_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the Write command (8-bit opcode + addr) */
|
||||
igb_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
|
||||
igb_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
|
||||
nvm->address_bits);
|
||||
|
||||
/* Loop to allow for up to whole page write of eeprom */
|
||||
while (widx < words) {
|
||||
u16 word_out = data[widx];
|
||||
|
||||
word_out = (word_out >> 8) | (word_out << 8);
|
||||
igb_shift_out_eec_bits(hw, word_out, 16);
|
||||
widx++;
|
||||
|
||||
if ((((offset + widx) * 2) % nvm->page_size) == 0) {
|
||||
igb_standby_nvm(hw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
nvm->ops.release(hw);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_part_string - Read device part number
|
||||
* @hw: pointer to the HW structure
|
||||
* @part_num: pointer to device part number
|
||||
* @part_num_size: size of part number buffer
|
||||
*
|
||||
* Reads the product board assembly (PBA) number from the EEPROM and stores
|
||||
* the value in part_num.
|
||||
**/
|
||||
s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 nvm_data;
|
||||
u16 pointer;
|
||||
u16 offset;
|
||||
u16 length;
|
||||
|
||||
if (part_num == NULL) {
|
||||
hw_dbg("PBA string buffer was null\n");
|
||||
ret_val = E1000_ERR_INVALID_ARGUMENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if nvm_data is not ptr guard the PBA must be in legacy format which
|
||||
* means pointer is actually our second data word for the PBA number
|
||||
* and we can decode it into an ascii string
|
||||
*/
|
||||
if (nvm_data != NVM_PBA_PTR_GUARD) {
|
||||
hw_dbg("NVM PBA number is not stored as string\n");
|
||||
|
||||
/* we will need 11 characters to store the PBA */
|
||||
if (part_num_size < 11) {
|
||||
hw_dbg("PBA string buffer too small\n");
|
||||
return E1000_ERR_NO_SPACE;
|
||||
}
|
||||
|
||||
/* extract hex string from data and pointer */
|
||||
part_num[0] = (nvm_data >> 12) & 0xF;
|
||||
part_num[1] = (nvm_data >> 8) & 0xF;
|
||||
part_num[2] = (nvm_data >> 4) & 0xF;
|
||||
part_num[3] = nvm_data & 0xF;
|
||||
part_num[4] = (pointer >> 12) & 0xF;
|
||||
part_num[5] = (pointer >> 8) & 0xF;
|
||||
part_num[6] = '-';
|
||||
part_num[7] = 0;
|
||||
part_num[8] = (pointer >> 4) & 0xF;
|
||||
part_num[9] = pointer & 0xF;
|
||||
|
||||
/* put a null character on the end of our string */
|
||||
part_num[10] = '\0';
|
||||
|
||||
/* switch all the data but the '-' to hex char */
|
||||
for (offset = 0; offset < 10; offset++) {
|
||||
if (part_num[offset] < 0xA)
|
||||
part_num[offset] += '0';
|
||||
else if (part_num[offset] < 0x10)
|
||||
part_num[offset] += 'A' - 0xA;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, pointer, 1, &length);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (length == 0xFFFF || length == 0) {
|
||||
hw_dbg("NVM PBA number section invalid length\n");
|
||||
ret_val = E1000_ERR_NVM_PBA_SECTION;
|
||||
goto out;
|
||||
}
|
||||
/* check if part_num buffer is big enough */
|
||||
if (part_num_size < (((u32)length * 2) - 1)) {
|
||||
hw_dbg("PBA string buffer too small\n");
|
||||
ret_val = E1000_ERR_NO_SPACE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* trim pba length from start of string */
|
||||
pointer++;
|
||||
length--;
|
||||
|
||||
for (offset = 0; offset < length; offset++) {
|
||||
ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
part_num[offset * 2] = (u8)(nvm_data >> 8);
|
||||
part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
|
||||
}
|
||||
part_num[offset * 2] = '\0';
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_mac_addr - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reads the device MAC address from the EEPROM and stores the value.
|
||||
* Since devices with two ports use the same EEPROM, we increment the
|
||||
* last bit in the MAC address for the second port.
|
||||
**/
|
||||
s32 igb_read_mac_addr(struct e1000_hw *hw)
|
||||
{
|
||||
u32 rar_high;
|
||||
u32 rar_low;
|
||||
u16 i;
|
||||
|
||||
rar_high = rd32(E1000_RAH(0));
|
||||
rar_low = rd32(E1000_RAL(0));
|
||||
|
||||
for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
|
||||
|
||||
for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_validate_nvm_checksum - Validate EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
|
||||
**/
|
||||
s32 igb_validate_nvm_checksum(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
|
||||
if (checksum != (u16) NVM_SUM) {
|
||||
hw_dbg("NVM Checksum Invalid\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_update_nvm_checksum - Update EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* up to the checksum. Then calculates the EEPROM checksum and writes the
|
||||
* value to the EEPROM.
|
||||
**/
|
||||
s32 igb_update_nvm_checksum(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
checksum = (u16) NVM_SUM - checksum;
|
||||
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
|
||||
if (ret_val)
|
||||
hw_dbg("NVM Write Error while updating checksum.\n");
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_get_fw_version - Get firmware version information
|
||||
* @hw: pointer to the HW structure
|
||||
* @fw_vers: pointer to output structure
|
||||
*
|
||||
* unsupported MAC types will return all 0 version structure
|
||||
**/
|
||||
void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
|
||||
{
|
||||
u16 eeprom_verh, eeprom_verl, etrack_test, fw_version;
|
||||
u8 q, hval, rem, result;
|
||||
u16 comb_verh, comb_verl, comb_offset;
|
||||
|
||||
memset(fw_vers, 0, sizeof(struct e1000_fw_version));
|
||||
|
||||
/* basic eeprom version numbers and bits used vary by part and by tool
|
||||
* used to create the nvm images. Check which data format we have.
|
||||
*/
|
||||
hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
|
||||
switch (hw->mac.type) {
|
||||
case e1000_i211:
|
||||
igb_read_invm_version(hw, fw_vers);
|
||||
return;
|
||||
case e1000_82575:
|
||||
case e1000_82576:
|
||||
case e1000_82580:
|
||||
/* Use this format, unless EETRACK ID exists,
|
||||
* then use alternate format
|
||||
*/
|
||||
if ((etrack_test & NVM_MAJOR_MASK) != NVM_ETRACK_VALID) {
|
||||
hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
|
||||
fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
|
||||
>> NVM_MAJOR_SHIFT;
|
||||
fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK)
|
||||
>> NVM_MINOR_SHIFT;
|
||||
fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK);
|
||||
goto etrack_id;
|
||||
}
|
||||
break;
|
||||
case e1000_i210:
|
||||
if (!(igb_get_flash_presence_i210(hw))) {
|
||||
igb_read_invm_version(hw, fw_vers);
|
||||
return;
|
||||
}
|
||||
/* fall through */
|
||||
case e1000_i350:
|
||||
/* find combo image version */
|
||||
hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
|
||||
if ((comb_offset != 0x0) &&
|
||||
(comb_offset != NVM_VER_INVALID)) {
|
||||
|
||||
hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
|
||||
+ 1), 1, &comb_verh);
|
||||
hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
|
||||
1, &comb_verl);
|
||||
|
||||
/* get Option Rom version if it exists and is valid */
|
||||
if ((comb_verh && comb_verl) &&
|
||||
((comb_verh != NVM_VER_INVALID) &&
|
||||
(comb_verl != NVM_VER_INVALID))) {
|
||||
|
||||
fw_vers->or_valid = true;
|
||||
fw_vers->or_major =
|
||||
comb_verl >> NVM_COMB_VER_SHFT;
|
||||
fw_vers->or_build =
|
||||
(comb_verl << NVM_COMB_VER_SHFT)
|
||||
| (comb_verh >> NVM_COMB_VER_SHFT);
|
||||
fw_vers->or_patch =
|
||||
comb_verh & NVM_COMB_VER_MASK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
|
||||
fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
|
||||
>> NVM_MAJOR_SHIFT;
|
||||
|
||||
/* check for old style version format in newer images*/
|
||||
if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) {
|
||||
eeprom_verl = (fw_version & NVM_COMB_VER_MASK);
|
||||
} else {
|
||||
eeprom_verl = (fw_version & NVM_MINOR_MASK)
|
||||
>> NVM_MINOR_SHIFT;
|
||||
}
|
||||
/* Convert minor value to hex before assigning to output struct
|
||||
* Val to be converted will not be higher than 99, per tool output
|
||||
*/
|
||||
q = eeprom_verl / NVM_HEX_CONV;
|
||||
hval = q * NVM_HEX_TENS;
|
||||
rem = eeprom_verl % NVM_HEX_CONV;
|
||||
result = hval + rem;
|
||||
fw_vers->eep_minor = result;
|
||||
|
||||
etrack_id:
|
||||
if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) {
|
||||
hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
|
||||
hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
|
||||
fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT)
|
||||
| eeprom_verl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_NVM_H_
|
||||
#define _E1000_NVM_H_
|
||||
|
||||
s32 igb_acquire_nvm(struct e1000_hw *hw);
|
||||
void igb_release_nvm(struct e1000_hw *hw);
|
||||
s32 igb_read_mac_addr(struct e1000_hw *hw);
|
||||
s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num);
|
||||
s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
|
||||
u32 part_num_size);
|
||||
s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igb_validate_nvm_checksum(struct e1000_hw *hw);
|
||||
s32 igb_update_nvm_checksum(struct e1000_hw *hw);
|
||||
|
||||
struct e1000_fw_version {
|
||||
u32 etrack_id;
|
||||
u16 eep_major;
|
||||
u16 eep_minor;
|
||||
u16 eep_build;
|
||||
|
||||
u8 invm_major;
|
||||
u8 invm_minor;
|
||||
u8 invm_img_type;
|
||||
|
||||
bool or_valid;
|
||||
u16 or_major;
|
||||
u16 or_build;
|
||||
u16 or_patch;
|
||||
};
|
||||
void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,782 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_nvm.h"
|
||||
|
||||
/**
|
||||
* igb_raise_eec_clk - Raise EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Enable/Raise the EEPROM clock bit.
|
||||
**/
|
||||
static void igb_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd | E1000_EECD_SK;
|
||||
wr32(E1000_EECD, *eecd);
|
||||
wrfl();
|
||||
udelay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_lower_eec_clk - Lower EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Clear/Lower the EEPROM clock bit.
|
||||
**/
|
||||
static void igb_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd & ~E1000_EECD_SK;
|
||||
wr32(E1000_EECD, *eecd);
|
||||
wrfl();
|
||||
udelay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_shift_out_eec_bits - Shift data bits our to the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @data: data to send to the EEPROM
|
||||
* @count: number of bits to shift out
|
||||
*
|
||||
* We need to shift 'count' bits out to the EEPROM. So, the 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.
|
||||
**/
|
||||
static void igb_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
u32 mask;
|
||||
|
||||
mask = 1u << (count - 1);
|
||||
if (nvm->type == e1000_nvm_eeprom_spi)
|
||||
eecd |= E1000_EECD_DO;
|
||||
|
||||
do {
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
|
||||
if (data & mask)
|
||||
eecd |= E1000_EECD_DI;
|
||||
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
|
||||
udelay(nvm->delay_usec);
|
||||
|
||||
igb_raise_eec_clk(hw, &eecd);
|
||||
igb_lower_eec_clk(hw, &eecd);
|
||||
|
||||
mask >>= 1;
|
||||
} while (mask);
|
||||
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
wr32(E1000_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_shift_in_eec_bits - Shift data bits in from the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @count: number of bits to shift in
|
||||
*
|
||||
* In order to read a register from the EEPROM, we need to shift 'count' 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 data out
|
||||
* "DO" bit. During this "shifting in" process the data in "DI" bit should
|
||||
* always be clear.
|
||||
**/
|
||||
static u16 igb_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
|
||||
{
|
||||
u32 eecd;
|
||||
u32 i;
|
||||
u16 data;
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
|
||||
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
|
||||
data = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
data <<= 1;
|
||||
igb_raise_eec_clk(hw, &eecd);
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
|
||||
eecd &= ~E1000_EECD_DI;
|
||||
if (eecd & E1000_EECD_DO)
|
||||
data |= 1;
|
||||
|
||||
igb_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_poll_eerd_eewr_done - Poll for EEPROM read/write completion
|
||||
* @hw: pointer to the HW structure
|
||||
* @ee_reg: EEPROM flag for polling
|
||||
*
|
||||
* Polls the EEPROM status bit for either read or write completion based
|
||||
* upon the value of 'ee_reg'.
|
||||
**/
|
||||
static s32 igb_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
|
||||
{
|
||||
u32 attempts = 100000;
|
||||
u32 i, reg = 0;
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
|
||||
for (i = 0; i < attempts; i++) {
|
||||
if (ee_reg == E1000_NVM_POLL_READ)
|
||||
reg = rd32(E1000_EERD);
|
||||
else
|
||||
reg = rd32(E1000_EEWR);
|
||||
|
||||
if (reg & E1000_NVM_RW_REG_DONE) {
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_acquire_nvm - Generic request for access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
|
||||
* Return successful if access grant bit set, else clear the request for
|
||||
* EEPROM access and return -E1000_ERR_NVM (-1).
|
||||
**/
|
||||
s32 igb_acquire_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
|
||||
s32 ret_val = 0;
|
||||
|
||||
|
||||
wr32(E1000_EECD, eecd | E1000_EECD_REQ);
|
||||
eecd = rd32(E1000_EECD);
|
||||
|
||||
while (timeout) {
|
||||
if (eecd & E1000_EECD_GNT)
|
||||
break;
|
||||
udelay(5);
|
||||
eecd = rd32(E1000_EECD);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
wr32(E1000_EECD, eecd);
|
||||
hw_dbg("Could not acquire NVM grant\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_standby_nvm - Return EEPROM to standby state
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Return the EEPROM to a standby state.
|
||||
**/
|
||||
static void igb_standby_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
|
||||
if (nvm->type == e1000_nvm_eeprom_spi) {
|
||||
/* Toggle CS to flush commands */
|
||||
eecd |= E1000_EECD_CS;
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
udelay(nvm->delay_usec);
|
||||
eecd &= ~E1000_EECD_CS;
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
udelay(nvm->delay_usec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_stop_nvm - Terminate EEPROM command
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Terminates the current command by inverting the EEPROM's chip select pin.
|
||||
**/
|
||||
static void e1000_stop_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
if (hw->nvm.type == e1000_nvm_eeprom_spi) {
|
||||
/* Pull CS high */
|
||||
eecd |= E1000_EECD_CS;
|
||||
igb_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_release_nvm - Release exclusive access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
|
||||
**/
|
||||
void igb_release_nvm(struct e1000_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
e1000_stop_nvm(hw);
|
||||
|
||||
eecd = rd32(E1000_EECD);
|
||||
eecd &= ~E1000_EECD_REQ;
|
||||
wr32(E1000_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_ready_nvm_eeprom - Prepares EEPROM for read/write
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups the EEPROM for reading and writing.
|
||||
**/
|
||||
static s32 igb_ready_nvm_eeprom(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(E1000_EECD);
|
||||
s32 ret_val = 0;
|
||||
u16 timeout = 0;
|
||||
u8 spi_stat_reg;
|
||||
|
||||
|
||||
if (nvm->type == e1000_nvm_eeprom_spi) {
|
||||
/* Clear SK and CS */
|
||||
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
|
||||
wr32(E1000_EECD, eecd);
|
||||
wrfl();
|
||||
udelay(1);
|
||||
timeout = NVM_MAX_RETRY_SPI;
|
||||
|
||||
/* Read "Status Register" repeatedly until the LSB is cleared.
|
||||
* The EEPROM will signal that the command has been completed
|
||||
* by clearing bit 0 of the internal status register. If it's
|
||||
* not cleared within 'timeout', then error out.
|
||||
*/
|
||||
while (timeout) {
|
||||
igb_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
|
||||
hw->nvm.opcode_bits);
|
||||
spi_stat_reg = (u8)igb_shift_in_eec_bits(hw, 8);
|
||||
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
|
||||
break;
|
||||
|
||||
udelay(5);
|
||||
igb_standby_nvm(hw);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
hw_dbg("SPI NVM Status error\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_nvm_spi - Read EEPROM's using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM.
|
||||
**/
|
||||
s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i = 0;
|
||||
s32 ret_val;
|
||||
u16 word_in;
|
||||
u8 read_opcode = NVM_READ_OPCODE_SPI;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = igb_ready_nvm_eeprom(hw);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
|
||||
igb_standby_nvm(hw);
|
||||
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
read_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the READ command (opcode + addr) */
|
||||
igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
|
||||
igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
|
||||
|
||||
/* Read the data. SPI NVMs increment the address with each byte
|
||||
* read and will roll over if reading beyond the end. This allows
|
||||
* us to read the whole NVM from any offset
|
||||
*/
|
||||
for (i = 0; i < words; i++) {
|
||||
word_in = igb_shift_in_eec_bits(hw, 16);
|
||||
data[i] = (word_in >> 8) | (word_in << 8);
|
||||
}
|
||||
|
||||
release:
|
||||
nvm->ops.release(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_nvm_eerd - Reads EEPROM using EERD register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM using the EERD register.
|
||||
**/
|
||||
s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
u32 i, eerd = 0;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
|
||||
E1000_NVM_RW_REG_START;
|
||||
|
||||
wr32(E1000_EERD, eerd);
|
||||
ret_val = igb_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
|
||||
if (ret_val)
|
||||
break;
|
||||
|
||||
data[i] = (rd32(E1000_EERD) >>
|
||||
E1000_NVM_RW_REG_DATA);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_write_nvm_spi - Write to EEPROM using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the EEPROM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the EEPROM
|
||||
*
|
||||
* Writes data to EEPROM at offset using SPI interface.
|
||||
*
|
||||
* If e1000_update_nvm_checksum is not called after this function , the
|
||||
* EEPROM will most likley contain an invalid checksum.
|
||||
**/
|
||||
s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
s32 ret_val = -E1000_ERR_NVM;
|
||||
u16 widx = 0;
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
hw_dbg("nvm parameter(s) out of bounds\n");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
while (widx < words) {
|
||||
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = igb_ready_nvm_eeprom(hw);
|
||||
if (ret_val) {
|
||||
nvm->ops.release(hw);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
igb_standby_nvm(hw);
|
||||
|
||||
/* Send the WRITE ENABLE command (8 bit opcode) */
|
||||
igb_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
|
||||
nvm->opcode_bits);
|
||||
|
||||
igb_standby_nvm(hw);
|
||||
|
||||
/* Some SPI eeproms use the 8th address bit embedded in the
|
||||
* opcode
|
||||
*/
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
write_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the Write command (8-bit opcode + addr) */
|
||||
igb_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
|
||||
igb_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
|
||||
nvm->address_bits);
|
||||
|
||||
/* Loop to allow for up to whole page write of eeprom */
|
||||
while (widx < words) {
|
||||
u16 word_out = data[widx];
|
||||
|
||||
word_out = (word_out >> 8) | (word_out << 8);
|
||||
igb_shift_out_eec_bits(hw, word_out, 16);
|
||||
widx++;
|
||||
|
||||
if ((((offset + widx) * 2) % nvm->page_size) == 0) {
|
||||
igb_standby_nvm(hw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
nvm->ops.release(hw);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_part_string - Read device part number
|
||||
* @hw: pointer to the HW structure
|
||||
* @part_num: pointer to device part number
|
||||
* @part_num_size: size of part number buffer
|
||||
*
|
||||
* Reads the product board assembly (PBA) number from the EEPROM and stores
|
||||
* the value in part_num.
|
||||
**/
|
||||
s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 nvm_data;
|
||||
u16 pointer;
|
||||
u16 offset;
|
||||
u16 length;
|
||||
|
||||
if (part_num == NULL) {
|
||||
hw_dbg("PBA string buffer was null\n");
|
||||
ret_val = E1000_ERR_INVALID_ARGUMENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if nvm_data is not ptr guard the PBA must be in legacy format which
|
||||
* means pointer is actually our second data word for the PBA number
|
||||
* and we can decode it into an ascii string
|
||||
*/
|
||||
if (nvm_data != NVM_PBA_PTR_GUARD) {
|
||||
hw_dbg("NVM PBA number is not stored as string\n");
|
||||
|
||||
/* we will need 11 characters to store the PBA */
|
||||
if (part_num_size < 11) {
|
||||
hw_dbg("PBA string buffer too small\n");
|
||||
return E1000_ERR_NO_SPACE;
|
||||
}
|
||||
|
||||
/* extract hex string from data and pointer */
|
||||
part_num[0] = (nvm_data >> 12) & 0xF;
|
||||
part_num[1] = (nvm_data >> 8) & 0xF;
|
||||
part_num[2] = (nvm_data >> 4) & 0xF;
|
||||
part_num[3] = nvm_data & 0xF;
|
||||
part_num[4] = (pointer >> 12) & 0xF;
|
||||
part_num[5] = (pointer >> 8) & 0xF;
|
||||
part_num[6] = '-';
|
||||
part_num[7] = 0;
|
||||
part_num[8] = (pointer >> 4) & 0xF;
|
||||
part_num[9] = pointer & 0xF;
|
||||
|
||||
/* put a null character on the end of our string */
|
||||
part_num[10] = '\0';
|
||||
|
||||
/* switch all the data but the '-' to hex char */
|
||||
for (offset = 0; offset < 10; offset++) {
|
||||
if (part_num[offset] < 0xA)
|
||||
part_num[offset] += '0';
|
||||
else if (part_num[offset] < 0x10)
|
||||
part_num[offset] += 'A' - 0xA;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, pointer, 1, &length);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (length == 0xFFFF || length == 0) {
|
||||
hw_dbg("NVM PBA number section invalid length\n");
|
||||
ret_val = E1000_ERR_NVM_PBA_SECTION;
|
||||
goto out;
|
||||
}
|
||||
/* check if part_num buffer is big enough */
|
||||
if (part_num_size < (((u32)length * 2) - 1)) {
|
||||
hw_dbg("PBA string buffer too small\n");
|
||||
ret_val = E1000_ERR_NO_SPACE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* trim pba length from start of string */
|
||||
pointer++;
|
||||
length--;
|
||||
|
||||
for (offset = 0; offset < length; offset++) {
|
||||
ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
part_num[offset * 2] = (u8)(nvm_data >> 8);
|
||||
part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
|
||||
}
|
||||
part_num[offset * 2] = '\0';
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_read_mac_addr - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reads the device MAC address from the EEPROM and stores the value.
|
||||
* Since devices with two ports use the same EEPROM, we increment the
|
||||
* last bit in the MAC address for the second port.
|
||||
**/
|
||||
s32 igb_read_mac_addr(struct e1000_hw *hw)
|
||||
{
|
||||
u32 rar_high;
|
||||
u32 rar_low;
|
||||
u16 i;
|
||||
|
||||
rar_high = rd32(E1000_RAH(0));
|
||||
rar_low = rd32(E1000_RAL(0));
|
||||
|
||||
for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
|
||||
|
||||
for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_validate_nvm_checksum - Validate EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
|
||||
**/
|
||||
s32 igb_validate_nvm_checksum(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
|
||||
if (checksum != (u16) NVM_SUM) {
|
||||
hw_dbg("NVM Checksum Invalid\n");
|
||||
ret_val = -E1000_ERR_NVM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_update_nvm_checksum - Update EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* up to the checksum. Then calculates the EEPROM checksum and writes the
|
||||
* value to the EEPROM.
|
||||
**/
|
||||
s32 igb_update_nvm_checksum(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
hw_dbg("NVM Read Error while updating checksum.\n");
|
||||
goto out;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
checksum = (u16) NVM_SUM - checksum;
|
||||
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
|
||||
if (ret_val)
|
||||
hw_dbg("NVM Write Error while updating checksum.\n");
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_get_fw_version - Get firmware version information
|
||||
* @hw: pointer to the HW structure
|
||||
* @fw_vers: pointer to output structure
|
||||
*
|
||||
* unsupported MAC types will return all 0 version structure
|
||||
**/
|
||||
void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
|
||||
{
|
||||
u16 eeprom_verh, eeprom_verl, etrack_test, fw_version;
|
||||
u8 q, hval, rem, result;
|
||||
u16 comb_verh, comb_verl, comb_offset;
|
||||
|
||||
memset(fw_vers, 0, sizeof(struct e1000_fw_version));
|
||||
|
||||
/* basic eeprom version numbers and bits used vary by part and by tool
|
||||
* used to create the nvm images. Check which data format we have.
|
||||
*/
|
||||
hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
|
||||
switch (hw->mac.type) {
|
||||
case e1000_i211:
|
||||
igb_read_invm_version(hw, fw_vers);
|
||||
return;
|
||||
case e1000_82575:
|
||||
case e1000_82576:
|
||||
case e1000_82580:
|
||||
/* Use this format, unless EETRACK ID exists,
|
||||
* then use alternate format
|
||||
*/
|
||||
if ((etrack_test & NVM_MAJOR_MASK) != NVM_ETRACK_VALID) {
|
||||
hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
|
||||
fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
|
||||
>> NVM_MAJOR_SHIFT;
|
||||
fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK)
|
||||
>> NVM_MINOR_SHIFT;
|
||||
fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK);
|
||||
goto etrack_id;
|
||||
}
|
||||
break;
|
||||
case e1000_i210:
|
||||
if (!(igb_get_flash_presence_i210(hw))) {
|
||||
igb_read_invm_version(hw, fw_vers);
|
||||
return;
|
||||
}
|
||||
/* fall through */
|
||||
case e1000_i350:
|
||||
/* find combo image version */
|
||||
hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
|
||||
if ((comb_offset != 0x0) &&
|
||||
(comb_offset != NVM_VER_INVALID)) {
|
||||
|
||||
hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
|
||||
+ 1), 1, &comb_verh);
|
||||
hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
|
||||
1, &comb_verl);
|
||||
|
||||
/* get Option Rom version if it exists and is valid */
|
||||
if ((comb_verh && comb_verl) &&
|
||||
((comb_verh != NVM_VER_INVALID) &&
|
||||
(comb_verl != NVM_VER_INVALID))) {
|
||||
|
||||
fw_vers->or_valid = true;
|
||||
fw_vers->or_major =
|
||||
comb_verl >> NVM_COMB_VER_SHFT;
|
||||
fw_vers->or_build =
|
||||
(comb_verl << NVM_COMB_VER_SHFT)
|
||||
| (comb_verh >> NVM_COMB_VER_SHFT);
|
||||
fw_vers->or_patch =
|
||||
comb_verh & NVM_COMB_VER_MASK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
|
||||
fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
|
||||
>> NVM_MAJOR_SHIFT;
|
||||
|
||||
/* check for old style version format in newer images*/
|
||||
if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) {
|
||||
eeprom_verl = (fw_version & NVM_COMB_VER_MASK);
|
||||
} else {
|
||||
eeprom_verl = (fw_version & NVM_MINOR_MASK)
|
||||
>> NVM_MINOR_SHIFT;
|
||||
}
|
||||
/* Convert minor value to hex before assigning to output struct
|
||||
* Val to be converted will not be higher than 99, per tool output
|
||||
*/
|
||||
q = eeprom_verl / NVM_HEX_CONV;
|
||||
hval = q * NVM_HEX_TENS;
|
||||
rem = eeprom_verl % NVM_HEX_CONV;
|
||||
result = hval + rem;
|
||||
fw_vers->eep_minor = result;
|
||||
|
||||
etrack_id:
|
||||
if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) {
|
||||
hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
|
||||
hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
|
||||
fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT)
|
||||
| eeprom_verl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_NVM_H_
|
||||
#define _E1000_NVM_H_
|
||||
|
||||
s32 igb_acquire_nvm(struct e1000_hw *hw);
|
||||
void igb_release_nvm(struct e1000_hw *hw);
|
||||
s32 igb_read_mac_addr(struct e1000_hw *hw);
|
||||
s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num);
|
||||
s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
|
||||
u32 part_num_size);
|
||||
s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igb_validate_nvm_checksum(struct e1000_hw *hw);
|
||||
s32 igb_update_nvm_checksum(struct e1000_hw *hw);
|
||||
|
||||
struct e1000_fw_version {
|
||||
u32 etrack_id;
|
||||
u16 eep_major;
|
||||
u16 eep_minor;
|
||||
u16 eep_build;
|
||||
|
||||
u8 invm_major;
|
||||
u8 invm_minor;
|
||||
u8 invm_img_type;
|
||||
|
||||
bool or_valid;
|
||||
u16 or_major;
|
||||
u16 or_build;
|
||||
u16 or_patch;
|
||||
};
|
||||
void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,145 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_PHY_H_
|
||||
#define _E1000_PHY_H_
|
||||
|
||||
enum e1000_ms_type {
|
||||
e1000_ms_hw_default = 0,
|
||||
e1000_ms_force_master,
|
||||
e1000_ms_force_slave,
|
||||
e1000_ms_auto
|
||||
};
|
||||
|
||||
enum e1000_smart_speed {
|
||||
e1000_smart_speed_default = 0,
|
||||
e1000_smart_speed_on,
|
||||
e1000_smart_speed_off
|
||||
};
|
||||
|
||||
s32 igb_check_downshift(struct e1000_hw *hw);
|
||||
s32 igb_check_reset_block(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_igp(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_m88(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_m88(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_igp_2(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_id(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_igp(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_m88(struct e1000_hw *hw);
|
||||
s32 igb_phy_sw_reset(struct e1000_hw *hw);
|
||||
s32 igb_phy_hw_reset(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active);
|
||||
s32 igb_setup_copper_link(struct e1000_hw *hw);
|
||||
s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
|
||||
u32 usec_interval, bool *success);
|
||||
void igb_power_up_phy_copper(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper(struct e1000_hw *hw);
|
||||
s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1512_phy(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1543_phy(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
|
||||
s32 igb_copper_link_setup_82580(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_82580(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_82580(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_check_polarity_m88(struct e1000_hw *hw);
|
||||
|
||||
/* IGP01E1000 Specific Registers */
|
||||
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
|
||||
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
|
||||
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
|
||||
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
|
||||
#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
|
||||
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
|
||||
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
|
||||
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
|
||||
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
|
||||
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
|
||||
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
|
||||
|
||||
#define I82580_ADDR_REG 16
|
||||
#define I82580_CFG_REG 22
|
||||
#define I82580_CFG_ASSERT_CRS_ON_TX BIT(15)
|
||||
#define I82580_CFG_ENABLE_DOWNSHIFT (3u << 10) /* auto downshift 100/10 */
|
||||
#define I82580_CTRL_REG 23
|
||||
#define I82580_CTRL_DOWNSHIFT_MASK (7u << 10)
|
||||
|
||||
/* 82580 specific PHY registers */
|
||||
#define I82580_PHY_CTRL_2 18
|
||||
#define I82580_PHY_LBK_CTRL 19
|
||||
#define I82580_PHY_STATUS_2 26
|
||||
#define I82580_PHY_DIAG_STATUS 31
|
||||
|
||||
/* I82580 PHY Status 2 */
|
||||
#define I82580_PHY_STATUS2_REV_POLARITY 0x0400
|
||||
#define I82580_PHY_STATUS2_MDIX 0x0800
|
||||
#define I82580_PHY_STATUS2_SPEED_MASK 0x0300
|
||||
#define I82580_PHY_STATUS2_SPEED_1000MBPS 0x0200
|
||||
#define I82580_PHY_STATUS2_SPEED_100MBPS 0x0100
|
||||
|
||||
/* I82580 PHY Control 2 */
|
||||
#define I82580_PHY_CTRL2_MANUAL_MDIX 0x0200
|
||||
#define I82580_PHY_CTRL2_AUTO_MDI_MDIX 0x0400
|
||||
#define I82580_PHY_CTRL2_MDIX_CFG_MASK 0x0600
|
||||
|
||||
/* I82580 PHY Diagnostics Status */
|
||||
#define I82580_DSTATUS_CABLE_LENGTH 0x03FC
|
||||
#define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2
|
||||
|
||||
/* 82580 PHY Power Management */
|
||||
#define E1000_82580_PHY_POWER_MGMT 0xE14
|
||||
#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
|
||||
#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
|
||||
|
||||
/* Enable flexible speed on link-up */
|
||||
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
|
||||
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
|
||||
#define IGP01E1000_PSSR_MDIX 0x0800
|
||||
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
|
||||
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
|
||||
#define IGP02E1000_PHY_CHANNEL_NUM 4
|
||||
#define IGP02E1000_PHY_AGC_A 0x11B1
|
||||
#define IGP02E1000_PHY_AGC_B 0x12B1
|
||||
#define IGP02E1000_PHY_AGC_C 0x14B1
|
||||
#define IGP02E1000_PHY_AGC_D 0x18B1
|
||||
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
|
||||
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
|
||||
#define IGP02E1000_AGC_RANGE 15
|
||||
|
||||
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
|
||||
|
||||
/* SFP modules ID memory locations */
|
||||
#define E1000_SFF_IDENTIFIER_OFFSET 0x00
|
||||
#define E1000_SFF_IDENTIFIER_SFF 0x02
|
||||
#define E1000_SFF_IDENTIFIER_SFP 0x03
|
||||
|
||||
#define E1000_SFF_ETH_FLAGS_OFFSET 0x06
|
||||
/* Flags for SFP modules compatible with ETH up to 1Gb */
|
||||
struct e1000_sfp_flags {
|
||||
u8 e1000_base_sx:1;
|
||||
u8 e1000_base_lx:1;
|
||||
u8 e1000_base_cx:1;
|
||||
u8 e1000_base_t:1;
|
||||
u8 e100_base_lx:1;
|
||||
u8 e100_base_fx:1;
|
||||
u8 e10_base_bx10:1;
|
||||
u8 e10_base_px:1;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,145 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_PHY_H_
|
||||
#define _E1000_PHY_H_
|
||||
|
||||
enum e1000_ms_type {
|
||||
e1000_ms_hw_default = 0,
|
||||
e1000_ms_force_master,
|
||||
e1000_ms_force_slave,
|
||||
e1000_ms_auto
|
||||
};
|
||||
|
||||
enum e1000_smart_speed {
|
||||
e1000_smart_speed_default = 0,
|
||||
e1000_smart_speed_on,
|
||||
e1000_smart_speed_off
|
||||
};
|
||||
|
||||
s32 igb_check_downshift(struct e1000_hw *hw);
|
||||
s32 igb_check_reset_block(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_igp(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_m88(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_m88(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_igp_2(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_id(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_igp(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_m88(struct e1000_hw *hw);
|
||||
s32 igb_phy_sw_reset(struct e1000_hw *hw);
|
||||
s32 igb_phy_hw_reset(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active);
|
||||
s32 igb_setup_copper_link(struct e1000_hw *hw);
|
||||
s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
|
||||
u32 usec_interval, bool *success);
|
||||
void igb_power_up_phy_copper(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper(struct e1000_hw *hw);
|
||||
s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1512_phy(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1543_phy(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
|
||||
s32 igb_copper_link_setup_82580(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_82580(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_82580(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_check_polarity_m88(struct e1000_hw *hw);
|
||||
|
||||
/* IGP01E1000 Specific Registers */
|
||||
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
|
||||
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
|
||||
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
|
||||
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
|
||||
#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
|
||||
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
|
||||
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
|
||||
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
|
||||
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
|
||||
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
|
||||
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
|
||||
|
||||
#define I82580_ADDR_REG 16
|
||||
#define I82580_CFG_REG 22
|
||||
#define I82580_CFG_ASSERT_CRS_ON_TX BIT(15)
|
||||
#define I82580_CFG_ENABLE_DOWNSHIFT (3u << 10) /* auto downshift 100/10 */
|
||||
#define I82580_CTRL_REG 23
|
||||
#define I82580_CTRL_DOWNSHIFT_MASK (7u << 10)
|
||||
|
||||
/* 82580 specific PHY registers */
|
||||
#define I82580_PHY_CTRL_2 18
|
||||
#define I82580_PHY_LBK_CTRL 19
|
||||
#define I82580_PHY_STATUS_2 26
|
||||
#define I82580_PHY_DIAG_STATUS 31
|
||||
|
||||
/* I82580 PHY Status 2 */
|
||||
#define I82580_PHY_STATUS2_REV_POLARITY 0x0400
|
||||
#define I82580_PHY_STATUS2_MDIX 0x0800
|
||||
#define I82580_PHY_STATUS2_SPEED_MASK 0x0300
|
||||
#define I82580_PHY_STATUS2_SPEED_1000MBPS 0x0200
|
||||
#define I82580_PHY_STATUS2_SPEED_100MBPS 0x0100
|
||||
|
||||
/* I82580 PHY Control 2 */
|
||||
#define I82580_PHY_CTRL2_MANUAL_MDIX 0x0200
|
||||
#define I82580_PHY_CTRL2_AUTO_MDI_MDIX 0x0400
|
||||
#define I82580_PHY_CTRL2_MDIX_CFG_MASK 0x0600
|
||||
|
||||
/* I82580 PHY Diagnostics Status */
|
||||
#define I82580_DSTATUS_CABLE_LENGTH 0x03FC
|
||||
#define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2
|
||||
|
||||
/* 82580 PHY Power Management */
|
||||
#define E1000_82580_PHY_POWER_MGMT 0xE14
|
||||
#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
|
||||
#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
|
||||
|
||||
/* Enable flexible speed on link-up */
|
||||
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
|
||||
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
|
||||
#define IGP01E1000_PSSR_MDIX 0x0800
|
||||
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
|
||||
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
|
||||
#define IGP02E1000_PHY_CHANNEL_NUM 4
|
||||
#define IGP02E1000_PHY_AGC_A 0x11B1
|
||||
#define IGP02E1000_PHY_AGC_B 0x12B1
|
||||
#define IGP02E1000_PHY_AGC_C 0x14B1
|
||||
#define IGP02E1000_PHY_AGC_D 0x18B1
|
||||
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
|
||||
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
|
||||
#define IGP02E1000_AGC_RANGE 15
|
||||
|
||||
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
|
||||
|
||||
/* SFP modules ID memory locations */
|
||||
#define E1000_SFF_IDENTIFIER_OFFSET 0x00
|
||||
#define E1000_SFF_IDENTIFIER_SFF 0x02
|
||||
#define E1000_SFF_IDENTIFIER_SFP 0x03
|
||||
|
||||
#define E1000_SFF_ETH_FLAGS_OFFSET 0x06
|
||||
/* Flags for SFP modules compatible with ETH up to 1Gb */
|
||||
struct e1000_sfp_flags {
|
||||
u8 e1000_base_sx:1;
|
||||
u8 e1000_base_lx:1;
|
||||
u8 e1000_base_cx:1;
|
||||
u8 e1000_base_t:1;
|
||||
u8 e100_base_lx:1;
|
||||
u8 e100_base_fx:1;
|
||||
u8 e10_base_bx10:1;
|
||||
u8 e10_base_px:1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,417 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_REGS_H_
|
||||
#define _E1000_REGS_H_
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
|
||||
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
|
||||
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
|
||||
#define E1000_MDIC 0x00020 /* MDI Control - RW */
|
||||
#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */
|
||||
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
|
||||
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
|
||||
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
|
||||
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
|
||||
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
|
||||
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
|
||||
#define E1000_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */
|
||||
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
|
||||
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
|
||||
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
|
||||
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
|
||||
#define E1000_RCTL 0x00100 /* RX Control - RW */
|
||||
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
|
||||
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
|
||||
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
|
||||
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
|
||||
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
|
||||
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
|
||||
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
|
||||
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
|
||||
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
|
||||
#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */
|
||||
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
|
||||
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
|
||||
#define E1000_TCTL 0x00400 /* TX Control - RW */
|
||||
#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */
|
||||
#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */
|
||||
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
|
||||
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
|
||||
#define E1000_LEDMUX 0x08130 /* LED MUX Control */
|
||||
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
|
||||
#define E1000_PBS 0x01008 /* Packet Buffer Size */
|
||||
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
|
||||
#define E1000_EEMNGCTL_I210 0x12030 /* MNG EEprom Control */
|
||||
#define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */
|
||||
#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
|
||||
#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
|
||||
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
|
||||
#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */
|
||||
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
|
||||
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
|
||||
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
|
||||
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
|
||||
#define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */
|
||||
#define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */
|
||||
#define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */
|
||||
#define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */
|
||||
#define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */
|
||||
#define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */
|
||||
#define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */
|
||||
#define E1000_MPHY_ADDR_CTRL 0x0024 /* GbE MPHY Address Control */
|
||||
#define E1000_MPHY_DATA 0x0E10 /* GBE MPHY Data */
|
||||
#define E1000_MPHY_STAT 0x0E0C /* GBE MPHY Statistics */
|
||||
|
||||
/* IEEE 1588 TIMESYNCH */
|
||||
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
|
||||
#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
|
||||
#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
|
||||
#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
|
||||
#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
|
||||
#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
|
||||
#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
|
||||
#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
|
||||
#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
|
||||
#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */
|
||||
#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */
|
||||
#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
|
||||
#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
|
||||
#define E1000_TRGTTIML0 0x0B644 /* Target Time Register 0 Low - RW */
|
||||
#define E1000_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */
|
||||
#define E1000_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */
|
||||
#define E1000_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */
|
||||
#define E1000_FREQOUT0 0x0B654 /* Frequency Out 0 Control Register - RW */
|
||||
#define E1000_FREQOUT1 0x0B658 /* Frequency Out 1 Control Register - RW */
|
||||
#define E1000_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Register Low - RO */
|
||||
#define E1000_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Register High - RO */
|
||||
#define E1000_AUXSTMPL1 0x0B664 /* Auxiliary Time Stamp 1 Register Low - RO */
|
||||
#define E1000_AUXSTMPH1 0x0B668 /* Auxiliary Time Stamp 1 Register High - RO */
|
||||
#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
|
||||
#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */
|
||||
#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */
|
||||
|
||||
/* Filtering Registers */
|
||||
#define E1000_SAQF(_n) (0x5980 + 4 * (_n))
|
||||
#define E1000_DAQF(_n) (0x59A0 + 4 * (_n))
|
||||
#define E1000_SPQF(_n) (0x59C0 + 4 * (_n))
|
||||
#define E1000_FTQF(_n) (0x59E0 + 4 * (_n))
|
||||
#define E1000_SAQF0 E1000_SAQF(0)
|
||||
#define E1000_DAQF0 E1000_DAQF(0)
|
||||
#define E1000_SPQF0 E1000_SPQF(0)
|
||||
#define E1000_FTQF0 E1000_FTQF(0)
|
||||
#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
|
||||
#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
|
||||
|
||||
#define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
|
||||
|
||||
/* DMA Coalescing registers */
|
||||
#define E1000_DMACR 0x02508 /* Control Register */
|
||||
#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */
|
||||
#define E1000_DMCTLX 0x02514 /* Time to Lx Request */
|
||||
#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
|
||||
#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */
|
||||
#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */
|
||||
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
|
||||
|
||||
/* TX Rate Limit Registers */
|
||||
#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */
|
||||
#define E1000_RTTBCNRM 0x3690 /* Tx BCN Rate-scheduler MMW */
|
||||
#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */
|
||||
|
||||
/* Split and Replication RX Control - RW */
|
||||
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
|
||||
|
||||
/* Thermal sensor configuration and status registers */
|
||||
#define E1000_THMJT 0x08100 /* Junction Temperature */
|
||||
#define E1000_THLOWTC 0x08104 /* Low Threshold Control */
|
||||
#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */
|
||||
#define E1000_THHIGHTC 0x0810C /* High Threshold Control */
|
||||
#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
|
||||
|
||||
/* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* E1000_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) \
|
||||
: (0x0C000 + ((_n) * 0x40)))
|
||||
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) \
|
||||
: (0x0C004 + ((_n) * 0x40)))
|
||||
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) \
|
||||
: (0x0C008 + ((_n) * 0x40)))
|
||||
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) \
|
||||
: (0x0C00C + ((_n) * 0x40)))
|
||||
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) \
|
||||
: (0x0C010 + ((_n) * 0x40)))
|
||||
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) \
|
||||
: (0x0C018 + ((_n) * 0x40)))
|
||||
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) \
|
||||
: (0x0C028 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) \
|
||||
: (0x0E000 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) \
|
||||
: (0x0E004 + ((_n) * 0x40)))
|
||||
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) \
|
||||
: (0x0E008 + ((_n) * 0x40)))
|
||||
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) \
|
||||
: (0x0E010 + ((_n) * 0x40)))
|
||||
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) \
|
||||
: (0x0E018 + ((_n) * 0x40)))
|
||||
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \
|
||||
: (0x0E028 + ((_n) * 0x40)))
|
||||
#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \
|
||||
(0x0C014 + ((_n) * 0x40)))
|
||||
#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n)
|
||||
#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \
|
||||
(0x0E014 + ((_n) * 0x40)))
|
||||
#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n)
|
||||
#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \
|
||||
: (0x0E038 + ((_n) * 0x40)))
|
||||
#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) \
|
||||
: (0x0E03C + ((_n) * 0x40)))
|
||||
|
||||
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
|
||||
#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
|
||||
|
||||
#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
|
||||
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
|
||||
#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
|
||||
#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */
|
||||
#define E1000_DTXCTL 0x03590 /* DMA TX Control - RW */
|
||||
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
|
||||
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
|
||||
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
|
||||
#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
|
||||
#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
|
||||
#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
|
||||
#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
|
||||
#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
|
||||
#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
|
||||
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
|
||||
#define E1000_DC 0x04030 /* Defer Count - R/clr */
|
||||
#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */
|
||||
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
|
||||
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
|
||||
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
|
||||
#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */
|
||||
#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */
|
||||
#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */
|
||||
#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */
|
||||
#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */
|
||||
#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */
|
||||
#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */
|
||||
#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */
|
||||
#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */
|
||||
#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */
|
||||
#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */
|
||||
#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */
|
||||
#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */
|
||||
#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */
|
||||
#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */
|
||||
#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */
|
||||
#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */
|
||||
#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */
|
||||
#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */
|
||||
#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */
|
||||
#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */
|
||||
#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */
|
||||
#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */
|
||||
#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */
|
||||
#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */
|
||||
#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
|
||||
#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */
|
||||
#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */
|
||||
#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */
|
||||
#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */
|
||||
#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */
|
||||
#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */
|
||||
#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */
|
||||
#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */
|
||||
#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */
|
||||
#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */
|
||||
#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */
|
||||
#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */
|
||||
#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */
|
||||
#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */
|
||||
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
|
||||
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
|
||||
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
|
||||
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
|
||||
/* Interrupt Cause Rx Packet Timer Expire Count */
|
||||
#define E1000_ICRXPTC 0x04104
|
||||
/* Interrupt Cause Rx Absolute Timer Expire Count */
|
||||
#define E1000_ICRXATC 0x04108
|
||||
/* Interrupt Cause Tx Packet Timer Expire Count */
|
||||
#define E1000_ICTXPTC 0x0410C
|
||||
/* Interrupt Cause Tx Absolute Timer Expire Count */
|
||||
#define E1000_ICTXATC 0x04110
|
||||
/* Interrupt Cause Tx Queue Empty Count */
|
||||
#define E1000_ICTXQEC 0x04118
|
||||
/* Interrupt Cause Tx Queue Minimum Threshold Count */
|
||||
#define E1000_ICTXQMTC 0x0411C
|
||||
/* Interrupt Cause Rx Descriptor Minimum Threshold Count */
|
||||
#define E1000_ICRXDMTC 0x04120
|
||||
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
|
||||
#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
|
||||
#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
|
||||
#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
|
||||
#define E1000_CBTMPC 0x0402C /* Circuit Breaker TX Packet Count */
|
||||
#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
|
||||
#define E1000_CBRMPC 0x040FC /* Circuit Breaker RX Packet Count */
|
||||
#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
|
||||
#define E1000_HGPTC 0x04118 /* Host Good Packets TX Count */
|
||||
#define E1000_HTCBDPC 0x04124 /* Host TX Circuit Breaker Dropped Count */
|
||||
#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
|
||||
#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
|
||||
#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
|
||||
#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
|
||||
#define E1000_LENERRS 0x04138 /* Length Errors Count */
|
||||
#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
|
||||
#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
|
||||
#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
|
||||
#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
|
||||
#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
|
||||
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
|
||||
#define E1000_RLPML 0x05004 /* RX Long Packet Max Length */
|
||||
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
|
||||
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
#define E1000_RA 0x05400 /* Receive Address - RW Array */
|
||||
#define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */
|
||||
#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
|
||||
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
#define E1000_VLAPQF 0x055B0 /* VLAN Priority Queue Filter VLAPQF */
|
||||
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
|
||||
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
|
||||
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
|
||||
#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
|
||||
#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
|
||||
#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
|
||||
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
|
||||
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
|
||||
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
|
||||
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
|
||||
#define E1000_WUS 0x05810 /* Wakeup Status - R/W1C */
|
||||
#define E1000_MANC 0x05820 /* Management Control - RW */
|
||||
#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
|
||||
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
|
||||
|
||||
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
|
||||
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
|
||||
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
|
||||
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
|
||||
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
|
||||
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
|
||||
#define E1000_SWSM 0x05B50 /* SW Semaphore */
|
||||
#define E1000_FWSM 0x05B54 /* FW Semaphore */
|
||||
#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
|
||||
|
||||
/* RSS registers */
|
||||
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
|
||||
#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
|
||||
#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
|
||||
#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt RX VLAN Priority - RW */
|
||||
/* MSI-X Allocation Register (_i) - RW */
|
||||
#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4))
|
||||
/* Redirection Table - RW Array */
|
||||
#define E1000_RETA(_i) (0x05C00 + ((_i) * 4))
|
||||
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */
|
||||
|
||||
/* VT Registers */
|
||||
#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */
|
||||
#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */
|
||||
#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */
|
||||
#define E1000_VFRE 0x00C8C /* VF Receive Enables */
|
||||
#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
|
||||
#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
|
||||
#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
|
||||
#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
|
||||
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
|
||||
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
|
||||
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
|
||||
#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
|
||||
#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
|
||||
/* These act per VF so an array friendly macro is used */
|
||||
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
|
||||
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
|
||||
#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
|
||||
#define E1000_DVMOLR(_n) (0x0C038 + (64 * (_n)))
|
||||
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN VM Filter */
|
||||
#define E1000_VMVIR(_n) (0x03700 + (4 * (_n)))
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
u32 igb_rd32(struct e1000_hw *hw, u32 reg);
|
||||
|
||||
/* write operations, indexed using DWORDS */
|
||||
#define wr32(reg, val) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \
|
||||
if (!E1000_REMOVED(hw_addr)) \
|
||||
writel((val), &hw_addr[(reg)]); \
|
||||
} while (0)
|
||||
|
||||
#define rd32(reg) (igb_rd32(hw, reg))
|
||||
|
||||
#define wrfl() ((void)rd32(E1000_STATUS))
|
||||
|
||||
#define array_wr32(reg, offset, value) \
|
||||
wr32((reg) + ((offset) << 2), (value))
|
||||
|
||||
#define array_rd32(reg, offset) (igb_rd32(hw, reg + ((offset) << 2)))
|
||||
|
||||
/* DMA Coalescing registers */
|
||||
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
|
||||
|
||||
/* Energy Efficient Ethernet "EEE" register */
|
||||
#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
|
||||
#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */
|
||||
#define E1000_EEE_SU 0X0E34 /* EEE Setup */
|
||||
#define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */
|
||||
#define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */
|
||||
#define E1000_MMDAC 13 /* MMD Access Control */
|
||||
#define E1000_MMDAAD 14 /* MMD Access Address/Data */
|
||||
|
||||
/* Thermal Sensor Register */
|
||||
#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
|
||||
|
||||
/* OS2BMC Registers */
|
||||
#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */
|
||||
#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */
|
||||
#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
|
||||
#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
|
||||
|
||||
#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */
|
||||
#define E1000_I210_FLMNGCTL 0x12038
|
||||
#define E1000_I210_FLMNGDATA 0x1203C
|
||||
#define E1000_I210_FLMNGCNT 0x12040
|
||||
|
||||
#define E1000_I210_FLSWCTL 0x12048
|
||||
#define E1000_I210_FLSWDATA 0x1204C
|
||||
#define E1000_I210_FLSWCNT 0x12050
|
||||
|
||||
#define E1000_I210_FLA 0x1201C
|
||||
|
||||
#define E1000_I210_DTXMXPKTSZ 0x355C
|
||||
|
||||
#define E1000_I210_TXDCTL(_n) (0x0E028 + ((_n) * 0x40))
|
||||
|
||||
#define E1000_I210_TQAVCTRL 0x3570
|
||||
#define E1000_I210_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
|
||||
#define E1000_I210_TQAVHC(_n) (0x300C + ((_n) * 0x40))
|
||||
|
||||
#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
|
||||
#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */
|
||||
|
||||
#define E1000_REMOVED(h) unlikely(!(h))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,417 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_REGS_H_
|
||||
#define _E1000_REGS_H_
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
|
||||
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
|
||||
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
|
||||
#define E1000_MDIC 0x00020 /* MDI Control - RW */
|
||||
#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */
|
||||
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
|
||||
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
|
||||
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
|
||||
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
|
||||
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
|
||||
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
|
||||
#define E1000_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */
|
||||
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
|
||||
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
|
||||
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
|
||||
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
|
||||
#define E1000_RCTL 0x00100 /* RX Control - RW */
|
||||
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
|
||||
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
|
||||
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
|
||||
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
|
||||
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
|
||||
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
|
||||
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
|
||||
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
|
||||
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
|
||||
#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */
|
||||
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
|
||||
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
|
||||
#define E1000_TCTL 0x00400 /* TX Control - RW */
|
||||
#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */
|
||||
#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */
|
||||
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
|
||||
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
|
||||
#define E1000_LEDMUX 0x08130 /* LED MUX Control */
|
||||
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
|
||||
#define E1000_PBS 0x01008 /* Packet Buffer Size */
|
||||
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
|
||||
#define E1000_EEMNGCTL_I210 0x12030 /* MNG EEprom Control */
|
||||
#define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */
|
||||
#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
|
||||
#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
|
||||
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
|
||||
#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */
|
||||
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
|
||||
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
|
||||
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
|
||||
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
|
||||
#define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */
|
||||
#define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */
|
||||
#define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */
|
||||
#define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */
|
||||
#define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */
|
||||
#define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */
|
||||
#define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */
|
||||
#define E1000_MPHY_ADDR_CTRL 0x0024 /* GbE MPHY Address Control */
|
||||
#define E1000_MPHY_DATA 0x0E10 /* GBE MPHY Data */
|
||||
#define E1000_MPHY_STAT 0x0E0C /* GBE MPHY Statistics */
|
||||
|
||||
/* IEEE 1588 TIMESYNCH */
|
||||
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
|
||||
#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
|
||||
#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
|
||||
#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
|
||||
#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
|
||||
#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
|
||||
#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
|
||||
#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
|
||||
#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
|
||||
#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */
|
||||
#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */
|
||||
#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
|
||||
#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
|
||||
#define E1000_TRGTTIML0 0x0B644 /* Target Time Register 0 Low - RW */
|
||||
#define E1000_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */
|
||||
#define E1000_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */
|
||||
#define E1000_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */
|
||||
#define E1000_FREQOUT0 0x0B654 /* Frequency Out 0 Control Register - RW */
|
||||
#define E1000_FREQOUT1 0x0B658 /* Frequency Out 1 Control Register - RW */
|
||||
#define E1000_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Register Low - RO */
|
||||
#define E1000_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Register High - RO */
|
||||
#define E1000_AUXSTMPL1 0x0B664 /* Auxiliary Time Stamp 1 Register Low - RO */
|
||||
#define E1000_AUXSTMPH1 0x0B668 /* Auxiliary Time Stamp 1 Register High - RO */
|
||||
#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
|
||||
#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */
|
||||
#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */
|
||||
|
||||
/* Filtering Registers */
|
||||
#define E1000_SAQF(_n) (0x5980 + 4 * (_n))
|
||||
#define E1000_DAQF(_n) (0x59A0 + 4 * (_n))
|
||||
#define E1000_SPQF(_n) (0x59C0 + 4 * (_n))
|
||||
#define E1000_FTQF(_n) (0x59E0 + 4 * (_n))
|
||||
#define E1000_SAQF0 E1000_SAQF(0)
|
||||
#define E1000_DAQF0 E1000_DAQF(0)
|
||||
#define E1000_SPQF0 E1000_SPQF(0)
|
||||
#define E1000_FTQF0 E1000_FTQF(0)
|
||||
#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
|
||||
#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
|
||||
|
||||
#define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
|
||||
|
||||
/* DMA Coalescing registers */
|
||||
#define E1000_DMACR 0x02508 /* Control Register */
|
||||
#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */
|
||||
#define E1000_DMCTLX 0x02514 /* Time to Lx Request */
|
||||
#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
|
||||
#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */
|
||||
#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */
|
||||
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
|
||||
|
||||
/* TX Rate Limit Registers */
|
||||
#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */
|
||||
#define E1000_RTTBCNRM 0x3690 /* Tx BCN Rate-scheduler MMW */
|
||||
#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */
|
||||
|
||||
/* Split and Replication RX Control - RW */
|
||||
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
|
||||
|
||||
/* Thermal sensor configuration and status registers */
|
||||
#define E1000_THMJT 0x08100 /* Junction Temperature */
|
||||
#define E1000_THLOWTC 0x08104 /* Low Threshold Control */
|
||||
#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */
|
||||
#define E1000_THHIGHTC 0x0810C /* High Threshold Control */
|
||||
#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
|
||||
|
||||
/* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* E1000_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) \
|
||||
: (0x0C000 + ((_n) * 0x40)))
|
||||
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) \
|
||||
: (0x0C004 + ((_n) * 0x40)))
|
||||
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) \
|
||||
: (0x0C008 + ((_n) * 0x40)))
|
||||
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) \
|
||||
: (0x0C00C + ((_n) * 0x40)))
|
||||
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) \
|
||||
: (0x0C010 + ((_n) * 0x40)))
|
||||
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) \
|
||||
: (0x0C018 + ((_n) * 0x40)))
|
||||
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) \
|
||||
: (0x0C028 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) \
|
||||
: (0x0E000 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) \
|
||||
: (0x0E004 + ((_n) * 0x40)))
|
||||
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) \
|
||||
: (0x0E008 + ((_n) * 0x40)))
|
||||
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) \
|
||||
: (0x0E010 + ((_n) * 0x40)))
|
||||
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) \
|
||||
: (0x0E018 + ((_n) * 0x40)))
|
||||
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \
|
||||
: (0x0E028 + ((_n) * 0x40)))
|
||||
#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \
|
||||
(0x0C014 + ((_n) * 0x40)))
|
||||
#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n)
|
||||
#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \
|
||||
(0x0E014 + ((_n) * 0x40)))
|
||||
#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n)
|
||||
#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \
|
||||
: (0x0E038 + ((_n) * 0x40)))
|
||||
#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) \
|
||||
: (0x0E03C + ((_n) * 0x40)))
|
||||
|
||||
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
|
||||
#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
|
||||
|
||||
#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
|
||||
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
|
||||
#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
|
||||
#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */
|
||||
#define E1000_DTXCTL 0x03590 /* DMA TX Control - RW */
|
||||
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
|
||||
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
|
||||
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
|
||||
#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
|
||||
#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
|
||||
#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
|
||||
#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
|
||||
#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
|
||||
#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
|
||||
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
|
||||
#define E1000_DC 0x04030 /* Defer Count - R/clr */
|
||||
#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */
|
||||
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
|
||||
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
|
||||
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
|
||||
#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */
|
||||
#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */
|
||||
#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */
|
||||
#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */
|
||||
#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */
|
||||
#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */
|
||||
#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */
|
||||
#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */
|
||||
#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */
|
||||
#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */
|
||||
#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */
|
||||
#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */
|
||||
#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */
|
||||
#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */
|
||||
#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */
|
||||
#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */
|
||||
#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */
|
||||
#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */
|
||||
#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */
|
||||
#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */
|
||||
#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */
|
||||
#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */
|
||||
#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */
|
||||
#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */
|
||||
#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */
|
||||
#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
|
||||
#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */
|
||||
#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */
|
||||
#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */
|
||||
#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */
|
||||
#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */
|
||||
#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */
|
||||
#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */
|
||||
#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */
|
||||
#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */
|
||||
#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */
|
||||
#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */
|
||||
#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */
|
||||
#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */
|
||||
#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */
|
||||
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
|
||||
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
|
||||
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
|
||||
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
|
||||
/* Interrupt Cause Rx Packet Timer Expire Count */
|
||||
#define E1000_ICRXPTC 0x04104
|
||||
/* Interrupt Cause Rx Absolute Timer Expire Count */
|
||||
#define E1000_ICRXATC 0x04108
|
||||
/* Interrupt Cause Tx Packet Timer Expire Count */
|
||||
#define E1000_ICTXPTC 0x0410C
|
||||
/* Interrupt Cause Tx Absolute Timer Expire Count */
|
||||
#define E1000_ICTXATC 0x04110
|
||||
/* Interrupt Cause Tx Queue Empty Count */
|
||||
#define E1000_ICTXQEC 0x04118
|
||||
/* Interrupt Cause Tx Queue Minimum Threshold Count */
|
||||
#define E1000_ICTXQMTC 0x0411C
|
||||
/* Interrupt Cause Rx Descriptor Minimum Threshold Count */
|
||||
#define E1000_ICRXDMTC 0x04120
|
||||
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
|
||||
#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
|
||||
#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
|
||||
#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
|
||||
#define E1000_CBTMPC 0x0402C /* Circuit Breaker TX Packet Count */
|
||||
#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
|
||||
#define E1000_CBRMPC 0x040FC /* Circuit Breaker RX Packet Count */
|
||||
#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
|
||||
#define E1000_HGPTC 0x04118 /* Host Good Packets TX Count */
|
||||
#define E1000_HTCBDPC 0x04124 /* Host TX Circuit Breaker Dropped Count */
|
||||
#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
|
||||
#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
|
||||
#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
|
||||
#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
|
||||
#define E1000_LENERRS 0x04138 /* Length Errors Count */
|
||||
#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
|
||||
#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
|
||||
#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
|
||||
#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
|
||||
#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
|
||||
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
|
||||
#define E1000_RLPML 0x05004 /* RX Long Packet Max Length */
|
||||
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
|
||||
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
#define E1000_RA 0x05400 /* Receive Address - RW Array */
|
||||
#define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */
|
||||
#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
|
||||
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
#define E1000_VLAPQF 0x055B0 /* VLAN Priority Queue Filter VLAPQF */
|
||||
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
|
||||
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
|
||||
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
|
||||
#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
|
||||
#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
|
||||
#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
|
||||
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
|
||||
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
|
||||
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
|
||||
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
|
||||
#define E1000_WUS 0x05810 /* Wakeup Status - R/W1C */
|
||||
#define E1000_MANC 0x05820 /* Management Control - RW */
|
||||
#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
|
||||
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
|
||||
|
||||
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
|
||||
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
|
||||
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
|
||||
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
|
||||
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
|
||||
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
|
||||
#define E1000_SWSM 0x05B50 /* SW Semaphore */
|
||||
#define E1000_FWSM 0x05B54 /* FW Semaphore */
|
||||
#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
|
||||
|
||||
/* RSS registers */
|
||||
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
|
||||
#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
|
||||
#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
|
||||
#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt RX VLAN Priority - RW */
|
||||
/* MSI-X Allocation Register (_i) - RW */
|
||||
#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4))
|
||||
/* Redirection Table - RW Array */
|
||||
#define E1000_RETA(_i) (0x05C00 + ((_i) * 4))
|
||||
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */
|
||||
|
||||
/* VT Registers */
|
||||
#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */
|
||||
#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */
|
||||
#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */
|
||||
#define E1000_VFRE 0x00C8C /* VF Receive Enables */
|
||||
#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
|
||||
#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
|
||||
#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
|
||||
#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
|
||||
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
|
||||
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
|
||||
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
|
||||
#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
|
||||
#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
|
||||
/* These act per VF so an array friendly macro is used */
|
||||
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
|
||||
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
|
||||
#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
|
||||
#define E1000_DVMOLR(_n) (0x0C038 + (64 * (_n)))
|
||||
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN VM Filter */
|
||||
#define E1000_VMVIR(_n) (0x03700 + (4 * (_n)))
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
u32 igb_rd32(struct e1000_hw *hw, u32 reg);
|
||||
|
||||
/* write operations, indexed using DWORDS */
|
||||
#define wr32(reg, val) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \
|
||||
if (!E1000_REMOVED(hw_addr)) \
|
||||
writel((val), &hw_addr[(reg)]); \
|
||||
} while (0)
|
||||
|
||||
#define rd32(reg) (igb_rd32(hw, reg))
|
||||
|
||||
#define wrfl() ((void)rd32(E1000_STATUS))
|
||||
|
||||
#define array_wr32(reg, offset, value) \
|
||||
wr32((reg) + ((offset) << 2), (value))
|
||||
|
||||
#define array_rd32(reg, offset) (igb_rd32(hw, reg + ((offset) << 2)))
|
||||
|
||||
/* DMA Coalescing registers */
|
||||
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
|
||||
|
||||
/* Energy Efficient Ethernet "EEE" register */
|
||||
#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
|
||||
#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */
|
||||
#define E1000_EEE_SU 0X0E34 /* EEE Setup */
|
||||
#define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */
|
||||
#define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */
|
||||
#define E1000_MMDAC 13 /* MMD Access Control */
|
||||
#define E1000_MMDAAD 14 /* MMD Access Address/Data */
|
||||
|
||||
/* Thermal Sensor Register */
|
||||
#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
|
||||
|
||||
/* OS2BMC Registers */
|
||||
#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */
|
||||
#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */
|
||||
#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
|
||||
#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
|
||||
|
||||
#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */
|
||||
#define E1000_I210_FLMNGCTL 0x12038
|
||||
#define E1000_I210_FLMNGDATA 0x1203C
|
||||
#define E1000_I210_FLMNGCNT 0x12040
|
||||
|
||||
#define E1000_I210_FLSWCTL 0x12048
|
||||
#define E1000_I210_FLSWDATA 0x1204C
|
||||
#define E1000_I210_FLSWCNT 0x12050
|
||||
|
||||
#define E1000_I210_FLA 0x1201C
|
||||
|
||||
#define E1000_I210_DTXMXPKTSZ 0x355C
|
||||
|
||||
#define E1000_I210_TXDCTL(_n) (0x0E028 + ((_n) * 0x40))
|
||||
|
||||
#define E1000_I210_TQAVCTRL 0x3570
|
||||
#define E1000_I210_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
|
||||
#define E1000_I210_TQAVHC(_n) (0x300C + ((_n) * 0x40))
|
||||
|
||||
#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
|
||||
#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */
|
||||
|
||||
#define E1000_REMOVED(h) unlikely(!(h))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,742 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _IGB_H_
|
||||
#define _IGB_H_
|
||||
|
||||
/* EtherCAT header file */
|
||||
#include "../ecdev.h"
|
||||
|
||||
#include "e1000_mac-4.19-ethercat.h"
|
||||
#include "e1000_82575-4.19-ethercat.h"
|
||||
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mdio.h>
|
||||
|
||||
struct igb_adapter;
|
||||
|
||||
#define E1000_PCS_CFG_IGN_SD 1
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGB_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGB_4K_ITR 980
|
||||
#define IGB_20K_ITR 196
|
||||
#define IGB_70K_ITR 56
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IGB_DEFAULT_TXD 256
|
||||
#define IGB_DEFAULT_TX_WORK 128
|
||||
#define IGB_MIN_TXD 80
|
||||
#define IGB_MAX_TXD 4096
|
||||
|
||||
#define IGB_DEFAULT_RXD 256
|
||||
#define IGB_MIN_RXD 80
|
||||
#define IGB_MAX_RXD 4096
|
||||
|
||||
#define IGB_DEFAULT_ITR 3 /* dynamic */
|
||||
#define IGB_MAX_ITR_USECS 10000
|
||||
#define IGB_MIN_ITR_USECS 10
|
||||
#define NON_Q_VECTORS 1
|
||||
#define MAX_Q_VECTORS 8
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
|
||||
/* Transmit and receive queues */
|
||||
#define IGB_MAX_RX_QUEUES 8
|
||||
#define IGB_MAX_RX_QUEUES_82575 4
|
||||
#define IGB_MAX_RX_QUEUES_I211 2
|
||||
#define IGB_MAX_TX_QUEUES 8
|
||||
#define IGB_MAX_VF_MC_ENTRIES 30
|
||||
#define IGB_MAX_VF_FUNCTIONS 8
|
||||
#define IGB_MAX_VFTA_ENTRIES 128
|
||||
#define IGB_82576_VF_DEV_ID 0x10CA
|
||||
#define IGB_I350_VF_DEV_ID 0x1520
|
||||
|
||||
/* NVM version defines */
|
||||
#define IGB_MAJOR_MASK 0xF000
|
||||
#define IGB_MINOR_MASK 0x0FF0
|
||||
#define IGB_BUILD_MASK 0x000F
|
||||
#define IGB_COMB_VER_MASK 0x00FF
|
||||
#define IGB_MAJOR_SHIFT 12
|
||||
#define IGB_MINOR_SHIFT 4
|
||||
#define IGB_COMB_VER_SHFT 8
|
||||
#define IGB_NVM_VER_INVALID 0xFFFF
|
||||
#define IGB_ETRACK_SHIFT 16
|
||||
#define NVM_ETRACK_WORD 0x0042
|
||||
#define NVM_COMB_VER_OFF 0x0083
|
||||
#define NVM_COMB_VER_PTR 0x003d
|
||||
|
||||
/* Transmit and receive latency (for PTP timestamps) */
|
||||
#define IGB_I210_TX_LATENCY_10 9542
|
||||
#define IGB_I210_TX_LATENCY_100 1024
|
||||
#define IGB_I210_TX_LATENCY_1000 178
|
||||
#define IGB_I210_RX_LATENCY_10 20662
|
||||
#define IGB_I210_RX_LATENCY_100 2213
|
||||
#define IGB_I210_RX_LATENCY_1000 448
|
||||
|
||||
struct vf_data_storage {
|
||||
unsigned char vf_mac_addresses[ETH_ALEN];
|
||||
u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
|
||||
u16 num_vf_mc_hashes;
|
||||
u32 flags;
|
||||
unsigned long last_nack;
|
||||
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
|
||||
u16 pf_qos;
|
||||
u16 tx_rate;
|
||||
bool spoofchk_enabled;
|
||||
bool trusted;
|
||||
};
|
||||
|
||||
/* Number of unicast MAC filters reserved for the PF in the RAR registers */
|
||||
#define IGB_PF_MAC_FILTERS_RESERVED 3
|
||||
|
||||
struct vf_mac_filter {
|
||||
struct list_head l;
|
||||
int vf;
|
||||
bool free;
|
||||
u8 vf_mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */
|
||||
#define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */
|
||||
#define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */
|
||||
#define IGB_VF_FLAG_PF_SET_MAC 0x00000008 /* PF has set MAC address */
|
||||
|
||||
/* RX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8)
|
||||
#define IGB_RX_HTHRESH 8
|
||||
#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
|
||||
#define IGB_TX_HTHRESH 1
|
||||
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
|
||||
(adapter->flags & IGB_FLAG_HAS_MSIX)) ? 1 : 4)
|
||||
#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \
|
||||
(adapter->flags & IGB_FLAG_HAS_MSIX)) ? 1 : 16)
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define IGB_RXBUFFER_256 256
|
||||
#define IGB_RXBUFFER_2048 2048
|
||||
#define IGB_RXBUFFER_3072 3072
|
||||
#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
|
||||
#define IGB_TS_HDR_LEN 16
|
||||
|
||||
#define IGB_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
#if (PAGE_SIZE < 8192)
|
||||
#define IGB_MAX_FRAME_BUILD_SKB \
|
||||
(SKB_WITH_OVERHEAD(IGB_RXBUFFER_2048) - IGB_SKB_PAD - IGB_TS_HDR_LEN)
|
||||
#else
|
||||
#define IGB_MAX_FRAME_BUILD_SKB (IGB_RXBUFFER_2048 - IGB_TS_HDR_LEN)
|
||||
#endif
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define IGB_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGB_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef IGB_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define IGB_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define IGB_MNG_VLAN_NONE -1
|
||||
|
||||
enum igb_tx_flags {
|
||||
/* cmd_type flags */
|
||||
IGB_TX_FLAGS_VLAN = 0x01,
|
||||
IGB_TX_FLAGS_TSO = 0x02,
|
||||
IGB_TX_FLAGS_TSTAMP = 0x04,
|
||||
|
||||
/* olinfo flags */
|
||||
IGB_TX_FLAGS_IPV4 = 0x10,
|
||||
IGB_TX_FLAGS_CSUM = 0x20,
|
||||
};
|
||||
|
||||
/* VLAN info */
|
||||
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define IGB_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
/* The largest size we can write to the descriptor is 65535. In order to
|
||||
* maintain a power of two alignment we have to limit ourselves to 32K.
|
||||
*/
|
||||
#define IGB_MAX_TXD_PWR 15
|
||||
#define IGB_MAX_DATA_PER_TXD (1u << IGB_MAX_TXD_PWR)
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
|
||||
/* EEPROM byte offsets */
|
||||
#define IGB_SFF_8472_SWAP 0x5C
|
||||
#define IGB_SFF_8472_COMP 0x5E
|
||||
|
||||
/* Bitmasks */
|
||||
#define IGB_SFF_ADDRESSING_MODE 0x4
|
||||
#define IGB_SFF_8472_UNSUP 0x00
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igb_tx_buffer {
|
||||
union e1000_adv_tx_desc *next_to_watch;
|
||||
unsigned long time_stamp;
|
||||
struct sk_buff *skb;
|
||||
unsigned int bytecount;
|
||||
u16 gso_segs;
|
||||
__be16 protocol;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct igb_rx_buffer {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
|
||||
__u32 page_offset;
|
||||
#else
|
||||
__u16 page_offset;
|
||||
#endif
|
||||
__u16 pagecnt_bias;
|
||||
};
|
||||
|
||||
struct igb_tx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 restart_queue;
|
||||
u64 restart_queue2;
|
||||
};
|
||||
|
||||
struct igb_rx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 csum_err;
|
||||
u64 alloc_failed;
|
||||
};
|
||||
|
||||
struct igb_ring_container {
|
||||
struct igb_ring *ring; /* pointer to linked list of rings */
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 work_limit; /* total work allowed per interrupt */
|
||||
u8 count; /* total number of rings in vector */
|
||||
u8 itr; /* current ITR setting for ring */
|
||||
};
|
||||
|
||||
struct igb_ring {
|
||||
struct igb_q_vector *q_vector; /* backlink to q_vector */
|
||||
struct net_device *netdev; /* back pointer to net_device */
|
||||
struct device *dev; /* device pointer for dma mapping */
|
||||
union { /* array of buffer info structs */
|
||||
struct igb_tx_buffer *tx_buffer_info;
|
||||
struct igb_rx_buffer *rx_buffer_info;
|
||||
};
|
||||
void *desc; /* descriptor ring memory */
|
||||
unsigned long flags; /* ring specific flags */
|
||||
void __iomem *tail; /* pointer to ring tail register */
|
||||
dma_addr_t dma; /* phys address of the ring */
|
||||
unsigned int size; /* length of desc. ring in bytes */
|
||||
|
||||
u16 count; /* number of desc. in the ring */
|
||||
u8 queue_index; /* logical index of the ring*/
|
||||
u8 reg_idx; /* physical index of the ring */
|
||||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
bool cbs_enable; /* indicates if CBS is enabled */
|
||||
s32 idleslope; /* idleSlope in kbps */
|
||||
s32 sendslope; /* sendSlope in kbps */
|
||||
s32 hicredit; /* hiCredit in bytes */
|
||||
s32 locredit; /* loCredit in bytes */
|
||||
|
||||
/* everything past this point are written often */
|
||||
u16 next_to_clean;
|
||||
u16 next_to_use;
|
||||
u16 next_to_alloc;
|
||||
|
||||
union {
|
||||
/* TX */
|
||||
struct {
|
||||
struct igb_tx_queue_stats tx_stats;
|
||||
struct u64_stats_sync tx_syncp;
|
||||
struct u64_stats_sync tx_syncp2;
|
||||
};
|
||||
/* RX */
|
||||
struct {
|
||||
struct sk_buff *skb;
|
||||
struct igb_rx_queue_stats rx_stats;
|
||||
struct u64_stats_sync rx_syncp;
|
||||
};
|
||||
};
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
struct igb_q_vector {
|
||||
struct igb_adapter *adapter; /* backlink */
|
||||
int cpu; /* CPU for DCA */
|
||||
u32 eims_value; /* EIMS mask value */
|
||||
|
||||
u16 itr_val;
|
||||
u8 set_itr;
|
||||
void __iomem *itr_register;
|
||||
|
||||
struct igb_ring_container rx, tx;
|
||||
|
||||
struct napi_struct napi;
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
|
||||
/* for dynamic allocation of rings associated with this q_vector */
|
||||
struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
|
||||
};
|
||||
|
||||
enum e1000_ring_flags_t {
|
||||
IGB_RING_FLAG_RX_3K_BUFFER,
|
||||
IGB_RING_FLAG_RX_BUILD_SKB_ENABLED,
|
||||
IGB_RING_FLAG_RX_SCTP_CSUM,
|
||||
IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
|
||||
IGB_RING_FLAG_TX_CTX_IDX,
|
||||
IGB_RING_FLAG_TX_DETECT_HANG
|
||||
};
|
||||
|
||||
#define ring_uses_large_buffer(ring) \
|
||||
test_bit(IGB_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define set_ring_uses_large_buffer(ring) \
|
||||
set_bit(IGB_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define clear_ring_uses_large_buffer(ring) \
|
||||
clear_bit(IGB_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
|
||||
#define ring_uses_build_skb(ring) \
|
||||
test_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
#define set_ring_build_skb_enabled(ring) \
|
||||
set_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
#define clear_ring_build_skb_enabled(ring) \
|
||||
clear_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
|
||||
static inline unsigned int igb_rx_bufsz(struct igb_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return IGB_RXBUFFER_3072;
|
||||
|
||||
if (ring_uses_build_skb(ring))
|
||||
return IGB_MAX_FRAME_BUILD_SKB + IGB_TS_HDR_LEN;
|
||||
#endif
|
||||
return IGB_RXBUFFER_2048;
|
||||
}
|
||||
|
||||
static inline unsigned int igb_rx_pg_order(struct igb_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define igb_rx_pg_size(_ring) (PAGE_SIZE << igb_rx_pg_order(_ring))
|
||||
|
||||
#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
|
||||
|
||||
#define IGB_RX_DESC(R, i) \
|
||||
(&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
|
||||
#define IGB_TX_DESC(R, i) \
|
||||
(&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
|
||||
#define IGB_TX_CTXTDESC(R, i) \
|
||||
(&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
|
||||
|
||||
/* igb_test_staterr - tests bits within Rx descriptor status and error fields */
|
||||
static inline __le32 igb_test_staterr(union e1000_adv_rx_desc *rx_desc,
|
||||
const u32 stat_err_bits)
|
||||
{
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
/* igb_desc_unused - calculate if we have unused descriptors */
|
||||
static inline int igb_desc_unused(struct igb_ring *ring)
|
||||
{
|
||||
if (ring->next_to_clean > ring->next_to_use)
|
||||
return ring->next_to_clean - ring->next_to_use - 1;
|
||||
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
|
||||
#define IGB_HWMON_TYPE_LOC 0
|
||||
#define IGB_HWMON_TYPE_TEMP 1
|
||||
#define IGB_HWMON_TYPE_CAUTION 2
|
||||
#define IGB_HWMON_TYPE_MAX 3
|
||||
|
||||
struct hwmon_attr {
|
||||
struct device_attribute dev_attr;
|
||||
struct e1000_hw *hw;
|
||||
struct e1000_thermal_diode_data *sensor;
|
||||
char name[12];
|
||||
};
|
||||
|
||||
struct hwmon_buff {
|
||||
struct attribute_group group;
|
||||
const struct attribute_group *groups[2];
|
||||
struct attribute *attrs[E1000_MAX_SENSORS * 4 + 1];
|
||||
struct hwmon_attr hwmon_list[E1000_MAX_SENSORS * 4];
|
||||
unsigned int n_hwmon;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* The number of L2 ether-type filter registers, Index 3 is reserved
|
||||
* for PTP 1588 timestamp
|
||||
*/
|
||||
#define MAX_ETYPE_FILTER (4 - 1)
|
||||
/* ETQF filter list: one static filter per filter consumer. This is
|
||||
* to avoid filter collisions later. Add new filters here!!
|
||||
*
|
||||
* Current filters: Filter 3
|
||||
*/
|
||||
#define IGB_ETQF_FILTER_1588 3
|
||||
|
||||
#define IGB_N_EXTTS 2
|
||||
#define IGB_N_PEROUT 2
|
||||
#define IGB_N_SDP 4
|
||||
#define IGB_RETA_SIZE 128
|
||||
|
||||
enum igb_filter_match_flags {
|
||||
IGB_FILTER_FLAG_ETHER_TYPE = 0x1,
|
||||
IGB_FILTER_FLAG_VLAN_TCI = 0x2,
|
||||
IGB_FILTER_FLAG_SRC_MAC_ADDR = 0x4,
|
||||
IGB_FILTER_FLAG_DST_MAC_ADDR = 0x8,
|
||||
};
|
||||
|
||||
#define IGB_MAX_RXNFC_FILTERS 16
|
||||
|
||||
/* RX network flow classification data structure */
|
||||
struct igb_nfc_input {
|
||||
/* Byte layout in order, all values with MSB first:
|
||||
* match_flags - 1 byte
|
||||
* etype - 2 bytes
|
||||
* vlan_tci - 2 bytes
|
||||
*/
|
||||
u8 match_flags;
|
||||
__be16 etype;
|
||||
__be16 vlan_tci;
|
||||
u8 src_addr[ETH_ALEN];
|
||||
u8 dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct igb_nfc_filter {
|
||||
struct hlist_node nfc_node;
|
||||
struct igb_nfc_input filter;
|
||||
unsigned long cookie;
|
||||
u16 etype_reg_index;
|
||||
u16 sw_idx;
|
||||
u16 action;
|
||||
};
|
||||
|
||||
struct igb_mac_addr {
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 queue;
|
||||
u8 state; /* bitmask */
|
||||
};
|
||||
|
||||
#define IGB_MAC_STATE_DEFAULT 0x1
|
||||
#define IGB_MAC_STATE_IN_USE 0x2
|
||||
#define IGB_MAC_STATE_SRC_ADDR 0x4
|
||||
#define IGB_MAC_STATE_QUEUE_STEERING 0x8
|
||||
|
||||
/* board specific private data structure */
|
||||
struct igb_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
|
||||
struct net_device *netdev;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int flags;
|
||||
|
||||
unsigned int num_q_vectors;
|
||||
struct msix_entry msix_entries[MAX_MSIX_ENTRIES];
|
||||
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 rx_itr_setting;
|
||||
u32 tx_itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
/* TX */
|
||||
u16 tx_work_limit;
|
||||
u32 tx_timeout_count;
|
||||
int num_tx_queues;
|
||||
struct igb_ring *tx_ring[16];
|
||||
|
||||
/* RX */
|
||||
int num_rx_queues;
|
||||
struct igb_ring *rx_ring[16];
|
||||
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 wol;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
u8 __iomem *io_addr; /* Mainly for iounmap use */
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
bool fc_autoneg;
|
||||
u8 tx_timeout_factor;
|
||||
struct timer_list blink_timer;
|
||||
unsigned long led_status;
|
||||
|
||||
/* OS defined structs */
|
||||
struct pci_dev *pdev;
|
||||
|
||||
spinlock_t stats64_lock;
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
|
||||
u32 test_icr;
|
||||
struct igb_ring test_tx_ring;
|
||||
struct igb_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
struct igb_q_vector *q_vector[MAX_Q_VECTORS];
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
u16 tx_ring_count;
|
||||
u16 rx_ring_count;
|
||||
unsigned int vfs_allocated_count;
|
||||
struct vf_data_storage *vf_data;
|
||||
int vf_rate_link_speed;
|
||||
u32 rss_queues;
|
||||
u32 wvbr;
|
||||
u32 *shadow_vfta;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct delayed_work ptp_overflow_work;
|
||||
struct work_struct ptp_tx_work;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
unsigned long last_rx_ptp_check;
|
||||
unsigned long last_rx_timestamp;
|
||||
unsigned int ptp_flags;
|
||||
spinlock_t tmreg_lock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 tx_hwtstamp_skipped;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
bool pps_sys_wrap_on;
|
||||
|
||||
struct ptp_pin_desc sdp_config[IGB_N_SDP];
|
||||
struct {
|
||||
struct timespec64 start;
|
||||
struct timespec64 period;
|
||||
} perout[IGB_N_PEROUT];
|
||||
|
||||
char fw_version[32];
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
struct hwmon_buff *igb_hwmon_buff;
|
||||
bool ets;
|
||||
#endif
|
||||
struct i2c_algo_bit_data i2c_algo;
|
||||
struct i2c_adapter i2c_adap;
|
||||
struct i2c_client *i2c_client;
|
||||
u32 rss_indir_tbl_init;
|
||||
u8 rss_indir_tbl[IGB_RETA_SIZE];
|
||||
|
||||
unsigned long link_check_timeout;
|
||||
int copper_tries;
|
||||
struct e1000_info ei;
|
||||
u16 eee_advert;
|
||||
|
||||
/* RX network flow classification support */
|
||||
struct hlist_head nfc_filter_list;
|
||||
struct hlist_head cls_flower_list;
|
||||
unsigned int nfc_filter_count;
|
||||
/* lock for RX network flow classification filter */
|
||||
spinlock_t nfc_lock;
|
||||
bool etype_bitmap[MAX_ETYPE_FILTER];
|
||||
|
||||
struct igb_mac_addr *mac_table;
|
||||
struct vf_mac_filter vf_macs;
|
||||
struct vf_mac_filter *vf_mac_list;
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
};
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGB_PTP_ENABLED BIT(0)
|
||||
#define IGB_PTP_OVERFLOW_CHECK BIT(1)
|
||||
|
||||
#define IGB_FLAG_HAS_MSI BIT(0)
|
||||
#define IGB_FLAG_DCA_ENABLED BIT(1)
|
||||
#define IGB_FLAG_QUAD_PORT_A BIT(2)
|
||||
#define IGB_FLAG_QUEUE_PAIRS BIT(3)
|
||||
#define IGB_FLAG_DMAC BIT(4)
|
||||
#define IGB_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
|
||||
#define IGB_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
|
||||
#define IGB_FLAG_WOL_SUPPORTED BIT(8)
|
||||
#define IGB_FLAG_NEED_LINK_UPDATE BIT(9)
|
||||
#define IGB_FLAG_MEDIA_RESET BIT(10)
|
||||
#define IGB_FLAG_MAS_CAPABLE BIT(11)
|
||||
#define IGB_FLAG_MAS_ENABLE BIT(12)
|
||||
#define IGB_FLAG_HAS_MSIX BIT(13)
|
||||
#define IGB_FLAG_EEE BIT(14)
|
||||
#define IGB_FLAG_VLAN_PROMISC BIT(15)
|
||||
#define IGB_FLAG_RX_LEGACY BIT(16)
|
||||
#define IGB_FLAG_FQTSS BIT(17)
|
||||
|
||||
/* Media Auto Sense */
|
||||
#define IGB_MAS_ENABLE_0 0X0001
|
||||
#define IGB_MAS_ENABLE_1 0X0002
|
||||
#define IGB_MAS_ENABLE_2 0X0004
|
||||
#define IGB_MAS_ENABLE_3 0X0008
|
||||
|
||||
/* DMA Coalescing defines */
|
||||
#define IGB_MIN_TXPBSIZE 20408
|
||||
#define IGB_TX_BUF_4096 4096
|
||||
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */
|
||||
|
||||
#define IGB_82576_TSYNC_SHIFT 19
|
||||
enum e1000_state_t {
|
||||
__IGB_TESTING,
|
||||
__IGB_RESETTING,
|
||||
__IGB_DOWN,
|
||||
__IGB_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igb_boards {
|
||||
board_82575,
|
||||
};
|
||||
|
||||
extern char igb_driver_name[];
|
||||
extern char igb_driver_version[];
|
||||
|
||||
int igb_open(struct net_device *netdev);
|
||||
int igb_close(struct net_device *netdev);
|
||||
int igb_up(struct igb_adapter *);
|
||||
void igb_down(struct igb_adapter *);
|
||||
void igb_reinit_locked(struct igb_adapter *);
|
||||
void igb_reset(struct igb_adapter *);
|
||||
int igb_reinit_queues(struct igb_adapter *);
|
||||
void igb_write_rss_indir_tbl(struct igb_adapter *);
|
||||
int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
|
||||
int igb_setup_tx_resources(struct igb_ring *);
|
||||
int igb_setup_rx_resources(struct igb_ring *);
|
||||
void igb_free_tx_resources(struct igb_ring *);
|
||||
void igb_free_rx_resources(struct igb_ring *);
|
||||
void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
|
||||
void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
|
||||
void igb_setup_tctl(struct igb_adapter *);
|
||||
void igb_setup_rctl(struct igb_adapter *);
|
||||
netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
|
||||
void igb_alloc_rx_buffers(struct igb_ring *, u16);
|
||||
void igb_update_stats(struct igb_adapter *);
|
||||
bool igb_has_link(struct igb_adapter *adapter);
|
||||
void igb_set_ethtool_ops(struct net_device *);
|
||||
void igb_power_up_link(struct igb_adapter *);
|
||||
void igb_set_fw_version(struct igb_adapter *);
|
||||
void igb_ptp_init(struct igb_adapter *adapter);
|
||||
void igb_ptp_stop(struct igb_adapter *adapter);
|
||||
void igb_ptp_reset(struct igb_adapter *adapter);
|
||||
void igb_ptp_suspend(struct igb_adapter *adapter);
|
||||
void igb_ptp_rx_hang(struct igb_adapter *adapter);
|
||||
void igb_ptp_tx_hang(struct igb_adapter *adapter);
|
||||
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
|
||||
void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
||||
struct sk_buff *skb);
|
||||
int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
|
||||
unsigned int igb_get_max_rss_queues(struct igb_adapter *);
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
void igb_sysfs_exit(struct igb_adapter *adapter);
|
||||
int igb_sysfs_init(struct igb_adapter *adapter);
|
||||
#endif
|
||||
static inline s32 igb_reset_phy(struct e1000_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
|
||||
{
|
||||
if (hw->phy.ops.write_reg)
|
||||
return hw->phy.ops.write_reg(hw, offset, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igb_get_phy_info(struct e1000_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_phy_info)
|
||||
return hw->phy.ops.get_phy_info(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring)
|
||||
{
|
||||
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
int igb_add_filter(struct igb_adapter *adapter,
|
||||
struct igb_nfc_filter *input);
|
||||
int igb_erase_filter(struct igb_adapter *adapter,
|
||||
struct igb_nfc_filter *input);
|
||||
|
||||
int igb_add_mac_steering_filter(struct igb_adapter *adapter,
|
||||
const u8 *addr, u8 queue, u8 flags);
|
||||
int igb_del_mac_steering_filter(struct igb_adapter *adapter,
|
||||
const u8 *addr, u8 queue, u8 flags);
|
||||
|
||||
#endif /* _IGB_H_ */
|
||||
|
|
@ -0,0 +1,735 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _IGB_H_
|
||||
#define _IGB_H_
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_82575.h"
|
||||
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mdio.h>
|
||||
|
||||
struct igb_adapter;
|
||||
|
||||
#define E1000_PCS_CFG_IGN_SD 1
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGB_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGB_4K_ITR 980
|
||||
#define IGB_20K_ITR 196
|
||||
#define IGB_70K_ITR 56
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IGB_DEFAULT_TXD 256
|
||||
#define IGB_DEFAULT_TX_WORK 128
|
||||
#define IGB_MIN_TXD 80
|
||||
#define IGB_MAX_TXD 4096
|
||||
|
||||
#define IGB_DEFAULT_RXD 256
|
||||
#define IGB_MIN_RXD 80
|
||||
#define IGB_MAX_RXD 4096
|
||||
|
||||
#define IGB_DEFAULT_ITR 3 /* dynamic */
|
||||
#define IGB_MAX_ITR_USECS 10000
|
||||
#define IGB_MIN_ITR_USECS 10
|
||||
#define NON_Q_VECTORS 1
|
||||
#define MAX_Q_VECTORS 8
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
|
||||
/* Transmit and receive queues */
|
||||
#define IGB_MAX_RX_QUEUES 8
|
||||
#define IGB_MAX_RX_QUEUES_82575 4
|
||||
#define IGB_MAX_RX_QUEUES_I211 2
|
||||
#define IGB_MAX_TX_QUEUES 8
|
||||
#define IGB_MAX_VF_MC_ENTRIES 30
|
||||
#define IGB_MAX_VF_FUNCTIONS 8
|
||||
#define IGB_MAX_VFTA_ENTRIES 128
|
||||
#define IGB_82576_VF_DEV_ID 0x10CA
|
||||
#define IGB_I350_VF_DEV_ID 0x1520
|
||||
|
||||
/* NVM version defines */
|
||||
#define IGB_MAJOR_MASK 0xF000
|
||||
#define IGB_MINOR_MASK 0x0FF0
|
||||
#define IGB_BUILD_MASK 0x000F
|
||||
#define IGB_COMB_VER_MASK 0x00FF
|
||||
#define IGB_MAJOR_SHIFT 12
|
||||
#define IGB_MINOR_SHIFT 4
|
||||
#define IGB_COMB_VER_SHFT 8
|
||||
#define IGB_NVM_VER_INVALID 0xFFFF
|
||||
#define IGB_ETRACK_SHIFT 16
|
||||
#define NVM_ETRACK_WORD 0x0042
|
||||
#define NVM_COMB_VER_OFF 0x0083
|
||||
#define NVM_COMB_VER_PTR 0x003d
|
||||
|
||||
/* Transmit and receive latency (for PTP timestamps) */
|
||||
#define IGB_I210_TX_LATENCY_10 9542
|
||||
#define IGB_I210_TX_LATENCY_100 1024
|
||||
#define IGB_I210_TX_LATENCY_1000 178
|
||||
#define IGB_I210_RX_LATENCY_10 20662
|
||||
#define IGB_I210_RX_LATENCY_100 2213
|
||||
#define IGB_I210_RX_LATENCY_1000 448
|
||||
|
||||
struct vf_data_storage {
|
||||
unsigned char vf_mac_addresses[ETH_ALEN];
|
||||
u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
|
||||
u16 num_vf_mc_hashes;
|
||||
u32 flags;
|
||||
unsigned long last_nack;
|
||||
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
|
||||
u16 pf_qos;
|
||||
u16 tx_rate;
|
||||
bool spoofchk_enabled;
|
||||
bool trusted;
|
||||
};
|
||||
|
||||
/* Number of unicast MAC filters reserved for the PF in the RAR registers */
|
||||
#define IGB_PF_MAC_FILTERS_RESERVED 3
|
||||
|
||||
struct vf_mac_filter {
|
||||
struct list_head l;
|
||||
int vf;
|
||||
bool free;
|
||||
u8 vf_mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */
|
||||
#define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */
|
||||
#define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */
|
||||
#define IGB_VF_FLAG_PF_SET_MAC 0x00000008 /* PF has set MAC address */
|
||||
|
||||
/* RX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8)
|
||||
#define IGB_RX_HTHRESH 8
|
||||
#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
|
||||
#define IGB_TX_HTHRESH 1
|
||||
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
|
||||
(adapter->flags & IGB_FLAG_HAS_MSIX)) ? 1 : 4)
|
||||
#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \
|
||||
(adapter->flags & IGB_FLAG_HAS_MSIX)) ? 1 : 16)
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define IGB_RXBUFFER_256 256
|
||||
#define IGB_RXBUFFER_2048 2048
|
||||
#define IGB_RXBUFFER_3072 3072
|
||||
#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
|
||||
#define IGB_TS_HDR_LEN 16
|
||||
|
||||
#define IGB_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
#if (PAGE_SIZE < 8192)
|
||||
#define IGB_MAX_FRAME_BUILD_SKB \
|
||||
(SKB_WITH_OVERHEAD(IGB_RXBUFFER_2048) - IGB_SKB_PAD - IGB_TS_HDR_LEN)
|
||||
#else
|
||||
#define IGB_MAX_FRAME_BUILD_SKB (IGB_RXBUFFER_2048 - IGB_TS_HDR_LEN)
|
||||
#endif
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define IGB_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGB_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef IGB_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define IGB_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define IGB_MNG_VLAN_NONE -1
|
||||
|
||||
enum igb_tx_flags {
|
||||
/* cmd_type flags */
|
||||
IGB_TX_FLAGS_VLAN = 0x01,
|
||||
IGB_TX_FLAGS_TSO = 0x02,
|
||||
IGB_TX_FLAGS_TSTAMP = 0x04,
|
||||
|
||||
/* olinfo flags */
|
||||
IGB_TX_FLAGS_IPV4 = 0x10,
|
||||
IGB_TX_FLAGS_CSUM = 0x20,
|
||||
};
|
||||
|
||||
/* VLAN info */
|
||||
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define IGB_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
/* The largest size we can write to the descriptor is 65535. In order to
|
||||
* maintain a power of two alignment we have to limit ourselves to 32K.
|
||||
*/
|
||||
#define IGB_MAX_TXD_PWR 15
|
||||
#define IGB_MAX_DATA_PER_TXD (1u << IGB_MAX_TXD_PWR)
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
|
||||
/* EEPROM byte offsets */
|
||||
#define IGB_SFF_8472_SWAP 0x5C
|
||||
#define IGB_SFF_8472_COMP 0x5E
|
||||
|
||||
/* Bitmasks */
|
||||
#define IGB_SFF_ADDRESSING_MODE 0x4
|
||||
#define IGB_SFF_8472_UNSUP 0x00
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igb_tx_buffer {
|
||||
union e1000_adv_tx_desc *next_to_watch;
|
||||
unsigned long time_stamp;
|
||||
struct sk_buff *skb;
|
||||
unsigned int bytecount;
|
||||
u16 gso_segs;
|
||||
__be16 protocol;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct igb_rx_buffer {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
|
||||
__u32 page_offset;
|
||||
#else
|
||||
__u16 page_offset;
|
||||
#endif
|
||||
__u16 pagecnt_bias;
|
||||
};
|
||||
|
||||
struct igb_tx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 restart_queue;
|
||||
u64 restart_queue2;
|
||||
};
|
||||
|
||||
struct igb_rx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 csum_err;
|
||||
u64 alloc_failed;
|
||||
};
|
||||
|
||||
struct igb_ring_container {
|
||||
struct igb_ring *ring; /* pointer to linked list of rings */
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 work_limit; /* total work allowed per interrupt */
|
||||
u8 count; /* total number of rings in vector */
|
||||
u8 itr; /* current ITR setting for ring */
|
||||
};
|
||||
|
||||
struct igb_ring {
|
||||
struct igb_q_vector *q_vector; /* backlink to q_vector */
|
||||
struct net_device *netdev; /* back pointer to net_device */
|
||||
struct device *dev; /* device pointer for dma mapping */
|
||||
union { /* array of buffer info structs */
|
||||
struct igb_tx_buffer *tx_buffer_info;
|
||||
struct igb_rx_buffer *rx_buffer_info;
|
||||
};
|
||||
void *desc; /* descriptor ring memory */
|
||||
unsigned long flags; /* ring specific flags */
|
||||
void __iomem *tail; /* pointer to ring tail register */
|
||||
dma_addr_t dma; /* phys address of the ring */
|
||||
unsigned int size; /* length of desc. ring in bytes */
|
||||
|
||||
u16 count; /* number of desc. in the ring */
|
||||
u8 queue_index; /* logical index of the ring*/
|
||||
u8 reg_idx; /* physical index of the ring */
|
||||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
bool cbs_enable; /* indicates if CBS is enabled */
|
||||
s32 idleslope; /* idleSlope in kbps */
|
||||
s32 sendslope; /* sendSlope in kbps */
|
||||
s32 hicredit; /* hiCredit in bytes */
|
||||
s32 locredit; /* loCredit in bytes */
|
||||
|
||||
/* everything past this point are written often */
|
||||
u16 next_to_clean;
|
||||
u16 next_to_use;
|
||||
u16 next_to_alloc;
|
||||
|
||||
union {
|
||||
/* TX */
|
||||
struct {
|
||||
struct igb_tx_queue_stats tx_stats;
|
||||
struct u64_stats_sync tx_syncp;
|
||||
struct u64_stats_sync tx_syncp2;
|
||||
};
|
||||
/* RX */
|
||||
struct {
|
||||
struct sk_buff *skb;
|
||||
struct igb_rx_queue_stats rx_stats;
|
||||
struct u64_stats_sync rx_syncp;
|
||||
};
|
||||
};
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
struct igb_q_vector {
|
||||
struct igb_adapter *adapter; /* backlink */
|
||||
int cpu; /* CPU for DCA */
|
||||
u32 eims_value; /* EIMS mask value */
|
||||
|
||||
u16 itr_val;
|
||||
u8 set_itr;
|
||||
void __iomem *itr_register;
|
||||
|
||||
struct igb_ring_container rx, tx;
|
||||
|
||||
struct napi_struct napi;
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
|
||||
/* for dynamic allocation of rings associated with this q_vector */
|
||||
struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
|
||||
};
|
||||
|
||||
enum e1000_ring_flags_t {
|
||||
IGB_RING_FLAG_RX_3K_BUFFER,
|
||||
IGB_RING_FLAG_RX_BUILD_SKB_ENABLED,
|
||||
IGB_RING_FLAG_RX_SCTP_CSUM,
|
||||
IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
|
||||
IGB_RING_FLAG_TX_CTX_IDX,
|
||||
IGB_RING_FLAG_TX_DETECT_HANG
|
||||
};
|
||||
|
||||
#define ring_uses_large_buffer(ring) \
|
||||
test_bit(IGB_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define set_ring_uses_large_buffer(ring) \
|
||||
set_bit(IGB_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define clear_ring_uses_large_buffer(ring) \
|
||||
clear_bit(IGB_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
|
||||
#define ring_uses_build_skb(ring) \
|
||||
test_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
#define set_ring_build_skb_enabled(ring) \
|
||||
set_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
#define clear_ring_build_skb_enabled(ring) \
|
||||
clear_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
|
||||
static inline unsigned int igb_rx_bufsz(struct igb_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return IGB_RXBUFFER_3072;
|
||||
|
||||
if (ring_uses_build_skb(ring))
|
||||
return IGB_MAX_FRAME_BUILD_SKB + IGB_TS_HDR_LEN;
|
||||
#endif
|
||||
return IGB_RXBUFFER_2048;
|
||||
}
|
||||
|
||||
static inline unsigned int igb_rx_pg_order(struct igb_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define igb_rx_pg_size(_ring) (PAGE_SIZE << igb_rx_pg_order(_ring))
|
||||
|
||||
#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
|
||||
|
||||
#define IGB_RX_DESC(R, i) \
|
||||
(&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
|
||||
#define IGB_TX_DESC(R, i) \
|
||||
(&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
|
||||
#define IGB_TX_CTXTDESC(R, i) \
|
||||
(&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
|
||||
|
||||
/* igb_test_staterr - tests bits within Rx descriptor status and error fields */
|
||||
static inline __le32 igb_test_staterr(union e1000_adv_rx_desc *rx_desc,
|
||||
const u32 stat_err_bits)
|
||||
{
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
/* igb_desc_unused - calculate if we have unused descriptors */
|
||||
static inline int igb_desc_unused(struct igb_ring *ring)
|
||||
{
|
||||
if (ring->next_to_clean > ring->next_to_use)
|
||||
return ring->next_to_clean - ring->next_to_use - 1;
|
||||
|
||||
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
|
||||
#define IGB_HWMON_TYPE_LOC 0
|
||||
#define IGB_HWMON_TYPE_TEMP 1
|
||||
#define IGB_HWMON_TYPE_CAUTION 2
|
||||
#define IGB_HWMON_TYPE_MAX 3
|
||||
|
||||
struct hwmon_attr {
|
||||
struct device_attribute dev_attr;
|
||||
struct e1000_hw *hw;
|
||||
struct e1000_thermal_diode_data *sensor;
|
||||
char name[12];
|
||||
};
|
||||
|
||||
struct hwmon_buff {
|
||||
struct attribute_group group;
|
||||
const struct attribute_group *groups[2];
|
||||
struct attribute *attrs[E1000_MAX_SENSORS * 4 + 1];
|
||||
struct hwmon_attr hwmon_list[E1000_MAX_SENSORS * 4];
|
||||
unsigned int n_hwmon;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* The number of L2 ether-type filter registers, Index 3 is reserved
|
||||
* for PTP 1588 timestamp
|
||||
*/
|
||||
#define MAX_ETYPE_FILTER (4 - 1)
|
||||
/* ETQF filter list: one static filter per filter consumer. This is
|
||||
* to avoid filter collisions later. Add new filters here!!
|
||||
*
|
||||
* Current filters: Filter 3
|
||||
*/
|
||||
#define IGB_ETQF_FILTER_1588 3
|
||||
|
||||
#define IGB_N_EXTTS 2
|
||||
#define IGB_N_PEROUT 2
|
||||
#define IGB_N_SDP 4
|
||||
#define IGB_RETA_SIZE 128
|
||||
|
||||
enum igb_filter_match_flags {
|
||||
IGB_FILTER_FLAG_ETHER_TYPE = 0x1,
|
||||
IGB_FILTER_FLAG_VLAN_TCI = 0x2,
|
||||
IGB_FILTER_FLAG_SRC_MAC_ADDR = 0x4,
|
||||
IGB_FILTER_FLAG_DST_MAC_ADDR = 0x8,
|
||||
};
|
||||
|
||||
#define IGB_MAX_RXNFC_FILTERS 16
|
||||
|
||||
/* RX network flow classification data structure */
|
||||
struct igb_nfc_input {
|
||||
/* Byte layout in order, all values with MSB first:
|
||||
* match_flags - 1 byte
|
||||
* etype - 2 bytes
|
||||
* vlan_tci - 2 bytes
|
||||
*/
|
||||
u8 match_flags;
|
||||
__be16 etype;
|
||||
__be16 vlan_tci;
|
||||
u8 src_addr[ETH_ALEN];
|
||||
u8 dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct igb_nfc_filter {
|
||||
struct hlist_node nfc_node;
|
||||
struct igb_nfc_input filter;
|
||||
unsigned long cookie;
|
||||
u16 etype_reg_index;
|
||||
u16 sw_idx;
|
||||
u16 action;
|
||||
};
|
||||
|
||||
struct igb_mac_addr {
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 queue;
|
||||
u8 state; /* bitmask */
|
||||
};
|
||||
|
||||
#define IGB_MAC_STATE_DEFAULT 0x1
|
||||
#define IGB_MAC_STATE_IN_USE 0x2
|
||||
#define IGB_MAC_STATE_SRC_ADDR 0x4
|
||||
#define IGB_MAC_STATE_QUEUE_STEERING 0x8
|
||||
|
||||
/* board specific private data structure */
|
||||
struct igb_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
|
||||
struct net_device *netdev;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int flags;
|
||||
|
||||
unsigned int num_q_vectors;
|
||||
struct msix_entry msix_entries[MAX_MSIX_ENTRIES];
|
||||
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 rx_itr_setting;
|
||||
u32 tx_itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
/* TX */
|
||||
u16 tx_work_limit;
|
||||
u32 tx_timeout_count;
|
||||
int num_tx_queues;
|
||||
struct igb_ring *tx_ring[16];
|
||||
|
||||
/* RX */
|
||||
int num_rx_queues;
|
||||
struct igb_ring *rx_ring[16];
|
||||
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 wol;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
u8 __iomem *io_addr; /* Mainly for iounmap use */
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
bool fc_autoneg;
|
||||
u8 tx_timeout_factor;
|
||||
struct timer_list blink_timer;
|
||||
unsigned long led_status;
|
||||
|
||||
/* OS defined structs */
|
||||
struct pci_dev *pdev;
|
||||
|
||||
spinlock_t stats64_lock;
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
|
||||
u32 test_icr;
|
||||
struct igb_ring test_tx_ring;
|
||||
struct igb_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
struct igb_q_vector *q_vector[MAX_Q_VECTORS];
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
u16 tx_ring_count;
|
||||
u16 rx_ring_count;
|
||||
unsigned int vfs_allocated_count;
|
||||
struct vf_data_storage *vf_data;
|
||||
int vf_rate_link_speed;
|
||||
u32 rss_queues;
|
||||
u32 wvbr;
|
||||
u32 *shadow_vfta;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct delayed_work ptp_overflow_work;
|
||||
struct work_struct ptp_tx_work;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
unsigned long last_rx_ptp_check;
|
||||
unsigned long last_rx_timestamp;
|
||||
unsigned int ptp_flags;
|
||||
spinlock_t tmreg_lock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 tx_hwtstamp_skipped;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
bool pps_sys_wrap_on;
|
||||
|
||||
struct ptp_pin_desc sdp_config[IGB_N_SDP];
|
||||
struct {
|
||||
struct timespec64 start;
|
||||
struct timespec64 period;
|
||||
} perout[IGB_N_PEROUT];
|
||||
|
||||
char fw_version[32];
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
struct hwmon_buff *igb_hwmon_buff;
|
||||
bool ets;
|
||||
#endif
|
||||
struct i2c_algo_bit_data i2c_algo;
|
||||
struct i2c_adapter i2c_adap;
|
||||
struct i2c_client *i2c_client;
|
||||
u32 rss_indir_tbl_init;
|
||||
u8 rss_indir_tbl[IGB_RETA_SIZE];
|
||||
|
||||
unsigned long link_check_timeout;
|
||||
int copper_tries;
|
||||
struct e1000_info ei;
|
||||
u16 eee_advert;
|
||||
|
||||
/* RX network flow classification support */
|
||||
struct hlist_head nfc_filter_list;
|
||||
struct hlist_head cls_flower_list;
|
||||
unsigned int nfc_filter_count;
|
||||
/* lock for RX network flow classification filter */
|
||||
spinlock_t nfc_lock;
|
||||
bool etype_bitmap[MAX_ETYPE_FILTER];
|
||||
|
||||
struct igb_mac_addr *mac_table;
|
||||
struct vf_mac_filter vf_macs;
|
||||
struct vf_mac_filter *vf_mac_list;
|
||||
};
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGB_PTP_ENABLED BIT(0)
|
||||
#define IGB_PTP_OVERFLOW_CHECK BIT(1)
|
||||
|
||||
#define IGB_FLAG_HAS_MSI BIT(0)
|
||||
#define IGB_FLAG_DCA_ENABLED BIT(1)
|
||||
#define IGB_FLAG_QUAD_PORT_A BIT(2)
|
||||
#define IGB_FLAG_QUEUE_PAIRS BIT(3)
|
||||
#define IGB_FLAG_DMAC BIT(4)
|
||||
#define IGB_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
|
||||
#define IGB_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
|
||||
#define IGB_FLAG_WOL_SUPPORTED BIT(8)
|
||||
#define IGB_FLAG_NEED_LINK_UPDATE BIT(9)
|
||||
#define IGB_FLAG_MEDIA_RESET BIT(10)
|
||||
#define IGB_FLAG_MAS_CAPABLE BIT(11)
|
||||
#define IGB_FLAG_MAS_ENABLE BIT(12)
|
||||
#define IGB_FLAG_HAS_MSIX BIT(13)
|
||||
#define IGB_FLAG_EEE BIT(14)
|
||||
#define IGB_FLAG_VLAN_PROMISC BIT(15)
|
||||
#define IGB_FLAG_RX_LEGACY BIT(16)
|
||||
#define IGB_FLAG_FQTSS BIT(17)
|
||||
|
||||
/* Media Auto Sense */
|
||||
#define IGB_MAS_ENABLE_0 0X0001
|
||||
#define IGB_MAS_ENABLE_1 0X0002
|
||||
#define IGB_MAS_ENABLE_2 0X0004
|
||||
#define IGB_MAS_ENABLE_3 0X0008
|
||||
|
||||
/* DMA Coalescing defines */
|
||||
#define IGB_MIN_TXPBSIZE 20408
|
||||
#define IGB_TX_BUF_4096 4096
|
||||
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */
|
||||
|
||||
#define IGB_82576_TSYNC_SHIFT 19
|
||||
enum e1000_state_t {
|
||||
__IGB_TESTING,
|
||||
__IGB_RESETTING,
|
||||
__IGB_DOWN,
|
||||
__IGB_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igb_boards {
|
||||
board_82575,
|
||||
};
|
||||
|
||||
extern char igb_driver_name[];
|
||||
extern char igb_driver_version[];
|
||||
|
||||
int igb_open(struct net_device *netdev);
|
||||
int igb_close(struct net_device *netdev);
|
||||
int igb_up(struct igb_adapter *);
|
||||
void igb_down(struct igb_adapter *);
|
||||
void igb_reinit_locked(struct igb_adapter *);
|
||||
void igb_reset(struct igb_adapter *);
|
||||
int igb_reinit_queues(struct igb_adapter *);
|
||||
void igb_write_rss_indir_tbl(struct igb_adapter *);
|
||||
int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
|
||||
int igb_setup_tx_resources(struct igb_ring *);
|
||||
int igb_setup_rx_resources(struct igb_ring *);
|
||||
void igb_free_tx_resources(struct igb_ring *);
|
||||
void igb_free_rx_resources(struct igb_ring *);
|
||||
void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
|
||||
void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
|
||||
void igb_setup_tctl(struct igb_adapter *);
|
||||
void igb_setup_rctl(struct igb_adapter *);
|
||||
netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
|
||||
void igb_alloc_rx_buffers(struct igb_ring *, u16);
|
||||
void igb_update_stats(struct igb_adapter *);
|
||||
bool igb_has_link(struct igb_adapter *adapter);
|
||||
void igb_set_ethtool_ops(struct net_device *);
|
||||
void igb_power_up_link(struct igb_adapter *);
|
||||
void igb_set_fw_version(struct igb_adapter *);
|
||||
void igb_ptp_init(struct igb_adapter *adapter);
|
||||
void igb_ptp_stop(struct igb_adapter *adapter);
|
||||
void igb_ptp_reset(struct igb_adapter *adapter);
|
||||
void igb_ptp_suspend(struct igb_adapter *adapter);
|
||||
void igb_ptp_rx_hang(struct igb_adapter *adapter);
|
||||
void igb_ptp_tx_hang(struct igb_adapter *adapter);
|
||||
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
|
||||
void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
|
||||
struct sk_buff *skb);
|
||||
int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
|
||||
unsigned int igb_get_max_rss_queues(struct igb_adapter *);
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
void igb_sysfs_exit(struct igb_adapter *adapter);
|
||||
int igb_sysfs_init(struct igb_adapter *adapter);
|
||||
#endif
|
||||
static inline s32 igb_reset_phy(struct e1000_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
|
||||
{
|
||||
if (hw->phy.ops.write_reg)
|
||||
return hw->phy.ops.write_reg(hw, offset, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igb_get_phy_info(struct e1000_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_phy_info)
|
||||
return hw->phy.ops.get_phy_info(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring)
|
||||
{
|
||||
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
int igb_add_filter(struct igb_adapter *adapter,
|
||||
struct igb_nfc_filter *input);
|
||||
int igb_erase_filter(struct igb_adapter *adapter,
|
||||
struct igb_nfc_filter *input);
|
||||
|
||||
int igb_add_mac_steering_filter(struct igb_adapter *adapter,
|
||||
const u8 *addr, u8 queue, u8 flags);
|
||||
int igb_del_mac_steering_filter(struct igb_adapter *adapter,
|
||||
const u8 *addr, u8 queue, u8 flags);
|
||||
|
||||
#endif /* _IGB_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,229 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#include "igb-4.19-ethercat.h"
|
||||
#include "e1000_82575-4.19-ethercat.h"
|
||||
#include "e1000_hw-4.19-ethercat.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
static struct i2c_board_info i350_sensor_info = {
|
||||
I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)),
|
||||
};
|
||||
|
||||
/* hwmon callback functions */
|
||||
static ssize_t igb_hwmon_show_location(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
return sprintf(buf, "loc%u\n",
|
||||
igb_attr->sensor->location);
|
||||
}
|
||||
|
||||
static ssize_t igb_hwmon_show_temp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
unsigned int value;
|
||||
|
||||
/* reset the temp field */
|
||||
igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw);
|
||||
|
||||
value = igb_attr->sensor->temp;
|
||||
|
||||
/* display millidegree */
|
||||
value *= 1000;
|
||||
|
||||
return sprintf(buf, "%u\n", value);
|
||||
}
|
||||
|
||||
static ssize_t igb_hwmon_show_cautionthresh(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
unsigned int value = igb_attr->sensor->caution_thresh;
|
||||
|
||||
/* display millidegree */
|
||||
value *= 1000;
|
||||
|
||||
return sprintf(buf, "%u\n", value);
|
||||
}
|
||||
|
||||
static ssize_t igb_hwmon_show_maxopthresh(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
unsigned int value = igb_attr->sensor->max_op_thresh;
|
||||
|
||||
/* display millidegree */
|
||||
value *= 1000;
|
||||
|
||||
return sprintf(buf, "%u\n", value);
|
||||
}
|
||||
|
||||
/* igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
|
||||
* @ adapter: pointer to the adapter structure
|
||||
* @ offset: offset in the eeprom sensor data table
|
||||
* @ type: type of sensor data to display
|
||||
*
|
||||
* For each file we want in hwmon's sysfs interface we need a device_attribute
|
||||
* This is included in our hwmon_attr struct that contains the references to
|
||||
* the data structures we need to get the data to display.
|
||||
*/
|
||||
static int igb_add_hwmon_attr(struct igb_adapter *adapter,
|
||||
unsigned int offset, int type)
|
||||
{
|
||||
int rc;
|
||||
unsigned int n_attr;
|
||||
struct hwmon_attr *igb_attr;
|
||||
|
||||
n_attr = adapter->igb_hwmon_buff->n_hwmon;
|
||||
igb_attr = &adapter->igb_hwmon_buff->hwmon_list[n_attr];
|
||||
|
||||
switch (type) {
|
||||
case IGB_HWMON_TYPE_LOC:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_location;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_label", offset + 1);
|
||||
break;
|
||||
case IGB_HWMON_TYPE_TEMP:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_temp;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_input", offset + 1);
|
||||
break;
|
||||
case IGB_HWMON_TYPE_CAUTION:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_max", offset + 1);
|
||||
break;
|
||||
case IGB_HWMON_TYPE_MAX:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_crit", offset + 1);
|
||||
break;
|
||||
default:
|
||||
rc = -EPERM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* These always the same regardless of type */
|
||||
igb_attr->sensor =
|
||||
&adapter->hw.mac.thermal_sensor_data.sensor[offset];
|
||||
igb_attr->hw = &adapter->hw;
|
||||
igb_attr->dev_attr.store = NULL;
|
||||
igb_attr->dev_attr.attr.mode = 0444;
|
||||
igb_attr->dev_attr.attr.name = igb_attr->name;
|
||||
sysfs_attr_init(&igb_attr->dev_attr.attr);
|
||||
|
||||
adapter->igb_hwmon_buff->attrs[n_attr] = &igb_attr->dev_attr.attr;
|
||||
|
||||
++adapter->igb_hwmon_buff->n_hwmon;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void igb_sysfs_del_adapter(struct igb_adapter *adapter)
|
||||
{
|
||||
}
|
||||
|
||||
/* called from igb_main.c */
|
||||
void igb_sysfs_exit(struct igb_adapter *adapter)
|
||||
{
|
||||
igb_sysfs_del_adapter(adapter);
|
||||
}
|
||||
|
||||
/* called from igb_main.c */
|
||||
int igb_sysfs_init(struct igb_adapter *adapter)
|
||||
{
|
||||
struct hwmon_buff *igb_hwmon;
|
||||
struct i2c_client *client;
|
||||
struct device *hwmon_dev;
|
||||
unsigned int i;
|
||||
int rc = 0;
|
||||
|
||||
/* If this method isn't defined we don't support thermals */
|
||||
if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
|
||||
goto exit;
|
||||
|
||||
/* Don't create thermal hwmon interface if no sensors present */
|
||||
rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw));
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
igb_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*igb_hwmon),
|
||||
GFP_KERNEL);
|
||||
if (!igb_hwmon) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
adapter->igb_hwmon_buff = igb_hwmon;
|
||||
|
||||
for (i = 0; i < E1000_MAX_SENSORS; i++) {
|
||||
|
||||
/* Only create hwmon sysfs entries for sensors that have
|
||||
* meaningful data.
|
||||
*/
|
||||
if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
|
||||
continue;
|
||||
|
||||
/* Bail if any hwmon attr struct fails to initialize */
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION);
|
||||
if (rc)
|
||||
goto exit;
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
|
||||
if (rc)
|
||||
goto exit;
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
|
||||
if (rc)
|
||||
goto exit;
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
|
||||
if (rc)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* init i2c_client */
|
||||
client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
|
||||
if (client == NULL) {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Failed to create new i2c device.\n");
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
adapter->i2c_client = client;
|
||||
|
||||
igb_hwmon->groups[0] = &igb_hwmon->group;
|
||||
igb_hwmon->group.attrs = igb_hwmon->attrs;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev,
|
||||
client->name,
|
||||
igb_hwmon,
|
||||
igb_hwmon->groups);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
rc = PTR_ERR(hwmon_dev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
igb_sysfs_del_adapter(adapter);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#include "igb.h"
|
||||
#include "e1000_82575.h"
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
static struct i2c_board_info i350_sensor_info = {
|
||||
I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)),
|
||||
};
|
||||
|
||||
/* hwmon callback functions */
|
||||
static ssize_t igb_hwmon_show_location(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
return sprintf(buf, "loc%u\n",
|
||||
igb_attr->sensor->location);
|
||||
}
|
||||
|
||||
static ssize_t igb_hwmon_show_temp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
unsigned int value;
|
||||
|
||||
/* reset the temp field */
|
||||
igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw);
|
||||
|
||||
value = igb_attr->sensor->temp;
|
||||
|
||||
/* display millidegree */
|
||||
value *= 1000;
|
||||
|
||||
return sprintf(buf, "%u\n", value);
|
||||
}
|
||||
|
||||
static ssize_t igb_hwmon_show_cautionthresh(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
unsigned int value = igb_attr->sensor->caution_thresh;
|
||||
|
||||
/* display millidegree */
|
||||
value *= 1000;
|
||||
|
||||
return sprintf(buf, "%u\n", value);
|
||||
}
|
||||
|
||||
static ssize_t igb_hwmon_show_maxopthresh(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
|
||||
dev_attr);
|
||||
unsigned int value = igb_attr->sensor->max_op_thresh;
|
||||
|
||||
/* display millidegree */
|
||||
value *= 1000;
|
||||
|
||||
return sprintf(buf, "%u\n", value);
|
||||
}
|
||||
|
||||
/* igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
|
||||
* @ adapter: pointer to the adapter structure
|
||||
* @ offset: offset in the eeprom sensor data table
|
||||
* @ type: type of sensor data to display
|
||||
*
|
||||
* For each file we want in hwmon's sysfs interface we need a device_attribute
|
||||
* This is included in our hwmon_attr struct that contains the references to
|
||||
* the data structures we need to get the data to display.
|
||||
*/
|
||||
static int igb_add_hwmon_attr(struct igb_adapter *adapter,
|
||||
unsigned int offset, int type)
|
||||
{
|
||||
int rc;
|
||||
unsigned int n_attr;
|
||||
struct hwmon_attr *igb_attr;
|
||||
|
||||
n_attr = adapter->igb_hwmon_buff->n_hwmon;
|
||||
igb_attr = &adapter->igb_hwmon_buff->hwmon_list[n_attr];
|
||||
|
||||
switch (type) {
|
||||
case IGB_HWMON_TYPE_LOC:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_location;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_label", offset + 1);
|
||||
break;
|
||||
case IGB_HWMON_TYPE_TEMP:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_temp;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_input", offset + 1);
|
||||
break;
|
||||
case IGB_HWMON_TYPE_CAUTION:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_max", offset + 1);
|
||||
break;
|
||||
case IGB_HWMON_TYPE_MAX:
|
||||
igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh;
|
||||
snprintf(igb_attr->name, sizeof(igb_attr->name),
|
||||
"temp%u_crit", offset + 1);
|
||||
break;
|
||||
default:
|
||||
rc = -EPERM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* These always the same regardless of type */
|
||||
igb_attr->sensor =
|
||||
&adapter->hw.mac.thermal_sensor_data.sensor[offset];
|
||||
igb_attr->hw = &adapter->hw;
|
||||
igb_attr->dev_attr.store = NULL;
|
||||
igb_attr->dev_attr.attr.mode = 0444;
|
||||
igb_attr->dev_attr.attr.name = igb_attr->name;
|
||||
sysfs_attr_init(&igb_attr->dev_attr.attr);
|
||||
|
||||
adapter->igb_hwmon_buff->attrs[n_attr] = &igb_attr->dev_attr.attr;
|
||||
|
||||
++adapter->igb_hwmon_buff->n_hwmon;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void igb_sysfs_del_adapter(struct igb_adapter *adapter)
|
||||
{
|
||||
}
|
||||
|
||||
/* called from igb_main.c */
|
||||
void igb_sysfs_exit(struct igb_adapter *adapter)
|
||||
{
|
||||
igb_sysfs_del_adapter(adapter);
|
||||
}
|
||||
|
||||
/* called from igb_main.c */
|
||||
int igb_sysfs_init(struct igb_adapter *adapter)
|
||||
{
|
||||
struct hwmon_buff *igb_hwmon;
|
||||
struct i2c_client *client;
|
||||
struct device *hwmon_dev;
|
||||
unsigned int i;
|
||||
int rc = 0;
|
||||
|
||||
/* If this method isn't defined we don't support thermals */
|
||||
if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
|
||||
goto exit;
|
||||
|
||||
/* Don't create thermal hwmon interface if no sensors present */
|
||||
rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw));
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
igb_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*igb_hwmon),
|
||||
GFP_KERNEL);
|
||||
if (!igb_hwmon) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
adapter->igb_hwmon_buff = igb_hwmon;
|
||||
|
||||
for (i = 0; i < E1000_MAX_SENSORS; i++) {
|
||||
|
||||
/* Only create hwmon sysfs entries for sensors that have
|
||||
* meaningful data.
|
||||
*/
|
||||
if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
|
||||
continue;
|
||||
|
||||
/* Bail if any hwmon attr struct fails to initialize */
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION);
|
||||
if (rc)
|
||||
goto exit;
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
|
||||
if (rc)
|
||||
goto exit;
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
|
||||
if (rc)
|
||||
goto exit;
|
||||
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
|
||||
if (rc)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* init i2c_client */
|
||||
client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
|
||||
if (client == NULL) {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Failed to create new i2c device.\n");
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
adapter->i2c_client = client;
|
||||
|
||||
igb_hwmon->groups[0] = &igb_hwmon->group;
|
||||
igb_hwmon->group.attrs = igb_hwmon->attrs;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev,
|
||||
client->name,
|
||||
igb_hwmon,
|
||||
igb_hwmon->groups);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
rc = PTR_ERR(hwmon_dev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
igb_sysfs_del_adapter(adapter);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue