summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/agere
diff options
context:
space:
mode:
authorMark Einon <mark.einon@gmail.com>2014-09-30 22:29:46 +0100
committerDavid S. Miller <davem@davemloft.net>2014-10-03 12:22:19 -0700
commit38df6492eb511d2a6823303cb1a194c4fe423154 (patch)
tree178f95aa9898127f5dc16a9635db59dfe558a5e6 /drivers/net/ethernet/agere
parent739e4a758e0e2930f4bcdddd244254bae8dd7499 (diff)
et131x: Add PCIe gigabit ethernet driver et131x to drivers/net
This adds the ethernet driver for Agere et131x devices to drivers/net/ethernet. The driver being added has been in the staging tree for some time, and will be removed from there in a seperate patch. This one merely disables the staging version to prevent two instances being built. Signed-off-by: Mark Einon <mark.einon@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/agere')
-rw-r--r--drivers/net/ethernet/agere/Kconfig31
-rw-r--r--drivers/net/ethernet/agere/Makefile5
-rw-r--r--drivers/net/ethernet/agere/et131x.c4121
-rw-r--r--drivers/net/ethernet/agere/et131x.h1433
4 files changed, 5590 insertions, 0 deletions
diff --git a/drivers/net/ethernet/agere/Kconfig b/drivers/net/ethernet/agere/Kconfig
new file mode 100644
index 000000000000..63e805de619e
--- /dev/null
+++ b/drivers/net/ethernet/agere/Kconfig
@@ -0,0 +1,31 @@
+#
+# Agere device configuration
+#
+
+config NET_VENDOR_AGERE
+ bool "Agere devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Agere devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_AGERE
+
+config ET131X
+ tristate "Agere ET-1310 Gigabit Ethernet support"
+ depends on PCI
+ select PHYLIB
+ ---help---
+ This driver supports Agere ET-1310 ethernet adapters.
+
+ To compile this driver as a module, choose M here. The module
+ will be called et131x.
+
+endif # NET_VENDOR_AGERE
diff --git a/drivers/net/ethernet/agere/Makefile b/drivers/net/ethernet/agere/Makefile
new file mode 100644
index 000000000000..027ff9453fe1
--- /dev/null
+++ b/drivers/net/ethernet/agere/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Agere ET-131x ethernet driver
+#
+
+obj-$(CONFIG_ET131X) += et131x.o
diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c
new file mode 100644
index 000000000000..384dc163851b
--- /dev/null
+++ b/drivers/net/ethernet/agere/et131x.c
@@ -0,0 +1,4121 @@
+/* Agere Systems Inc.
+ * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ * Copyright (c) 2011 Mark Einon <mark.einon@gmail.com>
+ *
+ *------------------------------------------------------------------------------
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following Disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/random.h>
+#include <linux/phy.h>
+
+#include "et131x.h"
+
+MODULE_AUTHOR("Victor Soriano <vjsoriano@agere.com>");
+MODULE_AUTHOR("Mark Einon <mark.einon@gmail.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere Systems");
+
+/* EEPROM defines */
+#define MAX_NUM_REGISTER_POLLS 1000
+#define MAX_NUM_WRITE_RETRIES 2
+
+/* MAC defines */
+#define COUNTER_WRAP_16_BIT 0x10000
+#define COUNTER_WRAP_12_BIT 0x1000
+
+/* PCI defines */
+#define INTERNAL_MEM_SIZE 0x400 /* 1024 of internal memory */
+#define INTERNAL_MEM_RX_OFFSET 0x1FF /* 50% Tx, 50% Rx */
+
+/* ISR defines */
+/* For interrupts, normal running is:
+ * rxdma_xfr_done, phy_interrupt, mac_stat_interrupt,
+ * watchdog_interrupt & txdma_xfer_done
+ *
+ * In both cases, when flow control is enabled for either Tx or bi-direction,
+ * we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the
+ * buffer rings are running low.
+ */
+#define INT_MASK_DISABLE 0xffffffff
+
+/* NOTE: Masking out MAC_STAT Interrupt for now...
+ * #define INT_MASK_ENABLE 0xfff6bf17
+ * #define INT_MASK_ENABLE_NO_FLOW 0xfff6bfd7
+ */
+#define INT_MASK_ENABLE 0xfffebf17
+#define INT_MASK_ENABLE_NO_FLOW 0xfffebfd7
+
+/* General defines */
+/* Packet and header sizes */
+#define NIC_MIN_PACKET_SIZE 60
+
+/* Multicast list size */
+#define NIC_MAX_MCAST_LIST 128
+
+/* Supported Filters */
+#define ET131X_PACKET_TYPE_DIRECTED 0x0001
+#define ET131X_PACKET_TYPE_MULTICAST 0x0002
+#define ET131X_PACKET_TYPE_BROADCAST 0x0004
+#define ET131X_PACKET_TYPE_PROMISCUOUS 0x0008
+#define ET131X_PACKET_TYPE_ALL_MULTICAST 0x0010
+
+/* Tx Timeout */
+#define ET131X_TX_TIMEOUT (1 * HZ)
+#define NIC_SEND_HANG_THRESHOLD 0
+
+/* MP_ADAPTER flags */
+#define FMP_ADAPTER_INTERRUPT_IN_USE 0x00000008
+
+/* MP_SHARED flags */
+#define FMP_ADAPTER_LOWER_POWER 0x00200000
+
+#define FMP_ADAPTER_NON_RECOVER_ERROR 0x00800000
+#define FMP_ADAPTER_HARDWARE_ERROR 0x04000000
+
+#define FMP_ADAPTER_FAIL_SEND_MASK 0x3ff00000
+
+/* Some offsets in PCI config space that are actually used. */
+#define ET1310_PCI_MAC_ADDRESS 0xA4
+#define ET1310_PCI_EEPROM_STATUS 0xB2
+#define ET1310_PCI_ACK_NACK 0xC0
+#define ET1310_PCI_REPLAY 0xC2
+#define ET1310_PCI_L0L1LATENCY 0xCF
+
+/* PCI Product IDs */
+#define ET131X_PCI_DEVICE_ID_GIG 0xED00 /* ET1310 1000 Base-T 8 */
+#define ET131X_PCI_DEVICE_ID_FAST 0xED01 /* ET1310 100 Base-T */
+
+/* Define order of magnitude converter */
+#define NANO_IN_A_MICRO 1000
+
+#define PARM_RX_NUM_BUFS_DEF 4
+#define PARM_RX_TIME_INT_DEF 10
+#define PARM_RX_MEM_END_DEF 0x2bc
+#define PARM_TX_TIME_INT_DEF 40
+#define PARM_TX_NUM_BUFS_DEF 4
+#define PARM_DMA_CACHE_DEF 0
+
+/* RX defines */
+#define FBR_CHUNKS 32
+#define MAX_DESC_PER_RING_RX 1024
+
+/* number of RFDs - default and min */
+#define RFD_LOW_WATER_MARK 40
+#define NIC_DEFAULT_NUM_RFD 1024
+#define NUM_FBRS 2
+
+#define MAX_PACKETS_HANDLED 256
+
+#define ALCATEL_MULTICAST_PKT 0x01000000
+#define ALCATEL_BROADCAST_PKT 0x02000000
+
+/* typedefs for Free Buffer Descriptors */
+struct fbr_desc {
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 word2; /* Bits 10-31 reserved, 0-9 descriptor */
+};
+
+/* Packet Status Ring Descriptors
+ *
+ * Word 0:
+ *
+ * top 16 bits are from the Alcatel Status Word as enumerated in
+ * PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2)
+ *
+ * 0: hp hash pass
+ * 1: ipa IP checksum assist
+ * 2: ipp IP checksum pass
+ * 3: tcpa TCP checksum assist
+ * 4: tcpp TCP checksum pass
+ * 5: wol WOL Event
+ * 6: rxmac_error RXMAC Error Indicator
+ * 7: drop Drop packet
+ * 8: ft Frame Truncated
+ * 9: jp Jumbo Packet
+ * 10: vp VLAN Packet
+ * 11-15: unused
+ * 16: asw_prev_pkt_dropped e.g. IFG too small on previous
+ * 17: asw_RX_DV_event short receive event detected
+ * 18: asw_false_carrier_event bad carrier since last good packet
+ * 19: asw_code_err one or more nibbles signalled as errors
+ * 20: asw_CRC_err CRC error
+ * 21: asw_len_chk_err frame length field incorrect
+ * 22: asw_too_long frame length > 1518 bytes
+ * 23: asw_OK valid CRC + no code error
+ * 24: asw_multicast has a multicast address
+ * 25: asw_broadcast has a broadcast address
+ * 26: asw_dribble_nibble spurious bits after EOP
+ * 27: asw_control_frame is a control frame
+ * 28: asw_pause_frame is a pause frame
+ * 29: asw_unsupported_op unsupported OP code
+ * 30: asw_VLAN_tag VLAN tag detected
+ * 31: asw_long_evt Rx long event
+ *
+ * Word 1:
+ * 0-15: length length in bytes
+ * 16-25: bi Buffer Index
+ * 26-27: ri Ring Index
+ * 28-31: reserved
+ */
+struct pkt_stat_desc {
+ u32 word0;
+ u32 word1;
+};
+
+/* Typedefs for the RX DMA status word */
+
+/* rx status word 0 holds part of the status bits of the Rx DMA engine
+ * that get copied out to memory by the ET-1310. Word 0 is a 32 bit word
+ * which contains the Free Buffer ring 0 and 1 available offset.
+ *
+ * bit 0-9 FBR1 offset
+ * bit 10 Wrap flag for FBR1
+ * bit 16-25 FBR0 offset
+ * bit 26 Wrap flag for FBR0
+ */
+
+/* RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine
+ * that get copied out to memory by the ET-1310. Word 3 is a 32 bit word
+ * which contains the Packet Status Ring available offset.
+ *
+ * bit 0-15 reserved
+ * bit 16-27 PSRoffset
+ * bit 28 PSRwrap
+ * bit 29-31 unused
+ */
+
+/* struct rx_status_block is a structure representing the status of the Rx
+ * DMA engine it sits in free memory, and is pointed to by 0x101c / 0x1020
+ */
+struct rx_status_block {
+ u32 word0;
+ u32 word1;
+};
+
+/* Structure for look-up table holding free buffer ring pointers, addresses
+ * and state.
+ */
+struct fbr_lookup {
+ void *virt[MAX_DESC_PER_RING_RX];
+ u32 bus_high[MAX_DESC_PER_RING_RX];
+ u32 bus_low[MAX_DESC_PER_RING_RX];
+ void *ring_virtaddr;
+ dma_addr_t ring_physaddr;
+ void *mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
+ dma_addr_t mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
+ u32 local_full;
+ u32 num_entries;
+ dma_addr_t buffsize;
+};
+
+/* struct rx_ring is the structure representing the adaptor's local
+ * reference(s) to the rings
+ */
+struct rx_ring {
+ struct fbr_lookup *fbr[NUM_FBRS];
+ void *ps_ring_virtaddr;
+ dma_addr_t ps_ring_physaddr;
+ u32 local_psr_full;
+ u32 psr_entries;
+
+ struct rx_status_block *rx_status_block;
+ dma_addr_t rx_status_bus;
+
+ struct list_head recv_list;
+ u32 num_ready_recv;
+
+ u32 num_rfd;
+
+ bool unfinished_receives;
+};
+
+/* TX defines */
+/* word 2 of the control bits in the Tx Descriptor ring for the ET-1310
+ *
+ * 0-15: length of packet
+ * 16-27: VLAN tag
+ * 28: VLAN CFI
+ * 29-31: VLAN priority
+ *
+ * word 3 of the control bits in the Tx Descriptor ring for the ET-1310
+ *
+ * 0: last packet in the sequence
+ * 1: first packet in the sequence
+ * 2: interrupt the processor when this pkt sent
+ * 3: Control word - no packet data
+ * 4: Issue half-duplex backpressure : XON/XOFF
+ * 5: send pause frame
+ * 6: Tx frame has error
+ * 7: append CRC
+ * 8: MAC override
+ * 9: pad packet
+ * 10: Packet is a Huge packet
+ * 11: append VLAN tag
+ * 12: IP checksum assist
+ * 13: TCP checksum assist
+ * 14: UDP checksum assist
+ */
+#define TXDESC_FLAG_LASTPKT 0x0001
+#define TXDESC_FLAG_FIRSTPKT 0x0002
+#define TXDESC_FLAG_INTPROC 0x0004
+
+/* struct tx_desc represents each descriptor on the ring */
+struct tx_desc {
+ u32 addr_hi;
+ u32 addr_lo;
+ u32 len_vlan; /* control words how to xmit the */
+ u32 flags; /* data (detailed above) */
+};
+
+/* The status of the Tx DMA engine it sits in free memory, and is pointed to
+ * by 0x101c / 0x1020. This is a DMA10 type
+ */
+
+/* TCB (Transmit Control Block: Host Side) */
+struct tcb {
+ struct tcb *next; /* Next entry in ring */
+ u32 count; /* Used to spot stuck/lost packets */
+ u32 stale; /* Used to spot stuck/lost packets */
+ struct sk_buff *skb; /* Network skb we are tied to */
+ u32 index; /* Ring indexes */
+ u32 index_start;
+};
+
+/* Structure representing our local reference(s) to the ring */
+struct tx_ring {
+ /* TCB (Transmit Control Block) memory and lists */
+ struct tcb *tcb_ring;
+
+ /* List of TCBs that are ready to be used */
+ struct tcb *tcb_qhead;
+ struct tcb *tcb_qtail;
+
+ /* list of TCBs that are currently being sent. */
+ struct tcb *send_head;
+ struct tcb *send_tail;
+ int used;
+
+ /* The actual descriptor ring */
+ struct tx_desc *tx_desc_ring;
+ dma_addr_t tx_desc_ring_pa;
+
+ /* send_idx indicates where we last wrote to in the descriptor ring. */
+ u32 send_idx;
+
+ /* The location of the write-back status block */
+ u32 *tx_status;
+ dma_addr_t tx_status_pa;
+
+ /* Packets since the last IRQ: used for interrupt coalescing */
+ int since_irq;
+};
+
+/* Do not change these values: if changed, then change also in respective
+ * TXdma and Rxdma engines
+ */
+#define NUM_DESC_PER_RING_TX 512 /* TX Do not change these values */
+#define NUM_TCB 64
+
+/* These values are all superseded by registry entries to facilitate tuning.
+ * Once the desired performance has been achieved, the optimal registry values
+ * should be re-populated to these #defines:
+ */
+#define TX_ERROR_PERIOD 1000
+
+#define LO_MARK_PERCENT_FOR_PSR 15
+#define LO_MARK_PERCENT_FOR_RX 15
+
+/* RFD (Receive Frame Descriptor) */
+struct rfd {
+ struct list_head list_node;
+ struct sk_buff *skb;
+ u32 len; /* total size of receive frame */
+ u16 bufferindex;
+ u8 ringindex;
+};
+
+/* Flow Control */
+#define FLOW_BOTH 0
+#define FLOW_TXONLY 1
+#define FLOW_RXONLY 2
+#define FLOW_NONE 3
+
+/* Struct to define some device statistics */
+struct ce_stats {
+ u32 multicast_pkts_rcvd;
+ u32 rcvd_pkts_dropped;
+
+ u32 tx_underflows;
+ u32 tx_collisions;
+ u32 tx_excessive_collisions;
+ u32 tx_first_collisions;
+ u32 tx_late_collisions;
+ u32 tx_max_pkt_errs;
+ u32 tx_deferred;
+
+ u32 rx_overflows;
+ u32 rx_length_errs;
+ u32 rx_align_errs;
+ u32 rx_crc_errs;
+ u32 rx_code_violations;
+ u32 rx_other_errs;
+
+ u32 interrupt_status;
+};
+
+/* The private adapter structure */
+struct et131x_adapter {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct mii_bus *mii_bus;
+ struct phy_device *phydev;
+ struct napi_struct napi;
+
+ /* Flags that indicate current state of the adapter */
+ u32 flags;
+
+ /* local link state, to determine if a state change has occurred */
+ int link;
+
+ /* Configuration */
+ u8 rom_addr[ETH_ALEN];
+ u8 addr[ETH_ALEN];
+ bool has_eeprom;
+ u8 eeprom_data[2];
+
+ spinlock_t tcb_send_qlock; /* protects the tx_ring send tcb list */
+ spinlock_t tcb_ready_qlock; /* protects the tx_ring ready tcb list */
+ spinlock_t rcv_lock; /* protects the rx_ring receive list */
+
+ /* Packet Filter and look ahead size */
+ u32 packet_filter;
+
+ /* multicast list */
+ u32 multicast_addr_count;
+ u8 multicast_list[NIC_MAX_MCAST_LIST][ETH_ALEN];
+
+ /* Pointer to the device's PCI register space */
+ struct address_map __iomem *regs;
+
+ /* Registry parameters */
+ u8 wanted_flow; /* Flow we want for 802.3x flow control */
+ u32 registry_jumbo_packet; /* Max supported ethernet packet size */
+
+ /* Derived from the registry: */
+ u8 flow; /* flow control validated by the far-end */
+
+ /* Minimize init-time */
+ struct timer_list error_timer;
+
+ /* variable putting the phy into coma mode when boot up with no cable
+ * plugged in after 5 seconds
+ */
+ u8 boot_coma;
+
+ /* Tx Memory Variables */
+ struct tx_ring tx_ring;
+
+ /* Rx Memory Variables */
+ struct rx_ring rx_ring;
+
+ struct ce_stats stats;
+};
+
+static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status)
+{
+ u32 reg;
+ int i;
+
+ /* 1. Check LBCIF Status Register for bits 6 & 3:2 all equal to 0 and
+ * bits 7,1:0 both equal to 1, at least once after reset.
+ * Subsequent operations need only to check that bits 1:0 are equal
+ * to 1 prior to starting a single byte read/write
+ */
+ for (i = 0; i < MAX_NUM_REGISTER_POLLS; i++) {
+ if (pci_read_config_dword(pdev, LBCIF_DWORD1_GROUP, &reg))
+ return -EIO;
+
+ /* I2C idle and Phy Queue Avail both true */
+ if ((reg & 0x3000) == 0x3000) {
+ if (status)
+ *status = reg;
+ return reg & 0xFF;
+ }
+ }
+ return -ETIMEDOUT;
+}
+
+static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int index = 0;
+ int retries;
+ int err = 0;
+ int writeok = 0;
+ u32 status;
+ u32 val = 0;
+
+ /* For an EEPROM, an I2C single byte write is defined as a START
+ * condition followed by the device address, EEPROM address, one byte
+ * of data and a STOP condition. The STOP condition will trigger the
+ * EEPROM's internally timed write cycle to the nonvolatile memory.
+ * All inputs are disabled during this write cycle and the EEPROM will
+ * not respond to any access until the internal write is complete.
+ */
+ err = eeprom_wait_ready(pdev, NULL);
+ if (err < 0)
+ return err;
+
+ /* 2. Write to the LBCIF Control Register: bit 7=1, bit 6=1, bit 3=0,
+ * and bits 1:0 both =0. Bit 5 should be set according to the
+ * type of EEPROM being accessed (1=two byte addressing, 0=one
+ * byte addressing).
+ */
+ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
+ LBCIF_CONTROL_LBCIF_ENABLE |
+ LBCIF_CONTROL_I2C_WRITE))
+ return -EIO;
+
+ /* Prepare EEPROM address for Step 3 */
+ for (retries = 0; retries < MAX_NUM_WRITE_RETRIES; retries++) {
+ if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER, addr))
+ break;
+ /* Write the data to the LBCIF Data Register (the I2C write
+ * will begin).
+ */
+ if (pci_write_config_byte(pdev, LBCIF_DATA_REGISTER, data))
+ break;
+ /* Monitor bit 1:0 of the LBCIF Status Register. When bits
+ * 1:0 are both equal to 1, the I2C write has completed and the
+ * internal write cycle of the EEPROM is about to start.
+ * (bits 1:0 = 01 is a legal state while waiting from both
+ * equal to 1, but bits 1:0 = 10 is invalid and implies that
+ * something is broken).
+ */
+ err = eeprom_wait_ready(pdev, &status);
+ if (err < 0)
+ return 0;
+
+ /* Check bit 3 of the LBCIF Status Register. If equal to 1,
+ * an error has occurred.Don't break here if we are revision
+ * 1, this is so we do a blind write for load bug.
+ */
+ if ((status & LBCIF_STATUS_GENERAL_ERROR) &&
+ adapter->pdev->revision == 0)
+ break;
+
+ /* Check bit 2 of the LBCIF Status Register. If equal to 1 an
+ * ACK error has occurred on the address phase of the write.
+ * This could be due to an actual hardware failure or the
+ * EEPROM may still be in its internal write cycle from a
+ * previous write. This write operation was ignored and must be
+ *repeated later.
+ */
+ if (status & LBCIF_STATUS_ACK_ERROR) {
+ /* This could be due to an actual hardware failure
+ * or the EEPROM may still be in its internal write
+ * cycle from a previous write. This write operation
+ * was ignored and must be repeated later.
+ */
+ udelay(10);
+ continue;
+ }
+
+ writeok = 1;
+ break;
+ }
+
+ udelay(10);
+
+ while (1) {
+ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
+ LBCIF_CONTROL_LBCIF_ENABLE))
+ writeok = 0;
+
+ /* Do read until internal ACK_ERROR goes away meaning write
+ * completed
+ */
+ do {
+ pci_write_config_dword(pdev,
+ LBCIF_ADDRESS_REGISTER,
+ addr);
+ do {
+ pci_read_config_dword(pdev,
+ LBCIF_DATA_REGISTER,
+ &val);
+ } while ((val & 0x00010000) == 0);
+ } while (val & 0x00040000);
+
+ if ((val & 0xFF00) != 0xC000 || index == 10000)
+ break;
+ index++;
+ }
+ return writeok ? 0 : -EIO;
+}
+
+static int eeprom_read(struct et131x_adapter *adapter, u32 addr, u8 *pdata)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int err;
+ u32 status;
+
+ /* A single byte read is similar to the single byte write, with the
+ * exception of the data flow:
+ */
+ err = eeprom_wait_ready(pdev, NULL);
+ if (err < 0)
+ return err;
+ /* Write to the LBCIF Control Register: bit 7=1, bit 6=0, bit 3=0,
+ * and bits 1:0 both =0. Bit 5 should be set according to the type
+ * of EEPROM being accessed (1=two byte addressing, 0=one byte
+ * addressing).
+ */
+ if (pci_write_config_byte(pdev, LBCIF_CONTROL_REGISTER,
+ LBCIF_CONTROL_LBCIF_ENABLE))
+ return -EIO;
+ /* Write the address to the LBCIF Address Register (I2C read will
+ * begin).
+ */
+ if (pci_write_config_dword(pdev, LBCIF_ADDRESS_REGISTER, addr))
+ return -EIO;
+ /* Monitor bit 0 of the LBCIF Status Register. When = 1, I2C read
+ * is complete. (if bit 1 =1 and bit 0 stays = 0, a hardware failure
+ * has occurred).
+ */
+ err = eeprom_wait_ready(pdev, &status);
+ if (err < 0)
+ return err;
+ /* Regardless of error status, read data byte from LBCIF Data
+ * Register.
+ */
+ *pdata = err;
+
+ return (status & LBCIF_STATUS_ACK_ERROR) ? -EIO : 0;
+}
+
+static int et131x_init_eeprom(struct et131x_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 eestatus;
+
+ pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, &eestatus);
+
+ /* THIS IS A WORKAROUND:
+ * I need to call this function twice to get my card in a
+ * LG M1 Express Dual running. I tried also a msleep before this
+ * function, because I thought there could be some time conditions
+ * but it didn't work. Call the whole function twice also work.
+ */
+ if (pci_read_config_byte(pdev, ET1310_PCI_EEPROM_STATUS, &eestatus)) {
+ dev_err(&pdev->dev,
+ "Could not read PCI config space for EEPROM Status\n");
+ return -EIO;
+ }
+
+ /* Determine if the error(s) we care about are present. If they are
+ * present we need to fail.
+ */
+ if (eestatus & 0x4C) {
+ int write_failed = 0;
+
+ if (pdev->revision == 0x01) {
+ int i;
+ static const u8 eedata[4] = { 0xFE, 0x13, 0x10, 0xFF };
+
+ /* Re-write the first 4 bytes if we have an eeprom
+ * present and the revision id is 1, this fixes the
+ * corruption seen with 1310 B Silicon
+ */
+ for (i = 0; i < 3; i++)
+ if (eeprom_write(adapter, i, eedata[i]) < 0)
+ write_failed = 1;
+ }
+ if (pdev->revision != 0x01 || write_failed) {
+ dev_err(&pdev->dev,
+ "Fatal EEPROM Status Error - 0x%04x\n",
+ eestatus);
+
+ /* This error could mean that there was an error
+ * reading the eeprom or that the eeprom doesn't exist.
+ * We will treat each case the same and not try to
+ * gather additional information that normally would
+ * come from the eeprom, like MAC Address
+ */
+ adapter->has_eeprom = 0;
+ return -EIO;
+ }
+ }
+ adapter->has_eeprom = 1;
+
+ /* Read the EEPROM for information regarding LED behavior. Refer to
+ * et131x_xcvr_init() for its use.
+ */
+ eeprom_read(adapter, 0x70, &adapter->eeprom_data[0]);
+ eeprom_read(adapter, 0x71, &adapter->eeprom_data[1]);
+
+ if (adapter->eeprom_data[0] != 0xcd)
+ /* Disable all optional features */
+ adapter->eeprom_data[1] = 0x00;
+
+ return 0;
+}
+
+static void et131x_rx_dma_enable(struct et131x_adapter *adapter)
+{
+ /* Setup the receive dma configuration register for normal operation */
+ u32 csr = ET_RXDMA_CSR_FBR1_ENABLE;
+ struct rx_ring *rx_ring = &adapter->rx_ring;
+
+ if (rx_ring->fbr[1]->buffsize == 4096)
+ csr |= ET_RXDMA_CSR_FBR1_SIZE_LO;
+ else if (rx_ring->fbr[1]->buffsize == 8192)
+ csr |= ET_RXDMA_CSR_FBR1_SIZE_HI;
+ else if (rx_ring->fbr[1]->buffsize == 16384)
+ csr |= ET_RXDMA_CSR_FBR1_SIZE_LO | ET_RXDMA_CSR_FBR1_SIZE_HI;
+
+ csr |= ET_RXDMA_CSR_FBR0_ENABLE;
+ if (rx_ring->fbr[0]->buffsize == 256)
+ csr |= ET_RXDMA_CSR_FBR0_SIZE_LO;
+ else if (rx_ring->fbr[0]->buffsize == 512)
+ csr |= ET_RXDMA_CSR_FBR0_SIZE_HI;
+ else if (rx_ring->fbr[0]->buffsize == 1024)
+ csr |= ET_RXDMA_CSR_FBR0_SIZE_LO | ET_RXDMA_CSR_FBR0_SIZE_HI;
+ writel(csr, &adapter->regs->rxdma.csr);
+
+ csr = readl(&adapter->regs->rxdma.csr);
+ if (csr & ET_RXDMA_CSR_HALT_STATUS) {
+ udelay(5);
+ csr = readl(&adapter->regs->rxdma.csr);
+ if (csr & ET_RXDMA_CSR_HALT_STATUS) {
+ dev_err(&adapter->pdev->dev,
+ "RX Dma failed to exit halt state. CSR 0x%08x\n",
+ csr);
+ }
+ }
+}
+
+static void et131x_rx_dma_disable(struct et131x_adapter *adapter)
+{
+ u32 csr;
+ /* Setup the receive dma configuration register */
+ writel(ET_RXDMA_CSR_HALT | ET_RXDMA_CSR_FBR1_ENABLE,
+ &adapter->regs->rxdma.csr);
+ csr = readl(&adapter->regs->rxdma.csr);
+ if (!(csr & ET_RXDMA_CSR_HALT_STATUS)) {
+ udelay(5);
+ csr = readl(&adapter->regs->rxdma.csr);
+ if (!(csr & ET_RXDMA_CSR_HALT_STATUS))
+ dev_err(&adapter->pdev->dev,
+ "RX Dma failed to enter halt state. CSR 0x%08x\n",
+ csr);
+ }
+}
+
+static void et131x_tx_dma_enable(struct et131x_adapter *adapter)
+{
+ /* Setup the transmit dma configuration register for normal
+ * operation
+ */
+ writel(ET_TXDMA_SNGL_EPKT | (PARM_DMA_CACHE_DEF << ET_TXDMA_CACHE_SHIFT),
+ &adapter->regs->txdma.csr);
+}
+
+static inline void add_10bit(u32 *v, int n)
+{
+ *v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP);
+}
+
+static inline void add_12bit(u32 *v, int n)
+{
+ *v = INDEX12(*v + n) | (*v & ET_DMA12_WRAP);
+}
+
+static void et1310_config_mac_regs1(struct et131x_adapter *adapter)
+{
+ struct mac_regs __iomem *macregs = &adapter->regs->mac;
+ u32 station1;
+ u32 station2;
+ u32 ipg;
+
+ /* First we need to reset everything. Write to MAC configuration
+ * register 1 to perform reset.
+ */
+ writel(ET_MAC_CFG1_SOFT_RESET | ET_MAC_CFG1_SIM_RESET |
+ ET_MAC_CFG1_RESET_RXMC | ET_MAC_CFG1_RESET_TXMC |
+ ET_MAC_CFG1_RESET_RXFUNC | ET_MAC_CFG1_RESET_TXFUNC,
+ &macregs->cfg1);
+
+ /* Next lets configure the MAC Inter-packet gap register */
+ ipg = 0x38005860; /* IPG1 0x38 IPG2 0x58 B2B 0x60 */
+ ipg |= 0x50 << 8; /* ifg enforce 0x50 */
+ writel(ipg, &macregs->ipg);
+
+ /* Next lets configure the MAC Half Duplex register */
+ /* BEB trunc 0xA, Ex Defer, Rexmit 0xF Coll 0x37 */
+ writel(0x00A1F037, &macregs->hfdp);
+
+ /* Next lets configure the MAC Interface Control register */
+ writel(0, &macregs->if_ctrl);
+
+ writel(ET_MAC_MIIMGMT_CLK_RST, &macregs->mii_mgmt_cfg);
+
+ /* Next lets configure the MAC Station Address register. These
+ * values are read from the EEPROM during initialization and stored
+ * in the adapter structure. We write what is stored in the adapter
+ * structure to the MAC Station Address registers high and low. This
+ * station address is used for generating and checking pause control
+ * packets.
+ */
+ station2 = (adapter->addr[1] << ET_MAC_STATION_ADDR2_OC2_SHIFT) |
+ (adapter->addr[0] << ET_MAC_STATION_ADDR2_OC1_SHIFT);
+ station1 = (adapter->addr[5] << ET_MAC_STATION_ADDR1_OC6_SHIFT) |
+ (adapter->addr[4] << ET_MAC_STATION_ADDR1_OC5_SHIFT) |
+ (adapter->addr[3] << ET_MAC_STATION_ADDR1_OC4_SHIFT) |
+ adapter->addr[2];
+ writel(station1, &macregs->station_addr_1);
+ writel(station2, &macregs->station_addr_2);
+
+ /* Max ethernet packet in bytes that will be passed by the mac without
+ * being truncated. Allow the MAC to pass 4 more than our max packet
+ * size. This is 4 for the Ethernet CRC.
+ *
+ * Packets larger than (registry_jumbo_packet) that do not contain a
+ * VLAN ID will be dropped by the Rx function.
+ */
+ writel(adapter->registry_jumbo_packet + 4, &macregs->max_fm_len);
+
+ /* clear out MAC config reset */
+ writel(0, &macregs->cfg1);
+}
+
+static void et1310_config_mac_regs2(struct et131x_adapter *adapter)
+{
+ int32_t delay = 0;
+ struct mac_regs __iomem *mac = &adapter->regs->mac;
+ struct phy_device *phydev = adapter->phydev;
+ u32 cfg1;
+ u32 cfg2;
+ u32 ifctrl;
+ u32 ctl;
+
+ ctl = readl(&adapter->regs->txmac.ctl);
+ cfg1 = readl(&mac->cfg1);
+ cfg2 = readl(&mac->cfg2);
+ ifctrl = readl(&mac->if_ctrl);
+
+ /* Set up the if mode bits */
+ cfg2 &= ~ET_MAC_CFG2_IFMODE_MASK;
+ if (phydev->speed == SPEED_1000) {
+ cfg2 |= ET_MAC_CFG2_IFMODE_1000;
+ ifctrl &= ~ET_MAC_IFCTRL_PHYMODE;
+ } else {
+ cfg2 |= ET_MAC_CFG2_IFMODE_100;
+ ifctrl |= ET_MAC_IFCTRL_PHYMODE;
+ }
+
+ cfg1 |= ET_MAC_CFG1_RX_ENABLE | ET_MAC_CFG1_TX_ENABLE |
+ ET_MAC_CFG1_TX_FLOW;
+
+ cfg1 &= ~(ET_MAC_CFG1_LOOPBACK | ET_MAC_CFG1_RX_FLOW);
+ if (adapter->flow == FLOW_RXONLY || adapter->flow == FLOW_BOTH)
+ cfg1 |= ET_MAC_CFG1_RX_FLOW;
+ writel(cfg1, &mac->cfg1);
+
+ /* Now we need to initialize the MAC Configuration 2 register */
+ /* preamble 7, check length, huge frame off, pad crc, crc enable
+ * full duplex off
+ */
+ cfg2 |= 0x7 << ET_MAC_CFG2_PREAMBLE_SHIFT;
+ cfg2 |= ET_MAC_CFG2_IFMODE_LEN_CHECK;
+ cfg2 |= ET_MAC_CFG2_IFMODE_PAD_CRC;
+ cfg2 |= ET_MAC_CFG2_IFMODE_CRC_ENABLE;
+ cfg2 &= ~ET_MAC_CFG2_IFMODE_HUGE_FRAME;
+ cfg2 &= ~ET_MAC_CFG2_IFMODE_FULL_DPLX;
+
+ if (phydev->duplex == DUPLEX_FULL)
+ cfg2 |= ET_MAC_CFG2_IFMODE_FULL_DPLX;
+
+ ifctrl &= ~ET_MAC_IFCTRL_GHDMODE;
+ if (phydev->duplex == DUPLEX_HALF)
+ ifctrl |= ET_MAC_IFCTRL_GHDMODE;
+
+ writel(ifctrl, &mac->if_ctrl);
+ writel(cfg2, &mac->cfg2);
+
+ do {
+ udelay(10);
+ delay++;
+ cfg1 = readl(&mac->cfg1);
+ } while ((cfg1 & ET_MAC_CFG1_WAIT) != ET_MAC_CFG1_WAIT && delay < 100);
+
+ if (delay == 100) {
+ dev_warn(&adapter->pdev->dev,
+ "Syncd bits did not respond correctly cfg1 word 0x%08x\n",
+ cfg1);
+ }
+
+ ctl |= ET_TX_CTRL_TXMAC_ENABLE | ET_TX_CTRL_FC_DISABLE;
+ writel(ctl, &adapter->regs->txmac.ctl);
+
+ if (adapter->flags & FMP_ADAPTER_LOWER_POWER) {
+ et131x_rx_dma_enable(adapter);
+ et131x_tx_dma_enable(adapter);
+ }
+}
+
+static int et1310_in_phy_coma(struct et131x_adapter *adapter)
+{
+ u32 pmcsr = readl(&adapter->regs->global.pm_csr);
+
+ return ET_PM_PHY_SW_COMA & pmcsr ? 1 : 0;
+}
+
+static void et1310_setup_device_for_multicast(struct et131x_adapter *adapter)
+{
+ struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac;
+ u32 hash1 = 0;
+ u32 hash2 = 0;
+ u32 hash3 = 0;
+ u32 hash4 = 0;
+ u32 pm_csr;
+
+ /* If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision
+ * the multi-cast LIST. If it is NOT specified, (and "ALL" is not
+ * specified) then we should pass NO multi-cast addresses to the
+ * driver.
+ */
+ if (adapter->packet_filter & ET131X_PACKET_TYPE_MULTICAST) {
+ int i;
+
+ /* Loop through our multicast array and set up the device */
+ for (i = 0; i < adapter->multicast_addr_count; i++) {
+ u32 result;
+
+ result = ether_crc(6, adapter->multicast_list[i]);
+
+ result = (result & 0x3F800000) >> 23;
+
+ if (result < 32) {
+ hash1 |= (1 << result);
+ } else if ((31 < result) && (result < 64)) {
+ result -= 32;
+ hash2 |= (1 << result);
+ } else if ((63 < result) && (result < 96)) {
+ result -= 64;
+ hash3 |= (1 << result);
+ } else {
+ result -= 96;
+ hash4 |= (1 << result);
+ }
+ }
+ }
+
+ /* Write out the new hash to the device */
+ pm_csr = readl(&adapter->regs->global.pm_csr);
+ if (!et1310_in_phy_coma(adapter)) {
+ writel(hash1, &rxmac->multi_hash1);
+ writel(hash2, &rxmac->multi_hash2);
+ writel(hash3, &rxmac->multi_hash3);
+ writel(hash4, &rxmac->multi_hash4);
+ }
+}
+
+static void et1310_setup_device_for_unicast(struct et131x_adapter *adapter)
+{
+ struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac;
+ u32 uni_pf1;
+ u32 uni_pf2;
+ u32 uni_pf3;
+ u32 pm_csr;
+
+ /* Set up unicast packet filter reg 3 to be the first two octets of
+ * the MAC address for both address
+ *
+ * Set up unicast packet filter reg 2 to be the octets 2 - 5 of the
+ * MAC address for second address
+ *
+ * Set up unicast packet filter reg 3 to be the octets 2 - 5 of the
+ * MAC address for first address
+ */
+ uni_pf3 = (adapter->addr[0] << ET_RX_UNI_PF_ADDR2_1_SHIFT) |
+ (adapter->addr[1] << ET_RX_UNI_PF_ADDR