summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Miletich <thomas.miletich@gmail.com>2012-01-30 23:10:52 +0000
committerMichael Brown <mcb30@ipxe.org>2012-01-30 23:10:53 +0000
commitf6840ba83e60631e6561a957f11867b206edd7d9 (patch)
treed045f66e772bd7b6f07c5fa076a8b0f76849123f
parent3a2bda7c7c5aac27d89c3f77f4994b059baae626 (diff)
[tg3] New tg3 driver
Replace the old Etherboot tg3 driver with a more up-to-date driver using the iPXE API. Signed-off-by: Thomas Miletich <thomas.miletich@gmail.com> Modified-by: Michael Brown <mcb30@ipxe.org> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/Makefile1
-rw-r--r--src/drivers/net/tg3.c3435
-rw-r--r--src/drivers/net/tg3/tg3.c942
-rw-r--r--src/drivers/net/tg3/tg3.h (renamed from src/drivers/net/tg3.h)2244
-rw-r--r--src/drivers/net/tg3/tg3_hw.c2676
-rw-r--r--src/drivers/net/tg3/tg3_phy.c1608
6 files changed, 7001 insertions, 3905 deletions
diff --git a/src/Makefile b/src/Makefile
index e2425d76..c30dc5c9 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -73,6 +73,7 @@ SRCDIRS += drivers/net/ath/ath5k
SRCDIRS += drivers/net/ath/ath9k
SRCDIRS += drivers/net/vxge
SRCDIRS += drivers/net/efi
+SRCDIRS += drivers/net/tg3
SRCDIRS += drivers/block
SRCDIRS += drivers/nvs
SRCDIRS += drivers/bitbash
diff --git a/src/drivers/net/tg3.c b/src/drivers/net/tg3.c
deleted file mode 100644
index e1562d4c..00000000
--- a/src/drivers/net/tg3.c
+++ /dev/null
@@ -1,3435 +0,0 @@
-/* $Id$
- * tg3.c: Broadcom Tigon3 ethernet driver.
- *
- * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)
- * Copyright (C) 2001, 2002 Jeff Garzik (jgarzik@mandrakesoft.com)
- * Copyright (C) 2003 Eric Biederman (ebiederman@lnxi.com) [etherboot port]
- */
-
-FILE_LICENCE ( GPL2_ONLY );
-
-/* 11-13-2003 timlegge Fix Issue with NetGear GA302T
- * 11-18-2003 ebiederm Generalize NetGear Fix to what the code was supposed to be.
- * 01-06-2005 Alf (Frederic Olivie) Add Dell bcm 5751 (0x1677) support
- * 04-15-2005 Martin Vogt Add Fujitsu Siemens Computer (FSC) 0x1734 bcm 5751 0x105d support
- */
-
-#include "etherboot.h"
-#include "nic.h"
-#include <errno.h>
-#include <ipxe/pci.h>
-#include <ipxe/ethernet.h>
-#include "string.h"
-#include <mii.h>
-#include "tg3.h"
-
-#define SUPPORT_COPPER_PHY 1
-#define SUPPORT_FIBER_PHY 1
-#define SUPPORT_LINK_REPORT 1
-#define SUPPORT_PARTNO_STR 1
-#define SUPPORT_PHY_STR 1
-
-static struct tg3 tg3;
-
-/* These numbers seem to be hard coded in the NIC firmware somehow.
- * You can't change the ring sizes, but you can change where you place
- * them in the NIC onboard memory.
- */
-#define TG3_RX_RING_SIZE 512
-#define TG3_DEF_RX_RING_PENDING 20 /* RX_RING_PENDING seems to be o.k. at 20 and 200 */
-#define TG3_RX_RCB_RING_SIZE 1024
-
-/* (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \
- 512 : 1024) */
-#define TG3_TX_RING_SIZE 512
-#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1)
-
-#define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RING_SIZE)
-#define TG3_RX_RCB_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RCB_RING_SIZE)
-
-#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * TG3_TX_RING_SIZE)
-#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
-#define PREV_TX(N) (((N) - 1) & (TG3_TX_RING_SIZE - 1))
-
-#define RX_PKT_BUF_SZ (1536 + 2 + 64)
-
-struct eth_frame {
- uint8_t dst_addr[ETH_ALEN];
- uint8_t src_addr[ETH_ALEN];
- uint16_t type;
- uint8_t data [ETH_FRAME_LEN - ETH_HLEN];
-};
-
-struct bss {
- struct tg3_rx_buffer_desc rx_std[TG3_RX_RING_SIZE];
- struct tg3_rx_buffer_desc rx_rcb[TG3_RX_RCB_RING_SIZE];
- struct tg3_tx_buffer_desc tx_ring[TG3_TX_RING_SIZE];
- struct tg3_hw_status hw_status;
- struct tg3_hw_stats hw_stats;
- unsigned char rx_bufs[TG3_DEF_RX_RING_PENDING][RX_PKT_BUF_SZ];
- struct eth_frame tx_frame[2];
-} tg3_bss __shared;
-
-/**
- * pci_save_state - save the PCI configuration space of a device before suspending
- * @dev: - PCI device that we're dealing with
- * @buffer: - buffer to hold config space context
- *
- * @buffer must be large enough to hold the entire PCI 2.2 config space
- * (>= 64 bytes).
- */
-static int pci_save_state(struct pci_device *dev, uint32_t *buffer)
-{
- int i;
- for (i = 0; i < 16; i++)
- pci_read_config_dword(dev, i * 4,&buffer[i]);
- return 0;
-}
-
-/**
- * pci_restore_state - Restore the saved state of a PCI device
- * @dev: - PCI device that we're dealing with
- * @buffer: - saved PCI config space
- *
- */
-static int pci_restore_state(struct pci_device *dev, uint32_t *buffer)
-{
- int i;
-
- for (i = 0; i < 16; i++)
- pci_write_config_dword(dev,i * 4, buffer[i]);
- return 0;
-}
-
-static void tg3_write_indirect_reg32(uint32_t off, uint32_t val)
-{
- pci_write_config_dword(tg3.pdev, TG3PCI_REG_BASE_ADDR, off);
- pci_write_config_dword(tg3.pdev, TG3PCI_REG_DATA, val);
-}
-
-#define tw32(reg,val) tg3_write_indirect_reg32((reg),(val))
-#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tg3.regs + (reg))
-#define tw16(reg,val) writew(((val) & 0xffff), tg3.regs + (reg))
-#define tw8(reg,val) writeb(((val) & 0xff), tg3.regs + (reg))
-#define tr32(reg) readl(tg3.regs + (reg))
-#define tr16(reg) readw(tg3.regs + (reg))
-#define tr8(reg) readb(tg3.regs + (reg))
-
-static void tw32_carefully(uint32_t reg, uint32_t val)
-{
- tw32(reg, val);
- tr32(reg);
- udelay(100);
-}
-
-static void tw32_mailbox2(uint32_t reg, uint32_t val)
-{
- tw32_mailbox(reg, val);
- tr32(reg);
-}
-
-static void tg3_write_mem(uint32_t off, uint32_t val)
-{
- pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
- pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val);
-
- /* Always leave this as zero. */
- pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-}
-
-static void tg3_read_mem(uint32_t off, uint32_t *val)
-{
- pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
- pci_read_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val);
-
- /* Always leave this as zero. */
- pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-}
-
-static void tg3_disable_ints(struct tg3 *tp)
-{
- tw32(TG3PCI_MISC_HOST_CTRL,
- (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox2(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
-}
-
-static void tg3_switch_clocks(struct tg3 *tp)
-{
- uint32_t orig_clock_ctrl, clock_ctrl;
-
- clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
-
- orig_clock_ctrl = clock_ctrl;
- clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE | 0x1f);
- tp->pci_clock_ctrl = clock_ctrl;
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
- (!((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
- && (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) &&
- (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE)!=0) {
- tw32_carefully(TG3PCI_CLOCK_CTRL,
- clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
- tw32_carefully(TG3PCI_CLOCK_CTRL,
- clock_ctrl | (CLOCK_CTRL_ALTCLK));
- }
- tw32_carefully(TG3PCI_CLOCK_CTRL, clock_ctrl);
-}
-
-#define PHY_BUSY_LOOPS 5000
-
-static int tg3_readphy(struct tg3 *tp, int reg, uint32_t *val)
-{
- uint32_t frame_val;
- int loops, ret;
-
- tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL);
-
- *val = 0xffffffff;
-
- frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
- MI_COM_PHY_ADDR_MASK);
- frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
- MI_COM_REG_ADDR_MASK);
- frame_val |= (MI_COM_CMD_READ | MI_COM_START);
-
- tw32_carefully(MAC_MI_COM, frame_val);
-
- loops = PHY_BUSY_LOOPS;
- while (loops-- > 0) {
- udelay(10);
- frame_val = tr32(MAC_MI_COM);
-
- if ((frame_val & MI_COM_BUSY) == 0) {
- udelay(5);
- frame_val = tr32(MAC_MI_COM);
- break;
- }
- }
-
- ret = -EBUSY;
- if (loops > 0) {
- *val = frame_val & MI_COM_DATA_MASK;
- ret = 0;
- }
-
- tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
- return ret;
-}
-
-static int tg3_writephy(struct tg3 *tp, int reg, uint32_t val)
-{
- uint32_t frame_val;
- int loops, ret;
-
- tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL);
-
- frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
- MI_COM_PHY_ADDR_MASK);
- frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
- MI_COM_REG_ADDR_MASK);
- frame_val |= (val & MI_COM_DATA_MASK);
- frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
-
- tw32_carefully(MAC_MI_COM, frame_val);
-
- loops = PHY_BUSY_LOOPS;
- while (loops-- > 0) {
- udelay(10);
- frame_val = tr32(MAC_MI_COM);
- if ((frame_val & MI_COM_BUSY) == 0) {
- udelay(5);
- frame_val = tr32(MAC_MI_COM);
- break;
- }
- }
-
- ret = -EBUSY;
- if (loops > 0)
- ret = 0;
-
- tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
- return ret;
-}
-
-static int tg3_writedsp(struct tg3 *tp, uint16_t addr, uint16_t val)
-{
- int err;
- err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, addr);
- err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
- return err;
-}
-
-
-static void tg3_phy_set_wirespeed(struct tg3 *tp)
-{
- uint32_t val;
-
- if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
- return;
-
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007);
- tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
- tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4)));
-}
-
-static int tg3_bmcr_reset(struct tg3 *tp)
-{
- uint32_t phy_control;
- int limit, err;
-
- /* OK, reset it, and poll the BMCR_RESET bit until it
- * clears or we time out.
- */
- phy_control = BMCR_RESET;
- err = tg3_writephy(tp, MII_BMCR, phy_control);
- if (err != 0)
- return -EBUSY;
-
- limit = 5000;
- while (limit--) {
- err = tg3_readphy(tp, MII_BMCR, &phy_control);
- if (err != 0)
- return -EBUSY;
-
- if ((phy_control & BMCR_RESET) == 0) {
- udelay(40);
- break;
- }
- udelay(10);
- }
- if (limit <= 0)
- return -EBUSY;
-
- return 0;
-}
-
-static int tg3_wait_macro_done(struct tg3 *tp)
-{
- int limit = 100;
-
- while (limit--) {
- uint32_t tmp32;
-
- tg3_readphy(tp, 0x16, &tmp32);
- if ((tmp32 & 0x1000) == 0)
- break;
- }
- if (limit <= 0)
- return -EBUSY;
-
- return 0;
-}
-
-static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
-{
- static const uint32_t test_pat[4][6] = {
- { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
- { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
- { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
- { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
- };
- int chan;
-
- for (chan = 0; chan < 4; chan++) {
- int i;
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
- (chan * 0x2000) | 0x0200);
- tg3_writephy(tp, 0x16, 0x0002);
-
- for (i = 0; i < 6; i++)
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
- test_pat[chan][i]);
-
- tg3_writephy(tp, 0x16, 0x0202);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
- (chan * 0x2000) | 0x0200);
- tg3_writephy(tp, 0x16, 0x0082);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
-
- tg3_writephy(tp, 0x16, 0x0802);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
-
- for (i = 0; i < 6; i += 2) {
- uint32_t low, high;
-
- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low);
- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high);
- if (tg3_wait_macro_done(tp)) {
- *resetp = 1;
- return -EBUSY;
- }
- low &= 0x7fff;
- high &= 0x000f;
- if (low != test_pat[chan][i] ||
- high != test_pat[chan][i+1]) {
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
-
- return -EBUSY;
- }
- }
- }
-
- return 0;
-}
-
-static int tg3_phy_reset_chanpat(struct tg3 *tp)
-{
- int chan;
-
- for (chan = 0; chan < 4; chan++) {
- int i;
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
- (chan * 0x2000) | 0x0200);
- tg3_writephy(tp, 0x16, 0x0002);
- for (i = 0; i < 6; i++)
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
- tg3_writephy(tp, 0x16, 0x0202);
- if (tg3_wait_macro_done(tp))
- return -EBUSY;
- }
-
- return 0;
-}
-
-static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
-{
- uint32_t reg32, phy9_orig;
- int retries, do_phy_reset, err;
-
- retries = 10;
- do_phy_reset = 1;
- do {
- if (do_phy_reset) {
- err = tg3_bmcr_reset(tp);
- if (err)
- return err;
- do_phy_reset = 0;
- }
-
- /* Disable transmitter and interrupt. */
- tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
- reg32 |= 0x3000;
- tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-
- /* Set full-duplex, 1000 mbps. */
- tg3_writephy(tp, MII_BMCR,
- BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
-
- /* Set to master mode. */
- tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig);
- tg3_writephy(tp, MII_TG3_CTRL,
- (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER));
-
- /* Enable SM_DSP_CLOCK and 6dB. */
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
-
- /* Block the PHY control access. */
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800);
-
- err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
- if (!err)
- break;
- } while (--retries);
-
- err = tg3_phy_reset_chanpat(tp);
- if (err)
- return err;
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000);
-
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
- tg3_writephy(tp, 0x16, 0x0000);
-
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
-
- tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
-
- tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
- reg32 &= ~0x3000;
- tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-
- return err;
-}
-
-/* This will reset the tigon3 PHY if there is no valid
- * link.
- */
-static int tg3_phy_reset(struct tg3 *tp)
-{
- uint32_t phy_status;
- int err;
-
- err = tg3_readphy(tp, MII_BMSR, &phy_status);
- err |= tg3_readphy(tp, MII_BMSR, &phy_status);
- if (err != 0)
- return -EBUSY;
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
- err = tg3_phy_reset_5703_4_5(tp);
- if (err)
- return err;
- goto out;
- }
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
- // Taken from Broadcom's source code
- tg3_writephy(tp, 0x18, 0x0c00);
- tg3_writephy(tp, 0x17, 0x000a);
- tg3_writephy(tp, 0x15, 0x310b);
- tg3_writephy(tp, 0x17, 0x201f);
- tg3_writephy(tp, 0x15, 0x9506);
- tg3_writephy(tp, 0x17, 0x401f);
- tg3_writephy(tp, 0x15, 0x14e2);
- tg3_writephy(tp, 0x18, 0x0400);
- }
- err = tg3_bmcr_reset(tp);
- if (err)
- return err;
- out:
- tg3_phy_set_wirespeed(tp);
- return 0;
-}
-
-static void tg3_set_power_state_0(struct tg3 *tp)
-{
- uint16_t power_control;
- int pm = tp->pm_cap;
-
- /* Make sure register accesses (indirect or otherwise)
- * will function correctly.
- */
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
-
- pci_read_config_word(tp->pdev, pm + PCI_PM_CTRL, &power_control);
-
- power_control |= PCI_PM_CTRL_PME_STATUS;
- power_control &= ~(PCI_PM_CTRL_STATE_MASK);
- power_control |= 0;
- pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
-
- tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-
- return;
-}
-
-
-#if SUPPORT_LINK_REPORT
-static void tg3_link_report(struct tg3 *tp)
-{
- if (!tp->carrier_ok) {
- printf("Link is down.\n");
- } else {
- printf("Link is up at %d Mbps, %s duplex. %s %s %s\n",
- (tp->link_config.active_speed == SPEED_1000 ?
- 1000 :
- (tp->link_config.active_speed == SPEED_100 ?
- 100 : 10)),
- (tp->link_config.active_duplex == DUPLEX_FULL ?
- "full" : "half"),
- (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "TX" : "",
- (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "RX" : "",
- (tp->tg3_flags & (TG3_FLAG_TX_PAUSE |TG3_FLAG_RX_PAUSE)) ? "flow control" : "");
- }
-}
-#else
-#define tg3_link_report(tp)
-#endif
-
-static void tg3_setup_flow_control(struct tg3 *tp, uint32_t local_adv, uint32_t remote_adv)
-{
- uint32_t new_tg3_flags = 0;
-
- if (local_adv & ADVERTISE_PAUSE_CAP) {
- if (local_adv & ADVERTISE_PAUSE_ASYM) {
- if (remote_adv & LPA_PAUSE_CAP)
- new_tg3_flags |=
- (TG3_FLAG_RX_PAUSE |
- TG3_FLAG_TX_PAUSE);
- else if (remote_adv & LPA_PAUSE_ASYM)
- new_tg3_flags |=
- (TG3_FLAG_RX_PAUSE);
- } else {
- if (remote_adv & LPA_PAUSE_CAP)
- new_tg3_flags |=
- (TG3_FLAG_RX_PAUSE |
- TG3_FLAG_TX_PAUSE);
- }
- } else if (local_adv & ADVERTISE_PAUSE_ASYM) {
- if ((remote_adv & LPA_PAUSE_CAP) &&
- (remote_adv & LPA_PAUSE_ASYM))
- new_tg3_flags |= TG3_FLAG_TX_PAUSE;
- }
-
- tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
- tp->tg3_flags |= new_tg3_flags;
-
- if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
- tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
- else
- tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
-
- if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
- tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
- else
- tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
-}
-
-#if SUPPORT_COPPER_PHY
-static void tg3_aux_stat_to_speed_duplex(
- struct tg3 *tp __unused, uint32_t val, uint8_t *speed, uint8_t *duplex)
-{
- static const uint8_t map[] = {
- [0] = (SPEED_INVALID << 2) | DUPLEX_INVALID,
- [MII_TG3_AUX_STAT_10HALF >> 8] = (SPEED_10 << 2) | DUPLEX_HALF,
- [MII_TG3_AUX_STAT_10FULL >> 8] = (SPEED_10 << 2) | DUPLEX_FULL,
- [MII_TG3_AUX_STAT_100HALF >> 8] = (SPEED_100 << 2) | DUPLEX_HALF,
- [MII_TG3_AUX_STAT_100_4 >> 8] = (SPEED_INVALID << 2) | DUPLEX_INVALID,
- [MII_TG3_AUX_STAT_100FULL >> 8] = (SPEED_100 << 2) | DUPLEX_FULL,
- [MII_TG3_AUX_STAT_1000HALF >> 8] = (SPEED_1000 << 2) | DUPLEX_HALF,
- [MII_TG3_AUX_STAT_1000FULL >> 8] = (SPEED_1000 << 2) | DUPLEX_FULL,
- };
- uint8_t result;
- result = map[(val & MII_TG3_AUX_STAT_SPDMASK) >> 8];
- *speed = result >> 2;
- *duplex = result & 3;
-}
-
-static int tg3_phy_copper_begin(struct tg3 *tp)
-{
- uint32_t new_adv;
-
- tp->link_config.advertising =
- (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
- ADVERTISED_Autoneg | ADVERTISED_MII);
-
- if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) {
- tp->link_config.advertising &=
- ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
- }
-
- new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- if (tp->link_config.advertising & ADVERTISED_10baseT_Half) {
- new_adv |= ADVERTISE_10HALF;
- }
- if (tp->link_config.advertising & ADVERTISED_10baseT_Full) {
- new_adv |= ADVERTISE_10FULL;
- }
- if (tp->link_config.advertising & ADVERTISED_100baseT_Half) {
- new_adv |= ADVERTISE_100HALF;
- }
- if (tp->link_config.advertising & ADVERTISED_100baseT_Full) {
- new_adv |= ADVERTISE_100FULL;
- }
- tg3_writephy(tp, MII_ADVERTISE, new_adv);
-
- if (tp->link_config.advertising &
- (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
- new_adv = 0;
- if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) {
- new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
- }
- if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) {
- new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
- }
- if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) &&
- (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) {
- new_adv |= (MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER);
- }
- tg3_writephy(tp, MII_TG3_CTRL, new_adv);
- } else {
- tg3_writephy(tp, MII_TG3_CTRL, 0);
- }
-
- tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
-
- return 0;
-}
-
-static int tg3_init_5401phy_dsp(struct tg3 *tp)
-{
- int err;
-
- /* Turn off tap power management. */
- err = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c20);
-
- err |= tg3_writedsp(tp, 0x0012, 0x1804);
- err |= tg3_writedsp(tp, 0x0013, 0x1204);
- err |= tg3_writedsp(tp, 0x8006, 0x0132);
- err |= tg3_writedsp(tp, 0x8006, 0x0232);
- err |= tg3_writedsp(tp, 0x201f, 0x0a20);
-
- udelay(40);
-
- return err;
-}
-
-static int tg3_setup_copper_phy(struct tg3 *tp)
-{
- int current_link_up;
- uint32_t bmsr, dummy;
- int i, err;
-
- tw32_carefully(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED
- | MAC_STATUS_LNKSTATE_CHANGED));
-
- tp->mi_mode = MAC_MI_MODE_BASE;
- tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
-
- /* Some third-party PHYs need to be reset on link going
- * down.
- */
- if ( ( (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
- (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)) &&
- (tp->carrier_ok)) {
- tg3_readphy(tp, MII_BMSR, &bmsr);
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if (!(bmsr & BMSR_LSTATUS))
- tg3_phy_reset(tp);
- }
-
- if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
- tg3_readphy(tp, MII_BMSR, &bmsr);
- tg3_readphy(tp, MII_BMSR, &bmsr);
-
- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE))
- bmsr = 0;
-
- if (!(bmsr & BMSR_LSTATUS)) {
- err = tg3_init_5401phy_dsp(tp);
- if (err)
- return err;
-
- tg3_readphy(tp, MII_BMSR, &bmsr);
- for (i = 0; i < 1000; i++) {
- udelay(10);
- tg3_readphy(tp, MII_BMSR, &bmsr);
- if (bmsr & BMSR_LSTATUS) {
- udelay(40);
- break;
- }
- }
-
- if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 &&
- !(bmsr & BMSR_LSTATUS) &&
- tp->link_config.active_speed == SPEED_1000) {
- err = tg3_phy_reset(tp);
- if (!err)
- err = tg3_init_5401phy_dsp(tp);
- if (err)
- return err;
- }
- }
- } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
- /* 5701 {A0,B0} CRC bug workaround */
- tg3_writephy(tp, 0x15, 0x0a75);
- tg3_writephy(tp, 0x1c, 0x8c68);
- tg3_writephy(tp, 0x1c, 0x8d68);
- tg3_writephy(tp, 0x1c, 0x8c68);
- }
-
- /* Clear pending interrupts... */
- tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
- tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
-
- tg3_writephy(tp, MII_TG3_IMASK, ~0);
-
- if (tp->led_mode == led_mode_three_link)
- tg3_writephy(tp, MII_TG3_EXT_CTRL,
- MII_TG3_EXT_CTRL_LNK3_LED_MODE);
- else
- tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
-
- current_link_up = 0;
-
- tg3_readphy(tp, MII_BMSR, &bmsr);
- tg3_readphy(tp, MII_BMSR, &bmsr);
-
- if (bmsr & BMSR_LSTATUS) {
- uint32_t aux_stat, bmcr;
-
- tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
- for (i = 0; i < 2000; i++) {
- udelay(10);
- tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
- if (aux_stat)
- break;
- }
-
- tg3_aux_stat_to_speed_duplex(tp, aux_stat,
- &tp->link_config.active_speed,
- &tp->link_config.active_duplex);
- tg3_readphy(tp, MII_BMCR, &bmcr);
- tg3_readphy(tp, MII_BMCR, &bmcr);
- if (bmcr & BMCR_ANENABLE) {
- uint32_t gig_ctrl;
-
- current_link_up = 1;
-
- /* Force autoneg restart if we are exiting
- * low power mode.
- */
- tg3_readphy(tp, MII_TG3_CTRL, &gig_ctrl);
- if (!(gig_ctrl & (MII_TG3_CTRL_ADV_1000_HALF |
- MII_TG3_CTRL_ADV_1000_FULL))) {
- current_link_up = 0;
- }
- } else {
- current_link_up = 0;
- }
- }
-
- if (current_link_up == 1 &&
- (tp->link_config.active_duplex == DUPLEX_FULL)) {
- uint32_t local_adv, remote_adv;
-
- tg3_readphy(tp, MII_ADVERTISE, &local_adv);
- local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
-
- tg3_readphy(tp, MII_LPA, &remote_adv);
- remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
- /* If we are not advertising full pause capability,
- * something is wrong. Bring the link down and reconfigure.
- */
- if (local_adv != ADVERTISE_PAUSE_CAP) {
- current_link_up = 0;
- } else {
- tg3_setup_flow_control(tp, local_adv, remote_adv);
- }
- }
-
- if (current_link_up == 0) {
- uint32_t tmp;
-
- tg3_phy_copper_begin(tp);
-
- tg3_readphy(tp, MII_BMSR, &tmp);
- tg3_readphy(tp, MII_BMSR, &tmp);
- if (tmp & BMSR_LSTATUS)
- current_link_up = 1;
- }
-
- tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
- if (current_link_up == 1) {
- if (tp->link_config.active_speed == SPEED_100 ||
- tp->link_config.active_speed == SPEED_10)
- tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
- else
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
- } else
- tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
-
- tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
- if (tp->link_config.active_duplex == DUPLEX_HALF)
- tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
-
- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
- if ((tp->led_mode == led_mode_link10) ||
- (current_link_up == 1 &&
- tp->link_config.active_speed == SPEED_10))
- tp->mac_mode |= MAC_MODE_LINK_POLARITY;
- } else {
- if (current_link_up == 1)
- tp->mac_mode |= MAC_MODE_LINK_POLARITY;
- tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1);
- }
-
- /* ??? Without this setting Netgear GA302T PHY does not
- * ??? send/receive packets...
- * With this other PHYs cannot bring up the link
- */
- if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
- tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
- tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
- tw32_carefully(MAC_MI_MODE, tp->mi_mode);
- }
-
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- /* Link change polled. */
- tw32_carefully(MAC_EVENT, 0);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
- current_link_up == 1 &&
- tp->link_config.active_speed == SPEED_1000 &&
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
- (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
- udelay(120);
- tw32_carefully(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
- tg3_write_mem(
- NIC_SRAM_FIRMWARE_MBOX,
- NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
- }
-
- if (current_link_up != tp->carrier_ok) {
- tp->carrier_ok = current_link_up;
- tg3_link_report(tp);
- }
-
- return 0;
-}
-#else
-#define tg3_setup_copper_phy(TP) (-EINVAL)
-#endif /* SUPPORT_COPPER_PHY */
-
-#if SUPPORT_FIBER_PHY
-struct tg3_fiber_aneginfo {
- int state;
-#define ANEG_STATE_UNKNOWN 0
-#define ANEG_STATE_AN_ENABLE 1
-#define ANEG_STATE_RESTART_INIT 2
-#define ANEG_STATE_RESTART 3
-#define ANEG_STATE_DISABLE_LINK_OK 4
-#define ANEG_STATE_ABILITY_DETECT_INIT 5
-#define ANEG_STATE_ABILITY_DETECT 6
-#define ANEG_STATE_ACK_DETECT_INIT 7
-#define ANEG_STATE_ACK_DETECT 8
-#define ANEG_STATE_COMPLETE_ACK_INIT 9
-#define ANEG_STATE_COMPLETE_ACK 10
-#define ANEG_STATE_IDLE_DETECT_INIT 11
-#define ANEG_STATE_IDLE_DETECT 12
-#define ANEG_STATE_LINK_OK 13
-#define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14
-#define ANEG_STATE_NEXT_PAGE_WAIT 15
-
- uint32_t flags;
-#define MR_AN_ENABLE 0x00000001
-#define MR_RESTART_AN 0x00000002
-#define MR_AN_COMPLETE 0x00000004
-#define MR_PAGE_RX 0x00000008
-#define MR_NP_LOADED 0x00000010
-#define MR_TOGGLE_TX 0x00000020
-#define MR_LP_ADV_FULL_DUPLEX 0x00000040
-#define MR_LP_ADV_HALF_DUPLEX 0x00000080
-#define MR_LP_ADV_SYM_PAUSE 0x00000100
-#define MR_LP_ADV_ASYM_PAUSE 0x00000200
-#define MR_LP_ADV_REMOTE_FAULT1 0x00000400
-#define MR_LP_ADV_REMOTE_FAULT2 0x00000800
-#define MR_LP_ADV_NEXT_PAGE 0x00001000
-#define MR_TOGGLE_RX 0x00002000
-#define MR_NP_RX 0x00004000
-
-#define MR_LINK_OK 0x80000000
-
- unsigned long link_time, cur_time;
-
- uint32_t ability_match_cfg;
- int ability_match_count;
-
- char ability_match, idle_match, ack_match;
-
- uint32_t txconfig, rxconfig;
-#define ANEG_CFG_NP 0x00000080
-#define ANEG_CFG_ACK 0x00000040
-#define ANEG_CFG_RF2 0x00000020
-#define ANEG_CFG_RF1 0x00000010
-#define ANEG_CFG_PS2 0x00000001
-#define ANEG_CFG_PS1 0x00008000
-#define ANEG_CFG_HD 0x00004000
-#define ANEG_CFG_FD 0x00002000
-#define ANEG_CFG_INVAL 0x00001f06
-
-};
-#define ANEG_OK 0
-#define ANEG_DONE 1
-#define ANEG_TIMER_ENAB 2
-#define ANEG_FAILED -1
-
-#define ANEG_STATE_SETTLE_TIME 10000
-
-static int tg3_fiber_aneg_smachine(struct tg3 *tp,
- struct tg3_fiber_aneginfo *ap)
-{
- unsigned long delta;
- uint32_t rx_cfg_reg;
- int ret;
-
- if (ap->state == ANEG_STATE_UNKNOWN) {
- ap->rxconfig = 0;
- ap->link_time = 0;
- ap->cur_time = 0;
- ap->ability_match_cfg = 0;
- ap->ability_match_count = 0;
- ap->ability_match = 0;
- ap->idle_match = 0;
- ap->ack_match = 0;
- }
- ap->cur_time++;
-
- if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
- rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
-
- if (rx_cfg_reg != ap->ability_match_cfg) {
- ap->ability_match_cfg = rx_cfg_reg;
- ap->ability_match = 0;
- ap->ability_match_count = 0;
- } else {
- if (++ap->ability_match_count > 1) {
- ap->ability_match = 1;
- ap->ability_match_cfg = rx_cfg_reg;
- }
- }
- if (rx_cfg_reg & ANEG_CFG_ACK)
- ap->ack_match = 1;
- else
- ap->ack_match = 0;
-
- ap->idle_match = 0;
- } else {
- ap->idle_match = 1;
- ap->ability_match_cfg = 0;
- ap->ability_match_count = 0;
- ap->ability_match = 0;
- ap->ack_match = 0;
-
- rx_cfg_reg = 0;
- }
-
- ap->rxconfig = rx_cfg_reg;
- ret = ANEG_OK;
-
- switch(ap->state) {
- case ANEG_STATE_UNKNOWN:
- if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
- ap->state = ANEG_STATE_AN_ENABLE;
-
- /* fallthru */
- case ANEG_STATE_AN_ENABLE:
- ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
- if (ap->flags & MR_AN_ENABLE) {
- ap->link_time = 0;
- ap->cur_time = 0;
- ap->ability_match_cfg = 0;
- ap->ability_match_count = 0;
- ap->ability_match = 0;
- ap->idle_match = 0;
- ap->ack_match = 0;
-
- ap->state = ANEG_STATE_RESTART_INIT;
- } else {
- ap->state = ANEG_STATE_DISABLE_LINK_OK;
- }
- break;
-
- case ANEG_STATE_RESTART_INIT:
- ap->link_time = ap->cur_time;
- ap->flags &= ~(MR_NP_LOADED);
- ap->txconfig = 0;
- tw32(MAC_TX_AUTO_NEG, 0);
- tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- ret = ANEG_TIMER_ENAB;
- ap->state = ANEG_STATE_RESTART;
-
- /* fallthru */
- case ANEG_STATE_RESTART:
- delta = ap->cur_time - ap->link_time;
- if (delta > ANEG_STATE_SETTLE_TIME) {
- ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
- } else {
- ret = ANEG_TIMER_ENAB;
- }
- break;
-
- case ANEG_STATE_DISABLE_LINK_OK:
- ret = ANEG_DONE;
- break;
-
- case ANEG_STATE_ABILITY_DETECT_INIT:
- ap->flags &= ~(MR_TOGGLE_TX);
- ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
- tw32(MAC_TX_AUTO_NEG, ap->txconfig);
- tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- ap->state = ANEG_STATE_ABILITY_DETECT;
- break;
-
- case ANEG_STATE_ABILITY_DETECT:
- if (ap->ability_match != 0 && ap->rxconfig != 0) {
- ap->state = ANEG_STATE_ACK_DETECT_INIT;
- }
- break;
-
- case ANEG_STATE_ACK_DETECT_INIT:
- ap->txconfig |= ANEG_CFG_ACK;
- tw32(MAC_TX_AUTO_NEG, ap->txconfig);
- tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- ap->state = ANEG_STATE_ACK_DETECT;
-
- /* fallthru */
- case ANEG_STATE_ACK_DETECT:
- if (ap->ack_match != 0) {
- if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
- (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
- ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
- } else {
- ap->state = ANEG_STATE_AN_ENABLE;
- }
- } else if (ap->ability_match != 0 &&
- ap->rxconfig == 0) {
- ap->state = ANEG_STATE_AN_ENABLE;
- }
- break;
-
- case ANEG_STATE_COMPLETE_ACK_INIT:
- if (ap->rxconfig & ANEG_CFG_INVAL) {
- ret = ANEG_FAILED;
- break;
- }
- ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
- MR_LP_ADV_HALF_DUPLEX |
- MR_LP_ADV_SYM_PAUSE |
- MR_LP_ADV_ASYM_PAUSE |
- MR_LP_ADV_REMOTE_FAULT1 |
- MR_LP_ADV_REMOTE_FAULT2 |
- MR_LP_ADV_NEXT_PAGE |
- MR_TOGGLE_RX |
- MR_NP_RX);
- if (ap->rxconfig & ANEG_CFG_FD)
- ap->flags |= MR_LP_ADV_FULL_DUPLEX;
- if (ap->rxconfig & ANEG_CFG_HD)
- ap->flags |= MR_LP_ADV_HALF_DUPLEX;
- if (ap->rxconfig & ANEG_CFG_PS1)
- ap->flags |= MR_LP_ADV_SYM_PAUSE;
- if (ap->rxconfig & ANEG_CFG_PS2)
- ap->flags |= MR_LP_ADV_ASYM_PAUSE;
- if (ap->rxconfig & ANEG_CFG_RF1)
- ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
- if (ap->rxconfig & ANEG_CFG_RF2)
- ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
- if (ap->rxconfig & ANEG_CFG_NP)
- ap->flags |= MR_LP_ADV_NEXT_PAGE;
-
- ap->link_time = ap->cur_time;
-
- ap->flags ^= (MR_TOGGLE_TX);
- if (ap->rxconfig & 0x0008)
- ap->flags |= MR_TOGGLE_RX;
- if (ap->rxconfig & ANEG_CFG_NP)
- ap->flags |= MR_NP_RX;
- ap->flags |= MR_PAGE_RX;
-
- ap->state = ANEG_STATE_COMPLETE_ACK;
- ret = ANEG_TIMER_ENAB;
- break;
-
- case ANEG_STATE_COMPLETE_ACK:
- if (ap->ability_match != 0 &&
- ap->rxconfig == 0) {
- ap->state = ANEG_STATE_AN_ENABLE;
- break;
- }
- delta = ap->cur_time - ap->link_time;
- if (delta > ANEG_STATE_SETTLE_TIME) {
- if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
- ap->state = ANEG_STATE_IDLE_DETECT_INIT;
- } else {
- if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
- !(ap->flags & MR_NP_RX)) {
- ap->state = ANEG_STATE_IDLE_DETECT_INIT;
- } else {
- ret = ANEG_FAILED;
- }
- }
- }
- break;
-
- case ANEG_STATE_IDLE_DETECT_INIT:
- ap->link_time = ap->cur_time;
- tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- ap->state = ANEG_STATE_IDLE_DETECT;
- ret = ANEG_TIMER_ENAB;
- break;
-
- case ANEG_STATE_IDLE_DETECT:
- if (ap->ability_match != 0 &&
- ap->rxconfig == 0) {
- ap->state = ANEG_STATE_AN_ENABLE;
- break;
- }
- delta = ap->cur_time - ap->link_time;
- if (delta > ANEG_STATE_SETTLE_TIME) {
- /* XXX another gem from the Broadcom driver :( */
- ap->state = ANEG_STATE_LINK_OK;
- }
- break;
-
- case ANEG_STATE_LINK_OK:
- ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
- ret = ANEG_DONE;
- break;
-
- case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
- /* ??? unimplemented */
- break;
-
- case ANEG_STATE_NEXT_PAGE_WAIT:
- /* ??? unimplemented */
- break;
-
- default:
- ret = ANEG_FAILED;
- break;
- };
-
- return ret;
-}
-
-static int tg3_setup_fiber_phy(struct tg3 *tp)
-{
- uint32_t orig_pause_cfg;
- uint16_t orig_active_speed;
- uint8_t orig_active_duplex;
- int current_link_up;
- int i;
-
- orig_pause_cfg =
- (tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
- TG3_FLAG_TX_PAUSE));
- orig_active_speed = tp->link_config.active_speed;
- orig_active_duplex = tp->link_config.active_duplex;
-
- tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
- tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- /* Reset when initting first time or we have a link. */
- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
- (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
- /* Set PLL lock range. */
- tg3_writephy(tp, 0x16, 0x8007);
-
- /* SW reset */
- tg3_writephy(tp, MII_BMCR, BMCR_RESET);
-
- /* Wait for reset to complete. */
- mdelay(5);
-
- /* Config mode; select PMA/Ch 1 regs. */
- tg3_writephy(tp, 0x10, 0x8411);
-
- /* Enable auto-lock and comdet, select txclk for tx. */
- tg3_writephy(tp, 0x11, 0x0a10);
-
- tg3_writephy(tp, 0x18, 0x00a0);
- tg3_writephy(tp, 0x16, 0x41ff);
-
- /* Assert and deassert POR. */
- tg3_writephy(tp, 0x13, 0x0400);
- udelay(40);
- tg3_writephy(tp, 0x13, 0x0000);
-
- tg3_writephy(tp, 0x11, 0x0a50);
- udelay(40);
- tg3_writephy(tp, 0x11, 0x0a10);
-
- /* Wait for signal to stabilize */
- mdelay(150);
-
- /* Deselect the channel register so we can read the PHYID
- * later.
- */
- tg3_writephy(tp, 0x10, 0x8011);
- }
-
- /* Disable link change interrupt. */
- tw32_carefully(MAC_EVENT, 0);
-
- current_link_up = 0;
- if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
- if (!(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) {
- struct tg3_fiber_aneginfo aninfo;
- int status = ANEG_FAILED;
- unsigned int tick;
- uint32_t tmp;
-
- memset(&aninfo, 0, sizeof(aninfo));
- aninfo.flags |= (MR_AN_ENABLE);
-
- tw32(MAC_TX_AUTO_NEG, 0);
-
- tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
- tw32_carefully(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-
- tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-
- aninfo.state = ANEG_STATE_UNKNOWN;
- aninfo.cur_time = 0;
- tick = 0;
- while (++tick < 195000) {
- status = tg3_fiber_aneg_smachine(tp, &aninfo);
- if (status == ANEG_DONE ||
- status == ANEG_FAILED)
- break;
-
- udelay(1);
- }
-
- tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- if (status == ANEG_DONE &&
- (aninfo.flags &
- (MR_AN_COMPLETE | MR_LINK_OK |
- MR_LP_ADV_FULL_DUPLEX))) {
- uint32_t local_adv, remote_adv;
-
- local_adv = ADVERTISE_PAUSE_CAP;
- remote_adv = 0;
- if (aninfo.flags & MR_LP_ADV_SYM_PAUSE)
- remote_adv |= LPA_PAUSE_CAP;
- if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE)
- remote_adv |= LPA_PAUSE_ASYM;
-
- tg3_setup_flow_control(tp, local_adv, remote_adv);
-
- tp->tg3_flags |=
- TG3_FLAG_GOT_SERDES_FLOWCTL;
- current_link_up = 1;
- }
- for (i = 0; i < 60; i++) {
- udelay(20);
- tw32_carefully(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
- if ((tr32(MAC_STATUS) &
- (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED)) == 0)
- break;
- }
- if (current_link_up == 0 &&
- (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
- current_link_up = 1;
- }
- } else {
- /* Forcing 1000FD link up. */
- current_link_up = 1;
- }
- }
-
- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- tp->hw_status->status =
- (SD_STATUS_UPDATED |
- (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
-
- for (i = 0; i < 100; i++) {
- udelay(20);
- tw32_carefully(MAC_STATUS,
- (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
- if ((tr32(MAC_STATUS) &
- (MAC_STATUS_SYNC_CHANGED |
- MAC_STATUS_CFG_CHANGED)) == 0)
- break;
- }
-
- if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
- current_link_up = 0;
-
- if (current_link_up == 1) {
- tp->link_config.active_speed = SPEED_1000;
- tp->link_config.active_duplex = DUPLEX_FULL;
- } else {
- tp->link_config.active_speed = SPEED_INVALID;
- tp->link_config.active_duplex = DUPLEX_INVALID;
- }
-
- if (current_link_up != tp->carrier_ok) {
- tp->carrier_ok = current_link_up;
- tg3_link_report(tp);
- } else {
- uint32_t now_pause_cfg =
- tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
- TG3_FLAG_TX_PAUSE);
- if (orig_pause_cfg != now_pause_cfg ||
- orig_active_speed != tp->link_config.active_speed ||
- orig_active_duplex != tp->link_config.active_duplex)
- tg3_link_report(tp);
- }
-
- if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
- tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
- if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
- tw32_carefully(MAC_MODE, tp->mac_mode);
- }
- }
-
- return 0;
-}
-#else
-#define tg3_setup_fiber_phy(TP) (-EINVAL)
-#endif /* SUPPORT_FIBER_PHY */
-
-static int tg3_setup_phy(struct tg3 *tp)
-{
- int err;
-
- if (tp->phy_id == PHY_ID_SERDES) {
- err = tg3_setup_fiber_phy(tp);
- } else {
- err = tg3_setup_copper_phy(tp);
- }
-
- if (tp->link_config.active_speed == SPEED_1000 &&
- tp->link_config.active_duplex == DUPLEX_HALF)
- tw32(MAC_TX_LENGTHS,
- ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
- (6 << TX_LENGTHS_IPG_SHIFT) |
- (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
- else
- tw32(MAC_TX_LENGTHS,
- ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
- (6 << TX_LENGTHS_IPG_SHIFT) |
- (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
-
- return err;
-}
-
-
-#define MAX_WAIT_CNT 1000
-
-/* To stop a block, clear the enable bit and poll till it
- * clears.
- */
-static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, uint32_t enable_bit)
-{
- unsigned int i;
- uint32_t val;
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
- switch(ofs) {
- case RCVLSC_MODE:
- case DMAC_MODE:
- case MBFREE_MODE:
- case BUFMGR_MODE:
- case MEMARB_MODE:
- /* We can't enable/disable these bits of the
- * 5705 or 5787, just say success.
- */
- return 0;
- default:
- break;
- }
- }
- val = tr32(ofs);
- val &= ~enable_bit;
- tw32(ofs, val);
- tr32(ofs);
-
- for (i = 0; i < MAX_WAIT_CNT; i++) {
- udelay(100);
- val = tr32(ofs);
- if ((val & enable_bit) == 0)
- break;
- }
-
- if (i == MAX_WAIT_CNT) {
- printf( "tg3_stop_block timed out, ofs=%#lx enable_bit=%3x\n",
- ofs, enable_bit );
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int tg3_abort_hw(struct tg3 *tp)
-{
- int i, err;
- uint32_t val;
-
- tg3_disable_ints(tp);
-
- tp->rx_mode &= ~RX_MODE_ENABLE;
- tw32_carefully(MAC_RX_MODE, tp->rx_mode);
-
- err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
- err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
- err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE);
- err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE);
- err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE);
- err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE);
-
- err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE);
- err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE);
- err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
- err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE);
- err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
- err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE);
- if (err)
- goto out;
-
- tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- tp->tx_mode &= ~TX_MODE_ENABLE;
- tw32_carefully(MAC_TX_MODE, tp->tx_mode);
-
- for (i = 0; i < MAX_WAIT_CNT; i++) {
- udelay(100);
- if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
- break;
- }
- if (i >= MAX_WAIT_CNT) {
- printf("tg3_abort_hw timed out TX_MODE_ENABLE will not clear MAC_TX_MODE=%x\n",
- (unsigned int) tr32(MAC_TX_MODE));
- return -ENODEV;
- }
-
- err = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
- err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE);
- err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
-
- val = tr32(FTQ_RESET);
- val |= FTQ_RESET_DMA_READ_QUEUE | FTQ_RESET_DMA_HIGH_PRI_READ |
- FTQ_RESET_SEND_BD_COMPLETION | FTQ_RESET_DMA_WRITE |
- FTQ_RESET_DMA_HIGH_PRI_WRITE | FTQ_RESET_SEND_DATA_COMPLETION |
- FTQ_RESET_HOST_COALESCING | FTQ_RESET_MAC_TX |
- FTQ_RESET_RX_BD_COMPLETE | FTQ_RESET_RX_LIST_PLCMT |
- FTQ_RESET_RX_DATA_COMPLETION;
- tw32(FTQ_RESET, val);
-
- err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
- err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
- if (err)
- goto out;
-
- memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
-
-out:
- return err;
-}
-
-static void tg3_chip_reset(struct tg3 *tp)
-{
- uint32_t val;
-
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
- /* Force NVRAM to settle.
- * This deals with a chip bug which can result in EEPROM
- * corruption.
- */
- if (tp->tg3_flags & TG3_FLAG_NVRAM) {
- int i;
-
- tw32(NVRAM_SWARB, SWARB_REQ_SET1);
- for (i = 0; i < 100000; i++) {
- if (tr32(NVRAM_SWARB) & SWARB_GNT1)
- break;
- udelay(10);
- }
- }
- }
- /* In Etherboot we don't need to worry about the 5701
- * REG_WRITE_BUG because we do all register writes indirectly.
- */
-
- // Alf: here patched
- /* do the reset */
- val = GRC_MISC_CFG_CORECLK_RESET;
- if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
- if (tr32(0x7e2c) == 0x60) {
- tw32(0x7e2c, 0x20);
- }
- if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
- tw32(GRC_MISC_CFG, (1 << 29));
- val |= (1 << 29);
- }
- }
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
- || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
- || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) {
- val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
- }
-
- // Alf : Please VALIDATE THIS.
- // It is necessary in my case (5751) to prevent a reboot, but
- // I have no idea about a side effect on any other version.
- // It appears to be what's done in tigon3.c from Broadcom
- if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
- tw32(GRC_MISC_CFG, 0x20000000) ;
- val |= 0x20000000 ;
- }
-
- tw32(GRC_MISC_CFG, val);
-
- /* Flush PCI posted writes. The normal MMIO registers
- * are inaccessible at this time so this is the only
- * way to make this reliably. I tried to use indirect
- * register read/write but this upset some 5701 variants.
- */
- pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
-
- udelay(120);
-
- /* Re-enable indirect register accesses. */
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
-
- /* Set MAX PCI retry to zero. */
- val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
- (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
- val |= PCISTATE_RETRY_SAME_DMA;
- pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
-
- pci_restore_state(tp->pdev, tp->pci_cfg_state);
-
- /* Make sure PCI-X relaxed ordering bit is clear. */
- pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
- val &= ~PCIX_CAPS_RELAXED_ORDERING;
- pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
-
- tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
-
- if (((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
- tp->pci_clock_ctrl |=
- (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE);
- tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
- }
-
- tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
-}
-
-static void tg3_stop_fw(struct tg3 *tp)
-{
- if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
- uint32_t val;
- int i;
-
- tg3_write_mem(NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
- val = tr32(GRC_RX_CPU_EVENT);
- val |= (1 << 14);
- tw32(GRC_RX_CPU_EVENT, val);
-
- /* Wait for RX cpu to ACK the event. */
- for (i = 0; i < 100; i++) {
- if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
- break;
- udelay(1);
- }
- }
-}
-
-static int tg3_restart_fw(struct tg3 *tp, uint32_t state)
-{
- uint32_t val;
- int i;
-
- tg3_write_mem(NIC_SRAM_FIRMWARE_MBOX,
- NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
- /* Wait for firmware initialization to complete. */
- for (i = 0; i < 100000; i++) {
- tg3_read_mem(NIC_SRAM_FIRMWARE_MBOX, &val);
- if (val == (uint32_t) ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
- break;
- udelay(10);
- }
- if (i >= 100000 &&
- !(tp->tg3_flags2 & TG3_FLG2_SUN_5704) &&
- !(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) {
- printf ( "Firmware will not restart magic=%#x\n",
- val );
- return -ENODEV;
- }
- if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
- state = DRV_STATE_SUSPEND;
- }
-
- if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
- (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)) {
- // Enable PCIE bug fix
- tg3_read_mem(0x7c00, &val);
- tg3_write_mem(0x7c00, val | 0x02000000);
- }
- tg3_write_mem(NIC_SRAM_FW_DRV_STATE_MBOX, state);
- return 0;
-}
-
-static int tg3_halt(struct tg3 *tp)
-{
- tg3_stop_fw(tp);
- tg3_abort_hw(tp);
- tg3_chip_reset(tp);
- return tg3_restart_fw(tp, DRV_STATE_UNLOAD);
-}
-
-static void __tg3_set_mac_addr(struct tg3 *tp)
-{
- uint32_t addr_high, addr_low;
- int i;
-
- addr_high = ((tp->nic->node_addr[0] << 8) |
- tp->nic->node_addr[1]);
- addr_low = ((tp->nic->node_addr[2] << 24) |
- (tp->nic->node_addr[3] << 16) |
- (tp->nic->node_addr[4] << 8) |
- (tp->nic->node_addr[5] << 0));
- for (i = 0; i < 4; i++) {
- tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
- tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
- }
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)) {
- for(i = 0; i < 12; i++) {
- tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
- tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
- }
- }
- addr_high = (tp->nic->node_addr[0] +
- tp->nic->node_addr[1] +
- tp->nic->node_addr[2] +
- tp->nic->node_addr[3] +
- tp->nic->node_addr[4] +
- tp->nic->node_addr[5]) &
- TX_BACKOFF_SEED_MASK;
- tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
-
-static void tg3_set_bdinfo(struct tg3 *tp, uint32_t bdinfo_addr,
- dma_addr_t mapping, uint32_t maxlen_flags,
- uint32_t nic_addr)
-{
- tg3_write_mem((bdinfo_addr +
- TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
- ((uint64_t) mapping >> 32));
- tg3_write_mem((bdinfo_addr +
- TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
- ((uint64_t) mapping & 0xffffffff));
- tg3_write_mem((bdinfo_addr +
- TG3_BDINFO_MAXLEN_FLAGS),
- maxlen_flags);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
- tg3_write_mem((bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr);
- }
-}
-
-
-static void tg3_init_rings(struct tg3 *tp)
-{
- unsigned i;
-
- /* Zero out the tg3 variables */
- memset(&tg3_bss, 0, sizeof(tg3_bss));
- tp->rx_std = &tg3_bss.rx_std[0];
- tp->rx_rcb = &tg3_bss.rx_rcb[0];
- tp->tx_ring = &tg3_bss.tx_ring[0];
- tp->hw_status = &tg3_bss.hw_status;
- tp->hw_stats = &tg3_bss.hw_stats;
- tp->mac_mode = 0;
-
-
- /* Initialize tx/rx rings for packet processing.
- *
- * The chip has been shut down and the driver detached from
- * the networking, so no interrupts or new tx packets will
- * end up in the driver.
- */
-
- /* Initialize invariants of the rings, we only set this
- * stuff once. This works because the card does not
- * write into the rx buffer posting rings.
- */
- for (i = 0; i < TG3_RX_RING_SIZE; i++) {
- struct tg3_rx_buffer_desc *rxd;
-
- rxd = &tp->rx_std[i];
- rxd->idx_len = (RX_PKT_BUF_SZ - 2 - 64) << RXD_LEN_SHIFT;
- rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
- rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT));
-
- /* Note where the receive buffer for the ring is placed */
- rxd->addr_hi = 0;
- rxd->addr_lo = virt_to_bus(
- &tg3_bss.rx_bufs[i%TG3_DEF_RX_RING_PENDING][2]);
- }
-}
-
-#define TG3_WRITE_SETTINGS(TABLE) \
-do { \
- const uint32_t *_table, *_end; \
- _table = TABLE; \
- _end = _table + sizeof(TABLE)/sizeof(TABLE[0]); \
- for(; _table < _end; _table += 2) { \
- tw32(_table[0], _table[1]); \
- } \
-} while(0)
-
-
-/* initialize/reset the tg3 */
-static int tg3_setup_hw(struct tg3 *tp)
-{
- uint32_t val, rdmac_mode;
- int i, err, limit;
-
- /* Simply don't support setups with extremly buggy firmware in etherboot */
- if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
- printf("Error 5701_A0 firmware bug detected\n");
- return -EINVAL;
- }
-
- tg3_disable_ints(tp);
-
- /* Originally this was all in tg3_init_hw */
-
- /* Force the chip into D0. */
- tg3_set_power_state_0(tp);
-
- tg3_switch_clocks(tp);
-
- tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-
- // This should go somewhere else
-#define T3_PCIE_CAPABILITY_ID_REG 0xD0
-#define T3_PCIE_CAPABILITY_ID 0x10
-#define T3_PCIE_CAPABILITY_REG 0xD2
-
- /* Originally this was all in tg3_reset_hw */
-
- tg3_stop_fw(tp);
-
- /* No need to call tg3_abort_hw here, it is called before tg3_setup_hw. */
-
- tg3_chip_reset(tp);
-
- tw32(GRC_MODE, tp->grc_mode); /* Redundant? */
-
- err = tg3_restart_fw(tp, DRV_STATE_START);
- if (err)
- return err;
-
- if (tp->phy_id == PHY_ID_SERDES) {
- tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
- }
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
-
- /* This works around an issue with Athlon chipsets on
- * B3 tigon3 silicon. This bit has no effect on any
- * other revision.
- * Alf: Except 5750 ! (which reboots)
- */
-
- if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
- tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
- tw32_carefully(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
-
- if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
- (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
- val = tr32(TG3PCI_PCISTATE);
- val |= PCISTATE_RETRY_SAME_DMA;
- tw32(TG3PCI_PCISTATE, val);
- }
-
- /* Descriptor ring init may make accesses to the
- * NIC SRAM area to setup the TX descriptors, so we
- * can only do this after the hardware has been
- * successfully reset.
- */
- tg3_init_rings(tp);
-
- /* Clear statistics/status block in chip */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
- for (i = NIC_SRAM_STATS_BLK;
- i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
- i += sizeof(uint32_t)) {
- tg3_write_mem(i, 0);
- udelay(40);
- }
- }
-
- /* This value is determined during the probe time DMA
- * engine test, tg3_setup_dma.
- */
- tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
-
- tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
- GRC_MODE_4X_NIC_SEND_RINGS |
- GRC_MODE_NO_TX_PHDR_CSUM |
- GRC_MODE_NO_RX_PHDR_CSUM);
- tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
- tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
- tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
-
- tw32(GRC_MODE,
- tp->grc_mode |
- (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
-
- /* Setup the timer prescalar register. Clock is always 66Mhz. */
- tw32(GRC_MISC_CFG,
- (65 << GRC_MISC_CFG_PRESCALAR_SHIFT));
-
- /* Initialize MBUF/DESC pool. */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
- /* Do nothing. */
- } else if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
- (tp->pci_chip_rev_id != CHIPREV_ID_5721)) {
- tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
- tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
- else
- tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
- tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
- tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
- }
- if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) {
- tw32(BUFMGR_MB_RDMA_LOW_WATER,
- tp->bufmgr_config.mbuf_read_dma_low_water);
- tw32(BUFMGR_MB_MACRX_LOW_WATER,
- tp->bufmgr_config.mbuf_mac_rx_low_water);
- tw32(BUFMGR_MB_HIGH_WATER,
- tp->bufmgr_config.mbuf_high_water);
- } else {
- tw32(BUFMGR_MB_RDMA_LOW_WATER,
- tp->bufmgr_config.mbuf_read_dma_low_water_jumbo);
- tw32(BUFMGR_MB_MACRX_LOW_WATER,
- tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo);
- tw32(BUFMGR_MB_HIGH_WATER,
- tp->bufmgr_config.mbuf_high_water_jumbo);
- }
- tw32(BUFMGR_DMA_LOW_WATER,
- tp->bufmgr_config.dma_low_water);
- tw32(BUFMGR_DMA_HIGH_WATER,
- tp->bufmgr_config.dma_high_water);
-
- tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
- for (i = 0; i < 2000; i++) {
- if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
- break;
- udelay(10);
- }
- if (i >= 2000) {
- printf("tg3_setup_hw cannot enable BUFMGR\n");
- return -ENODEV;
- }
-
- tw32(FTQ_RESET, 0xffffffff);
- tw32(FTQ_RESET, 0x00000000);
- for (i = 0; i < 2000; i++) {
- if (tr32(FTQ_RESET) == 0x00000000)
- break;
- udelay(10);
- }
- if (i >= 2000) {
- printf("tg3_setup_hw cannot reset FTQ\n");
- return -ENODEV;
- }
-
- /* Initialize TG3_BDINFO's at:
- * RCVDBDI_STD_BD: standard eth size rx ring
- * RCVDBDI_JUMBO_BD: jumbo frame rx ring
- * RCVDBDI_MINI_BD: small frame rx ring (??? does not work)
- *
- * like so:
- * TG3_BDINFO_HOST_ADDR: high/low parts of DMA address of ring
- * TG3_BDINFO_MAXLEN_FLAGS: (rx max buffer size << 16) |
- * ring attribute flags
- * TG3_BDINFO_NIC_ADDR: location of descriptors in nic SRAM
- *
- * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
- * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
- *
- * ??? No space allocated for mini receive ring? :(
- *
- * The size of each ring is fixed in the firmware, but the location is
- * configurable.
- */
- {
- static const uint32_t table_all[] = {
- /* Setup replenish thresholds. */
- RCVBDI_STD_THRESH, TG3_DEF_RX_RING_PENDING / 8,
-
- /* Etherboot lives below 4GB */
- RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
- RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC,
- };
- static const uint32_t table_not_5705[] = {
- /* Buffer maximum length */
- RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT,
-
- /* Disable the mini frame rx ring */
- RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED,
-
- /* Disable the jumbo frame rx ring */
- RCVBDI_JUMBO_THRESH, 0,
- RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED,
-
-
- };
- TG3_WRITE_SETTINGS(table_all);
- tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
- virt_to_bus(tp->rx_std));
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
- tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
- RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT);
- } else {
- TG3_WRITE_SETTINGS(table_not_5705);
- }
- }
-
-
- /* There is only one send ring on 5705 and 5787, no need to explicitly
- * disable the others.
- */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) {
- /* Clear out send RCB ring in SRAM. */
- for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
- tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED);
- }
-
- tp->tx_prod = 0;
- tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
- tw32_mailbox2(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
- tg3_set_bdinfo(tp,
- NIC_SRAM_SEND_RCB,
- virt_to_bus(tp->tx_ring),
- (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
- NIC_SRAM_TX_BUFFER_DESC);
-
- /* There is only one receive return ring on 5705 and 5787, no need to
- * explicitly disable the others.
- */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) {
- for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; i += TG3_BDINFO_SIZE) {
- tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS,
- BDINFO_FLAGS_DISABLED);
- }
- }
-
- tp->rx_rcb_ptr = 0;
- tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
- tg3_set_bdinfo(tp,
- NIC_SRAM_RCV_RET_RCB,
- virt_to_bus(tp->rx_rcb),
- (TG3_RX_RCB_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
- 0);
-
- tp->rx_std_ptr = TG3_DEF_RX_RING_PENDING;
- tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
- tp->rx_std_ptr);
-
- tw32_mailbox2(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, 0);
-
- /* Initialize MAC address and backoff seed. */
- __tg3_set_mac_addr(tp);
-
- /* Calculate RDMAC_MODE setting early, we need it to determine
- * the RCVLPC_STATE_ENABLE mask.
- */
- rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
- RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
- RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
- RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
- RDMAC_MODE_LNGREAD_ENAB);
- if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
- rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
- if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
- if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
- !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
- rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
- }
- }
- }
-
- /* Setup host coalescing engine. */
- tw32(HOSTCC_MODE, 0);
- for (i = 0; i < 2000; i++) {
- if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
- break;
- udelay(10);
- }
-
- tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
- MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
- tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
-
- tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
- tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OUTPUT1);
- tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
- tr32(MAILBOX_INTERRUPT_0);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
- tw32_carefully(DMAC_MODE, DMAC_MODE_ENABLE);
- }
-
- val = ( WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
- WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
- WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
- WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
- WDMAC_MODE_LNGREAD_ENAB);
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
- ((tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0) &&
- !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
- val |= WDMAC_MODE_RX_ACCEL;
- }
-
- /* Host coalescing bug fix */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- val |= (1 << 29);
-
- tw32_carefully(WDMAC_MODE, val);
-
- if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
- val = tr32(TG3PCI_X_CAPS);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
- val &= PCIX_CAPS_BURST_MASK;
- val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
- } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
- val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
- val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
- if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
- val |= (tp->split_mode_max_reqs <<
- PCIX_CAPS_SPLIT_SHIFT);
- }
- tw32(TG3PCI_X_CAPS, val);
- }
-
- tw32_carefully(RDMAC_MODE, rdmac_mode);
- {
- static const uint32_t table_all[] = {
- /* MTU + ethernet header + FCS + optional VLAN tag */
- MAC_RX_MTU_SIZE, ETH_MAX_MTU + ETH_HLEN + 8,
-
- /* The slot time is changed by tg3_setup_phy if we
- * run at gigabit with half duplex.
- */
- MAC_TX_LENGTHS,
- (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
- (6 << TX_LENGTHS_IPG_SHIFT) |
- (32 << TX_LENGTHS_SLOT_TIME_SHIFT),
-
- /* Receive rules. */
- MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS,
- RCVLPC_CONFIG, 0x0181,
-
- /* Receive/send statistics. */
- RCVLPC_STATS_ENABLE, 0xffffff,
- RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE,
- SNDDATAI_STATSENAB, 0xffffff,
- SNDDATAI_STATSCTRL, (SNDDATAI_SCTRL_ENABLE |SNDDATAI_SCTRL_FASTUPD),
-
- /* Host coalescing engine */
- HOSTCC_RXCOL_TICKS, 0,
- HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS,
- HOSTCC_RXMAX_FRAMES, 1,
- HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES,
- HOSTCC_RXCOAL_MAXF_INT, 1,
- HOSTCC_TXCOAL_MAXF_INT, 0,
-
- /* Status/statistics block address. */
- /* Etherboot lives below 4GB, so HIGH == 0 */
- HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
-
- /* No need to enable 32byte coalesce mode. */
- HOSTCC_MODE, HOSTCC_MODE_ENABLE | 0,
-
- RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE,
- RCVLPC_MODE, RCVLPC_MODE_ENABLE,
-
- RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE,
-
- SNDDATAC_MODE, SNDDATAC_MODE_ENABLE,
- SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE,
- RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB,
- RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ,
- SNDDATAI_MODE, SNDDATAI_MODE_ENABLE,
- SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE,
- SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE,
-
- /* Accept all multicast frames. */
- MAC_HASH_REG_0, 0xffffffff,
- MAC_HASH_REG_1, 0xffffffff,
- MAC_HASH_REG_2, 0xffffffff,
- MAC_HASH_REG_3, 0xffffffff,
- };
- static const uint32_t table_not_5705[] = {
- /* Host coalescing engine */
- HOSTCC_RXCOAL_TICK_INT, 0,
- HOSTCC_TXCOAL_TICK_INT, 0,
-
- /* Status/statistics block address. */
- /* Etherboot lives below 4GB, so HIGH == 0 */
- HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS,
- HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
- HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK,
- HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK,
-
- RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE,
-
- MBFREE_MODE, MBFREE_MODE_ENABLE,
- };
- TG3_WRITE_SETTINGS(table_all);
- tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
- virt_to_bus(tp->hw_stats));
- tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
- virt_to_bus(tp->hw_status));
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) {
- TG3_WRITE_SETTINGS(table_not_5705);
- }
- }
-
- tp->tx_mode = TX_MODE_ENABLE;
- tw32_carefully(MAC_TX_MODE, tp->tx_mode);
-
- tp->rx_mode = RX_MODE_ENABLE;
- tw32_carefully(MAC_RX_MODE, tp->rx_mode);
-
- tp->mi_mode = MAC_MI_MODE_BASE;
- tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
- tw32(MAC_LED_CTRL, 0);
- tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
- if (tp->phy_id == PHY_ID_SERDES) {
- tw32_carefully(MAC_RX_MODE, RX_MODE_RESET);
- }
- tp->rx_mode |= RX_MODE_KEEP_VLAN_TAG; /* drop tagged vlan packets */
- tw32_carefully(MAC_RX_MODE, tp->rx_mode);
-
- if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
- tw32(MAC_SERDES_CFG, 0x616000);
-
- /* Prevent chip from dropping frames when flow control
- * is enabled.
- */
- tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
- tr32(MAC_LOW_WMARK_MAX_RX_FRAME);
-
- err = tg3_setup_phy(tp);
-
- /* Ignore CRC stats */
-
- /* Initialize receive rules. */
- tw32(MAC_RCV_RULE_0, 0xc2000000 & RCV_RULE_DISABLE_MASK);
- tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
- tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK);
- tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
- || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750))
- limit = 8;
- else
- limit = 16;
- if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)
- limit -= 4;
- switch (limit) {
- case 16: tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0);
- case 15: tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0);
- case 14: tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0);
- case 13: tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0);
- case 12: tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0);
- case 11: tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0);
- case 10: tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0);
- case 9: tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0);
- case 8: tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0);
- case 7: tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0);
- case 6: tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0);
- case 5: tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0);
- case 4: /* tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); */
- case 3: /* tw32(MAC_RCV_RULE_2, 0); tw32(MAC_RCV_VALUE_2, 0); */
- case 2:
- case 1:
- default:
- break;
- };
-
- return err;
-}
-
-
-
-/* Chips other than 5700/5701 use the NVRAM for fetching info. */
-static void tg3_nvram_init(struct tg3 *tp)
-{
- tw32(GRC_EEPROM_ADDR,
- (EEPROM_ADDR_FSM_RESET |
- (EEPROM_DEFAULT_CLOCK_PERIOD <<
- EEPROM_ADDR_CLKPERD_SHIFT)));
-
- mdelay(1);
-
- /* Enable seeprom accesses. */
- tw32_carefully(GRC_LOCAL_CTRL,
- tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
- uint32_t nvcfg1 = tr32(NVRAM_CFG1);
-
- tp->tg3_flags |= TG3_FLAG_NVRAM;
- if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
- if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE)
- tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
- } else {
- nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
- tw32(NVRAM_CFG1, nvcfg1);
- }
-
- } else {
- tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
- }
-}
-
-
-static int tg3_nvram_read_using_eeprom(
- struct tg3 *tp __unused, uint32_t offset, uint32_t *val)
-{
- uint32_t tmp;
- int i;
-
- if (offset > EEPROM_ADDR_ADDR_MASK ||
- (offset % 4) != 0) {
- return -EINVAL;
- }
-
- tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
- EEPROM_ADDR_DEVID_MASK |
- EEPROM_ADDR_READ);
- tw32(GRC_EEPROM_ADDR,
- tmp |
- (0 << EEPROM_ADDR_DEVID_SHIFT) |
- ((offset << EEPROM_ADDR_ADDR_SHIFT) &
- EEPROM_ADDR_ADDR_MASK) |
- EEPROM_ADDR_READ | EEPROM_ADDR_START);
-
- for (i = 0; i < 10000; i++) {
- tmp = tr32(GRC_EEPROM_ADDR);
-
- if (tmp & EEPROM_ADDR_COMPLETE)
- break;
- udelay(100);
- }
- if (!(tmp & EEPROM_ADDR_COMPLETE)) {
- return -EBUSY;
- }
-
- *val = tr32(GRC_EEPROM_DATA);
- return 0;
-}
-
-static int tg3_nvram_read(struct tg3 *tp, uint32_t offset, uint32_t *val)
-{
- int i, saw_done_clear;
-
- if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
- return tg3_nvram_read_using_eeprom(tp, offset, val);
-
- if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED)
- offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) <<
- NVRAM_BUFFERED_PAGE_POS) +
- (offset % NVRAM_BUFFERED_PAGE_SIZE);
-
- if (offset > NVRAM_ADDR_MSK)
- return -EINVAL;
-
- tw32(NVRAM_SWARB, SWARB_REQ_SET1);
- for (i = 0; i < 1000; i++) {
- if (tr32(NVRAM_SWARB) & SWARB_GNT1)
- break;
- udelay(20);
- }
-
- tw32(NVRAM_ADDR, offset);
- tw32(NVRAM_CMD,
- NVRAM_CMD_RD | NVRAM_CMD_GO |
- NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
-
- /* Wait for done bit to clear then set again. */
- saw_done_clear = 0;
- for (i = 0; i < 1000; i++) {
- udelay(10);
- if (!saw_done_clear &&
- !(tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
- saw_done_clear = 1;
- else if (saw_done_clear &&
- (tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
- break;
- }
- if (i >= 1000) {
- tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
- return -EBUSY;
- }
-
- *val = bswap_32(tr32(NVRAM_RDDATA));
- tw32(NVRAM_SWARB, 0x20);
-
- return 0;
-}
-
-struct subsys_tbl_ent {
- uint16_t subsys_vendor, subsys_devid;
- uint32_t phy_id;
-};
-
-static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
- /* Broadcom boards. */
- { 0x14e4, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
- { 0x14e4, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
- { 0x14e4, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
- { 0x14e4, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */
- { 0x14e4, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
- { 0x14e4, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
- { 0x14e4, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */
- { 0x14e4, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
- { 0x14e4, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
- { 0x14e4, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */
- { 0x14e4, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */
-
- /* 3com boards. */
- { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
- { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
- /* { PCI_VENDOR_ID_3COM, 0x1002, PHY_ID_XXX }, 3C996CT */
- /* { PCI_VENDOR_ID_3COM, 0x1003, PHY_ID_XXX }, 3C997T */
- { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */
- /* { PCI_VENDOR_ID_3COM, 0x1005, PHY_ID_XXX }, 3C997SZ */
- { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
- { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
-
- /* DELL boards. */
- { PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */
- { PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */
- { PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */
- { PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */
- { PCI_VENDOR_ID_DELL, 0x0179, PHY_ID_BCM5751 }, /* EtherXpress */
-
- /* Fujitsu Siemens Computer */
- { PCI_VENDOR_ID_FSC, 0x105d, PHY_ID_BCM5751 }, /* Futro C200 */
-
- /* Compaq boards. */
- { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
- { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
- { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */
- { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
- { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 } /* NC7780_2 */
-};
-
-static int tg3_phy_probe(struct tg3 *tp)
-{
- uint32_t eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
- uint32_t hw_phy_id, hw_phy_id_masked;
- enum phy_led_mode eeprom_led_mode;
- uint32_t val;
- unsigned i;
- int eeprom_signature_found, err;
-
- tp->phy_id = PHY_ID_INVALID;
-
- for (i = 0; i < sizeof(subsys_id_to_phy_id)/sizeof(subsys_id_to_phy_id[0]); i++) {
- if ((subsys_id_to_phy_id[i].subsys_vendor == tp->subsystem_vendor) &&
- (subsys_id_to_phy_id[i].subsys_devid == tp->subsystem_device)) {
- tp->phy_id = subsys_id_to_phy_id[i].phy_id;
- break;
- }
- }
-
- eeprom_phy_id = PHY_ID_INVALID;
- eeprom_led_mode = led_mode_auto;
- eeprom_signature_found = 0;
- tg3_read_mem(NIC_SRAM_DATA_SIG, &val);
- if (val == NIC_SRAM_DATA_SIG_MAGIC) {
- uint32_t nic_cfg;
-
- tg3_read_mem(NIC_SRAM_DATA_CFG, &nic_cfg);
- tp->nic_sram_data_cfg = nic_cfg;
-
- eeprom_signature_found = 1;
-
- if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
- NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
- eeprom_phy_id = PHY_ID_SERDES;
- } else {
- uint32_t nic_phy_id;
-
- tg3_read_mem(NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
- if (nic_phy_id != 0) {
- uint32_t id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
- uint32_t id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
-
- eeprom_phy_id = (id1 >> 16) << 10;
- eeprom_phy_id |= (id2 & 0xfc00) << 16;
- eeprom_phy_id |= (id2 & 0x03ff) << 0;
- }
- }
-
- switch (nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK) {
- case NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD:
- eeprom_led_mode = led_mode_three_link;
- break;
-
- case NIC_SRAM_DATA_CFG_LED_LINK_SPD:
- eeprom_led_mode = led_mode_link10;
- break;
-
- default:
- eeprom_led_mode = led_mode_auto;
- break;
- };
- if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) &&
- (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) {
- tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
- }
-
- if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE)
- tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
- if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
- tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
- }
-
- /* Now read the physical PHY_ID from the chip and verify
- * that it is sane. If it doesn't look good, we fall back
- * to either the hard-coded table based PHY_ID and failing
- * that the value found in the eeprom area.
- */
- err = tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
- err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
-
- hw_phy_id = (hw_phy_id_1 & 0xffff) << 10;
- hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
- hw_phy_id |= (hw_phy_id_2 & 0x03ff) << 0;
-
- hw_phy_id_masked = hw_phy_id & PHY_ID_MASK;
-
- if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
- tp->phy_id = hw_phy_id;
- } else {
- /* phy_id currently holds the value found in the
- * subsys_id_to_phy_id[] table or PHY_ID_INVALID
- * if a match was not found there.
- */
- if (tp->phy_id == PHY_ID_INVALID) {
- if (!eeprom_signature_found ||
- !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
- return -ENODEV;
- tp->phy_id = eeprom_phy_id;
- }
- }
-
- err = tg3_phy_reset(tp);
- if (err)
- return err;
-
- if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
- uint32_t mii_tg3_ctrl;
-
- /* These chips, when reset, only advertise 10Mb
- * capabilities. Fix that.
- */
- err = tg3_writephy(tp, MII_ADVERTISE,
- (ADVERTISE_CSMA |
- ADVERTISE_PAUSE_CAP |
- ADVERTISE_10HALF |
- ADVERTISE_10FULL |
- ADVERTISE_100HALF |
- ADVERTISE_100FULL));
- mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
- MII_TG3_CTRL_ADV_1000_FULL |
- MII_TG3_CTRL_AS_MASTER |
- MII_TG3_CTRL_ENABLE_AS_MASTER);
- if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
- mii_tg3_ctrl = 0;
-
- err |= tg3_writephy(tp, MII_TG3_CTRL, mii_tg3_ctrl);
- err |= tg3_writephy(tp, MII_BMCR,
- (BMCR_ANRESTART | BMCR_ANENABLE));
- }
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
- tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
- tg3_writedsp(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
- }
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
- tg3_writephy(tp, 0x1c, 0x8d68);
- tg3_writephy(tp, 0x1c, 0x8d68);
- }
-
- /* Enable Ethernet@WireSpeed */
- tg3_phy_set_wirespeed(tp);
-
- if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) {
- err = tg3_init_5401phy_dsp(tp);
- }
-
- /* Determine the PHY led mode.
- * Be careful if this gets set wrong it can result in an inability to
- * establish a link.
- */
- if (tp->phy_id == PHY_ID_SERDES) {
- tp->led_mode = led_mode_three_link;
- }
- else if (tp->subsystem_vendor == PCI_VENDOR_ID_DELL) {
- tp->led_mode = led_mode_link10;
- } else {
- tp->led_mode = led_mode_three_link;
- if (eeprom_signature_found &&
- eeprom_led_mode != led_mode_auto)
- tp->led_mode = eeprom_led_mode;
- }
-
- if (tp->phy_id == PHY_ID_SERDES)
- tp->link_config.advertising =
- (ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full |
- ADVERTISED_Autoneg |
- ADVERTISED_FIBRE);
- if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
- tp->link_config.advertising &=
- ~(ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full);
-
- return err;
-}
-
-#if SUPPORT_PARTNO_STR
-static void tg3_read_partno(struct tg3 *tp)
-{
- unsigned char vpd_data[256];
- int i;
-
- for (i = 0; i < 256; i += 4) {
- uint32_t tmp;
-
- if (tg3_nvram_read(tp, 0x100 + i, &tmp))
- goto out_not_found;
-
- vpd_data[i + 0] = ((tmp >> 0) & 0xff);
- vpd_data[i + 1] = ((tmp >> 8) & 0xff);
- vpd_data[i + 2] = ((tmp >> 16) & 0xff);
- vpd_data[i + 3] = ((tmp >> 24) & 0xff);
- }
-
- /* Now parse and find the part number. */
- for (i = 0; i < 256; ) {
- unsigned char val = vpd_data[i];
- int block_end;
-
- if (val == 0x82 || val == 0x91) {
- i = (i + 3 +
- (vpd_data[i + 1] +
- (vpd_data[i + 2] << 8)));
- continue;
- }
-
- if (val != 0x90)
- goto out_not_found;
-
- block_end = (i + 3 +
- (vpd_data[i + 1] +
- (vpd_data[i + 2] << 8)));
- i += 3;
- while (i < block_end) {
- if (vpd_data[i + 0] == 'P' &&
- vpd_data[i + 1] == 'N') {
- int partno_len = vpd_data[i + 2];
-
- if (partno_len > 24)
- goto out_not_found;
-
- memcpy(tp->board_part_number,
- &vpd_data[i + 3],
- partno_len);
-
- /* Success. */
- return;
- }
- }
-
- /* Part number not found. */
- goto out_not_found;
- }
-
-out_not_found:
- memcpy(tp->board_part_number, "none", sizeof("none"));
-}
-#else
-#define tg3_read_partno(TP) ((TP)->board_part_number[0] = '\0')
-#endif
-
-static int tg3_get_invariants(struct tg3 *tp)
-{
- uint32_t misc_ctrl_reg;
- uint32_t pci_state_reg, grc_misc_cfg;
- uint16_t pci_cmd;
- uint8_t pci_latency;
- uint32_t val ;
- int err;
-
- /* Read the subsystem vendor and device ids */
- pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor);
- pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device);
-
- /* The sun_5704 code needs infrastructure etherboot does have
- * ignore it for now.
- */
-
- /* If we have an AMD 762 or Intel ICH/ICH0 chipset, write
- * reordering to the mailbox registers done by the host
- * controller can cause major troubles. We read back from
- * every mailbox register write to force the writes to be
- * posted to the chip in order.
- *
- * TG3_FLAG_MBOX_WRITE_REORDER has been forced on.
- */
-
- /* Force memory write invalidate off. If we leave it on,
- * then on 5700_BX chips we have to enable a workaround.
- * The workaround is to set the TG3PCI_DMA_RW_CTRL boundry
- * to match the cacheline size. The Broadcom driver have this
- * workaround but turns MWI off all the times so never uses
- * it. This seems to suggest that the workaround is insufficient.
- */
- pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
- pci_cmd &= ~PCI_COMMAND_INVALIDATE;
- /* Also, force SERR#/PERR# in PCI command. */
- pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
- pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
-
- /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
- * has the register indirect write enable bit set before
- * we try to access any of the MMIO registers. It is also
- * critical that the PCI-X hw workaround situation is decided
- * before that as well.
- */
- pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, &misc_ctrl_reg);
-
- tp->pci_chip_rev_id = (misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT);
-
- /* Initialize misc host control in PCI block. */
- tp->misc_host_ctrl |= (misc_ctrl_reg &
- MISC_HOST_CTRL_CHIPREV);
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
-
- pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 64) {
- pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, 64);
- }
-
- pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg);
-
- /* If this is a 5700 BX chipset, and we are in PCI-X
- * mode, enable register write workaround.
- *
- * The workaround is to use indirect register accesses
- * for all chip writes not to mailbox registers.
- *
- * In etherboot to simplify things we just always use this work around.
- */
- if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
- tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
- }
- /* Back to back register writes can cause problems on the 5701,
- * the workaround is to read back all reg writes except those to
- * mailbox regs.
- * In etherboot we always use indirect register accesses so
- * we don't see this.
- */
-
- if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
- tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
- if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
- tp->tg3_flags |= TG3_FLAG_PCI_32BIT;
-
- /* Chip-specific fixup from Broadcom driver */
- if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&
- (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) {
- pci_state_reg |= PCISTATE_RETRY_SAME_DMA;
- pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
- }
-
- /* determine if it is PCIE system */
- // Alf : I have no idea what this is about...
- // But it's definitely usefull
- val = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
- if (val)
- tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
-
- /* Force the chip into D0. */
- tg3_set_power_state_0(tp);
-
- /* Etherboot does not ask the tg3 to do checksums */
- /* Etherboot does not ask the tg3 to do jumbo frames */
- /* Ehterboot does not ask the tg3 to use WakeOnLan. */
-
- /* A few boards don't want Ethernet@WireSpeed phy feature */
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
- ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
- (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
- (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) {
- tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
- }
-
- /* Avoid tagged irq status etherboot does not use irqs */
-
- /* Only 5701 and later support tagged irq status mode.
- * Also, 5788 chips cannot use tagged irq status.
- *
- * However, since etherboot does not use irqs avoid tagged irqs
- * status because the interrupt condition is more difficult to
- * fully clear in that mode.
- */
-
- /* Since some 5700_AX && 5700_BX have problems with 32BYTE
- * coalesce_mode, and the rest work fine anything set.
- * Don't enable HOST_CC_MODE_32BYTE in etherboot.
- */
-
- /* Initialize MAC MI mode, polling disabled. */
- tw32_carefully(MAC_MI_MODE, tp->mi_mode);
-
- /* Initialize data/descriptor byte/word swapping. */
- tw32(GRC_MODE, tp->grc_mode);
-
- tg3_switch_clocks(tp);
-
- /* Clear this out for sanity. */
- tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-
- /* Etherboot does not need to check if the PCIX_TARGET_HWBUG
- * is needed. It always uses it.
- */
-
- udelay(50);
- tg3_nvram_init(tp);
-
- /* The TX descriptors will reside in main memory.
- */
-
- /* See which board we are using.
- */
- grc_misc_cfg = tr32(GRC_MISC_CFG);
- grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
- grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
- tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
- tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
- }
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
- (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
- grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
- tp->tg3_flags2 |= TG3_FLG2_IS_5788;
-
-#define PCI_DEVICE_ID_TIGON3_5901 0x170d
-#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
-
- /* these are limited to 10/100 only */
- if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) &&
- ((grc_misc_cfg == 0x8000) || (grc_misc_cfg == 0x4000))) ||
- ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
- (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM) &&
- ((tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901) ||
- (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2)))) {
- tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
- }
-
- err = tg3_phy_probe(tp);
- if (err) {
- printf("phy probe failed, err %d\n", err);
- }
-
- tg3_read_partno(tp);
-
-
- /* 5700 BX chips need to have their TX producer index mailboxes
- * written twice to workaround a bug.
- * In etherboot we do this unconditionally to simplify things.
- */
-
- /* 5700 chips can get confused if TX buffers straddle the
- * 4GB address boundary in some cases.
- *
- * In etherboot we can ignore the problem as etherboot lives below 4GB.
- */
-
- /* In etherboot wake-on-lan is unconditionally disabled */
- return err;
-}
-
-static int tg3_get_device_address(struct tg3 *tp)
-{
- struct nic *nic = tp->nic;
- uint32_t hi, lo, mac_offset;
-
- if (PCI_FUNC(tp->pdev->busdevfn) == 0)
- mac_offset = 0x7c;
- else
- mac_offset = 0xcc;
-
- /* First try to get it from MAC address mailbox. */
- tg3_read_mem(NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
- if ((hi >> 16) == 0x484b) {
- nic->node_addr[0] = (hi >> 8) & 0xff;
- nic->node_addr[1] = (hi >> 0) & 0xff;
-
- tg3_read_mem(NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo);
- nic->node_addr[2] = (lo >> 24) & 0xff;
- nic->node_addr[3] = (lo >> 16) & 0xff;
- nic->node_addr[4] = (lo >> 8) & 0xff;
- nic->node_addr[5] = (lo >> 0) & 0xff;
- }
- /* Next, try NVRAM. */
- else if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
- !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
- nic->node_addr[0] = ((hi >> 16) & 0xff);
- nic->node_addr[1] = ((hi >> 24) & 0xff);
- nic->node_addr[2] = ((lo >> 0) & 0xff);
- nic->node_addr[3] = ((lo >> 8) & 0xff);
- nic->node_addr[4] = ((lo >> 16) & 0xff);
- nic->node_addr[5] = ((lo >> 24) & 0xff);
- }
- /* Finally just fetch it out of the MAC control regs. */
- else {
- hi = tr32(MAC_ADDR_0_HIGH);
- lo = tr32(MAC_ADDR_0_LOW);
-
- nic->node_addr[5] = lo & 0xff;
- nic->node_addr[4] = (lo >> 8) & 0xff;
- nic->node_addr[3] = (lo >> 16) & 0xff;
- nic->node_addr[2] = (lo >> 24) & 0xff;
- nic->node_addr[1] = hi & 0xff;
- nic->node_addr[0] = (hi >> 8) & 0xff;
- }
-
- return 0;
-}
-
-
-static int tg3_setup_dma(struct tg3 *tp)
-{
- tw32(TG3PCI_CLOCK_CTRL, 0);
-
- if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) == 0) {
- tp->dma_rwctrl =
- (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
- (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
- (0x7 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
- (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
- (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
- tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA << DMA_RWCTRL_MIN_DMA_SHIFT);
- }
- } else {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
- tp->dma_rwctrl =
- (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
- (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
- (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
- (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
- (0x00 << DMA_RWCTRL_MIN_DMA_SHIFT);
- else
- tp->dma_rwctrl =
- (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
- (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
- (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
- (0x3 << DMA_RWCTRL_READ_WATER_SHIFT) |
- (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
-
- /* Wheee, some more chip bugs... */
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)) {
- uint32_t ccval = tr32(TG3PCI_CLOCK_CTRL) & 0x1f;
-
- if ((ccval == 0x6) || (ccval == 0x7)) {
- tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
- }
- }
- }
-
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)) {
- tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA << DMA_RWCTRL_MIN_DMA_SHIFT);
- }
-
- /*
- Alf : Tried that, but it does not work. Should be this way though :-(
- if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
- tp->dma_rwctrl |= 0x001f0000;
- }
- */
- tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
-
- tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
-
- return 0;
-}
-
-static void tg3_init_link_config(struct tg3 *tp)
-{
- tp->link_config.advertising =
- (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
- ADVERTISED_Autoneg | ADVERTISED_MII);
- tp->carrier_ok = 0;
- tp->link_config.active_speed = SPEED_INVALID;
- tp->link_config.active_duplex = DUPLEX_INVALID;
-}
-
-
-#if SUPPORT_PHY_STR
-static const char * tg3_phy_string(struct tg3 *tp)
-{
- switch (tp->phy_id & PHY_ID_MASK) {
- case PHY_ID_BCM5400: return "5400";
- case PHY_ID_BCM5401: return "5401";
- case PHY_ID_BCM5411: return "5411";
- case PHY_ID_BCM5701: return "5701";
- case PHY_ID_BCM5703: return "5703";
- case PHY_ID_BCM5704: return "5704";
- case PHY_ID_BCM5705: return "5705";
- case PHY_ID_BCM5750: return "5750";
- case PHY_ID_BCM5751: return "5751";
- case PHY_ID_BCM5787: return "5787";
- case PHY_ID_BCM8002: return "8002/serdes";
- case PHY_ID_SERDES: return "serdes";
- default: return "unknown";
- };
-}
-#else
-#define tg3_phy_string(TP) "?"
-#endif
-
-
-static void tg3_poll_link(struct tg3 *tp)
-{
- uint32_t mac_stat;
-
- mac_stat = tr32(MAC_STATUS);
- if (tp->phy_id == PHY_ID_SERDES) {
- if (tp->carrier_ok?
- (mac_stat & MAC_STATUS_LNKSTATE_CHANGED):
- (mac_stat & MAC_STATUS_PCS_SYNCED)) {
- tw32_carefully(MAC_MODE, tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK);
- tw32_carefully(MAC_MODE, tp->mac_mode);
-
- tg3_setup_phy(tp);
- }
- }
- else {
- if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED) {
- tg3_setup_phy(tp);
- }
- }
-}
-
-/**************************************************************************
-POLL - Wait for a frame
-***************************************************************************/
-static void tg3_ack_irqs(struct tg3 *tp)
-{
- if (tp->hw_status->status & SD_STATUS_UPDATED) {
- /*
- * writing any value to intr-mbox-0 clears PCI INTA# and
- * chip-internal interrupt pending events.
- * writing non-zero to intr-mbox-0 additional tells the
- * NIC to stop sending us irqs, engaging "in-intr-handler"
- * event coalescing.
- */
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000001);
- /*
- * Flush PCI write. This also guarantees that our
- * status block has been flushed to host memory.
- */
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
- tp->hw_status->status &= ~SD_STATUS_UPDATED;
- }
-}
-
-static int tg3_poll(struct nic *nic, int retrieve)
-{
- /* return true if there's an ethernet packet ready to read */
- /* nic->packet should contain data on return */
- /* nic->packetlen should contain length of data */
-
- struct tg3 *tp = &tg3;
- int result;
-
- result = 0;
-
- if ( (tp->hw_status->idx[0].rx_producer != tp->rx_rcb_ptr) && !retrieve )
- return 1;
-
- tg3_ack_irqs(tp);
-
- if (tp->hw_status->idx[0].rx_producer != tp->rx_rcb_ptr) {
- struct tg3_rx_buffer_desc *desc;
- unsigned int len;
- desc = &tp->rx_rcb[tp->rx_rcb_ptr];
- if ((desc->opaque & RXD_OPAQUE_RING_MASK) == RXD_OPAQUE_RING_STD) {
- len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
-
- nic->packetlen = len;
- memcpy(nic->packet, bus_to_virt(desc->addr_lo), len);
- result = 1;
- }
- tp->rx_rcb_ptr = (tp->rx_rcb_ptr + 1) % TG3_RX_RCB_RING_SIZE;
-
- /* ACK the status ring */
- tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, tp->rx_rcb_ptr);
-
- /* Refill RX ring. */
- if (result) {
- tp->rx_std_ptr = (tp->rx_std_ptr + 1) % TG3_RX_RING_SIZE;
- tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_std_ptr);
- }
- }
- tg3_poll_link(tp);
- return result;
-}
-
-/**************************************************************************
-TRANSMIT - Transmit a frame
-***************************************************************************/
-#if 0
-static void tg3_set_txd(struct tg3 *tp, int entry,
- dma_addr_t mapping, int len, uint32_t flags,
- uint32_t mss_and_is_end)
-{
- struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
- int is_end = (mss_and_is_end & 0x1);
- if (is_end) {
- flags |= TXD_FLAG_END;
- }
-
- txd->addr_hi = 0;
- txd->addr_lo = mapping & 0xffffffff;
- txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
- txd->vlan_tag = 0 << TXD_VLAN_TAG_SHIFT;
-}
-#endif
-
-static void tg3_transmit(struct nic *nic, const char *dst_addr,
- unsigned int type, unsigned int size, const char *packet)
-{
- static int frame_idx;
- struct eth_frame *frame;
-
- /* send the packet to destination */
- struct tg3_tx_buffer_desc *txd;
- struct tg3 *tp;
- uint32_t entry;
- int i;
-
- /* Wait until there is a free packet frame */
- tp = &tg3;
- i = 0;
- entry = tp->tx_prod;
- while((tp->hw_status->idx[0].tx_consumer != entry) &&
- (tp->hw_status->idx[0].tx_consumer != PREV_TX(entry))) {
- mdelay(10); /* give the nick a chance */
- if (++i > 500) { /* timeout 5s for transmit */
- printf("transmit timed out\n");
- tg3_halt(tp);
- tg3_setup_hw(tp);
- return;
- }
- }
- if (i != 0) {
- printf("#");
- }
-
- /* Copy the packet to the our local buffer */
- frame = &tg3_bss.tx_frame[frame_idx];
- memcpy(frame->dst_addr, dst_addr, ETH_ALEN);
- memcpy(frame->src_addr, nic->node_addr, ETH_ALEN);
- frame->type = htons(type);
- memset(frame->data, 0, sizeof(frame->data));
- memcpy(frame->data, packet, size);
-
- /* Setup the ring buffer entry to transmit */
- txd = &tp->tx_ring[entry];
- txd->addr_hi = 0; /* Etherboot runs under 4GB */
- txd->addr_lo = virt_to_bus(frame);
- txd->len_flags = ((size + ETH_HLEN) << TXD_LEN_SHIFT) | TXD_FLAG_END;
- txd->vlan_tag = 0 << TXD_VLAN_TAG_SHIFT;
-
- /* Advance to the next entry */
- entry = NEXT_TX(entry);
- frame_idx ^= 1;
-
- /* Packets are ready, update Tx producer idx local and on card */
- tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
- tw32_mailbox2((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
- tp->tx_prod = entry;
-}
-
-/**************************************************************************
-DISABLE - Turn off ethernet interface
-***************************************************************************/
-static void tg3_disable ( struct nic *nic __unused ) {
- struct tg3 *tp = &tg3;
- /* put the card in its initial state */
- /* This function serves 3 purposes.
- * This disables DMA and interrupts so we don't receive
- * unexpected packets or interrupts from the card after
- * etherboot has finished.
- * This frees resources so etherboot may use
- * this driver on another interface
- * This allows etherboot to reinitialize the interface
- * if something is something goes wrong.
- */
- tg3_halt(tp);
- tp->tg3_flags &= ~(TG3_FLAG_INIT_COMPLETE|TG3_FLAG_GOT_SERDES_FLOWCTL);
- tp->carrier_ok = 0;
- iounmap((void *)tp->regs);
-}
-
-/**************************************************************************
-IRQ - Enable, Disable, or Force interrupts
-***************************************************************************/
-static void tg3_irq(struct nic *nic __unused, irq_action_t action __unused)
-{
- switch ( action ) {
- case DISABLE :
- break;
- case ENABLE :
- break;
- case FORCE :
- break;
- }
-}
-
-static struct nic_operations tg3_operations = {
- .connect = dummy_connect,
- .poll = tg3_poll,
- .transmit = tg3_transmit,
- .irq = tg3_irq,
-
-};
-
-/**************************************************************************
-PROBE - Look for an adapter, this routine's visible to the outside
-You should omit the last argument struct pci_device * for a non-PCI NIC
-***************************************************************************/
-static int tg3_probe ( struct nic *nic, struct pci_device *pdev ) {
-
- struct tg3 *tp = &tg3;
- unsigned long tg3reg_base, tg3reg_len;
- int i, err, pm_cap;
-
- memset(tp, 0, sizeof(*tp));
-
- adjust_pci_device(pdev);
-
- nic->irqno = 0;
- nic->ioaddr = pdev->ioaddr;
-
- /* Find power-management capability. */
- pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pm_cap == 0) {
- printf("Cannot find PowerManagement capability, aborting.\n");
- return 0;
- }
- tg3reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
- if (tg3reg_base == -1UL) {
- printf("Unuseable bar\n");
- return 0;
- }
- tg3reg_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
-
- tp->pdev = pdev;
- tp->nic = nic;
- tp->pm_cap = pm_cap;
- tp->rx_mode = 0;
- tp->tx_mode = 0;
- tp->mi_mode = MAC_MI_MODE_BASE;
- tp->tg3_flags = 0 & ~TG3_FLAG_INIT_COMPLETE;
-
- /* The word/byte swap controls here control register access byte
- * swapping. DMA data byte swapping is controlled in the GRC_MODE
- * setting below.
- */
- tp->misc_host_ctrl =
- MISC_HOST_CTRL_MASK_PCI_INT |
- MISC_HOST_CTRL_WORD_SWAP |
- MISC_HOST_CTRL_INDIR_ACCESS |
- MISC_HOST_CTRL_PCISTATE_RW;
-
- /* The NONFRM (non-frame) byte/word swap controls take effect
- * on descriptor entries, anything which isn't packet data.
- *
- * The StrongARM chips on the board (one for tx, one for rx)
- * are running in big-endian mode.
- */
- tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA |
- GRC_MODE_WSWAP_NONFRM_DATA);
-#if __BYTE_ORDER == __BIG_ENDIAN
- tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
-#endif
- tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
- if (tp->regs == 0UL) {
- printf("Cannot map device registers, aborting\n");
- return 0;
- }
-
- tg3_init_link_config(tp);
-
- err = tg3_get_invariants(tp);
- if (err) {
- printf("Problem fetching invariants of chip, aborting.\n");
- goto err_out_iounmap;
- }
-
- err = tg3_get_device_address(tp);
- if (err) {
- printf("Could not obtain valid ethernet address, aborting.\n");
- goto err_out_iounmap;
- }
-
- DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
-
- tg3_setup_dma(tp);
-
- /* Now that we have fully setup the chip, save away a snapshot
- * of the PCI config space. We need to restore this after
- * GRC_MISC_CFG core clock resets and some resume events.
- */
- pci_save_state(tp->pdev, tp->pci_cfg_state);
-
- printf("Tigon3 [partno(%s) rev %hx PHY(%s)] (PCI%s:%s:%s)\n",
- tp->board_part_number,
- tp->pci_chip_rev_id,
- tg3_phy_string(tp),
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
- ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
- ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"));
-
-
- err = tg3_setup_hw(tp);
- if (err) {
- goto err_out_disable;
- }
- tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-
- /* Wait for a reasonable time for the link to come up */
- tg3_poll_link(tp);
- for(i = 0; !tp->carrier_ok && (i < VALID_LINK_TIMEOUT*100); i++) {
- mdelay(1);
- tg3_poll_link(tp);
- }
- if (!tp->carrier_ok){
- printf("Valid link not established\n");
- goto err_out_disable;
- }
-
- nic->nic_op = &tg3_operations;
- return 1;
-
- err_out_iounmap:
- iounmap((void *)tp->regs);
- return 0;
- err_out_disable:
- tg3_disable(nic);
- return 0;
-}
-
-
-static struct pci_device_id tg3_nics[] = {
-PCI_ROM(0x14e4, 0x1644, "tg3-5700", "Broadcom Tigon 3 5700", 0),
-PCI_ROM(0x14e4, 0x1645, "tg3-5701", "Broadcom Tigon 3 5701", 0),
-PCI_ROM(0x14e4, 0x1646, "tg3-5702", "Broadcom Tigon 3 5702", 0),
-PCI_ROM(0x14e4, 0x1647, "tg3-5703", "Broadcom Tigon 3 5703", 0),
-PCI_ROM(0x14e4, 0x1648, "tg3-5704", "Broadcom Tigon 3 5704", 0),
-PCI_ROM(0x14e4, 0x164d, "tg3-5702FE", "Broadcom Tigon 3 5702FE", 0),
-PCI_ROM(0x14e4, 0x1653, "tg3-5705", "Broadcom Tigon 3 5705", 0),
-PCI_ROM(0x14e4, 0x1654, "tg3-5705_2", "Broadcom Tigon 3 5705_2", 0),
-PCI_ROM(0x14e4, 0x1659, "tg3-5721", "Broadcom Tigon 3 5721", 0),
-PCI_ROM(0x14e4, 0x165d, "tg3-5705M", "Broadcom Tigon 3 5705M", 0),
-PCI_ROM(0x14e4, 0x165e, "tg3-5705M_2", "Broadcom Tigon 3 5705M_2", 0),
-PCI_ROM(0x14e4, 0x1677, "tg3-5751", "Broadcom Tigon 3 5751", 0),
-PCI_ROM(0x14e4, 0x167a, "tg3-5754", "Broadcom Tigon 3 5754", 0),
-PCI_ROM(0x14e4, 0x1693, "tg3-5787", "Broadcom Tigon 3 5787", 0),
-PCI_ROM(0x14e4, 0x1696, "tg3-5782", "Broadcom Tigon 3 5782", 0),
-PCI_ROM(0x14e4, 0x169a, "tg3-5786", "Broadcom Tigon 3 5786", 0),
-PCI_ROM(0x14e4, 0x169c, "tg3-5788", "Broadcom Tigon 3 5788", 0),
-PCI_ROM(0x14e4, 0x169d, "tg3-5789", "Broadcom Tigon 3 5789", 0),
-PCI_ROM(0x14e4, 0x16a6, "tg3-5702X", "Broadcom Tigon 3 5702X", 0),
-PCI_ROM(0x14e4, 0x16a7, "tg3-5703X", "Broadcom Tigon 3 5703X", 0),
-PCI_ROM(0x14e4, 0x16a8, "tg3-5704S", "Broadcom Tigon 3 5704S", 0),
-PCI_ROM(0x14e4, 0x16c6, "tg3-5702A3", "Broadcom Tigon 3 5702A3", 0),
-PCI_ROM(0x14e4, 0x16c7, "tg3-5703A3", "Broadcom Tigon 3 5703A3", 0),
-PCI_ROM(0x14e4, 0x170d, "tg3-5901", "Broadcom Tigon 3 5901", 0),
-PCI_ROM(0x14e4, 0x170e, "tg3-5901_2", "Broadcom Tigon 3 5901_2", 0),
-PCI_ROM(0x1148, 0x4400, "tg3-9DXX", "Syskonnect 9DXX", 0),
-PCI_ROM(0x1148, 0x4500, "tg3-9MXX", "Syskonnect 9MXX", 0),
-PCI_ROM(0x173b, 0x03e8, "tg3-ac1000", "Altima AC1000", 0),
-PCI_ROM(0x173b, 0x03e9, "tg3-ac1001", "Altima AC1001", 0),
-PCI_ROM(0x173b, 0x03ea, "tg3-ac9100", "Altima AC9100", 0),
-PCI_ROM(0x173b, 0x03eb, "tg3-ac1003", "Altima AC1003", 0),
-PCI_ROM(0x0e11, 0x00ca, "tg3-hp", "HP Tigon 3", 0),
-};
-
-PCI_DRIVER ( tg3_driver, tg3_nics, PCI_NO_CLASS );
-
-DRIVER ( "TG3", nic_driver, pci_driver, tg3_driver,
- tg3_probe, tg3_disable );
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * c-indent-level: 8
- * tab-width: 8
- * End:
- */
diff --git a/src/drivers/net/tg3/tg3.c b/src/drivers/net/tg3/tg3.c
new file mode 100644
index 00000000..9d6b26d5
--- /dev/null
+++ b/src/drivers/net/tg3/tg3.c
@@ -0,0 +1,942 @@
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+
+#include "tg3.h"
+
+#define TG3_DEF_RX_MODE 0
+#define TG3_DEF_TX_MODE 0
+
+static void tg3_refill_prod_ring(struct tg3 *tp);
+
+/* Do not place this n-ring entries value into the tp struct itself,
+ * we really want to expose these constants to GCC so that modulo et
+ * al. operations are done with shifts and masks instead of with
+ * hw multiply/modulo instructions. Another solution would be to
+ * replace things like '% foo' with '& (foo - 1)'.
+ */
+
+#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \
+ TG3_TX_RING_SIZE)
+
+/* FIXME: does TG3_RX_RET_MAX_SIZE_5705 work for all cards? */
+#define TG3_RX_RCB_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * (TG3_RX_RET_MAX_SIZE_5705))
+
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr)
+{ DBGP("%s\n", __func__);
+
+ if (tpr->rx_std) {
+ free_dma(tpr->rx_std, TG3_RX_STD_RING_BYTES(tp));
+ tpr->rx_std = NULL;
+ }
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down.
+ */
+static void tg3_free_consistent(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tp->tx_ring) {
+ free_dma(tp->tx_ring, TG3_TX_RING_BYTES);
+ tp->tx_ring = NULL;
+ }
+
+ free(tp->tx_buffers);
+ tp->tx_buffers = NULL;
+
+ if (tp->rx_rcb) {
+ free_dma(tp->rx_rcb, TG3_RX_RCB_RING_BYTES(tp));
+ tp->rx_rcb_mapping = 0;
+ tp->rx_rcb = NULL;
+ }
+
+ tg3_rx_prodring_fini(&tp->prodring);
+
+ if (tp->hw_status) {
+ free_dma(tp->hw_status, TG3_HW_STATUS_SIZE);
+ tp->status_mapping = 0;
+ tp->hw_status = NULL;
+ }
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down. Can sleep.
+ */
+int tg3_alloc_consistent(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_hw_status *sblk;
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+ tp->hw_status = malloc_dma(TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT);
+ if (!tp->hw_status) {
+ DBGC(tp->dev, "hw_status alloc failed\n");
+ goto err_out;
+ }
+ tp->status_mapping = virt_to_bus(tp->hw_status);
+
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+ sblk = tp->hw_status;
+
+ tpr->rx_std = malloc_dma(TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+ if (!tpr->rx_std) {
+ DBGC(tp->dev, "rx prodring alloc failed\n");
+ goto err_out;
+ }
+ tpr->rx_std_mapping = virt_to_bus(tpr->rx_std);
+ memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
+
+ tp->tx_buffers = zalloc(sizeof(struct ring_info) * TG3_TX_RING_SIZE);
+ if (!tp->tx_buffers)
+ goto err_out;
+
+ tp->tx_ring = malloc_dma(TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT);
+ if (!tp->tx_ring)
+ goto err_out;
+ tp->tx_desc_mapping = virt_to_bus(tp->tx_ring);
+
+ /*
+ * When RSS is enabled, the status block format changes
+ * slightly. The "rx_jumbo_consumer", "reserved",
+ * and "rx_mini_consumer" members get mapped to the
+ * other three rx return ring producer indexes.
+ */
+
+ tp->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
+
+ tp->rx_rcb = malloc_dma(TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+ if (!tp->rx_rcb)
+ goto err_out;
+ tp->rx_rcb_mapping = virt_to_bus(tp->rx_rcb);
+
+ memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+ return 0;
+
+err_out:
+ tg3_free_consistent(tp);
+ return -ENOMEM;
+}
+
+#define TG3_RX_STD_BUFF_RING_BYTES(tp) \
+ (sizeof(struct ring_info) * TG3_RX_STD_MAX_SIZE_5700)
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+/* Initialize rx rings for packet processing.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.
+ */
+static int tg3_rx_prodring_alloc(struct tg3 __unused *tp,
+ struct tg3_rx_prodring_set *tpr)
+{ DBGP("%s\n", __func__);
+
+ u32 i;
+
+ tpr->rx_std_cons_idx = 0;
+ tpr->rx_std_prod_idx = 0;
+
+ /* Initialize invariants of the rings, we only set this
+ * stuff once. This works because the card does not
+ * write into the rx buffer posting rings.
+ */
+ /* FIXME: does TG3_RX_STD_MAX_SIZE_5700 work on all cards? */
+ for (i = 0; i < TG3_RX_STD_MAX_SIZE_5700; i++) {
+ struct tg3_rx_buffer_desc *rxd;
+
+ rxd = &tpr->rx_std[i];
+ rxd->idx_len = (TG3_RX_STD_DMA_SZ - 64 - 2) << RXD_LEN_SHIFT;
+ rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
+ rxd->opaque = (RXD_OPAQUE_RING_STD |
+ (i << RXD_OPAQUE_INDEX_SHIFT));
+ }
+
+ return 0;
+}
+
+static void tg3_rx_iob_free(struct io_buffer *iobs[], int i)
+{ DBGP("%s\n", __func__);
+
+ if (iobs[i] == NULL)
+ return;
+
+ free_iob(iobs[i]);
+ iobs[i] = NULL;
+}
+
+static void tg3_rx_prodring_free(struct tg3_rx_prodring_set *tpr)
+{ DBGP("%s\n", __func__);
+
+ unsigned int i;
+
+ for (i = 0; i < TG3_DEF_RX_RING_PENDING; i++)
+ tg3_rx_iob_free(tpr->rx_iobufs, i);
+}
+
+/* Initialize tx/rx rings for packet processing.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.
+ */
+int tg3_init_rings(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ /* Free up all the SKBs. */
+/// tg3_free_rings(tp);
+
+ tp->last_tag = 0;
+ tp->last_irq_tag = 0;
+ tp->hw_status->status = 0;
+ tp->hw_status->status_tag = 0;
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+ tp->tx_prod = 0;
+ tp->tx_cons = 0;
+ if (tp->tx_ring)
+ memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
+
+ tp->rx_rcb_ptr = 0;
+ if (tp->rx_rcb)
+ memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+ if (tg3_rx_prodring_alloc(tp, &tp->prodring)) {
+ DBGC(tp->dev, "tg3_rx_prodring_alloc() failed\n");
+ tg3_rx_prodring_free(&tp->prodring);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int tg3_open(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+ int err = 0;
+
+ tg3_set_power_state_0(tp);
+
+ /* Initialize MAC address and backoff seed. */
+ __tg3_set_mac_addr(tp, 0);
+
+ err = tg3_alloc_consistent(tp);
+ if (err)
+ return err;
+
+ tpr->rx_std_iob_cnt = 0;
+ tg3_refill_prod_ring(tp);
+
+ err = tg3_init_hw(tp, 1);
+ if (err != 0)
+ DBGC(tp->dev, "tg3_init_hw failed: %s\n", strerror(err));
+
+ return err;
+}
+
+static inline u32 tg3_tx_avail(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ /* Tell compiler to fetch tx indices from memory. */
+ barrier();
+ return TG3_DEF_TX_RING_PENDING -
+ ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1));
+}
+
+#if 0
+/**
+ *
+ * Prints all registers that could cause a set ERR bit in hw_status->status
+ */
+static void tg3_dump_err_reg(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ printf("FLOW_ATTN: %#08x\n", tr32(HOSTCC_FLOW_ATTN));
+ printf("MAC ATTN: %#08x\n", tr32(MAC_STATUS));
+ printf("MSI STATUS: %#08x\n", tr32(MSGINT_STATUS));
+ printf("DMA RD: %#08x\n", tr32(RDMAC_STATUS));
+ printf("DMA WR: %#08x\n", tr32(WDMAC_STATUS));
+ printf("TX CPU STATE: %#08x\n", tr32(TX_CPU_STATE));
+ printf("RX CPU STATE: %#08x\n", tr32(RX_CPU_STATE));
+}
+
+static void __unused tw32_mailbox2(struct tg3 *tp, uint32_t reg, uint32_t val)
+{ DBGP("%s\n", __func__);
+
+ tw32_mailbox(reg, val);
+ tr32(reg);
+}
+#endif
+
+#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
+
+/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
+ * support TG3_FLAG_HW_TSO_1 or firmware TSO only.
+ */
+static int tg3_transmit(struct net_device *dev, struct io_buffer *iob)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ u32 len, entry;
+ dma_addr_t mapping;
+ u32 bmsr;
+
+ if (tg3_tx_avail(tp) < 1) {
+ DBGC(dev, "Transmit ring full\n");
+ return -ENOBUFS;
+ }
+
+ entry = tp->tx_prod;
+
+ iob_pad(iob, ETH_ZLEN);
+ mapping = virt_to_bus(iob->data);
+ len = iob_len(iob);
+
+ tp->tx_buffers[entry].iob = iob;
+
+ tg3_set_txd(tp, entry, mapping, len, TXD_FLAG_END);
+
+ entry = NEXT_TX(entry);
+
+ /* Packets are ready, update Tx producer idx local and on card. */
+ tw32_tx_mbox(tp->prodmbox, entry);
+
+ writel(entry, tp->regs + MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+
+ tp->tx_prod = entry;
+
+ mb();
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+
+ return 0;
+}
+
+static void tg3_tx_complete(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
+ u32 sw_idx = tp->tx_cons;
+
+ while (sw_idx != hw_idx) {
+ struct io_buffer *iob = tp->tx_buffers[sw_idx].iob;
+
+ DBGC2(dev, "Transmitted packet: %zd bytes\n", iob_len(iob));
+
+ netdev_tx_complete(dev, iob);
+ sw_idx = NEXT_TX(sw_idx);
+ }
+
+ tp->tx_cons = sw_idx;
+}
+
+#define TG3_RX_STD_BUFF_RING_BYTES(tp) \
+ (sizeof(struct ring_info) * TG3_RX_STD_MAX_SIZE_5700)
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
+
+/* Returns 0 or < 0 on error.
+ *
+ * We only need to fill in the address because the other members
+ * of the RX descriptor are invariant, see tg3_init_rings.
+ *
+ * Note the purposeful assymetry of cpu vs. chip accesses. For
+ * posting buffers we only dirty the first cache line of the RX
+ * descriptor (containing the address). Whereas for the RX status
+ * buffers the cpu only reads the last cacheline of the RX descriptor
+ * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
+ */
+static int tg3_alloc_rx_iob(struct tg3_rx_prodring_set *tpr, u32 dest_idx_unmasked)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_rx_buffer_desc *desc;
+ struct io_buffer *iob;
+ dma_addr_t mapping;
+ int dest_idx, iob_idx;
+
+ dest_idx = dest_idx_unmasked & (TG3_RX_STD_MAX_SIZE_5700 - 1);
+ desc = &tpr->rx_std[dest_idx];
+
+ /* Do not overwrite any of the map or rp information
+ * until we are sure we can commit to a new buffer.
+ *
+ * Callers depend upon this behavior and assume that
+ * we leave everything unchanged if we fail.
+ */
+ iob = alloc_iob(TG3_RX_STD_DMA_SZ);
+ if (iob == NULL)
+ return -ENOMEM;
+
+ iob_idx = dest_idx % TG3_DEF_RX_RING_PENDING;
+ tpr->rx_iobufs[iob_idx] = iob;
+
+ mapping = virt_to_bus(iob->data);
+
+ desc->addr_hi = ((u64)mapping >> 32);
+ desc->addr_lo = ((u64)mapping & 0xffffffff);
+
+ return 0;
+}
+
+static void tg3_refill_prod_ring(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+ int idx = tpr->rx_std_prod_idx;
+
+ DBGCP(tp->dev, "%s\n", __func__);
+
+ while (tpr->rx_std_iob_cnt < TG3_DEF_RX_RING_PENDING) {
+ if (tpr->rx_iobufs[idx % TG3_DEF_RX_RING_PENDING] == NULL) {
+ if (tg3_alloc_rx_iob(tpr, idx) < 0) {
+ DBGC(tp->dev, "alloc_iob() failed for descriptor %d\n", idx);
+ break;
+ }
+ DBGC2(tp->dev, "allocated iob_buffer for descriptor %d\n", idx);
+ }
+
+ idx = (idx + 1) % TG3_RX_STD_MAX_SIZE_5700;
+ tpr->rx_std_iob_cnt++;
+ }
+
+ tpr->rx_std_prod_idx = idx;
+ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+}
+
+static void tg3_rx_complete(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ u32 sw_idx = tp->rx_rcb_ptr;
+ u16 hw_idx;
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+ hw_idx = *(tp->rx_rcb_prod_idx);
+
+ while (sw_idx != hw_idx) {
+ struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx];
+ u32 desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
+ int iob_idx = desc_idx % TG3_DEF_RX_RING_PENDING;
+ struct io_buffer *iob = tpr->rx_iobufs[iob_idx];
+ unsigned int len;
+
+ DBGC2(dev, "RX - desc_idx: %d sw_idx: %d hw_idx: %d\n", desc_idx, sw_idx, hw_idx);
+
+ assert(iob != NULL);
+
+ if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
+ (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
+ /* drop packet */
+ DBGC(dev, "Corrupted packet received\n");
+ netdev_rx_err(dev, iob, -EINVAL);
+ } else {
+ len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
+ ETH_FCS_LEN;
+ iob_put(iob, len);
+ netdev_rx(dev, iob);
+
+ DBGC2(dev, "Received packet: %d bytes %d %d\n", len, sw_idx, hw_idx);
+ }
+
+ sw_idx++;
+ sw_idx &= TG3_RX_RET_MAX_SIZE_5705 - 1;
+
+ tpr->rx_iobufs[iob_idx] = NULL;
+ tpr->rx_std_iob_cnt--;
+ }
+
+ tp->rx_rcb_ptr = sw_idx;
+
+ tg3_refill_prod_ring(tp);
+}
+
+static void tg3_poll(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ /* ACK interrupts */
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00);
+ tp->hw_status->status &= ~SD_STATUS_UPDATED;
+
+ tg3_poll_link(tp);
+ tg3_tx_complete(dev);
+ tg3_rx_complete(dev);
+}
+
+static void tg3_close(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ DBGP("%s\n", __func__);
+
+ tg3_halt(tp);
+ tg3_rx_prodring_free(&tp->prodring);
+ tg3_flag_clear(tp, INIT_COMPLETE);
+
+ tg3_free_consistent(tp);
+
+}
+
+static void tg3_irq(struct net_device *dev, int enable)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+
+ DBGP("%s: %d\n", __func__, enable);
+
+ if (enable)
+ tg3_enable_ints(tp);
+ else
+ tg3_disable_ints(tp);
+}
+
+static struct net_device_operations tg3_netdev_ops = {
+ .open = tg3_open,
+ .close = tg3_close,
+ .poll = tg3_poll,
+ .transmit = tg3_transmit,
+ .irq = tg3_irq,
+};
+
+#define TEST_BUFFER_SIZE 0x2000
+
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device);
+void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val);
+
+static int tg3_test_dma(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ dma_addr_t buf_dma;
+ u32 *buf, saved_dma_rwctrl;
+ int ret = 0;
+
+ buf = malloc_dma(TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out_nofree;
+ }
+ buf_dma = virt_to_bus(buf);
+ DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#08x\n", buf, buf_dma);
+
+ tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
+ (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
+
+ tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
+
+ if (tg3_flag(tp, 57765_PLUS))
+ goto out;
+
+ if (tg3_flag(tp, PCI_EXPRESS)) {
+ /* DMA read watermark not used on PCIE */
+ tp->dma_rwctrl |= 0x00180000;
+ } else if (!tg3_flag(tp, PCIX_MODE)) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+ tp->dma_rwctrl |= 0x003f0000;
+ else
+ tp->dma_rwctrl |= 0x003f000f;
+ } else {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
+ u32 read_water = 0x7;
+
+ if (ccval == 0x6 || ccval == 0x7)
+ tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
+ read_water = 4;
+ /* Set bit 23 to enable PCIX hw bug fix */
+ tp->dma_rwctrl |=
+ (read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
+ (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+ (1 << 23);
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+ /* 5780 always in PCIX mode */
+ tp->dma_rwctrl |= 0x00144000;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ /* 5714 always in PCIX mode */
+ tp->dma_rwctrl |= 0x00148000;
+ } else {
+ tp->dma_rwctrl |= 0x001b000f;
+ }
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tp->dma_rwctrl &= 0xfffffff0;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ /* Remove this if it causes problems for some boards. */
+ tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT;
+
+ /* On 5700/5701 chips, we need to set this bit.
+ * Otherwise the chip will issue cacheline transactions
+ * to streamable DMA memory with not all the byte
+ * enables turned on. This is an error on several
+ * RISC PCI controllers, in particular sparc64.
+ *
+ * On 5703/5704 chips, this bit has been reassigned
+ * a different meaning. In particular, it is used
+ * on those chips to enable a PCI-X workaround.
+ */
+ tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
+ }
+
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+#if 0
+ /* Unneeded, already done by tg3_get_invariants. */
+ tg3_switch_clocks(tp);
+#endif
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
+ goto out;
+
+ /* It is best to perform DMA test with maximum write burst size
+ * to expose the 5700/5701 write DMA bug.
+ */
+ saved_dma_rwctrl = tp->dma_rwctrl;
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+ while (1) {
+ u32 *p = buf, i;
+
+ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++)
+ p[i] = i;
+
+ /* Send the buffer to the chip. */
+ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1);
+ if (ret) {
+ DBGC(&tp->pdev->dev,
+ "%s: Buffer write failed. err = %d\n",
+ __func__, ret);
+ break;
+ }
+
+ /* validate data reached card RAM correctly. */
+ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+ u32 val;
+ tg3_read_mem(tp, 0x2100 + (i*4), &val);
+ if (le32_to_cpu(val) != p[i]) {
+ DBGC(&tp->pdev->dev,
+ "%s: Buffer corrupted on device! "
+ "(%d != %d)\n", __func__, val, i);
+ /* ret = -ENODEV here? */
+ }
+ p[i] = 0;
+ }
+
+ /* Now read it back. */
+ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
+ if (ret) {
+ DBGC(&tp->pdev->dev, "%s: Buffer read failed. "
+ "err = %d\n", __func__, ret);
+ break;
+ }
+
+ /* Verify it. */
+ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+ if (p[i] == i)
+ continue;
+
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ break;
+ } else {
+ DBGC(&tp->pdev->dev,
+ "%s: Buffer corrupted on read back! "
+ "(%d != %d)\n", __func__, p[i], i);
+ ret = -ENODEV;
+ goto out;
+ }
+ }
+
+ if (i == (TEST_BUFFER_SIZE / sizeof(u32))) {
+ /* Success. */
+ ret = 0;
+ break;
+ }
+ }
+
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ /* DMA test passed without adjusting DMA boundary,
+ * now look for chipsets that are known to expose the
+ * DMA bug without failing the test.
+ */
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
+
+out:
+ free_dma(buf, TEST_BUFFER_SIZE);
+out_nofree:
+ return ret;
+}
+
+static int tg3_init_one(struct pci_device *pdev)
+{ DBGP("%s\n", __func__);
+
+ struct net_device *dev;
+ struct tg3 *tp;
+ int err = 0;
+ unsigned long reg_base, reg_size;
+
+ adjust_pci_device(pdev);
+
+ dev = alloc_etherdev(sizeof(*tp));
+ if (!dev) {
+ DBGC(&pdev->dev, "Failed to allocate etherdev\n");
+ err = -ENOMEM;
+ goto err_out_disable_pdev;
+ }
+
+ netdev_init(dev, &tg3_netdev_ops);
+ pci_set_drvdata(pdev, dev);
+
+ dev->dev = &pdev->dev;
+
+ tp = netdev_priv(dev);
+ tp->pdev = pdev;
+ tp->dev = dev;
+ tp->rx_mode = TG3_DEF_RX_MODE;
+ tp->tx_mode = TG3_DEF_TX_MODE;
+
+ /* Subsystem IDs are required later */
+ pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor);
+ pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device);
+
+ /* The word/byte swap controls here control register access byte
+ * swapping. DMA data byte swapping is controlled in the GRC_MODE
+ * setting below.
+ */
+ tp->misc_host_ctrl =
+ MISC_HOST_CTRL_MASK_PCI_INT |
+ MISC_HOST_CTRL_WORD_SWAP |
+ MISC_HOST_CTRL_INDIR_ACCESS |
+ MISC_HOST_CTRL_PCISTATE_RW;
+
+ /* The NONFRM (non-frame) byte/word swap controls take effect
+ * on descriptor entries, anything which isn't packet data.
+ *
+ * The StrongARM chips on the board (one for tx, one for rx)
+ * are running in big-endian mode.
+ */
+ tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA |
+ GRC_MODE_WSWAP_NONFRM_DATA);
+#if __BYTE_ORDER == __BIG_ENDIAN
+ tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
+#endif
+
+ /* FIXME: how can we detect errors here? */
+ reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ reg_size = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+
+ tp->regs = ioremap(reg_base, reg_size);
+ if (!tp->regs) {
+ DBGC(&pdev->dev, "Failed to remap device registers\n");
+ errno = -ENOENT;
+ goto err_out_disable_pdev;
+ }
+
+ err = tg3_get_invariants(tp);
+ if (err) {
+ DBGC(&pdev->dev, "Problem fetching invariants of chip, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ tg3_init_bufmgr_config(tp);
+
+ err = tg3_get_device_address(tp);
+ if (err) {
+ DBGC(&pdev->dev, "Could not obtain valid ethernet address, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ /*
+ * Reset chip in case UNDI or EFI driver did not shutdown
+ * DMA self test will enable WDMAC and we'll see (spurious)
+ * pending DMA on the PCI bus at that point.
+ */
+ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+ (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+ tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+ tg3_halt(tp);
+ }
+
+ err = tg3_test_dma(tp);
+ if (err) {
+ DBGC(&pdev->dev, "DMA engine test failed, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ tp->int_mbox = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+ tp->consmbox = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
+ tp->prodmbox = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+
+ tp->coal_now = HOSTCC_MODE_NOW;
+
+ err = register_netdev(dev);
+ if (err) {
+ DBGC(&pdev->dev, "Cannot register net device, aborting\n");
+ goto err_out_iounmap;
+ }
+
+ /* Call tg3_setup_phy() to start autoneg process, which saves time
+ * over starting autoneg in tg3_open();
+ */
+ err = tg3_setup_phy(tp, 0);
+ if (err) {
+ DBGC(tp->dev, "tg3_setup_phy() call failed in %s\n", __func__);
+ goto err_out_iounmap;
+ }
+
+ return 0;
+
+err_out_iounmap:
+ if (tp->regs) {
+ iounmap(tp->regs);
+ tp->regs = NULL;
+ }
+
+ netdev_put(dev);
+
+err_out_disable_pdev:
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void tg3_remove_one(struct pci_device *pci)
+{ DBGP("%s\n", __func__);
+
+ struct net_device *netdev = pci_get_drvdata(pci);
+
+ unregister_netdev(netdev);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+static struct pci_device_id tg3_nics[] = {
+ PCI_ROM(0x14e4, 0x1644, "14e4-1644", "14e4-1644", 0),
+ PCI_ROM(0x14e4, 0x1645, "14e4-1645", "14e4-1645", 0),
+ PCI_ROM(0x14e4, 0x1646, "14e4-1646", "14e4-1646", 0),
+ PCI_ROM(0x14e4, 0x1647, "14e4-1647", "14e4-1647", 0),
+ PCI_ROM(0x14e4, 0x1648, "14e4-1648", "14e4-1648", 0),
+ PCI_ROM(0x14e4, 0x164d, "14e4-164d", "14e4-164d", 0),
+ PCI_ROM(0x14e4, 0x1653, "14e4-1653", "14e4-1653", 0),
+ PCI_ROM(0x14e4, 0x1654, "14e4-1654", "14e4-1654", 0),
+ PCI_ROM(0x14e4, 0x165d, "14e4-165d", "14e4-165d", 0),
+ PCI_ROM(0x14e4, 0x165e, "14e4-165e", "14e4-165e", 0),
+ PCI_ROM(0x14e4, 0x16a6, "14e4-16a6", "14e4-16a6", 0),
+ PCI_ROM(0x14e4, 0x16a7, "14e4-16a7", "14e4-16a7", 0),
+ PCI_ROM(0x14e4, 0x16a8, "14e4-16a8", "14e4-16a8", 0),
+ PCI_ROM(0x14e4, 0x16c6, "14e4-16c6", "14e4-16c6", 0),
+ PCI_ROM(0x14e4, 0x16c7, "14e4-16c7", "14e4-16c7", 0),
+ PCI_ROM(0x14e4, 0x1696, "14e4-1696", "14e4-1696", 0),
+ PCI_ROM(0x14e4, 0x169c, "14e4-169c", "14e4-169c", 0),
+ PCI_ROM(0x14e4, 0x169d, "14e4-169d", "14e4-169d", 0),
+ PCI_ROM(0x14e4, 0x170d, "14e4-170d", "14e4-170d", 0),
+ PCI_ROM(0x14e4, 0x170e, "14e4-170e", "14e4-170e", 0),
+ PCI_ROM(0x14e4, 0x1649, "14e4-1649", "14e4-1649", 0),
+ PCI_ROM(0x14e4, 0x166e, "14e4-166e", "14e4-166e", 0),
+ PCI_ROM(0x14e4, 0x1659, "14e4-1659", "14e4-1659", 0),
+ PCI_ROM(0x14e4, 0x165a, "14e4-165a", "14e4-165a", 0),
+ PCI_ROM(0x14e4, 0x1677, "14e4-1677", "14e4-1677", 0),
+ PCI_ROM(0x14e4, 0x167d, "14e4-167d", "14e4-167d", 0),
+ PCI_ROM(0x14e4, 0x167e, "14e4-167e", "14e4-167e", 0),
+ PCI_ROM(0x14e4, 0x1600, "14e4-1600", "14e4-1600", 0),
+ PCI_ROM(0x14e4, 0x1601, "14e4-1601", "14e4-1601", 0),
+ PCI_ROM(0x14e4, 0x16f7, "14e4-16f7", "14e4-16f7", 0),
+ PCI_ROM(0x14e4, 0x16fd, "14e4-16fd", "14e4-16fd", 0),
+ PCI_ROM(0x14e4, 0x16fe, "14e4-16fe", "14e4-16fe", 0),
+ PCI_ROM(0x14e4, 0x167a, "14e4-167a", "14e4-167a", 0),
+ PCI_ROM(0x14e4, 0x1672, "14e4-1672", "14e4-1672", 0),
+ PCI_ROM(0x14e4, 0x167b, "14e4-167b", "14e4-167b", 0),
+ PCI_ROM(0x14e4, 0x1673, "14e4-1673", "14e4-1673", 0),
+ PCI_ROM(0x14e4, 0x1674, "14e4-1674", "14e4-1674", 0),
+ PCI_ROM(0x14e4, 0x169a, "14e4-169a", "14e4-169a", 0),
+ PCI_ROM(0x14e4, 0x169b, "14e4-169b", "14e4-169b", 0),
+ PCI_ROM(0x14e4, 0x1693, "14e4-1693", "14e4-1693", 0),
+ PCI_ROM(0x14e4, 0x167f, "14e4-167f", "14e4-167f", 0),
+ PCI_ROM(0x14e4, 0x1668, "14e4-1668", "14e4-1668", 0),
+ PCI_ROM(0x14e4, 0x1669, "14e4-1669", "14e4-1669", 0),
+ PCI_ROM(0x14e4, 0x1678, "14e4-1678", "14e4-1678", 0),
+ PCI_ROM(0x14e4, 0x1679, "14e4-1679", "14e4-1679", 0),
+ PCI_ROM(0x14e4, 0x166a, "14e4-166a", "14e4-166a", 0),
+ PCI_ROM(0x14e4, 0x166b, "14e4-166b", "14e4-166b", 0),
+ PCI_ROM(0x14e4, 0x16dd, "14e4-16dd", "14e4-16dd", 0),
+ PCI_ROM(0x14e4, 0x1712, "14e4-1712", "14e4-1712", 0),
+ PCI_ROM(0x14e4, 0x1713, "14e4-1713", "14e4-1713", 0),
+ PCI_ROM(0x14e4, 0x1698, "14e4-1698", "14e4-1698", 0),
+ PCI_ROM(0x14e4, 0x1684, "14e4-1684", "14e4-1684", 0),
+ PCI_ROM(0x14e4, 0x165b, "14e4-165b", "14e4-165b", 0),
+ PCI_ROM(0x14e4, 0x1681, "14e4-1681", "14e4-1681", 0),
+ PCI_ROM(0x14e4, 0x1680, "14e4-1680", "14e4-1680", 0),
+ PCI_ROM(0x14e4, 0x1688, "14e4-1688", "14e4-1688", 0),
+ PCI_ROM(0x14e4, 0x1689, "14e4-1689", "14e4-1689", 0),
+ PCI_ROM(0x14e4, 0x1699, "14e4-1699", "14e4-1699", 0),
+ PCI_ROM(0x14e4, 0x16a0, "14e4-16a0", "14e4-16a0", 0),
+ PCI_ROM(0x14e4, 0x1692, "14e4-1692", "14e4-1692", 0),
+ PCI_ROM(0x14e4, 0x1690, "14e4-1690", "14e4-1690", 0),
+ PCI_ROM(0x14e4, 0x1694, "14e4-1694", "14e4-1694", 0),
+ PCI_ROM(0x14e4, 0x1691, "14e4-1691", "14e4-1691", 0),
+ PCI_ROM(0x14e4, 0x1655, "14e4-1655", "14e4-1655", 0),
+ PCI_ROM(0x14e4, 0x1656, "14e4-1656", "14e4-1656", 0),
+ PCI_ROM(0x14e4, 0x16b1, "14e4-16b1", "14e4-16b1", 0),
+ PCI_ROM(0x14e4, 0x16b5, "14e4-16b5", "14e4-16b5", 0),
+ PCI_ROM(0x14e4, 0x16b0, "14e4-16b0", "14e4-16b0", 0),
+ PCI_ROM(0x14e4, 0x16b4, "14e4-16b4", "14e4-16b4", 0),
+ PCI_ROM(0x14e4, 0x16b2, "14e4-16b2", "14e4-16b2", 0),
+ PCI_ROM(0x14e4, 0x16b6, "14e4-16b6", "14e4-16b6", 0),
+ PCI_ROM(0x14e4, 0x1657, "14e4-1657", "14e4-1657", 0),
+ PCI_ROM(0x14e4, 0x165f, "14e4-165f", "14e4-165f", 0),
+ PCI_ROM(0x1148, 0x4400, "1148-4400", "1148-4400", 0),
+ PCI_ROM(0x1148, 0x4500, "1148-4500", "1148-4500", 0),
+ PCI_ROM(0x173b, 0x03e8, "173b-03e8", "173b-03e8", 0),
+ PCI_ROM(0x173b, 0x03e9, "173b-03e9", "173b-03e9", 0),
+ PCI_ROM(0x173b, 0x03eb, "173b-03eb", "173b-03eb", 0),
+ PCI_ROM(0x173b, 0x03ea, "173b-03ea", "173b-03ea", 0),
+ PCI_ROM(0x106b, 0x1645, "106b-1645", "106b-1645", 0),
+};
+
+struct pci_driver tg3_pci_driver __pci_driver = {
+ .ids = tg3_nics,
+ .id_count = ARRAY_SIZE(tg3_nics),
+ .probe = tg3_init_one,
+ .remove = tg3_remove_one,
+};
diff --git a/src/drivers/net/tg3.h b/src/drivers/net/tg3/tg3.h
index deeb0add..ac243875 100644
--- a/src/drivers/net/tg3.h
+++ b/src/drivers/net/tg3/tg3.h
@@ -1,83 +1,144 @@
-/* $Id$
+/* $Id: tg3.h,v 1.37.2.32 2002/03/11 12:18:18 davem Exp $
* tg3.h: Definitions for Broadcom Tigon3 ethernet driver.
*
- * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)
- * Copyright (C) 2001 Jeff Garzik (jgarzik@mandrakesoft.com)
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2007-2011 Broadcom Corporation.
*/
-FILE_LICENCE ( GPL2_ONLY );
-
#ifndef _T3_H
#define _T3_H
-#include "stdint.h"
-
-typedef unsigned long dma_addr_t;
-
-/* From mii.h */
-
-/* Indicates what features are advertised by the interface. */
-#define ADVERTISED_10baseT_Half (1 << 0)
-#define ADVERTISED_10baseT_Full (1 << 1)
-#define ADVERTISED_100baseT_Half (1 << 2)
-#define ADVERTISED_100baseT_Full (1 << 3)
-#define ADVERTISED_1000baseT_Half (1 << 4)
-#define ADVERTISED_1000baseT_Full (1 << 5)
-#define ADVERTISED_Autoneg (1 << 6)
-#define ADVERTISED_TP (1 << 7)
-#define ADVERTISED_AUI (1 << 8)
-#define ADVERTISED_MII (1 << 9)
-#define ADVERTISED_FIBRE (1 << 10)
-#define ADVERTISED_BNC (1 << 11)
-
-/* The following are all involved in forcing a particular link
- * mode for the device for setting things. When getting the
- * devices settings, these indicate the current mode and whether
- * it was foced up into this mode or autonegotiated.
- */
-
-/* The forced speed, 10Mb, 100Mb, gigabit. */
-#define SPEED_10 0
-#define SPEED_100 1
-#define SPEED_1000 2
-#define SPEED_INVALID 3
-
-
-/* Duplex, half or full. */
-#define DUPLEX_HALF 0x00
-#define DUPLEX_FULL 0x01
-#define DUPLEX_INVALID 0x02
-
-/* Which connector port. */
-#define PORT_TP 0x00
-#define PORT_AUI 0x01
-#define PORT_MII 0x02
-#define PORT_FIBRE 0x03
-#define PORT_BNC 0x04
-
-/* Which tranceiver to use. */
-#define XCVR_INTERNAL 0x00
-#define XCVR_EXTERNAL 0x01
-#define XCVR_DUMMY1 0x02
-#define XCVR_DUMMY2 0x03
-#define XCVR_DUMMY3 0x04
-
-/* Enable or disable autonegotiation. If this is set to enable,
- * the forced link modes above are completely ignored.
- */
-#define AUTONEG_DISABLE 0x00
-#define AUTONEG_ENABLE 0x01
-
-/* Wake-On-Lan options. */
-#define WAKE_PHY (1 << 0)
-#define WAKE_UCAST (1 << 1)
-#define WAKE_MCAST (1 << 2)
-#define WAKE_BCAST (1 << 3)
-#define WAKE_ARP (1 << 4)
-#define WAKE_MAGIC (1 << 5)
-#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
-
-/* From tg3.h */
+#undef ERRFILE
+#define ERRFILE ERRFILE_tg3
+
+/* From linux/include/linux/pci_regs.h: */
+#define PCI_EXP_LNKCTL 16 /* Link Control */
+#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+
+#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */
+#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
+
+#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
+/* </pci_regs.h> */
+
+/* ethtool.h: */
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+#define ADVERTISED_Autoneg (1 << 6)
+/* </ethtool.h> */
+
+/* mdio.h: */
+#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
+
+#define MDIO_MMD_AN 7 /* Auto-Negotiation */
+
+#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */
+#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */
+/* </mdio.h> */
+
+/* mii.h */
+#define FLOW_CTRL_TX 0x01
+#define FLOW_CTRL_RX 0x02
+/* </mii.h> */
+
+/* pci_regs.h */
+#define PCI_X_CMD 2 /* Modes & Features */
+#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+
+#define PCI_EXP_DEVCTL 8 /* Device Control */
+#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
+#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
+#define PCI_EXP_DEVSTA 10 /* Device Status */
+#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */
+#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */
+#define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */
+#define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */
+/* </pci_regs.h> */
+
+/* pci_ids.h: */
+#define PCI_VENDOR_ID_BROADCOM 0x14e4
+#define PCI_DEVICE_ID_TIGON3_5752 0x1600
+#define PCI_DEVICE_ID_TIGON3_5752M 0x1601
+#define PCI_DEVICE_ID_NX2_5709 0x1639
+#define PCI_DEVICE_ID_NX2_5709S 0x163a
+#define PCI_DEVICE_ID_TIGON3_5700 0x1644
+#define PCI_DEVICE_ID_TIGON3_5701 0x1645
+#define PCI_DEVICE_ID_TIGON3_5702 0x1646
+#define PCI_DEVICE_ID_TIGON3_5703 0x1647
+#define PCI_DEVICE_ID_TIGON3_5704 0x1648
+#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649
+#define PCI_DEVICE_ID_NX2_5706 0x164a
+#define PCI_DEVICE_ID_NX2_5708 0x164c
+#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d
+#define PCI_DEVICE_ID_NX2_57710 0x164e
+#define PCI_DEVICE_ID_NX2_57711 0x164f
+#define PCI_DEVICE_ID_NX2_57711E 0x1650
+#define PCI_DEVICE_ID_TIGON3_5705 0x1653
+#define PCI_DEVICE_ID_TIGON3_5705_2 0x1654
+#define PCI_DEVICE_ID_TIGON3_5721 0x1659
+#define PCI_DEVICE_ID_TIGON3_5722 0x165a
+#define PCI_DEVICE_ID_TIGON3_5723 0x165b
+#define PCI_DEVICE_ID_TIGON3_5705M 0x165d
+#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e
+#define PCI_DEVICE_ID_NX2_57712 0x1662
+#define PCI_DEVICE_ID_NX2_57712E 0x1663
+#define PCI_DEVICE_ID_TIGON3_5714 0x1668
+#define PCI_DEVICE_ID_TIGON3_5714S 0x1669
+#define PCI_DEVICE_ID_TIGON3_5780 0x166a
+#define PCI_DEVICE_ID_TIGON3_5780S 0x166b
+#define PCI_DEVICE_ID_TIGON3_5705F 0x166e
+#define PCI_DEVICE_ID_TIGON3_5754M 0x1672
+#define PCI_DEVICE_ID_TIGON3_5755M 0x1673
+#define PCI_DEVICE_ID_TIGON3_5756 0x1674
+#define PCI_DEVICE_ID_TIGON3_5751 0x1677
+#define PCI_DEVICE_ID_TIGON3_5715 0x1678
+#define PCI_DEVICE_ID_TIGON3_5715S 0x1679
+#define PCI_DEVICE_ID_TIGON3_5754 0x167a
+#define PCI_DEVICE_ID_TIGON3_5755 0x167b
+#define PCI_DEVICE_ID_TIGON3_5751M 0x167d
+#define PCI_DEVICE_ID_TIGON3_5751F 0x167e
+#define PCI_DEVICE_ID_TIGON3_5787F 0x167f
+#define PCI_DEVICE_ID_TIGON3_5761E 0x1680
+#define PCI_DEVICE_ID_TIGON3_5761 0x1681
+#define PCI_DEVICE_ID_TIGON3_5764 0x1684
+#define PCI_DEVICE_ID_TIGON3_5787M 0x1693
+#define PCI_DEVICE_ID_TIGON3_5782 0x1696
+#define PCI_DEVICE_ID_TIGON3_5784 0x1698
+#define PCI_DEVICE_ID_TIGON3_5786 0x169a
+#define PCI_DEVICE_ID_TIGON3_5787 0x169b
+#define PCI_DEVICE_ID_TIGON3_5788 0x169c
+#define PCI_DEVICE_ID_TIGON3_5789 0x169d
+#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6
+#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7
+#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
+#define PCI_DEVICE_ID_NX2_5706S 0x16aa
+#define PCI_DEVICE_ID_NX2_5708S 0x16ac
+#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6
+#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7
+#define PCI_DEVICE_ID_TIGON3_5781 0x16dd
+#define PCI_DEVICE_ID_TIGON3_5753 0x16f7
+#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd
+#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe
+#define PCI_DEVICE_ID_TIGON3_5901 0x170d
+#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
+#define PCI_DEVICE_ID_TIGON3_5906 0x1712
+#define PCI_DEVICE_ID_TIGON3_5906M 0x1713
+/* </pci_ids.h> */
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
#define TG3_64BIT_REG_HIGH 0x00UL
#define TG3_64BIT_REG_LOW 0x04UL
@@ -92,11 +153,13 @@ typedef unsigned long dma_addr_t;
#define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */
#define TG3_BDINFO_SIZE 0x10UL
-#define RX_COPY_THRESHOLD 256
-
-#define RX_STD_MAX_SIZE 1536
-#define RX_STD_MAX_SIZE_5705 512
-#define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */
+#define TG3_RX_STD_MAX_SIZE_5700 512
+#define TG3_RX_STD_MAX_SIZE_5717 2048
+#define TG3_RX_JMB_MAX_SIZE_5700 256
+#define TG3_RX_JMB_MAX_SIZE_5717 1024
+#define TG3_RX_RET_MAX_SIZE_5700 1024
+#define TG3_RX_RET_MAX_SIZE_5705 512
+#define TG3_RX_RET_MAX_SIZE_5717 4096
/* First 256 bytes are a mirror of PCI config space. */
#define TG3PCI_VENDOR 0x00000000
@@ -106,51 +169,57 @@ typedef unsigned long dma_addr_t;
#define TG3PCI_DEVICE_TIGON3_2 0x1645 /* BCM5701 */
#define TG3PCI_DEVICE_TIGON3_3 0x1646 /* BCM5702 */
#define TG3PCI_DEVICE_TIGON3_4 0x1647 /* BCM5703 */
-#define TG3PCI_COMMAND 0x00000004
-#define TG3PCI_STATUS 0x00000006
-#define TG3PCI_CCREVID 0x00000008
-#define TG3PCI_CACHELINESZ 0x0000000c
-#define TG3PCI_LATTIMER 0x0000000d
-#define TG3PCI_HEADERTYPE 0x0000000e
-#define TG3PCI_BIST 0x0000000f
-#define TG3PCI_BASE0_LOW 0x00000010
-#define TG3PCI_BASE0_HIGH 0x00000014
-/* 0x18 --> 0x2c unused */
-#define TG3PCI_SUBSYSVENID 0x0000002c
-#define TG3PCI_SUBSYSID 0x0000002e
-#define TG3PCI_ROMADDR 0x00000030
-#define TG3PCI_CAPLIST 0x00000034
-/* 0x35 --> 0x3c unused */
-#define TG3PCI_IRQ_LINE 0x0000003c
-#define TG3PCI_IRQ_PIN 0x0000003d
-#define TG3PCI_MIN_GNT 0x0000003e
-#define TG3PCI_MAX_LAT 0x0000003f
-#define TG3PCI_X_CAPS 0x00000040
-#define PCIX_CAPS_RELAXED_ORDERING 0x00020000
-#define PCIX_CAPS_SPLIT_MASK 0x00700000
-#define PCIX_CAPS_SPLIT_SHIFT 20
-#define PCIX_CAPS_BURST_MASK 0x000c0000
-#define PCIX_CAPS_BURST_SHIFT 18
-#define PCIX_CAPS_MAX_BURST_CPIOB 2
-#define TG3PCI_PM_CAP_PTR 0x00000041
-#define TG3PCI_X_COMMAND 0x00000042
-#define TG3PCI_X_STATUS 0x00000044
-#define TG3PCI_PM_CAP_ID 0x00000048
-#define TG3PCI_VPD_CAP_PTR 0x00000049
-#define TG3PCI_PM_CAPS 0x0000004a
-#define TG3PCI_PM_CTRL_STAT 0x0000004c
-#define TG3PCI_BR_SUPP_EXT 0x0000004e
-#define TG3PCI_PM_DATA 0x0000004f
-#define TG3PCI_VPD_CAP_ID 0x00000050
-#define TG3PCI_MSI_CAP_PTR 0x00000051
-#define TG3PCI_VPD_ADDR_FLAG 0x00000052
-#define VPD_ADDR_FLAG_WRITE 0x00008000
-#define TG3PCI_VPD_DATA 0x00000054
-#define TG3PCI_MSI_CAP_ID 0x00000058
-#define TG3PCI_NXT_CAP_PTR 0x00000059
-#define TG3PCI_MSI_CTRL 0x0000005a
-#define TG3PCI_MSI_ADDR_LOW 0x0000005c
-#define TG3PCI_MSI_ADDR_HIGH 0x00000060
+#define TG3PCI_DEVICE_TIGON3_5761S 0x1688
+#define TG3PCI_DEVICE_TIGON3_5761SE 0x1689
+#define TG3PCI_DEVICE_TIGON3_57780 0x1692
+#define TG3PCI_DEVICE_TIGON3_57760 0x1690
+#define TG3PCI_DEVICE_TIGON3_57790 0x1694
+#define TG3PCI_DEVICE_TIGON3_57788 0x1691
+#define TG3PCI_DEVICE_TIGON3_5785_G 0x1699 /* GPHY */
+#define TG3PCI_DEVICE_TIGON3_5785_F 0x16a0 /* 10/100 only */
+#define TG3PCI_DEVICE_TIGON3_5717 0x1655
+#define TG3PCI_DEVICE_TIGON3_5718 0x1656
+#define TG3PCI_DEVICE_TIGON3_57781 0x16b1
+#define TG3PCI_DEVICE_TIGON3_57785 0x16b5
+#define TG3PCI_DEVICE_TIGON3_57761 0x16b0
+#define TG3PCI_DEVICE_TIGON3_57765 0x16b4
+#define TG3PCI_DEVICE_TIGON3_57791 0x16b2
+#define TG3PCI_DEVICE_TIGON3_57795 0x16b6
+#define TG3PCI_DEVICE_TIGON3_5719 0x1657
+#define TG3PCI_DEVICE_TIGON3_5720 0x165f
+/* 0x04 --> 0x2c unused */
+#define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5 0x0001
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6 0x0002
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9 0x0003
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1 0x0005
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8 0x0006
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7 0x0007
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10 0x0008
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12 0x8008
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1 0x0009
+#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2 0x8009
+#define TG3PCI_SUBVENDOR_ID_3COM PCI_VENDOR_ID_3COM
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996T 0x1000
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996BT 0x1006
+#define TG3PCI_SUBDEVICE_ID_3COM_3C996SX 0x1004
+#define TG3PCI_SUBDEVICE_ID_3COM_3C1000T 0x1007
+#define TG3PCI_SUBDEVICE_ID_3COM_3C940BR01 0x1008
+#define TG3PCI_SUBVENDOR_ID_DELL PCI_VENDOR_ID_DELL
+#define TG3PCI_SUBDEVICE_ID_DELL_VIPER 0x00d1
+#define TG3PCI_SUBDEVICE_ID_DELL_JAGUAR 0x0106
+#define TG3PCI_SUBDEVICE_ID_DELL_MERLOT 0x0109
+#define TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT 0x010a
+#define TG3PCI_SUBVENDOR_ID_COMPAQ PCI_VENDOR_ID_COMPAQ
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE 0x007c
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2 0x009a
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING 0x007d
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780 0x0085
+#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2 0x0099
+#define TG3PCI_SUBVENDOR_ID_IBM PCI_VENDOR_ID_IBM
+#define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2 0x0281
+/* 0x30 --> 0x64 unused */
#define TG3PCI_MSI_DATA 0x00000064
/* 0x66 --> 0x68 unused */
#define TG3PCI_MISC_HOST_CTRL 0x00000068
@@ -187,14 +256,26 @@ typedef unsigned long dma_addr_t;
#define CHIPREV_ID_5704_A0 0x2000
#define CHIPREV_ID_5704_A1 0x2001
#define CHIPREV_ID_5704_A2 0x2002
+#define CHIPREV_ID_5704_A3 0x2003
#define CHIPREV_ID_5705_A0 0x3000
#define CHIPREV_ID_5705_A1 0x3001
-#define CHIPREV_ID_5705_A2 0x3002
-#define CHIPREV_ID_5705_A3 0x3003
-#define CHIPREV_ID_5721 0x4101
-#define CHIPREV_ID_5750_A0 0x4000
-#define CHIPREV_ID_5750_A1 0x4001
-#define CHIPREV_ID_5750_A3 0x4003
+#define CHIPREV_ID_5705_A2 0x3002
+#define CHIPREV_ID_5705_A3 0x3003
+#define CHIPREV_ID_5750_A0 0x4000
+#define CHIPREV_ID_5750_A1 0x4001
+#define CHIPREV_ID_5750_A3 0x4003
+#define CHIPREV_ID_5750_C2 0x4202
+#define CHIPREV_ID_5752_A0_HW 0x5000
+#define CHIPREV_ID_5752_A0 0x6000
+#define CHIPREV_ID_5752_A1 0x6001
+#define CHIPREV_ID_5714_A2 0x9002
+#define CHIPREV_ID_5906_A1 0xc001
+#define CHIPREV_ID_57780_A0 0x57780000
+#define CHIPREV_ID_57780_A1 0x57780001
+#define CHIPREV_ID_5717_A0 0x05717000
+#define CHIPREV_ID_57765_A0 0x57785000
+#define CHIPREV_ID_5719_A0 0x05719000
+#define CHIPREV_ID_5720_A0 0x05720000
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00
@@ -202,12 +283,34 @@ typedef unsigned long dma_addr_t;
#define ASIC_REV_5704 0x02
#define ASIC_REV_5705 0x03
#define ASIC_REV_5750 0x04
+#define ASIC_REV_5752 0x06
+#define ASIC_REV_5780 0x08
+#define ASIC_REV_5714 0x09
+#define ASIC_REV_5755 0x0a
#define ASIC_REV_5787 0x0b
+#define ASIC_REV_5906 0x0c
+#define ASIC_REV_USE_PROD_ID_REG 0x0f
+#define ASIC_REV_5784 0x5784
+#define ASIC_REV_5761 0x5761
+#define ASIC_REV_5785 0x5785
+#define ASIC_REV_57780 0x57780
+#define ASIC_REV_5717 0x5717
+#define ASIC_REV_57765 0x57785
+#define ASIC_REV_5719 0x5719
+#define ASIC_REV_5720 0x5720
#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
#define CHIPREV_5700_AX 0x70
#define CHIPREV_5700_BX 0x71
#define CHIPREV_5700_CX 0x72
#define CHIPREV_5701_AX 0x00
+#define CHIPREV_5703_AX 0x10
+#define CHIPREV_5704_AX 0x20
+#define CHIPREV_5704_BX 0x21
+#define CHIPREV_5750_AX 0x40
+#define CHIPREV_5750_BX 0x41
+#define CHIPREV_5784_AX 0x57840
+#define CHIPREV_5761_AX 0x57610
+#define CHIPREV_57765_AX 0x577650
#define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff)
#define METAL_REV_A0 0x00
#define METAL_REV_A1 0x01
@@ -215,13 +318,17 @@ typedef unsigned long dma_addr_t;
#define METAL_REV_B1 0x01
#define METAL_REV_B2 0x02
#define TG3PCI_DMA_RW_CTRL 0x0000006c
-#define DMA_RWCTRL_MIN_DMA 0x000000ff
-#define DMA_RWCTRL_MIN_DMA_SHIFT 0
+#define DMA_RWCTRL_DIS_CACHE_ALIGNMENT 0x00000001
+#define DMA_RWCTRL_TAGGED_STAT_WA 0x00000080
+#define DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK 0x00000380
#define DMA_RWCTRL_READ_BNDRY_MASK 0x00000700
#define DMA_RWCTRL_READ_BNDRY_DISAB 0x00000000
#define DMA_RWCTRL_READ_BNDRY_16 0x00000100
+#define DMA_RWCTRL_READ_BNDRY_128_PCIX 0x00000100
#define DMA_RWCTRL_READ_BNDRY_32 0x00000200
+#define DMA_RWCTRL_READ_BNDRY_256_PCIX 0x00000200
#define DMA_RWCTRL_READ_BNDRY_64 0x00000300
+#define DMA_RWCTRL_READ_BNDRY_384_PCIX 0x00000300
#define DMA_RWCTRL_READ_BNDRY_128 0x00000400
#define DMA_RWCTRL_READ_BNDRY_256 0x00000500
#define DMA_RWCTRL_READ_BNDRY_512 0x00000600
@@ -229,8 +336,11 @@ typedef unsigned long dma_addr_t;
#define DMA_RWCTRL_WRITE_BNDRY_MASK 0x00003800
#define DMA_RWCTRL_WRITE_BNDRY_DISAB 0x00000000
#define DMA_RWCTRL_WRITE_BNDRY_16 0x00000800
+#define DMA_RWCTRL_WRITE_BNDRY_128_PCIX 0x00000800
#define DMA_RWCTRL_WRITE_BNDRY_32 0x00001000
+#define DMA_RWCTRL_WRITE_BNDRY_256_PCIX 0x00001000
#define DMA_RWCTRL_WRITE_BNDRY_64 0x00001800
+#define DMA_RWCTRL_WRITE_BNDRY_384_PCIX 0x00001800
#define DMA_RWCTRL_WRITE_BNDRY_128 0x00002000
#define DMA_RWCTRL_WRITE_BNDRY_256 0x00002800
#define DMA_RWCTRL_WRITE_BNDRY_512 0x00003000
@@ -246,6 +356,9 @@ typedef unsigned long dma_addr_t;
#define DMA_RWCTRL_PCI_READ_CMD_SHIFT 24
#define DMA_RWCTRL_PCI_WRITE_CMD 0xf0000000
#define DMA_RWCTRL_PCI_WRITE_CMD_SHIFT 28
+#define DMA_RWCTRL_WRITE_BNDRY_64_PCIE 0x10000000
+#define DMA_RWCTRL_WRITE_BNDRY_128_PCIE 0x30000000
+#define DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE 0x70000000
#define TG3PCI_PCISTATE 0x00000070
#define PCISTATE_FORCE_RESET 0x00000001
#define PCISTATE_INT_NOT_ACTIVE 0x00000002
@@ -256,6 +369,9 @@ typedef unsigned long dma_addr_t;
#define PCISTATE_ROM_RETRY_ENABLE 0x00000040
#define PCISTATE_FLAT_VIEW 0x00000100
#define PCISTATE_RETRY_SAME_DMA 0x00002000
+#define PCISTATE_ALLOW_APE_CTLSPC_WR 0x00010000
+#define PCISTATE_ALLOW_APE_SHMEM_WR 0x00020000
+#define PCISTATE_ALLOW_APE_PSPACE_WR 0x00040000
#define TG3PCI_CLOCK_CTRL 0x00000074
#define CLOCK_CTRL_CORECLK_DISABLE 0x00000200
#define CLOCK_CTRL_RXCLK_DISABLE 0x00000400
@@ -271,16 +387,25 @@ typedef unsigned long dma_addr_t;
#define TG3PCI_MEM_WIN_BASE_ADDR 0x0000007c
#define TG3PCI_REG_DATA 0x00000080
#define TG3PCI_MEM_WIN_DATA 0x00000084
-#define TG3PCI_MODE_CTRL 0x00000088
-#define TG3PCI_MISC_CFG 0x0000008c
#define TG3PCI_MISC_LOCAL_CTRL 0x00000090
/* 0x94 --> 0x98 unused */
#define TG3PCI_STD_RING_PROD_IDX 0x00000098 /* 64-bit */
#define TG3PCI_RCV_RET_RING_CON_IDX 0x000000a0 /* 64-bit */
-#define TG3PCI_SND_PROD_IDX 0x000000a8 /* 64-bit */
-/* 0xb0 --> 0x100 unused */
-
-/* 0x100 --> 0x200 unused */
+/* 0xa8 --> 0xb8 unused */
+#define TG3PCI_DUAL_MAC_CTRL 0x000000b8
+#define DUAL_MAC_CTRL_CH_MASK 0x00000003
+#define DUAL_MAC_CTRL_ID 0x00000004
+#define TG3PCI_PRODID_ASICREV 0x000000bc
+#define PROD_ID_ASIC_REV_MASK 0x0fffffff
+/* 0xc0 --> 0xf4 unused */
+
+#define TG3PCI_GEN2_PRODID_ASICREV 0x000000f4
+#define TG3PCI_GEN15_PRODID_ASICREV 0x000000fc
+/* 0xf8 --> 0x200 unused */
+
+#define TG3_CORR_ERR_STAT 0x00000110
+#define TG3_CORR_ERR_STAT_CLEAR 0xffffffff
+/* 0x114 --> 0x200 unused */
/* Mailbox registers */
#define MAILBOX_INTERRUPT_0 0x00000200 /* 64-bit */
@@ -297,7 +422,11 @@ typedef unsigned long dma_addr_t;
#define MAILBOX_GENERAL_7 0x00000258 /* 64-bit */
#define MAILBOX_RELOAD_STAT 0x00000260 /* 64-bit */
#define MAILBOX_RCV_STD_PROD_IDX 0x00000268 /* 64-bit */
+#define TG3_RX_STD_PROD_IDX_REG (MAILBOX_RCV_STD_PROD_IDX + \
+ TG3_64BIT_REG_LOW)
#define MAILBOX_RCV_JUMBO_PROD_IDX 0x00000270 /* 64-bit */
+#define TG3_RX_JMB_PROD_IDX_REG (MAILBOX_RCV_JUMBO_PROD_IDX + \
+ TG3_64BIT_REG_LOW)
#define MAILBOX_RCV_MINI_PROD_IDX 0x00000278 /* 64-bit */
#define MAILBOX_RCVRET_CON_IDX_0 0x00000280 /* 64-bit */
#define MAILBOX_RCVRET_CON_IDX_1 0x00000288 /* 64-bit */
@@ -375,6 +504,9 @@ typedef unsigned long dma_addr_t;
#define MAC_MODE_TDE_ENABLE 0x00200000
#define MAC_MODE_RDE_ENABLE 0x00400000
#define MAC_MODE_FHDE_ENABLE 0x00800000
+#define MAC_MODE_KEEP_FRAME_IN_WOL 0x01000000
+#define MAC_MODE_APE_RX_EN 0x08000000
+#define MAC_MODE_APE_TX_EN 0x10000000
#define MAC_STATUS 0x00000404
#define MAC_STATUS_PCS_SYNCED 0x00000001
#define MAC_STATUS_SIGNAL_DET 0x00000002
@@ -410,9 +542,12 @@ typedef unsigned long dma_addr_t;
#define LED_CTRL_100MBPS_STATUS 0x00000100
#define LED_CTRL_10MBPS_STATUS 0x00000200
#define LED_CTRL_TRAFFIC_STATUS 0x00000400
-#define LED_CTRL_MAC_MODE 0x00000000
-#define LED_CTRL_PHY_MODE_1 0x00000800
-#define LED_CTRL_PHY_MODE_2 0x00001000
+#define LED_CTRL_MODE_MAC 0x00000000
+#define LED_CTRL_MODE_PHY_1 0x00000800
+#define LED_CTRL_MODE_PHY_2 0x00001000
+#define LED_CTRL_MODE_SHASTA_MAC 0x00002000
+#define LED_CTRL_MODE_SHARED 0x00004000
+#define LED_CTRL_MODE_COMBO 0x00008000
#define LED_CTRL_BLINK_RATE_MASK 0x7ff80000
#define LED_CTRL_BLINK_RATE_SHIFT 19
#define LED_CTRL_BLINK_PER_OVERRIDE 0x00080000
@@ -459,11 +594,12 @@ typedef unsigned long dma_addr_t;
#define MI_COM_DATA_MASK 0x0000ffff
#define MAC_MI_STAT 0x00000450
#define MAC_MI_STAT_LNKSTAT_ATTN_ENAB 0x00000001
+#define MAC_MI_STAT_10MBPS_MODE 0x00000002
#define MAC_MI_MODE 0x00000454
#define MAC_MI_MODE_CLK_10MHZ 0x00000001
#define MAC_MI_MODE_SHORT_PREAMBLE 0x00000002
#define MAC_MI_MODE_AUTO_POLL 0x00000010
-#define MAC_MI_MODE_CORE_CLK_62MHZ 0x00008000
+#define MAC_MI_MODE_500KHZ_CONST 0x00008000
#define MAC_MI_MODE_BASE 0x000c0000 /* XXX magic values XXX */
#define MAC_AUTO_POLL_STATUS 0x00000458
#define MAC_AUTO_POLL_ERROR 0x00000001
@@ -473,6 +609,9 @@ typedef unsigned long dma_addr_t;
#define TX_MODE_FLOW_CTRL_ENABLE 0x00000010
#define TX_MODE_BIG_BCKOFF_ENABLE 0x00000020
#define TX_MODE_LONG_PAUSE_ENABLE 0x00000040
+#define TX_MODE_MBUF_LOCKUP_FIX 0x00000100
+#define TX_MODE_JMB_FRM_LEN 0x00400000
+#define TX_MODE_CNT_DN_MODE 0x00800000
#define MAC_TX_STATUS 0x00000460
#define TX_STATUS_XOFFED 0x00000001
#define TX_STATUS_SENT_XOFF 0x00000002
@@ -487,6 +626,8 @@ typedef unsigned long dma_addr_t;
#define TX_LENGTHS_IPG_SHIFT 8
#define TX_LENGTHS_IPG_CRS_MASK 0x00003000
#define TX_LENGTHS_IPG_CRS_SHIFT 12
+#define TX_LENGTHS_JMB_FRM_LEN_MSK 0x00ff0000
+#define TX_LENGTHS_CNT_DWN_VAL_MSK 0xff000000
#define MAC_RX_MODE 0x00000468
#define RX_MODE_RESET 0x00000001
#define RX_MODE_ENABLE 0x00000002
@@ -499,6 +640,13 @@ typedef unsigned long dma_addr_t;
#define RX_MODE_PROMISC 0x00000100
#define RX_MODE_NO_CRC_CHECK 0x00000200
#define RX_MODE_KEEP_VLAN_TAG 0x00000400
+#define RX_MODE_RSS_IPV4_HASH_EN 0x00010000
+#define RX_MODE_RSS_TCP_IPV4_HASH_EN 0x00020000
+#define RX_MODE_RSS_IPV6_HASH_EN 0x00040000
+#define RX_MODE_RSS_TCP_IPV6_HASH_EN 0x00080000
+#define RX_MODE_RSS_ITBL_HASH_BITS_7 0x00700000
+#define RX_MODE_RSS_ENABLE 0x00800000
+#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000
#define MAC_RX_STATUS 0x0000046c
#define RX_STATUS_REMOTE_TX_XOFFED 0x00000001
#define RX_STATUS_XOFF_RCVD 0x00000002
@@ -573,11 +721,192 @@ typedef unsigned long dma_addr_t;
#define MAC_EXTADDR_11_HIGH 0x00000588
#define MAC_EXTADDR_11_LOW 0x0000058c
#define MAC_SERDES_CFG 0x00000590
+#define MAC_SERDES_CFG_EDGE_SELECT 0x00001000
#define MAC_SERDES_STAT 0x00000594
-/* 0x598 --> 0x600 unused */
+/* 0x598 --> 0x5a0 unused */
+#define MAC_PHYCFG1 0x000005a0
+#define MAC_PHYCFG1_RGMII_INT 0x00000001
+#define MAC_PHYCFG1_RXCLK_TO_MASK 0x00001ff0
+#define MAC_PHYCFG1_RXCLK_TIMEOUT 0x00001000
+#define MAC_PHYCFG1_TXCLK_TO_MASK 0x01ff0000
+#define MAC_PHYCFG1_TXCLK_TIMEOUT 0x01000000
+#define MAC_PHYCFG1_RGMII_EXT_RX_DEC 0x02000000
+#define MAC_PHYCFG1_RGMII_SND_STAT_EN 0x04000000
+#define MAC_PHYCFG1_TXC_DRV 0x20000000
+#define MAC_PHYCFG2 0x000005a4
+#define MAC_PHYCFG2_INBAND_ENABLE 0x00000001
+#define MAC_PHYCFG2_EMODE_MASK_MASK 0x000001c0
+#define MAC_PHYCFG2_EMODE_MASK_AC131 0x000000c0
+#define MAC_PHYCFG2_EMODE_MASK_50610 0x00000100
+#define MAC_PHYCFG2_EMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_EMODE_MASK_RT8201 0x000001c0
+#define MAC_PHYCFG2_EMODE_COMP_MASK 0x00000e00
+#define MAC_PHYCFG2_EMODE_COMP_AC131 0x00000600
+#define MAC_PHYCFG2_EMODE_COMP_50610 0x00000400
+#define MAC_PHYCFG2_EMODE_COMP_RT8211 0x00000800
+#define MAC_PHYCFG2_EMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_FMODE_MASK_MASK 0x00007000
+#define MAC_PHYCFG2_FMODE_MASK_AC131 0x00006000
+#define MAC_PHYCFG2_FMODE_MASK_50610 0x00004000
+#define MAC_PHYCFG2_FMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_FMODE_MASK_RT8201 0x00007000
+#define MAC_PHYCFG2_FMODE_COMP_MASK 0x00038000
+#define MAC_PHYCFG2_FMODE_COMP_AC131 0x00030000
+#define MAC_PHYCFG2_FMODE_COMP_50610 0x00008000
+#define MAC_PHYCFG2_FMODE_COMP_RT8211 0x00038000
+#define MAC_PHYCFG2_FMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_GMODE_MASK_MASK 0x001c0000
+#define MAC_PHYCFG2_GMODE_MASK_AC131 0x001c0000
+#define MAC_PHYCFG2_GMODE_MASK_50610 0x00100000
+#define MAC_PHYCFG2_GMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_GMODE_MASK_RT8201 0x001c0000
+#define MAC_PHYCFG2_GMODE_COMP_MASK 0x00e00000
+#define MAC_PHYCFG2_GMODE_COMP_AC131 0x00e00000
+#define MAC_PHYCFG2_GMODE_COMP_50610 0x00000000
+#define MAC_PHYCFG2_GMODE_COMP_RT8211 0x00200000
+#define MAC_PHYCFG2_GMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_ACT_MASK_MASK 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_AC131 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_50610 0x01000000
+#define MAC_PHYCFG2_ACT_MASK_RT8211 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_RT8201 0x01000000
+#define MAC_PHYCFG2_ACT_COMP_MASK 0x0c000000
+#define MAC_PHYCFG2_ACT_COMP_AC131 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_50610 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_RT8211 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_RT8201 0x08000000
+#define MAC_PHYCFG2_QUAL_MASK_MASK 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_AC131 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_50610 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_RT8211 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_RT8201 0x30000000
+#define MAC_PHYCFG2_QUAL_COMP_MASK 0xc0000000
+#define MAC_PHYCFG2_QUAL_COMP_AC131 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_50610 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_RT8211 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_50610_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_50610 | \
+ MAC_PHYCFG2_EMODE_COMP_50610 | \
+ MAC_PHYCFG2_FMODE_MASK_50610 | \
+ MAC_PHYCFG2_FMODE_COMP_50610 | \
+ MAC_PHYCFG2_GMODE_MASK_50610 | \
+ MAC_PHYCFG2_GMODE_COMP_50610 | \
+ MAC_PHYCFG2_ACT_MASK_50610 | \
+ MAC_PHYCFG2_ACT_COMP_50610 | \
+ MAC_PHYCFG2_QUAL_MASK_50610 | \
+ MAC_PHYCFG2_QUAL_COMP_50610)
+#define MAC_PHYCFG2_AC131_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_AC131 | \
+ MAC_PHYCFG2_EMODE_COMP_AC131 | \
+ MAC_PHYCFG2_FMODE_MASK_AC131 | \
+ MAC_PHYCFG2_FMODE_COMP_AC131 | \
+ MAC_PHYCFG2_GMODE_MASK_AC131 | \
+ MAC_PHYCFG2_GMODE_COMP_AC131 | \
+ MAC_PHYCFG2_ACT_MASK_AC131 | \
+ MAC_PHYCFG2_ACT_COMP_AC131 | \
+ MAC_PHYCFG2_QUAL_MASK_AC131 | \
+ MAC_PHYCFG2_QUAL_COMP_AC131)
+#define MAC_PHYCFG2_RTL8211C_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_EMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_FMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_FMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_GMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_GMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_ACT_MASK_RT8211 | \
+ MAC_PHYCFG2_ACT_COMP_RT8211 | \
+ MAC_PHYCFG2_QUAL_MASK_RT8211 | \
+ MAC_PHYCFG2_QUAL_COMP_RT8211)
+#define MAC_PHYCFG2_RTL8201E_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_EMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_FMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_FMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_GMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_GMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_ACT_MASK_RT8201 | \
+ MAC_PHYCFG2_ACT_COMP_RT8201 | \
+ MAC_PHYCFG2_QUAL_MASK_RT8201 | \
+ MAC_PHYCFG2_QUAL_COMP_RT8201)
+#define MAC_EXT_RGMII_MODE 0x000005a8
+#define MAC_RGMII_MODE_TX_ENABLE 0x00000001
+#define MAC_RGMII_MODE_TX_LOWPWR 0x00000002
+#define MAC_RGMII_MODE_TX_RESET 0x00000004
+#define MAC_RGMII_MODE_RX_INT_B 0x00000100
+#define MAC_RGMII_MODE_RX_QUALITY 0x00000200
+#define MAC_RGMII_MODE_RX_ACTIVITY 0x00000400
+#define MAC_RGMII_MODE_RX_ENG_DET 0x00000800
+/* 0x5ac --> 0x5b0 unused */
+#define SERDES_RX_CTRL 0x000005b0 /* 5780/5714 only */
+#define SERDES_RX_SIG_DETECT 0x00000400
+#define SG_DIG_CTRL 0x000005b0
+#define SG_DIG_USING_HW_AUTONEG 0x80000000
+#define SG_DIG_SOFT_RESET 0x40000000
+#define SG_DIG_DISABLE_LINKRDY 0x20000000
+#define SG_DIG_CRC16_CLEAR_N 0x01000000
+#define SG_DIG_EN10B 0x00800000
+#define SG_DIG_CLEAR_STATUS 0x00400000
+#define SG_DIG_LOCAL_DUPLEX_STATUS 0x00200000
+#define SG_DIG_LOCAL_LINK_STATUS 0x00100000
+#define SG_DIG_SPEED_STATUS_MASK 0x000c0000
+#define SG_DIG_SPEED_STATUS_SHIFT 18
+#define SG_DIG_JUMBO_PACKET_DISABLE 0x00020000
+#define SG_DIG_RESTART_AUTONEG 0x00010000
+#define SG_DIG_FIBER_MODE 0x00008000
+#define SG_DIG_REMOTE_FAULT_MASK 0x00006000
+#define SG_DIG_PAUSE_MASK 0x00001800
+#define SG_DIG_PAUSE_CAP 0x00000800
+#define SG_DIG_ASYM_PAUSE 0x00001000
+#define SG_DIG_GBIC_ENABLE 0x00000400
+#define SG_DIG_CHECK_END_ENABLE 0x00000200
+#define SG_DIG_SGMII_AUTONEG_TIMER 0x00000100
+#define SG_DIG_CLOCK_PHASE_SELECT 0x00000080
+#define SG_DIG_GMII_INPUT_SELECT 0x00000040
+#define SG_DIG_MRADV_CRC16_SELECT 0x00000020
+#define SG_DIG_COMMA_DETECT_ENABLE 0x00000010
+#define SG_DIG_AUTONEG_TIMER_REDUCE 0x00000008
+#define SG_DIG_AUTONEG_LOW_ENABLE 0x00000004
+#define SG_DIG_REMOTE_LOOPBACK 0x00000002
+#define SG_DIG_LOOPBACK 0x00000001
+#define SG_DIG_COMMON_SETUP (SG_DIG_CRC16_CLEAR_N | \
+ SG_DIG_LOCAL_DUPLEX_STATUS | \
+ SG_DIG_LOCAL_LINK_STATUS | \
+ (0x2 << SG_DIG_SPEED_STATUS_SHIFT) | \
+ SG_DIG_FIBER_MODE | SG_DIG_GBIC_ENABLE)
+#define SG_DIG_STATUS 0x000005b4
+#define SG_DIG_CRC16_BUS_MASK 0xffff0000
+#define SG_DIG_PARTNER_FAULT_MASK 0x00600000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_ASYM_PAUSE 0x00100000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_PAUSE_CAPABLE 0x00080000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_HALF_DUPLEX 0x00040000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_FULL_DUPLEX 0x00020000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_PARTNER_NEXT_PAGE 0x00010000 /* If !MRADV_CRC16_SELECT */
+#define SG_DIG_AUTONEG_STATE_MASK 0x00000ff0
+#define SG_DIG_IS_SERDES 0x00000100
+#define SG_DIG_COMMA_DETECTOR 0x00000008
+#define SG_DIG_MAC_ACK_STATUS 0x00000004
+#define SG_DIG_AUTONEG_COMPLETE 0x00000002
+#define SG_DIG_AUTONEG_ERROR 0x00000001
+/* 0x5b8 --> 0x600 unused */
#define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */
#define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */
-/* 0x624 --> 0x800 unused */
+/* 0x624 --> 0x670 unused */
+
+#define MAC_RSS_INDIR_TBL_0 0x00000630
+
+#define MAC_RSS_HASH_KEY_0 0x00000670
+#define MAC_RSS_HASH_KEY_1 0x00000674
+#define MAC_RSS_HASH_KEY_2 0x00000678
+#define MAC_RSS_HASH_KEY_3 0x0000067c
+#define MAC_RSS_HASH_KEY_4 0x00000680
+#define MAC_RSS_HASH_KEY_5 0x00000684
+#define MAC_RSS_HASH_KEY_6 0x00000688
+#define MAC_RSS_HASH_KEY_7 0x0000068c
+#define MAC_RSS_HASH_KEY_8 0x00000690
+#define MAC_RSS_HASH_KEY_9 0x00000694
+/* 0x698 --> 0x800 unused */
+
#define MAC_TX_STATS_OCTETS 0x00000800
#define MAC_TX_STATS_RESV1 0x00000804
#define MAC_TX_STATS_COLLISIONS 0x00000808
@@ -642,7 +971,8 @@ typedef unsigned long dma_addr_t;
#define SNDDATAI_SCTRL_FORCE_ZERO 0x00000010
#define SNDDATAI_STATSENAB 0x00000c0c
#define SNDDATAI_STATSINCMASK 0x00000c10
-/* 0xc14 --> 0xc80 unused */
+#define ISO_PKT_TX 0x00000c20
+/* 0xc24 --> 0xc80 unused */
#define SNDDATAI_COS_CNT_0 0x00000c80
#define SNDDATAI_COS_CNT_1 0x00000c84
#define SNDDATAI_COS_CNT_2 0x00000c88
@@ -673,6 +1003,7 @@ typedef unsigned long dma_addr_t;
#define SNDDATAC_MODE 0x00001000
#define SNDDATAC_MODE_RESET 0x00000001
#define SNDDATAC_MODE_ENABLE 0x00000002
+#define SNDDATAC_MODE_CDELAY 0x00000010
/* 0x1004 --> 0x1400 unused */
/* Send BD ring selector */
@@ -707,6 +1038,7 @@ typedef unsigned long dma_addr_t;
#define SNDBDI_MODE_RESET 0x00000001
#define SNDBDI_MODE_ENABLE 0x00000002
#define SNDBDI_MODE_ATTN_ENABLE 0x00000004
+#define SNDBDI_MODE_MULTI_TXQ_EN 0x00000020
#define SNDBDI_STATUS 0x00001804
#define SNDBDI_STATUS_ERROR_ATTN 0x00000004
#define SNDBDI_IN_PROD_IDX_0 0x00001808
@@ -757,6 +1089,8 @@ typedef unsigned long dma_addr_t;
#define RCVLPC_STATSCTRL_ENABLE 0x00000001
#define RCVLPC_STATSCTRL_FASTUPD 0x00000002
#define RCVLPC_STATS_ENABLE 0x00002018
+#define RCVLPC_STATSENAB_ASF_FIX 0x00000002
+#define RCVLPC_STATSENAB_DACK_FIX 0x00040000
#define RCVLPC_STATSENAB_LNGBRST_RFIX 0x00400000
#define RCVLPC_STATS_INCMASK 0x0000201c
/* 0x2020 --> 0x2100 unused */
@@ -781,6 +1115,7 @@ typedef unsigned long dma_addr_t;
#define RCVDBDI_MODE_JUMBOBD_NEEDED 0x00000004
#define RCVDBDI_MODE_FRM_TOO_BIG 0x00000008
#define RCVDBDI_MODE_INV_RING_SZ 0x00000010
+#define RCVDBDI_MODE_LRG_RING_SZ 0x00010000
#define RCVDBDI_STATUS 0x00002404
#define RCVDBDI_STATUS_JUMBOBD_NEEDED 0x00000004
#define RCVDBDI_STATUS_FRM_TOO_BIG 0x00000008
@@ -833,7 +1168,11 @@ typedef unsigned long dma_addr_t;
#define RCVBDI_MINI_THRESH 0x00002c14
#define RCVBDI_STD_THRESH 0x00002c18
#define RCVBDI_JUMBO_THRESH 0x00002c1c
-/* 0x2c20 --> 0x3000 unused */
+/* 0x2c20 --> 0x2d00 unused */
+
+#define STD_REPLENISH_LWM 0x00002d00
+#define JMB_REPLENISH_LWM 0x00002d04
+/* 0x2d08 --> 0x3000 unused */
/* Receive BD Completion Control Registers */
#define RCVCC_MODE 0x00003000
@@ -854,7 +1193,75 @@ typedef unsigned long dma_addr_t;
#define RCVLSC_MODE_ATTN_ENABLE 0x00000004
#define RCVLSC_STATUS 0x00003404
#define RCVLSC_STATUS_ERROR_ATTN 0x00000004
-/* 0x3408 --> 0x3800 unused */
+/* 0x3408 --> 0x3600 unused */
+
+/* CPMU registers */
+#define TG3_CPMU_CTRL 0x00003600
+#define CPMU_CTRL_LINK_IDLE_MODE 0x00000200
+#define CPMU_CTRL_LINK_AWARE_MODE 0x00000400
+#define CPMU_CTRL_LINK_SPEED_MODE 0x00004000
+#define CPMU_CTRL_GPHY_10MB_RXONLY 0x00010000
+#define TG3_CPMU_LSPD_10MB_CLK 0x00003604
+#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000
+#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000
+/* 0x3608 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c
+#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000
+#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000
+#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000
+#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610
+#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000
+#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC 0x0000361c
+#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000
+#define CPMU_HST_ACC_MACCLK_6_25 0x00130000
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_ORIDE 0x00003624
+#define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000
+
+#define TG3_CPMU_CLCK_STAT 0x00003630
+#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000
+#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000
+#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000
+#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000
+/* 0x3634 --> 0x365c unused */
+
+#define TG3_CPMU_MUTEX_REQ 0x0000365c
+#define CPMU_MUTEX_REQ_DRIVER 0x00001000
+#define TG3_CPMU_MUTEX_GNT 0x00003660
+#define CPMU_MUTEX_GNT_DRIVER 0x00001000
+#define TG3_CPMU_PHY_STRAP 0x00003664
+#define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020
+/* 0x3664 --> 0x36b0 unused */
+
+#define TG3_CPMU_EEE_MODE 0x000036b0
+#define TG3_CPMU_EEEMD_APE_TX_DET_EN 0x00000004
+#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET 0x00000008
+#define TG3_CPMU_EEEMD_SND_IDX_DET_EN 0x00000040
+#define TG3_CPMU_EEEMD_LPI_ENABLE 0x00000080
+#define TG3_CPMU_EEEMD_LPI_IN_TX 0x00000100
+#define TG3_CPMU_EEEMD_LPI_IN_RX 0x00000200
+#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000
+#define TG3_CPMU_EEE_DBTMR1 0x000036b4
+#define TG3_CPMU_DBTMR1_PCIEXIT_2047US 0x07ff0000
+#define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000070ff
+#define TG3_CPMU_EEE_DBTMR2 0x000036b8
+#define TG3_CPMU_DBTMR2_APE_TX_2047US 0x07ff0000
+#define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000070ff
+#define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc
+#define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000
+#define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004
+/* 0x36c0 --> 0x36d0 unused */
+
+#define TG3_CPMU_EEE_CTRL 0x000036d0
+#define TG3_CPMU_EEE_CTRL_EXIT_16_5_US 0x0000019d
+#define TG3_CPMU_EEE_CTRL_EXIT_36_US 0x00000384
+#define TG3_CPMU_EEE_CTRL_EXIT_20_1_US 0x000001f8
+/* 0x36d4 --> 0x3800 unused */
/* Mbuf cluster free registers */
#define MBFREE_MODE 0x00003800
@@ -876,40 +1283,56 @@ typedef unsigned long dma_addr_t;
#define HOSTCC_MODE_CLRTICK_TXBD 0x00000400
#define HOSTCC_MODE_NOINT_ON_NOW 0x00000800
#define HOSTCC_MODE_NOINT_ON_FORCE 0x00001000
+#define HOSTCC_MODE_COAL_VEC1_NOW 0x00002000
#define HOSTCC_STATUS 0x00003c04
#define HOSTCC_STATUS_ERROR_ATTN 0x00000004
#define HOSTCC_RXCOL_TICKS 0x00003c08
#define LOW_RXCOL_TICKS 0x00000032
+#define LOW_RXCOL_TICKS_CLRTCKS 0x00000014
#define DEFAULT_RXCOL_TICKS 0x00000048
#define HIGH_RXCOL_TICKS 0x00000096
+#define MAX_RXCOL_TICKS 0x000003ff
#define HOSTCC_TXCOL_TICKS 0x00003c0c
#define LOW_TXCOL_TICKS 0x00000096
+#define LOW_TXCOL_TICKS_CLRTCKS 0x00000048
#define DEFAULT_TXCOL_TICKS 0x0000012c
#define HIGH_TXCOL_TICKS 0x00000145
+#define MAX_TXCOL_TICKS 0x000003ff
#define HOSTCC_RXMAX_FRAMES 0x00003c10
#define LOW_RXMAX_FRAMES 0x00000005
#define DEFAULT_RXMAX_FRAMES 0x00000008
#define HIGH_RXMAX_FRAMES 0x00000012
+#define MAX_RXMAX_FRAMES 0x000000ff
#define HOSTCC_TXMAX_FRAMES 0x00003c14
#define LOW_TXMAX_FRAMES 0x00000035
#define DEFAULT_TXMAX_FRAMES 0x0000004b
#define HIGH_TXMAX_FRAMES 0x00000052
+#define MAX_TXMAX_FRAMES 0x000000ff
#define HOSTCC_RXCOAL_TICK_INT 0x00003c18
#define DEFAULT_RXCOAL_TICK_INT 0x00000019
+#define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014
+#define MAX_RXCOAL_TICK_INT 0x000003ff
#define HOSTCC_TXCOAL_TICK_INT 0x00003c1c
#define DEFAULT_TXCOAL_TICK_INT 0x00000019
+#define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014
+#define MAX_TXCOAL_TICK_INT 0x000003ff
#define HOSTCC_RXCOAL_MAXF_INT 0x00003c20
#define DEFAULT_RXCOAL_MAXF_INT 0x00000005
+#define MAX_RXCOAL_MAXF_INT 0x000000ff
#define HOSTCC_TXCOAL_MAXF_INT 0x00003c24
#define DEFAULT_TXCOAL_MAXF_INT 0x00000005
+#define MAX_TXCOAL_MAXF_INT 0x000000ff
#define HOSTCC_STAT_COAL_TICKS 0x00003c28
#define DEFAULT_STAT_COAL_TICKS 0x000f4240
+#define MAX_STAT_COAL_TICKS 0xd693d400
+#define MIN_STAT_COAL_TICKS 0x00000064
/* 0x3c2c --> 0x3c30 unused */
#define HOSTCC_STATS_BLK_HOST_ADDR 0x00003c30 /* 64-bit */
#define HOSTCC_STATUS_BLK_HOST_ADDR 0x00003c38 /* 64-bit */
#define HOSTCC_STATS_BLK_NIC_ADDR 0x00003c40
#define HOSTCC_STATUS_BLK_NIC_ADDR 0x00003c44
#define HOSTCC_FLOW_ATTN 0x00003c48
+#define HOSTCC_FLOW_ATTN_MBUF_LWM 0x00000040
/* 0x3c4c --> 0x3c50 unused */
#define HOSTCC_JUMBO_CON_IDX 0x00003c50
#define HOSTCC_STD_CON_IDX 0x00003c54
@@ -947,7 +1370,16 @@ typedef unsigned long dma_addr_t;
#define HOSTCC_SND_CON_IDX_13 0x00003cf4
#define HOSTCC_SND_CON_IDX_14 0x00003cf8
#define HOSTCC_SND_CON_IDX_15 0x00003cfc
-/* 0x3d00 --> 0x4000 unused */
+#define HOSTCC_STATBLCK_RING1 0x00003d00
+/* 0x3d00 --> 0x3d80 unused */
+
+#define HOSTCC_RXCOL_TICKS_VEC1 0x00003d80
+#define HOSTCC_TXCOL_TICKS_VEC1 0x00003d84
+#define HOSTCC_RXMAX_FRAMES_VEC1 0x00003d88
+#define HOSTCC_TXMAX_FRAMES_VEC1 0x00003d8c
+#define HOSTCC_RXCOAL_MAXF_INT_VEC1 0x00003d90
+#define HOSTCC_TXCOAL_MAXF_INT_VEC1 0x00003d94
+/* 0x3d98 --> 0x4000 unused */
/* Memory arbiter control registers */
#define MEMARB_MODE 0x00004000
@@ -965,6 +1397,7 @@ typedef unsigned long dma_addr_t;
#define BUFMGR_MODE_ATTN_ENABLE 0x00000004
#define BUFMGR_MODE_BM_TEST 0x00000008
#define BUFMGR_MODE_MBLOW_ATTN_ENAB 0x00000010
+#define BUFMGR_MODE_NO_TX_UNDERRUN 0x80000000
#define BUFMGR_STATUS 0x00004404
#define BUFMGR_STATUS_ERROR 0x00000004
#define BUFMGR_STATUS_MBLOW 0x00000010
@@ -974,14 +1407,23 @@ typedef unsigned long dma_addr_t;
#define DEFAULT_MB_RDMA_LOW_WATER 0x00000050
#define DEFAULT_MB_RDMA_LOW_WATER_5705 0x00000000
#define DEFAULT_MB_RDMA_LOW_WATER_JUMBO 0x00000130
+#define DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780 0x00000000
#define BUFMGR_MB_MACRX_LOW_WATER 0x00004414
#define DEFAULT_MB_MACRX_LOW_WATER 0x00000020
#define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010
+#define DEFAULT_MB_MACRX_LOW_WATER_5906 0x00000004
+#define DEFAULT_MB_MACRX_LOW_WATER_57765 0x0000002a
#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098
+#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b
+#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765 0x0000007e
#define BUFMGR_MB_HIGH_WATER 0x00004418
#define DEFAULT_MB_HIGH_WATER 0x00000060
#define DEFAULT_MB_HIGH_WATER_5705 0x00000060
+#define DEFAULT_MB_HIGH_WATER_5906 0x00000010
+#define DEFAULT_MB_HIGH_WATER_57765 0x000000a0
#define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c
+#define DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096
+#define DEFAULT_MB_HIGH_WATER_JUMBO_57765 0x000000ea
#define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c
#define BUFMGR_MB_ALLOC_BIT 0x10000000
#define BUFMGR_RX_MB_ALLOC_RESP 0x00004420
@@ -1015,9 +1457,16 @@ typedef unsigned long dma_addr_t;
#define RDMAC_MODE_FIFOOREAD_ENAB 0x00000100
#define RDMAC_MODE_LNGREAD_ENAB 0x00000200
#define RDMAC_MODE_SPLIT_ENABLE 0x00000800
+#define RDMAC_MODE_BD_SBD_CRPT_ENAB 0x00000800
#define RDMAC_MODE_SPLIT_RESET 0x00001000
+#define RDMAC_MODE_MBUF_RBD_CRPT_ENAB 0x00001000
+#define RDMAC_MODE_MBUF_SBD_CRPT_ENAB 0x00002000
#define RDMAC_MODE_FIFO_SIZE_128 0x00020000
#define RDMAC_MODE_FIFO_LONG_BURST 0x00030000
+#define RDMAC_MODE_MULT_DMA_RD_DIS 0x01000000
+#define RDMAC_MODE_IPV4_LSO_EN 0x08000000
+#define RDMAC_MODE_IPV6_LSO_EN 0x10000000
+#define RDMAC_MODE_H2BNC_VLAN_DET 0x20000000
#define RDMAC_STATUS 0x00004804
#define RDMAC_STATUS_TGTABORT 0x00000004
#define RDMAC_STATUS_MSTABORT 0x00000008
@@ -1027,7 +1476,22 @@ typedef unsigned long dma_addr_t;
#define RDMAC_STATUS_FIFOURUN 0x00000080
#define RDMAC_STATUS_FIFOOREAD 0x00000100
#define RDMAC_STATUS_LNGREAD 0x00000200
-/* 0x4808 --> 0x4c00 unused */
+/* 0x4808 --> 0x4900 unused */
+
+#define TG3_RDMA_RSRVCTRL_REG 0x00004900
+#define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX 0x00000004
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K 0x00000c00
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK 0x00000ff0
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K 0x000c0000
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK 0x000ff000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_320B 0x28000000
+#define TG3_RDMA_RSRVCTRL_TXMRGN_MASK 0xffe00000
+/* 0x4904 --> 0x4910 unused */
+
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL 0x00004910
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K 0x000c0000
+/* 0x4914 --> 0x4c00 unused */
/* Write DMA control registers */
#define WDMAC_MODE 0x00004c00
@@ -1041,7 +1505,9 @@ typedef unsigned long dma_addr_t;
#define WDMAC_MODE_FIFOURUN_ENAB 0x00000080
#define WDMAC_MODE_FIFOOREAD_ENAB 0x00000100
#define WDMAC_MODE_LNGREAD_ENAB 0x00000200
-#define WDMAC_MODE_RX_ACCEL 0x00000400
+#define WDMAC_MODE_RX_ACCEL 0x00000400
+#define WDMAC_MODE_STATUS_TAG_FIX 0x20000000
+#define WDMAC_MODE_BURST_ALL_DATA 0xc0000000
#define WDMAC_STATUS 0x00004c04
#define WDMAC_STATUS_TGTABORT 0x00000004
#define WDMAC_STATUS_MSTABORT 0x00000008
@@ -1107,9 +1573,26 @@ typedef unsigned long dma_addr_t;
/* 0x280 --> 0x400 unused */
#define RX_CPU_BASE 0x00005000
+#define RX_CPU_MODE 0x00005000
+#define RX_CPU_STATE 0x00005004
+#define RX_CPU_PGMCTR 0x0000501c
+#define RX_CPU_HWBKPT 0x00005034
#define TX_CPU_BASE 0x00005400
+#define TX_CPU_MODE 0x00005400
+#define TX_CPU_STATE 0x00005404
+#define TX_CPU_PGMCTR 0x0000541c
+
+#define VCPU_STATUS 0x00005100
+#define VCPU_STATUS_INIT_DONE 0x04000000
+#define VCPU_STATUS_DRV_RESET 0x08000000
+
+#define VCPU_CFGSHDW 0x00005104
+#define VCPU_CFGSHDW_WOL_ENABLE 0x00000001
+#define VCPU_CFGSHDW_WOL_MAGPKT 0x00000004
+#define VCPU_CFGSHDW_ASPM_DBNC 0x00001000
/* Mailboxes */
+#define GRCMBOX_BASE 0x00005600
#define GRCMBOX_INTERRUPT_0 0x00005800 /* 64-bit */
#define GRCMBOX_INTERRUPT_1 0x00005808 /* 64-bit */
#define GRCMBOX_INTERRUPT_2 0x00005810 /* 64-bit */
@@ -1182,17 +1665,6 @@ typedef unsigned long dma_addr_t;
/* Flow Through queues */
#define FTQ_RESET 0x00005c00
-#define FTQ_RESET_DMA_READ_QUEUE (1 << 1)
-#define FTQ_RESET_DMA_HIGH_PRI_READ (1 << 2)
-#define FTQ_RESET_SEND_BD_COMPLETION (1 << 4)
-#define FTQ_RESET_DMA_WRITE (1 << 6)
-#define FTQ_RESET_DMA_HIGH_PRI_WRITE (1 << 7)
-#define FTQ_RESET_SEND_DATA_COMPLETION (1 << 9)
-#define FTQ_RESET_HOST_COALESCING (1 << 10)
-#define FTQ_RESET_MAC_TX (1 << 11)
-#define FTQ_RESET_RX_BD_COMPLETE (1 << 13)
-#define FTQ_RESET_RX_LIST_PLCMT (1 << 14)
-#define FTQ_RESET_RX_DATA_COMPLETION (1 << 16)
/* 0x5c04 --> 0x5c10 unused */
#define FTQ_DMA_NORM_READ_CTL 0x00005c10
#define FTQ_DMA_NORM_READ_FULL_CNT 0x00005c14
@@ -1268,7 +1740,10 @@ typedef unsigned long dma_addr_t;
#define MSGINT_MODE 0x00006000
#define MSGINT_MODE_RESET 0x00000001
#define MSGINT_MODE_ENABLE 0x00000002
+#define MSGINT_MODE_ONE_SHOT_DISABLE 0x00000020
+#define MSGINT_MODE_MULTIVEC_EN 0x00000080
#define MSGINT_STATUS 0x00006004
+#define MSGINT_STATUS_MSI_REQ 0x00000001
#define MSGINT_FIFO 0x00006008
/* 0x600c --> 0x6400 unused */
@@ -1285,6 +1760,8 @@ typedef unsigned long dma_addr_t;
#define GRC_MODE_WSWAP_NONFRM_DATA 0x00000004
#define GRC_MODE_BSWAP_DATA 0x00000010
#define GRC_MODE_WSWAP_DATA 0x00000020
+#define GRC_MODE_BYTE_SWAP_B2HRX_DATA 0x00000040
+#define GRC_MODE_WORD_SWAP_B2HRX_DATA 0x00000080
#define GRC_MODE_SPLITHDR 0x00000100
#define GRC_MODE_NOFRM_CRACKING 0x00000200
#define GRC_MODE_INCL_CRC 0x00000400
@@ -1292,9 +1769,14 @@ typedef unsigned long dma_addr_t;
#define GRC_MODE_NOIRQ_ON_SENDS 0x00002000
#define GRC_MODE_NOIRQ_ON_RCV 0x00004000
#define GRC_MODE_FORCE_PCI32BIT 0x00008000
+#define GRC_MODE_B2HRX_ENABLE 0x00008000
#define GRC_MODE_HOST_STACKUP 0x00010000
#define GRC_MODE_HOST_SENDBDS 0x00020000
+#define GRC_MODE_HTX2B_ENABLE 0x00040000
#define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000
+#define GRC_MODE_NVRAM_WR_ENABLE 0x00200000
+#define GRC_MODE_PCIE_TL_SEL 0x00000000
+#define GRC_MODE_PCIE_PL_SEL 0x00400000
#define GRC_MODE_NO_RX_PHDR_CSUM 0x00800000
#define GRC_MODE_IRQ_ON_TX_CPU_ATTN 0x01000000
#define GRC_MODE_IRQ_ON_RX_CPU_ATTN 0x02000000
@@ -1302,7 +1784,13 @@ typedef unsigned long dma_addr_t;
#define GRC_MODE_IRQ_ON_DMA_ATTN 0x08000000
#define GRC_MODE_IRQ_ON_FLOW_ATTN 0x10000000
#define GRC_MODE_4X_NIC_SEND_RINGS 0x20000000
+#define GRC_MODE_PCIE_DL_SEL 0x20000000
#define GRC_MODE_MCAST_FRM_ENABLE 0x40000000
+#define GRC_MODE_PCIE_HI_1K_EN 0x80000000
+#define GRC_MODE_PCIE_PORT_MASK (GRC_MODE_PCIE_TL_SEL | \
+ GRC_MODE_PCIE_PL_SEL | \
+ GRC_MODE_PCIE_DL_SEL | \
+ GRC_MODE_PCIE_HI_1K_EN)
#define GRC_MISC_CFG 0x00006804
#define GRC_MISC_CFG_CORECLK_RESET 0x00000001
#define GRC_MISC_CFG_PRESCALAR_MASK 0x000000fe
@@ -1319,12 +1807,19 @@ typedef unsigned long dma_addr_t;
#define GRC_MISC_CFG_BOARD_ID_5788 0x00010000
#define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000
#define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000
+#define GRC_MISC_CFG_EPHY_IDDQ 0x00200000
#define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000
#define GRC_LOCAL_CTRL 0x00006808
#define GRC_LCLCTRL_INT_ACTIVE 0x00000001
#define GRC_LCLCTRL_CLEARINT 0x00000002
#define GRC_LCLCTRL_SETINT 0x00000004
#define GRC_LCLCTRL_INT_ON_ATTN 0x00000008
+#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */
+#define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */
+#define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */
+#define GRC_LCLCTRL_GPIO_INPUT3 0x00000020
+#define GRC_LCLCTRL_GPIO_OE3 0x00000040
+#define GRC_LCLCTRL_GPIO_OUTPUT3 0x00000080
#define GRC_LCLCTRL_GPIO_INPUT0 0x00000100
#define GRC_LCLCTRL_GPIO_INPUT1 0x00000200
#define GRC_LCLCTRL_GPIO_INPUT2 0x00000400
@@ -1348,6 +1843,7 @@ typedef unsigned long dma_addr_t;
#define GRC_LCLCTRL_AUTO_SEEPROM 0x01000000
#define GRC_TIMER 0x0000680c
#define GRC_RX_CPU_EVENT 0x00006810
+#define GRC_RX_CPU_DRIVER_EVENT 0x00004000
#define GRC_RX_TIMER_REF 0x00006814
#define GRC_RX_CPU_SEM 0x00006818
#define GRC_REMOTE_RX_CPU_ATTN 0x0000681c
@@ -1373,7 +1869,11 @@ typedef unsigned long dma_addr_t;
#define GRC_EEPROM_CTRL 0x00006840
#define GRC_MDI_CTRL 0x00006844
#define GRC_SEEPROM_DELAY 0x00006848
-/* 0x684c --> 0x6c00 unused */
+/* 0x684c --> 0x6890 unused */
+#define GRC_VCPU_EXT_CTRL 0x00006890
+#define GRC_VCPU_EXT_CTRL_HALT_CPU 0x00400000
+#define GRC_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000
+#define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */
/* 0x6c00 --> 0x7000 unused */
@@ -1387,6 +1887,8 @@ typedef unsigned long dma_addr_t;
#define NVRAM_CMD_ERASE 0x00000040
#define NVRAM_CMD_FIRST 0x00000080
#define NVRAM_CMD_LAST 0x00000100
+#define NVRAM_CMD_WREN 0x00010000
+#define NVRAM_CMD_WRDI 0x00020000
#define NVRAM_STAT 0x00007004
#define NVRAM_WRDATA 0x00007008
#define NVRAM_ADDR 0x0000700c
@@ -1396,8 +1898,117 @@ typedef unsigned long dma_addr_t;
#define NVRAM_CFG1_FLASHIF_ENAB 0x00000001
#define NVRAM_CFG1_BUFFERED_MODE 0x00000002
#define NVRAM_CFG1_PASS_THRU 0x00000004
+#define NVRAM_CFG1_STATUS_BITS 0x00000070
#define NVRAM_CFG1_BIT_BANG 0x00000008
+#define NVRAM_CFG1_FLASH_SIZE 0x02000000
#define NVRAM_CFG1_COMPAT_BYPASS 0x80000000
+#define NVRAM_CFG1_VENDOR_MASK 0x03000003
+#define FLASH_VENDOR_ATMEL_EEPROM 0x02000000
+#define FLASH_VENDOR_ATMEL_FLASH_BUFFERED 0x02000003
+#define FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED 0x00000003
+#define FLASH_VENDOR_ST 0x03000001
+#define FLASH_VENDOR_SAIFUN 0x01000003
+#define FLASH_VENDOR_SST_SMALL 0x00000001
+#define FLASH_VENDOR_SST_LARGE 0x02000001
+#define NVRAM_CFG1_5752VENDOR_MASK 0x03c00003
+#define FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ 0x00000000
+#define FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ 0x02000000
+#define FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED 0x02000003
+#define FLASH_5752VENDOR_ST_M45PE10 0x02400000
+#define FLASH_5752VENDOR_ST_M45PE20 0x02400002
+#define FLASH_5752VENDOR_ST_M45PE40 0x02400001
+#define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001
+#define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002
+#define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000
+#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003
+#define FLASH_5755VENDOR_ATMEL_FLASH_5 0x02000003
+#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003
+#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002
+#define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003
+#define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002
+#define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000
+#define FLASH_5787VENDOR_MICRO_EEPROM_376KHZ 0x02000000
+#define FLASH_5761VENDOR_ATMEL_MDB021D 0x00800003
+#define FLASH_5761VENDOR_ATMEL_MDB041D 0x00800000
+#define FLASH_5761VENDOR_ATMEL_MDB081D 0x00800002
+#define FLASH_5761VENDOR_ATMEL_MDB161D 0x00800001
+#define FLASH_5761VENDOR_ATMEL_ADB021D 0x00000003
+#define FLASH_5761VENDOR_ATMEL_ADB041D 0x00000000
+#define FLASH_5761VENDOR_ATMEL_ADB081D 0x00000002
+#define FLASH_5761VENDOR_ATMEL_ADB161D 0x00000001
+#define FLASH_5761VENDOR_ST_M_M45PE20 0x02800001
+#define FLASH_5761VENDOR_ST_M_M45PE40 0x02800000
+#define FLASH_5761VENDOR_ST_M_M45PE80 0x02800002
+#define FLASH_5761VENDOR_ST_M_M45PE16 0x02800003
+#define FLASH_5761VENDOR_ST_A_M45PE20 0x02000001
+#define FLASH_5761VENDOR_ST_A_M45PE40 0x02000000
+#define FLASH_5761VENDOR_ST_A_M45PE80 0x02000002
+#define FLASH_5761VENDOR_ST_A_M45PE16 0x02000003
+#define FLASH_57780VENDOR_ATMEL_AT45DB011D 0x00400000
+#define FLASH_57780VENDOR_ATMEL_AT45DB011B 0x03400000
+#define FLASH_57780VENDOR_ATMEL_AT45DB021D 0x00400002
+#define FLASH_57780VENDOR_ATMEL_AT45DB021B 0x03400002
+#define FLASH_57780VENDOR_ATMEL_AT45DB041D 0x00400001
+#define FLASH_57780VENDOR_ATMEL_AT45DB041B 0x03400001
+#define FLASH_5717VENDOR_ATMEL_EEPROM 0x02000001
+#define FLASH_5717VENDOR_MICRO_EEPROM 0x02000003
+#define FLASH_5717VENDOR_ATMEL_MDB011D 0x01000001
+#define FLASH_5717VENDOR_ATMEL_MDB021D 0x01000003
+#define FLASH_5717VENDOR_ST_M_M25PE10 0x02000000
+#define FLASH_5717VENDOR_ST_M_M25PE20 0x02000002
+#define FLASH_5717VENDOR_ST_M_M45PE10 0x00000001
+#define FLASH_5717VENDOR_ST_M_M45PE20 0x00000003
+#define FLASH_5717VENDOR_ATMEL_ADB011B 0x01400000
+#define FLASH_5717VENDOR_ATMEL_ADB021B 0x01400002
+#define FLASH_5717VENDOR_ATMEL_ADB011D 0x01400001
+#define FLASH_5717VENDOR_ATMEL_ADB021D 0x01400003
+#define FLASH_5717VENDOR_ST_A_M25PE10 0x02400000
+#define FLASH_5717VENDOR_ST_A_M25PE20 0x02400002
+#define FLASH_5717VENDOR_ST_A_M45PE10 0x02400001
+#define FLASH_5717VENDOR_ST_A_M45PE20 0x02400003
+#define FLASH_5717VENDOR_ATMEL_45USPT 0x03400000
+#define FLASH_5717VENDOR_ST_25USPT 0x03400002
+#define FLASH_5717VENDOR_ST_45USPT 0x03400001
+#define FLASH_5720_EEPROM_HD 0x00000001
+#define FLASH_5720_EEPROM_LD 0x00000003
+#define FLASH_5720VENDOR_M_ATMEL_DB011D 0x01000000
+#define FLASH_5720VENDOR_M_ATMEL_DB021D 0x01000002
+#define FLASH_5720VENDOR_M_ATMEL_DB041D 0x01000001
+#define FLASH_5720VENDOR_M_ATMEL_DB081D 0x01000003
+#define FLASH_5720VENDOR_M_ST_M25PE10 0x02000000
+#define FLASH_5720VENDOR_M_ST_M25PE20 0x02000002
+#define FLASH_5720VENDOR_M_ST_M25PE40 0x02000001
+#define FLASH_5720VENDOR_M_ST_M25PE80 0x02000003
+#define FLASH_5720VENDOR_M_ST_M45PE10 0x03000000
+#define FLASH_5720VENDOR_M_ST_M45PE20 0x03000002
+#define FLASH_5720VENDOR_M_ST_M45PE40 0x03000001
+#define FLASH_5720VENDOR_M_ST_M45PE80 0x03000003
+#define FLASH_5720VENDOR_A_ATMEL_DB011B 0x01800000
+#define FLASH_5720VENDOR_A_ATMEL_DB021B 0x01800002
+#define FLASH_5720VENDOR_A_ATMEL_DB041B 0x01800001
+#define FLASH_5720VENDOR_A_ATMEL_DB011D 0x01c00000
+#define FLASH_5720VENDOR_A_ATMEL_DB021D 0x01c00002
+#define FLASH_5720VENDOR_A_ATMEL_DB041D 0x01c00001
+#define FLASH_5720VENDOR_A_ATMEL_DB081D 0x01c00003
+#define FLASH_5720VENDOR_A_ST_M25PE10 0x02800000
+#define FLASH_5720VENDOR_A_ST_M25PE20 0x02800002
+#define FLASH_5720VENDOR_A_ST_M25PE40 0x02800001
+#define FLASH_5720VENDOR_A_ST_M25PE80 0x02800003
+#define FLASH_5720VENDOR_A_ST_M45PE10 0x02c00000
+#define FLASH_5720VENDOR_A_ST_M45PE20 0x02c00002
+#define FLASH_5720VENDOR_A_ST_M45PE40 0x02c00001
+#define FLASH_5720VENDOR_A_ST_M45PE80 0x02c00003
+#define FLASH_5720VENDOR_ATMEL_45USPT 0x03c00000
+#define FLASH_5720VENDOR_ST_25USPT 0x03c00002
+#define FLASH_5720VENDOR_ST_45USPT 0x03c00001
+#define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000
+#define FLASH_5752PAGE_SIZE_256 0x00000000
+#define FLASH_5752PAGE_SIZE_512 0x10000000
+#define FLASH_5752PAGE_SIZE_1K 0x20000000
+#define FLASH_5752PAGE_SIZE_2K 0x30000000
+#define FLASH_5752PAGE_SIZE_4K 0x40000000
+#define FLASH_5752PAGE_SIZE_264 0x50000000
+#define FLASH_5752PAGE_SIZE_528 0x60000000
#define NVRAM_CFG2 0x00007018
#define NVRAM_CFG3 0x0000701c
#define NVRAM_SWARB 0x00007020
@@ -1417,11 +2028,142 @@ typedef unsigned long dma_addr_t;
#define SWARB_REQ1 0x00002000
#define SWARB_REQ2 0x00004000
#define SWARB_REQ3 0x00008000
-#define NVRAM_BUFFERED_PAGE_SIZE 264
-#define NVRAM_BUFFERED_PAGE_POS 9
-/* 0x7024 --> 0x7400 unused */
+#define NVRAM_ACCESS 0x00007024
+#define ACCESS_ENABLE 0x00000001
+#define ACCESS_WR_ENABLE 0x00000002
+#define NVRAM_WRITE1 0x00007028
+/* 0x702c unused */
+
+#define NVRAM_ADDR_LOCKOUT 0x00007030
+/* 0x7034 --> 0x7500 unused */
+
+#define OTP_MODE 0x00007500
+#define OTP_MODE_OTP_THRU_GRC 0x00000001
+#define OTP_CTRL 0x00007504
+#define OTP_CTRL_OTP_PROG_ENABLE 0x00200000
+#define OTP_CTRL_OTP_CMD_READ 0x00000000
+#define OTP_CTRL_OTP_CMD_INIT 0x00000008
+#define OTP_CTRL_OTP_CMD_START 0x00000001
+#define OTP_STATUS 0x00007508
+#define OTP_STATUS_CMD_DONE 0x00000001
+#define OTP_ADDRESS 0x0000750c
+#define OTP_ADDRESS_MAGIC1 0x000000a0
+#define OTP_ADDRESS_MAGIC2 0x00000080
+/* 0x7510 unused */
+
+#define OTP_READ_DATA 0x00007514
+/* 0x7518 --> 0x7c04 unused */
+
+#define PCIE_TRANSACTION_CFG 0x00007c04
+#define PCIE_TRANS_CFG_1SHOT_MSI 0x20000000
+#define PCIE_TRANS_CFG_LOM 0x00000020
+/* 0x7c08 --> 0x7d28 unused */
+
+#define PCIE_PWR_MGMT_THRESH 0x00007d28
+#define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00
+#define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00
+#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000
+/* 0x7d2c --> 0x7d54 unused */
+
+#define TG3_PCIE_LNKCTL 0x00007d54
+#define TG3_PCIE_LNKCTL_L1_PLL_PD_EN 0x00000008
+#define TG3_PCIE_LNKCTL_L1_PLL_PD_DIS 0x00000080
+/* 0x7d58 --> 0x7e70 unused */
+
+#define TG3_PCIE_PHY_TSTCTL 0x00007e2c
+#define TG3_PCIE_PHY_TSTCTL_PCIE10 0x00000040
+#define TG3_PCIE_PHY_TSTCTL_PSCRAM 0x00000020
+
+#define TG3_PCIE_EIDLE_DELAY 0x00007e70
+#define TG3_PCIE_EIDLE_DELAY_MASK 0x0000001f
+#define TG3_PCIE_EIDLE_DELAY_13_CLKS 0x0000000c
+/* 0x7e74 --> 0x8000 unused */
+
+
+/* Alternate PCIE definitions */
+#define TG3_PCIE_TLDLPL_PORT 0x00007c00
+#define TG3_PCIE_DL_LO_FTSMAX 0x0000000c
+#define TG3_PCIE_DL_LO_FTSMAX_MSK 0x000000ff
+#define TG3_PCIE_DL_LO_FTSMAX_VAL 0x0000002c
+#define TG3_PCIE_PL_LO_PHYCTL1 0x00000004
+#define TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN 0x00001000
+#define TG3_PCIE_PL_LO_PHYCTL5 0x00000014
+#define TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ 0x80000000
+
+#define TG3_REG_BLK_SIZE 0x00008000
+
+/* OTP bit definitions */
+#define TG3_OTP_AGCTGT_MASK 0x000000e0
+#define TG3_OTP_AGCTGT_SHIFT 1
+#define TG3_OTP_HPFFLTR_MASK 0x00000300
+#define TG3_OTP_HPFFLTR_SHIFT 1
+#define TG3_OTP_HPFOVER_MASK 0x00000400
+#define TG3_OTP_HPFOVER_SHIFT 1
+#define TG3_OTP_LPFDIS_MASK 0x00000800
+#define TG3_OTP_LPFDIS_SHIFT 11
+#define TG3_OTP_VDAC_MASK 0xff000000
+#define TG3_OTP_VDAC_SHIFT 24
+#define TG3_OTP_10BTAMP_MASK 0x0000f000
+#define TG3_OTP_10BTAMP_SHIFT 8
+#define TG3_OTP_ROFF_MASK 0x00e00000
+#define TG3_OTP_ROFF_SHIFT 11
+#define TG3_OTP_RCOFF_MASK 0x001c0000
+#define TG3_OTP_RCOFF_SHIFT 16
+
+#define TG3_OTP_DEFAULT 0x286c1640
+
+
+/* Hardware Legacy NVRAM layout */
+#define TG3_NVM_VPD_OFF 0x100
+#define TG3_NVM_VPD_LEN 256
+
+/* Hardware Selfboot NVRAM layout */
+#define TG3_NVM_HWSB_CFG1 0x00000004
+#define TG3_NVM_HWSB_CFG1_MAJMSK 0xf8000000
+#define TG3_NVM_HWSB_CFG1_MAJSFT 27
+#define TG3_NVM_HWSB_CFG1_MINMSK 0x07c00000
+#define TG3_NVM_HWSB_CFG1_MINSFT 22
+
+#define TG3_EEPROM_MAGIC 0x669955aa
+#define TG3_EEPROM_MAGIC_FW 0xa5000000
+#define TG3_EEPROM_MAGIC_FW_MSK 0xff000000
+#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000
+#define TG3_EEPROM_SB_FORMAT_1 0x00200000
+#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000
+#define TG3_EEPROM_SB_REVISION_0 0x00000000
+#define TG3_EEPROM_SB_REVISION_2 0x00020000
+#define TG3_EEPROM_SB_REVISION_3 0x00030000
+#define TG3_EEPROM_SB_REVISION_4 0x00040000
+#define TG3_EEPROM_SB_REVISION_5 0x00050000
+#define TG3_EEPROM_SB_REVISION_6 0x00060000
+#define TG3_EEPROM_MAGIC_HW 0xabcd
+#define TG3_EEPROM_MAGIC_HW_MSK 0xffff
+
+#define TG3_NVM_DIR_START 0x18
+#define TG3_NVM_DIR_END 0x78
+#define TG3_NVM_DIRENT_SIZE 0xc
+#define TG3_NVM_DIRTYPE_SHIFT 24
+#define TG3_NVM_DIRTYPE_LENMSK 0x003fffff
+#define TG3_NVM_DIRTYPE_ASFINI 1
+#define TG3_NVM_DIRTYPE_EXTVPD 20
+#define TG3_NVM_PTREV_BCVER 0x94
+#define TG3_NVM_BCVER_MAJMSK 0x0000ff00
+#define TG3_NVM_BCVER_MAJSFT 8
+#define TG3_NVM_BCVER_MINMSK 0x000000ff
+
+#define TG3_EEPROM_SB_F1R0_EDH_OFF 0x10
+#define TG3_EEPROM_SB_F1R2_EDH_OFF 0x14
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+#define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18
+#define TG3_EEPROM_SB_F1R4_EDH_OFF 0x1c
+#define TG3_EEPROM_SB_F1R5_EDH_OFF 0x20
+#define TG3_EEPROM_SB_F1R6_EDH_OFF 0x4c
+#define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700
+#define TG3_EEPROM_SB_EDH_MAJ_SHFT 8
+#define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff
+#define TG3_EEPROM_SB_EDH_BLD_MASK 0x0000f800
+#define TG3_EEPROM_SB_EDH_BLD_SHFT 11
-/* 0x7400 --> 0x8000 unused */
/* 32K Window into NIC internal memory */
#define NIC_SRAM_WIN_BASE 0x00008000
@@ -1442,11 +2184,9 @@ typedef unsigned long dma_addr_t;
#define NIC_SRAM_DATA_CFG 0x00000b58
#define NIC_SRAM_DATA_CFG_LED_MODE_MASK 0x0000000c
-#define NIC_SRAM_DATA_CFG_LED_MODE_UNKNOWN 0x00000000
-#define NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD 0x00000004
-#define NIC_SRAM_DATA_CFG_LED_OPEN_DRAIN 0x00000004
-#define NIC_SRAM_DATA_CFG_LED_LINK_SPD 0x00000008
-#define NIC_SRAM_DATA_CFG_LED_OUTPUT 0x00000008
+#define NIC_SRAM_DATA_CFG_LED_MODE_MAC 0x00000000
+#define NIC_SRAM_DATA_CFG_LED_MODE_PHY_1 0x00000004
+#define NIC_SRAM_DATA_CFG_LED_MODE_PHY_2 0x00000008
#define NIC_SRAM_DATA_CFG_PHY_TYPE_MASK 0x00000030
#define NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN 0x00000000
#define NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER 0x00000010
@@ -1456,6 +2196,11 @@ typedef unsigned long dma_addr_t;
#define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100
#define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000
#define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000
+#define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000
+#define NIC_SRAM_DATA_CFG_APE_ENABLE 0x00200000
+
+#define NIC_SRAM_DATA_VER 0x00000b5c
+#define NIC_SRAM_DATA_VER_SHIFT 16
#define NIC_SRAM_DATA_PHY_ID 0x00000b74
#define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000
@@ -1468,12 +2213,17 @@ typedef unsigned long dma_addr_t;
#define FWCMD_NICDRV_IPV6ADDR_CHG 0x00000004
#define FWCMD_NICDRV_FIX_DMAR 0x00000005
#define FWCMD_NICDRV_FIX_DMAW 0x00000006
+#define FWCMD_NICDRV_LINK_UPDATE 0x0000000c
+#define FWCMD_NICDRV_ALIVE2 0x0000000d
+#define FWCMD_NICDRV_ALIVE3 0x0000000e
#define NIC_SRAM_FW_CMD_LEN_MBOX 0x00000b7c
#define NIC_SRAM_FW_CMD_DATA_MBOX 0x00000b80
#define NIC_SRAM_FW_ASF_STATUS_MBOX 0x00000c00
#define NIC_SRAM_FW_DRV_STATE_MBOX 0x00000c04
#define DRV_STATE_START 0x00000001
+#define DRV_STATE_START_DONE 0x80000001
#define DRV_STATE_UNLOAD 0x00000002
+#define DRV_STATE_UNLOAD_DONE 0x80000002
#define DRV_STATE_WOL 0x00000003
#define DRV_STATE_SUSPEND 0x00000004
@@ -1482,6 +2232,30 @@ typedef unsigned long dma_addr_t;
#define NIC_SRAM_MAC_ADDR_HIGH_MBOX 0x00000c14
#define NIC_SRAM_MAC_ADDR_LOW_MBOX 0x00000c18
+#define NIC_SRAM_WOL_MBOX 0x00000d30
+#define WOL_SIGNATURE 0x474c0000
+#define WOL_DRV_STATE_SHUTDOWN 0x00000001
+#define WOL_DRV_WOL 0x00000002
+#define WOL_SET_MAGIC_PKT 0x00000004
+
+#define NIC_SRAM_DATA_CFG_2 0x00000d38
+
+#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00000400
+#define SHASTA_EXT_LED_MODE_MASK 0x00018000
+#define SHASTA_EXT_LED_LEGACY 0x00000000
+#define SHASTA_EXT_LED_SHARED 0x00008000
+#define SHASTA_EXT_LED_MAC 0x00010000
+#define SHASTA_EXT_LED_COMBO 0x00018000
+
+#define NIC_SRAM_DATA_CFG_3 0x00000d3c
+#define NIC_SRAM_ASPM_DEBOUNCE 0x00000002
+
+#define NIC_SRAM_DATA_CFG_4 0x00000d60
+#define NIC_SRAM_GMII_MODE 0x00000002
+#define NIC_SRAM_RGMII_INBAND_DISABLE 0x00000004
+#define NIC_SRAM_RGMII_EXT_IBND_RX_EN 0x00000008
+#define NIC_SRAM_RGMII_EXT_IBND_TX_EN 0x00000010
+
#define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000
#define NIC_SRAM_DMA_DESC_POOL_BASE 0x00002000
@@ -1495,10 +2269,19 @@ typedef unsigned long dma_addr_t;
#define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000
#define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5700 128
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5755 64
+#define TG3_SRAM_RX_STD_BDCACHE_SIZE_5906 32
+
+#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5700 64
+#define TG3_SRAM_RX_JMB_BDCACHE_SIZE_5717 16
+
+
/* Currently this is fixed. */
-#define PHY_ADDR 0x01
+#define TG3_PHY_MII_ADDR 0x01
+
-/* Tigon3 specific PHY MII registers. */
+/*** Tigon3 specific PHY MII registers. ***/
#define TG3_BMCR_SPEED1000 0x0040
#define MII_TG3_CTRL 0x09 /* 1000-baseT control register */
@@ -1507,20 +2290,67 @@ typedef unsigned long dma_addr_t;
#define MII_TG3_CTRL_AS_MASTER 0x0800
#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
+#define MII_TG3_MMD_CTRL 0x0d /* MMD Access Control register */
+#define MII_TG3_MMD_CTRL_DATA_NOINC 0x4000
+#define MII_TG3_MMD_ADDRESS 0x0e /* MMD Address Data register */
+
#define MII_TG3_EXT_CTRL 0x10 /* Extended control register */
+#define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001
#define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002
+#define MII_TG3_EXT_CTRL_FORCE_LED_OFF 0x0008
#define MII_TG3_EXT_CTRL_TBI 0x8000
#define MII_TG3_EXT_STAT 0x11 /* Extended status register */
#define MII_TG3_EXT_STAT_LPASS 0x0100
+#define MII_TG3_RXR_COUNTERS 0x14 /* Local/Remote Receiver Counts */
#define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */
-
+#define MII_TG3_DSP_CONTROL 0x16 /* DSP control register */
#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */
-#define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */
-
-#define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */
+#define MII_TG3_DSP_TAP1 0x0001
+#define MII_TG3_DSP_TAP1_AGCTGT_DFLT 0x0007
+#define MII_TG3_DSP_TAP26 0x001a
+#define MII_TG3_DSP_TAP26_ALNOKO 0x0001
+#define MII_TG3_DSP_TAP26_RMRXSTO 0x0002
+#define MII_TG3_DSP_TAP26_OPCSINPT 0x0004
+#define MII_TG3_DSP_AADJ1CH0 0x001f
+#define MII_TG3_DSP_CH34TP2 0x4022
+#define MII_TG3_DSP_CH34TP2_HIBW01 0x017b
+#define MII_TG3_DSP_AADJ1CH3 0x601f
+#define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002
+#define MII_TG3_DSP_EXP1_INT_STAT 0x0f01
+#define MII_TG3_DSP_EXP8 0x0f08
+#define MII_TG3_DSP_EXP8_REJ2MHz 0x0001
+#define MII_TG3_DSP_EXP8_AEDW 0x0200
+#define MII_TG3_DSP_EXP75 0x0f75
+#define MII_TG3_DSP_EXP96 0x0f96
+#define MII_TG3_DSP_EXP97 0x0f97
+
+#define MII_TG3_AUX_CTRL 0x18 /* auxiliary control register */
+
+#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000
+#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400
+#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800
+#define MII_TG3_AUXCTL_ACTL_EXTPKTLEN 0x4000
+
+#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002
+#define MII_TG3_AUXCTL_PCTL_WOL_EN 0x0008
+#define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010
+#define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE 0x0020
+#define MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC 0x0040
+#define MII_TG3_AUXCTL_PCTL_VREG_11V 0x0180
+
+#define MII_TG3_AUXCTL_SHDWSEL_MISCTEST 0x0004
+
+#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007
+#define MII_TG3_AUXCTL_MISC_WIRESPD_EN 0x0010
+#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200
+#define MII_TG3_AUXCTL_MISC_RDSEL_SHIFT 12
+#define MII_TG3_AUXCTL_MISC_WREN 0x8000
+
+
+#define MII_TG3_AUX_STAT 0x19 /* auxiliary status register */
#define MII_TG3_AUX_STAT_LPASS 0x0004
#define MII_TG3_AUX_STAT_SPDMASK 0x0700
#define MII_TG3_AUX_STAT_10HALF 0x0100
@@ -1530,6 +2360,8 @@ typedef unsigned long dma_addr_t;
#define MII_TG3_AUX_STAT_100FULL 0x0500
#define MII_TG3_AUX_STAT_1000HALF 0x0600
#define MII_TG3_AUX_STAT_1000FULL 0x0700
+#define MII_TG3_AUX_STAT_100 0x0008
+#define MII_TG3_AUX_STAT_FULL 0x0001
#define MII_TG3_ISTAT 0x1a /* IRQ status register */
#define MII_TG3_IMASK 0x1b /* IRQ mask register */
@@ -1540,13 +2372,121 @@ typedef unsigned long dma_addr_t;
#define MII_TG3_INT_DUPLEXCHG 0x0008
#define MII_TG3_INT_ANEG_PAGE_RX 0x0400
+#define MII_TG3_MISC_SHDW 0x1c
+#define MII_TG3_MISC_SHDW_WREN 0x8000
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
+#define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020
+#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
+
+#define MII_TG3_MISC_SHDW_SCR5_C125OE 0x0001
+#define MII_TG3_MISC_SHDW_SCR5_DLLAPD 0x0002
+#define MII_TG3_MISC_SHDW_SCR5_SDTL 0x0004
+#define MII_TG3_MISC_SHDW_SCR5_DLPTLM 0x0008
+#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010
+#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400
+
+#define MII_TG3_TEST1 0x1e
+#define MII_TG3_TEST1_TRIM_EN 0x0010
+#define MII_TG3_TEST1_CRC_EN 0x8000
+
+/* Clause 45 expansion registers */
+#define TG3_CL45_D7_EEERES_STAT 0x803e
+#define TG3_CL45_D7_EEERES_STAT_LP_100TX 0x0002
+#define TG3_CL45_D7_EEERES_STAT_LP_1000T 0x0004
+
+
+/* Fast Ethernet Tranceiver definitions */
+#define MII_TG3_FET_PTEST 0x17
+#define MII_TG3_FET_PTEST_FRC_TX_LINK 0x1000
+#define MII_TG3_FET_PTEST_FRC_TX_LOCK 0x0800
+
+#define MII_TG3_FET_TEST 0x1f
+#define MII_TG3_FET_SHADOW_EN 0x0080
+
+#define MII_TG3_FET_SHDW_MISCCTRL 0x10
+#define MII_TG3_FET_SHDW_MISCCTRL_MDIX 0x4000
+
+#define MII_TG3_FET_SHDW_AUXMODE4 0x1a
+#define MII_TG3_FET_SHDW_AUXMODE4_SBPD 0x0008
+
+#define MII_TG3_FET_SHDW_AUXSTAT2 0x1b
+#define MII_TG3_FET_SHDW_AUXSTAT2_APD 0x0020
+
+
+/* APE registers. Accessible through BAR1 */
+#define TG3_APE_EVENT 0x000c
+#define APE_EVENT_1 0x00000001
+#define TG3_APE_LOCK_REQ 0x002c
+#define APE_LOCK_REQ_DRIVER 0x00001000
+#define TG3_APE_LOCK_GRANT 0x004c
+#define APE_LOCK_GRANT_DRIVER 0x00001000
+#define TG3_APE_SEG_SIG 0x4000
+#define APE_SEG_SIG_MAGIC 0x41504521
+
+/* APE shared memory. Accessible through BAR1 */
+#define TG3_APE_FW_STATUS 0x400c
+#define APE_FW_STATUS_READY 0x00000100
+#define TG3_APE_FW_FEATURES 0x4010
+#define TG3_APE_FW_FEATURE_NCSI 0x00000002
+#define TG3_APE_FW_VERSION 0x4018
+#define APE_FW_VERSION_MAJMSK 0xff000000
+#define APE_FW_VERSION_MAJSFT 24
+#define APE_FW_VERSION_MINMSK 0x00ff0000
+#define APE_FW_VERSION_MINSFT 16
+#define APE_FW_VERSION_REVMSK 0x0000ff00
+#define APE_FW_VERSION_REVSFT 8
+#define APE_FW_VERSION_BLDMSK 0x000000ff
+#define TG3_APE_HOST_SEG_SIG 0x4200
+#define APE_HOST_SEG_SIG_MAGIC 0x484f5354
+#define TG3_APE_HOST_SEG_LEN 0x4204
+#define APE_HOST_SEG_LEN_MAGIC 0x00000020
+#define TG3_APE_HOST_INIT_COUNT 0x4208
+#define TG3_APE_HOST_DRIVER_ID 0x420c
+#define APE_HOST_DRIVER_ID_LINUX 0xf0000000
+#define APE_HOST_DRIVER_ID_MAGIC(maj, min) \
+ (APE_HOST_DRIVER_ID_LINUX | (maj & 0xff) << 16 | (min & 0xff) << 8)
+#define TG3_APE_HOST_BEHAVIOR 0x4210
+#define APE_HOST_BEHAV_NO_PHYLOCK 0x00000001
+#define TG3_APE_HOST_HEARTBEAT_INT_MS 0x4214
+#define APE_HOST_HEARTBEAT_INT_DISABLE 0
+#define APE_HOST_HEARTBEAT_INT_5SEC 5000
+#define TG3_APE_HOST_HEARTBEAT_COUNT 0x4218
+#define TG3_APE_HOST_DRVR_STATE 0x421c
+#define TG3_APE_HOST_DRVR_STATE_START 0x00000001
+#define TG3_APE_HOST_DRVR_STATE_UNLOAD 0x00000002
+#define TG3_APE_HOST_DRVR_STATE_WOL 0x00000003
+#define TG3_APE_HOST_WOL_SPEED 0x4224
+#define TG3_APE_HOST_WOL_SPEED_AUTO 0x00008000
+
+#define TG3_APE_EVENT_STATUS 0x4300
+
+#define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010
+#define APE_EVENT_STATUS_STATE_CHNGE 0x00000500
+#define APE_EVENT_STATUS_STATE_START 0x00010000
+#define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000
+#define APE_EVENT_STATUS_STATE_WOL 0x00030000
+#define APE_EVENT_STATUS_STATE_SUSPEND 0x00040000
+#define APE_EVENT_STATUS_EVENT_PENDING 0x80000000
+
+#define TG3_APE_PER_LOCK_REQ 0x8400
+#define APE_LOCK_PER_REQ_DRIVER 0x00001000
+#define TG3_APE_PER_LOCK_GRANT 0x8420
+#define APE_PER_LOCK_GRANT_DRIVER 0x00001000
+
+/* APE convenience enumerations. */
+#define TG3_APE_LOCK_GRC 1
+#define TG3_APE_LOCK_MEM 4
+
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+
/* There are two ways to manage the TX descriptors on the tigon3.
* Either the descriptors are in host DMA'able memory, or they
* exist only in the cards on-chip SRAM. All 16 send bds are under
* the same mode, they may not be configured individually.
*
- * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags.
+ * This driver always uses host memory TX descriptors.
*
* To use host memory TX descriptors:
* 1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register.
@@ -1578,14 +2518,15 @@ typedef unsigned long dma_addr_t;
* TG3_BDINFO_MAXLEN_FLAGS of all unused SEND_RCB indices.
*/
struct tg3_tx_buffer_desc {
- uint32_t addr_hi;
- uint32_t addr_lo;
+ u32 addr_hi;
+ u32 addr_lo;
- uint32_t len_flags;
+ u32 len_flags;
#define TXD_FLAG_TCPUDP_CSUM 0x0001
#define TXD_FLAG_IP_CSUM 0x0002
#define TXD_FLAG_END 0x0004
#define TXD_FLAG_IP_FRAG 0x0008
+#define TXD_FLAG_JMB_PKT 0x0008
#define TXD_FLAG_IP_FRAG_END 0x0010
#define TXD_FLAG_VLAN 0x0040
#define TXD_FLAG_COAL_NOW 0x0080
@@ -1596,7 +2537,7 @@ struct tg3_tx_buffer_desc {
#define TXD_FLAG_NO_CRC 0x8000
#define TXD_LEN_SHIFT 16
- uint32_t vlan_tag;
+ u32 vlan_tag;
#define TXD_VLAN_TAG_SHIFT 0
#define TXD_MSS_SHIFT 16
};
@@ -1607,16 +2548,16 @@ struct tg3_tx_buffer_desc {
#define TXD_SIZE 0x10UL
struct tg3_rx_buffer_desc {
- uint32_t addr_hi;
- uint32_t addr_lo;
+ u32 addr_hi;
+ u32 addr_lo;
- uint32_t idx_len;
+ u32 idx_len;
#define RXD_IDX_MASK 0xffff0000
#define RXD_IDX_SHIFT 16
#define RXD_LEN_MASK 0x0000ffff
#define RXD_LEN_SHIFT 0
- uint32_t type_flags;
+ u32 type_flags;
#define RXD_TYPE_SHIFT 16
#define RXD_FLAGS_SHIFT 0
@@ -1629,13 +2570,13 @@ struct tg3_rx_buffer_desc {
#define RXD_FLAG_TCPUDP_CSUM 0x2000
#define RXD_FLAG_IS_TCP 0x4000
- uint32_t ip_tcp_csum;
+ u32 ip_tcp_csum;
#define RXD_IPCSUM_MASK 0xffff0000
#define RXD_IPCSUM_SHIFT 16
#define RXD_TCPCSUM_MASK 0x0000ffff
#define RXD_TCPCSUM_SHIFT 0
- uint32_t err_vlan;
+ u32 err_vlan;
#define RXD_VLAN_MASK 0x0000ffff
@@ -1650,8 +2591,8 @@ struct tg3_rx_buffer_desc {
#define RXD_ERR_HUGE_FRAME 0x01000000
#define RXD_ERR_MASK 0xffff0000
- uint32_t reserved;
- uint32_t opaque;
+ u32 reserved;
+ u32 opaque;
#define RXD_OPAQUE_INDEX_MASK 0x0000ffff
#define RXD_OPAQUE_INDEX_SHIFT 0
#define RXD_OPAQUE_RING_STD 0x00010000
@@ -1662,11 +2603,11 @@ struct tg3_rx_buffer_desc {
struct tg3_ext_rx_buffer_desc {
struct {
- uint32_t addr_hi;
- uint32_t addr_lo;
+ u32 addr_hi;
+ u32 addr_lo;
} addrlist[3];
- uint32_t len2_len1;
- uint32_t resv_len3;
+ u32 len2_len1;
+ u32 resv_len3;
struct tg3_rx_buffer_desc std;
};
@@ -1675,68 +2616,68 @@ struct tg3_ext_rx_buffer_desc {
* descriptors used by the chip at NIC_SRAM_DMA_DESCS.
*/
struct tg3_internal_buffer_desc {
- uint32_t addr_hi;
- uint32_t addr_lo;
- uint32_t nic_mbuf;
+ u32 addr_hi;
+ u32 addr_lo;
+ u32 nic_mbuf;
/* XXX FIX THIS */
#if __BYTE_ORDER == __BIG_ENDIAN
- uint16_t cqid_sqid;
- uint16_t len;
+ u16 cqid_sqid;
+ u16 len;
#else
- uint16_t len;
- uint16_t cqid_sqid;
+ u16 len;
+ u16 cqid_sqid;
#endif
- uint32_t flags;
- uint32_t __cookie1;
- uint32_t __cookie2;
- uint32_t __cookie3;
+ u32 flags;
+ u32 __cookie1;
+ u32 __cookie2;
+ u32 __cookie3;
};
#define TG3_HW_STATUS_SIZE 0x50
struct tg3_hw_status {
- uint32_t status;
+ u32 status;
#define SD_STATUS_UPDATED 0x00000001
#define SD_STATUS_LINK_CHG 0x00000002
#define SD_STATUS_ERROR 0x00000004
- uint32_t status_tag;
+ u32 status_tag;
#if __BYTE_ORDER == __BIG_ENDIAN
- uint16_t rx_consumer;
- uint16_t rx_jumbo_consumer;
+ u16 rx_consumer;
+ u16 rx_jumbo_consumer;
#else
- uint16_t rx_jumbo_consumer;
- uint16_t rx_consumer;
+ u16 rx_jumbo_consumer;
+ u16 rx_consumer;
#endif
-#if __BYTE_ORDER == __BIG_ENDIAN
- uint16_t reserved;
- uint16_t rx_mini_consumer;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 reserved;
+ u16 rx_mini_consumer;
#else
- uint16_t rx_mini_consumer;
- uint16_t reserved;
+ u16 rx_mini_consumer;
+ u16 reserved;
#endif
struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- uint16_t tx_consumer;
- uint16_t rx_producer;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 tx_consumer;
+ u16 rx_producer;
#else
- uint16_t rx_producer;
- uint16_t tx_consumer;
+ u16 rx_producer;
+ u16 tx_consumer;
#endif
} idx[16];
};
typedef struct {
- uint32_t high, low;
+ u32 high, low;
} tg3_stat64_t;
struct tg3_hw_stats {
- uint8_t __reserved0[0x400-0x300];
+ u8 __reserved0[0x400-0x300];
/* Statistics maintained by Receive MAC. */
tg3_stat64_t rx_octets;
- uint64_t __reserved1;
+ u64 __reserved1;
tg3_stat64_t rx_fragments;
tg3_stat64_t rx_ucast_packets;
tg3_stat64_t rx_mcast_packets;
@@ -1763,11 +2704,11 @@ struct tg3_hw_stats {
tg3_stat64_t rx_4096_to_8191_octet_packets;
tg3_stat64_t rx_8192_to_9022_octet_packets;
- uint64_t __unused0[37];
+ u64 __unused0[37];
/* Statistics maintained by Transmit MAC. */
tg3_stat64_t tx_octets;
- uint64_t __reserved2;
+ u64 __reserved2;
tg3_stat64_t tx_collisions;
tg3_stat64_t tx_xon_sent;
tg3_stat64_t tx_xoff_sent;
@@ -1776,7 +2717,7 @@ struct tg3_hw_stats {
tg3_stat64_t tx_single_collisions;
tg3_stat64_t tx_mult_collisions;
tg3_stat64_t tx_deferred;
- uint64_t __reserved3;
+ u64 __reserved3;
tg3_stat64_t tx_excessive_collisions;
tg3_stat64_t tx_late_collisions;
tg3_stat64_t tx_collide_2times;
@@ -1800,7 +2741,7 @@ struct tg3_hw_stats {
tg3_stat64_t tx_discards;
tg3_stat64_t tx_errors;
- uint64_t __unused1[31];
+ u64 __unused1[31];
/* Statistics maintained by Receive List Placement. */
tg3_stat64_t COS_rx_packets[16];
@@ -1812,7 +2753,7 @@ struct tg3_hw_stats {
tg3_stat64_t rx_errors;
tg3_stat64_t rx_threshold_hit;
- uint64_t __unused2[9];
+ u64 __unused2[9];
/* Statistics maintained by Send Data Initiator. */
tg3_stat64_t COS_out_packets[16];
@@ -1827,295 +2768,658 @@ struct tg3_hw_stats {
tg3_stat64_t nic_avoided_irqs;
tg3_stat64_t nic_tx_threshold_hit;
- uint8_t __reserved4[0xb00-0x9c0];
-};
+ /* NOT a part of the hardware statistics block format.
+ * These stats are here as storage for tg3_periodic_fetch_stats().
+ */
+ tg3_stat64_t mbuf_lwm_thresh_hit;
-enum phy_led_mode {
- led_mode_auto,
- led_mode_three_link,
- led_mode_link10
+ u8 __reserved4[0xb00-0x9c8];
};
-#if 0
+typedef u32 dma_addr_t;
+
/* 'mapping' is superfluous as the chip does not write into
* the tx/rx post rings so we could just fetch it from there.
* But the cache behavior is better how we are doing it now.
*/
struct ring_info {
- struct sk_buff *skb;
- DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
-struct tx_ring_info {
- struct sk_buff *skb;
- DECLARE_PCI_UNMAP_ADDR(mapping)
- uint32_t prev_vlan_tag;
-};
-#endif
-
-struct tg3_config_info {
- uint32_t flags;
+ struct io_buffer *iob;
+/// dma_addr_t mapping;
};
struct tg3_link_config {
/* Describes what we're trying to get. */
- uint32_t advertising;
-#if 0
- uint16_t speed;
- uint8_t duplex;
- uint8_t autoneg;
+ u32 advertising;
+ u16 speed;
+ u8 duplex;
+ u8 autoneg;
+ u8 flowctrl;
+
+ /* Describes what we actually have. */
+ u8 active_flowctrl;
+
+ u8 active_duplex;
#define SPEED_INVALID 0xffff
#define DUPLEX_INVALID 0xff
#define AUTONEG_INVALID 0xff
-#endif
-
- /* Describes what we actually have. */
- uint8_t active_speed;
- uint8_t active_duplex;
+ u16 active_speed;
/* When we go in and out of low power mode we need
* to swap with this state.
*/
-#if 0
- int phy_is_low_power;
- uint16_t orig_speed;
- uint8_t orig_duplex;
- uint8_t orig_autoneg;
-#endif
+ u16 orig_speed;
+ u8 orig_duplex;
+ u8 orig_autoneg;
+ u32 orig_advertising;
};
struct tg3_bufmgr_config {
- uint32_t mbuf_read_dma_low_water;
- uint32_t mbuf_mac_rx_low_water;
- uint32_t mbuf_high_water;
+ u32 mbuf_read_dma_low_water;
+ u32 mbuf_mac_rx_low_water;
+ u32 mbuf_high_water;
- uint32_t mbuf_read_dma_low_water_jumbo;
- uint32_t mbuf_mac_rx_low_water_jumbo;
- uint32_t mbuf_high_water_jumbo;
+ u32 mbuf_read_dma_low_water_jumbo;
+ u32 mbuf_mac_rx_low_water_jumbo;
+ u32 mbuf_high_water_jumbo;
- uint32_t dma_low_water;
- uint32_t dma_high_water;
+ u32 dma_low_water;
+ u32 dma_high_water;
};
+struct tg3_ethtool_stats {
+ /* Statistics maintained by Receive MAC. */
+ u64 rx_octets;
+ u64 rx_fragments;
+ u64 rx_ucast_packets;
+ u64 rx_mcast_packets;
+ u64 rx_bcast_packets;
+ u64 rx_fcs_errors;
+ u64 rx_align_errors;
+ u64 rx_xon_pause_rcvd;
+ u64 rx_xoff_pause_rcvd;
+ u64 rx_mac_ctrl_rcvd;
+ u64 rx_xoff_entered;
+ u64 rx_frame_too_long_errors;
+ u64 rx_jabbers;
+ u64 rx_undersize_packets;
+ u64 rx_in_length_errors;
+ u64 rx_out_length_errors;
+ u64 rx_64_or_less_octet_packets;
+ u64 rx_65_to_127_octet_packets;
+ u64 rx_128_to_255_octet_packets;
+ u64 rx_256_to_511_octet_packets;
+ u64 rx_512_to_1023_octet_packets;
+ u64 rx_1024_to_1522_octet_packets;
+ u64 rx_1523_to_2047_octet_packets;
+ u64 rx_2048_to_4095_octet_packets;
+ u64 rx_4096_to_8191_octet_packets;
+ u64 rx_8192_to_9022_octet_packets;
+
+ /* Statistics maintained by Transmit MAC. */
+ u64 tx_octets;
+ u64 tx_collisions;
+ u64 tx_xon_sent;
+ u64 tx_xoff_sent;
+ u64 tx_flow_control;
+ u64 tx_mac_errors;
+ u64 tx_single_collisions;
+ u64 tx_mult_collisions;
+ u64 tx_deferred;
+ u64 tx_excessive_collisions;
+ u64 tx_late_collisions;
+ u64 tx_collide_2times;
+ u64 tx_collide_3times;
+ u64 tx_collide_4times;
+ u64 tx_collide_5times;
+ u64 tx_collide_6times;
+ u64 tx_collide_7times;
+ u64 tx_collide_8times;
+ u64 tx_collide_9times;
+ u64 tx_collide_10times;
+ u64 tx_collide_11times;
+ u64 tx_collide_12times;
+ u64 tx_collide_13times;
+ u64 tx_collide_14times;
+ u64 tx_collide_15times;
+ u64 tx_ucast_packets;
+ u64 tx_mcast_packets;
+ u64 tx_bcast_packets;
+ u64 tx_carrier_sense_errors;
+ u64 tx_discards;
+ u64 tx_errors;
+
+ /* Statistics maintained by Receive List Placement. */
+ u64 dma_writeq_full;
+ u64 dma_write_prioq_full;
+ u64 rxbds_empty;
+ u64 rx_discards;
+ u64 rx_errors;
+ u64 rx_threshold_hit;
+
+ /* Statistics maintained by Send Data Initiator. */
+ u64 dma_readq_full;
+ u64 dma_read_prioq_full;
+ u64 tx_comp_queue_full;
+
+ /* Statistics maintained by Host Coalescing. */
+ u64 ring_set_send_prod_index;
+ u64 ring_status_update;
+ u64 nic_irqs;
+ u64 nic_avoided_irqs;
+ u64 nic_tx_threshold_hit;
+
+ u64 mbuf_lwm_thresh_hit;
+};
+
+/* number of io_buffers to allocate */
+#define TG3_DEF_RX_RING_PENDING 8
+
+struct tg3_rx_prodring_set {
+ u32 rx_std_prod_idx;
+ u32 rx_std_cons_idx;
+ u32 rx_std_iob_cnt;
+ struct tg3_rx_buffer_desc *rx_std;
+ struct io_buffer *rx_iobufs[TG3_DEF_RX_RING_PENDING];
+ dma_addr_t rx_std_mapping;
+};
+
+#define TG3_IRQ_MAX_VECS_RSS 5
+#define TG3_IRQ_MAX_VECS TG3_IRQ_MAX_VECS_RSS
+
+enum TG3_FLAGS {
+ TG3_FLAG_TAGGED_STATUS = 0,
+ TG3_FLAG_TXD_MBOX_HWBUG,
+ TG3_FLAG_USE_LINKCHG_REG,
+ TG3_FLAG_ERROR_PROCESSED,
+ TG3_FLAG_ENABLE_ASF,
+ TG3_FLAG_ASPM_WORKAROUND,
+ TG3_FLAG_POLL_SERDES,
+ TG3_FLAG_MBOX_WRITE_REORDER,
+ TG3_FLAG_PCIX_TARGET_HWBUG,
+ TG3_FLAG_WOL_SPEED_100MB,
+ TG3_FLAG_WOL_ENABLE,
+ TG3_FLAG_EEPROM_WRITE_PROT,
+ TG3_FLAG_NVRAM,
+ TG3_FLAG_NVRAM_BUFFERED,
+ TG3_FLAG_SUPPORT_MSI,
+ TG3_FLAG_SUPPORT_MSIX,
+ TG3_FLAG_PCIX_MODE,
+ TG3_FLAG_PCI_HIGH_SPEED,
+ TG3_FLAG_PCI_32BIT,
+ TG3_FLAG_SRAM_USE_CONFIG,
+ TG3_FLAG_TX_RECOVERY_PENDING,
+ TG3_FLAG_WOL_CAP,
+ TG3_FLAG_JUMBO_RING_ENABLE,
+ TG3_FLAG_PAUSE_AUTONEG,
+ TG3_FLAG_CPMU_PRESENT,
+ TG3_FLAG_BROKEN_CHECKSUMS,
+ TG3_FLAG_JUMBO_CAPABLE,
+ TG3_FLAG_CHIP_RESETTING,
+ TG3_FLAG_INIT_COMPLETE,
+ TG3_FLAG_RESTART_TIMER,
+ TG3_FLAG_TSO_BUG,
+ TG3_FLAG_IS_5788,
+ TG3_FLAG_MAX_RXPEND_64,
+ TG3_FLAG_TSO_CAPABLE,
+ TG3_FLAG_PCI_EXPRESS,
+ TG3_FLAG_ASF_NEW_HANDSHAKE,
+ TG3_FLAG_HW_AUTONEG,
+ TG3_FLAG_IS_NIC,
+ TG3_FLAG_FLASH,
+ TG3_FLAG_HW_TSO_1,
+ TG3_FLAG_5705_PLUS,
+ TG3_FLAG_5750_PLUS,
+ TG3_FLAG_HW_TSO_3,
+ TG3_FLAG_USING_MSI,
+ TG3_FLAG_USING_MSIX,
+ TG3_FLAG_ICH_WORKAROUND,
+ TG3_FLAG_5780_CLASS,
+ TG3_FLAG_HW_TSO_2,
+ TG3_FLAG_1SHOT_MSI,
+ TG3_FLAG_NO_FWARE_REPORTED,
+ TG3_FLAG_NO_NVRAM_ADDR_TRANS,
+ TG3_FLAG_ENABLE_APE,
+ TG3_FLAG_PROTECTED_NVRAM,
+ TG3_FLAG_MDIOBUS_INITED,
+ TG3_FLAG_LRG_PROD_RING_CAP,
+ TG3_FLAG_RGMII_INBAND_DISABLE,
+ TG3_FLAG_RGMII_EXT_IBND_RX_EN,
+ TG3_FLAG_RGMII_EXT_IBND_TX_EN,
+ TG3_FLAG_CLKREQ_BUG,
+ TG3_FLAG_5755_PLUS,
+ TG3_FLAG_NO_NVRAM,
+ TG3_FLAG_ENABLE_RSS,
+ TG3_FLAG_ENABLE_TSS,
+ TG3_FLAG_4G_DMA_BNDRY_BUG,
+ TG3_FLAG_USE_JUMBO_BDFLAG,
+ TG3_FLAG_L1PLLPD_EN,
+ TG3_FLAG_57765_PLUS,
+ TG3_FLAG_APE_HAS_NCSI,
+ TG3_FLAG_5717_PLUS,
+
+ /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
+ TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */
+};
+
+/* Following definition is copied from linux-3.0rc1/include/linux/kernel.h */
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+/* bitops.h */
+#define BITS_PER_BYTE 8
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+/* types.h: */
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
struct tg3 {
-#if 0
+ /* begin "general, frequently-used members" cacheline section */
+
+ /* If the IRQ handler (which runs lockless) needs to be
+ * quiesced, the following bitmask state is used. The
+ * SYNC flag is set by non-IRQ context code to initiate
+ * the quiescence.
+ *
+ * When the IRQ handler notices that SYNC is set, it
+ * disables interrupts and returns.
+ *
+ * When all outstanding IRQ handlers have returned after
+ * the SYNC flag has been set, the setter can be assured
+ * that interrupts will no longer get run.
+ *
+ * In this way all SMP driver locks are never acquired
+ * in hw IRQ context, only sw IRQ context or lower.
+ */
+ unsigned int irq_sync;
+
/* SMP locking strategy:
*
- * lock: Held during all operations except TX packet
- * processing.
+ * lock: Held during reset, PHY access, timer, and when
+ * updating tg3_flags.
+ *
+ * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds
+ * netif_tx_lock when it needs to call
+ * netif_wake_queue.
*
- * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx
+ * Both of these locks are to be held with BH safety.
*
- * If you want to shut up all asynchronous processing you must
- * acquire both locks, 'lock' taken before 'tx_lock'. IRQs must
- * be disabled to take 'lock' but only softirq disabling is
- * necessary for acquisition of 'tx_lock'.
+ * Because the IRQ handler, tg3_poll, and tg3_start_xmit
+ * are running lockless, it is necessary to completely
+ * quiesce the chip with tg3_netif_stop and tg3_full_lock
+ * before reconfiguring the device.
+ *
+ * indirect_lock: Held when accessing registers indirectly
+ * with IRQ disabling.
*/
- spinlock_t lock;
- spinlock_t tx_lock;
-#endif
- uint32_t tx_prod;
-#if 0
- uint32_t tx_cons;
-#endif
- uint32_t rx_rcb_ptr;
- uint32_t rx_std_ptr;
-#if 0
- uint32_t rx_jumbo_ptr;
- spinlock_t indirect_lock;
-
- struct net_device_stats net_stats;
- struct net_device_stats net_stats_prev;
-#endif
- unsigned long phy_crc_errors;
+ u32 (*read32_mbox) (struct tg3 *, u32);
+ void (*write32_mbox) (struct tg3 *, u32,
+ u32);
+ void *regs;
+ struct net_device *dev;
+ struct pci_device *pdev;
-#if 0
- uint32_t rx_offset;
-#endif
- uint32_t tg3_flags;
-#if 0
-#define TG3_FLAG_HOST_TXDS 0x00000001
-#endif
-#define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002
-#define TG3_FLAG_RX_CHECKSUMS 0x00000004
-#define TG3_FLAG_USE_LINKCHG_REG 0x00000008
-#define TG3_FLAG_USE_MI_INTERRUPT 0x00000010
-#define TG3_FLAG_ENABLE_ASF 0x00000020
-#define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040
-#define TG3_FLAG_POLL_SERDES 0x00000080
-#define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100
-#define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200
-#define TG3_FLAG_WOL_SPEED_100MB 0x00000400
-#define TG3_FLAG_WOL_ENABLE 0x00000800
-#define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000
-#define TG3_FLAG_NVRAM 0x00002000
-#define TG3_FLAG_NVRAM_BUFFERED 0x00004000
-#define TG3_FLAG_RX_PAUSE 0x00008000
-#define TG3_FLAG_TX_PAUSE 0x00010000
-#define TG3_FLAG_PCIX_MODE 0x00020000
-#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
-#define TG3_FLAG_PCI_32BIT 0x00080000
-#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000
-#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000
-#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
-#define TG3_FLAG_JUMBO_ENABLE 0x00800000
-#define TG3_FLAG_10_100_ONLY 0x01000000
-#define TG3_FLAG_PAUSE_AUTONEG 0x02000000
-#define TG3_FLAG_PAUSE_RX 0x04000000
-#define TG3_FLAG_PAUSE_TX 0x08000000
-#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
-#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
-#define TG3_FLAG_SPLIT_MODE 0x40000000
-#define TG3_FLAG_INIT_COMPLETE 0x80000000
-
- uint32_t tg3_flags2;
-#define TG3_FLG2_RESTART_TIMER 0x00000001
-#define TG3_FLG2_SUN_5704 0x00000002
-#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004
-#define TG3_FLG2_IS_5788 0x00000008
-#define TG3_FLG2_MAX_RXPEND_64 0x00000010
-#define TG3_FLG2_TSO_CAPABLE 0x00000020
- // Alf: Hope I'm not breaking anything here !
-#define TG3_FLG2_PCI_EXPRESS 0x00000040
-
-
-
- uint32_t split_mode_max_reqs;
-#define SPLIT_MODE_5704_MAX_REQ 3
-
-#if 0
- struct timer_list timer;
- uint16_t timer_counter;
- uint16_t timer_multiplier;
- uint32_t timer_offset;
- uint16_t asf_counter;
- uint16_t asf_multiplier;
-#endif
+ u32 msg_enable;
- struct tg3_link_config link_config;
- struct tg3_bufmgr_config bufmgr_config;
+ /* begin "tx thread" cacheline section */
+ void (*write32_tx_mbox) (struct tg3 *, u32,
+ u32);
-#if 0
- uint32_t rx_pending;
- uint32_t rx_jumbo_pending;
- uint32_t tx_pending;
-#endif
+ /* begin "rx thread" cacheline section */
+ void (*write32_rx_mbox) (struct tg3 *, u32,
+ u32);
+ u32 rx_std_max_post;
+ u32 rx_pkt_map_sz;
- /* cache h/w values, often passed straight to h/w */
- uint32_t rx_mode;
- uint32_t tx_mode;
- uint32_t mac_mode;
- uint32_t mi_mode;
- uint32_t misc_host_ctrl;
- uint32_t grc_mode;
- uint32_t grc_local_ctrl;
- uint32_t dma_rwctrl;
-#if 0
- uint32_t coalesce_mode;
-#endif
+ /* was struct tg3_napi: */
+ struct tg3_hw_status *hw_status;
- /* PCI block */
- uint16_t pci_chip_rev_id;
-#if 0
- uint8_t pci_cacheline_sz;
- uint8_t pci_lat_timer;
- uint8_t pci_hdr_type;
- uint8_t pci_bist;
-#endif
- uint32_t pci_cfg_state[64 / sizeof(uint32_t)];
+ u32 last_tag;
+ u32 last_irq_tag;
+ u32 int_mbox;
+ /* NOTE: there was a coal_now in struct tg3_napi and struct tg3. We
+ * didn't use coal_now in struct tg3, so it was removed */
+ u32 coal_now;
+
+ u32 consmbox;
+ u32 rx_rcb_ptr;
+ u16 *rx_rcb_prod_idx;
+ struct tg3_rx_prodring_set prodring;
+ struct tg3_rx_buffer_desc *rx_rcb;
- int pm_cap;
+ u32 tx_prod;
+ u32 tx_cons;
+ u32 prodmbox;
+ struct tg3_tx_buffer_desc *tx_ring;
+ struct ring_info *tx_buffers;
- /* PHY info */
- uint32_t phy_id;
-#define PHY_ID_MASK 0xfffffff0
-#define PHY_ID_BCM5400 0x60008040
-#define PHY_ID_BCM5401 0x60008050
-#define PHY_ID_BCM5411 0x60008070
-#define PHY_ID_BCM5701 0x60008110
-#define PHY_ID_BCM5703 0x60008160
-#define PHY_ID_BCM5704 0x60008190
-#define PHY_ID_BCM5705 0x600081a0
-#define PHY_ID_BCM5750 0x60008180
-#define PHY_ID_BCM5787 0xbc050ce0
-#define PHY_ID_BCM8002 0x60010140
-#define PHY_ID_BCM5751 0x00206180
-#define PHY_ID_SERDES 0xfeedbee0
-#define PHY_ID_INVALID 0xffffffff
-#define PHY_ID_REV_MASK 0x0000000f
-#define PHY_REV_BCM5401_B0 0x1
-#define PHY_REV_BCM5401_B2 0x3
-#define PHY_REV_BCM5401_C0 0x6
-#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */
-
- enum phy_led_mode led_mode;
-
- char board_part_number[24];
- uint32_t nic_sram_data_cfg;
- uint32_t pci_clock_ctrl;
-#if 0
- struct pci_device *pdev_peer;
-#endif
+ dma_addr_t status_mapping;
+ dma_addr_t rx_rcb_mapping;
+ dma_addr_t tx_desc_mapping;
+ /* end tg3_napi */
- /* This macro assumes the passed PHY ID is already masked
- * with PHY_ID_MASK.
- */
-#define KNOWN_PHY_ID(X) \
- ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \
- (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
- (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
- (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
- (X) == PHY_ID_BCM5751 || (X) == PHY_ID_BCM5787 || \
- (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
-
- unsigned long regs;
- struct pci_device *pdev;
- struct nic *nic;
-#if 0
- struct net_device *dev;
-#endif
-#if TG3_VLAN_TAG_USED
- struct vlan_group *vlgrp;
-#endif
+ /* begin "everything else" cacheline(s) section */
+ unsigned long rx_dropped;
- struct tg3_rx_buffer_desc *rx_std;
-#if 0
- struct ring_info *rx_std_buffers;
- dma_addr_t rx_std_mapping;
- struct tg3_rx_buffer_desc *rx_jumbo;
- struct ring_info *rx_jumbo_buffers;
- dma_addr_t rx_jumbo_mapping;
-#endif
+ DECLARE_BITMAP(tg3_flags, TG3_FLAG_NUMBER_OF_FLAGS);
- struct tg3_rx_buffer_desc *rx_rcb;
-#if 0
- dma_addr_t rx_rcb_mapping;
-#endif
+ union {
+ unsigned long phy_crc_errors;
+ };
- /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */
- struct tg3_tx_buffer_desc *tx_ring;
-#if 0
- struct tx_ring_info *tx_buffers;
- dma_addr_t tx_desc_mapping;
-#endif
+ u16 timer_counter;
+ u16 timer_multiplier;
+ u32 timer_offset;
+ u16 asf_counter;
+ u16 asf_multiplier;
- struct tg3_hw_status *hw_status;
-#if 0
- dma_addr_t status_mapping;
-#endif
-#if 0
- uint32_t msg_enable;
-#endif
+ /* 1 second counter for transient serdes link events */
+ u32 serdes_counter;
+#define SERDES_AN_TIMEOUT_5704S 2
+#define SERDES_PARALLEL_DET_TIMEOUT 1
+#define SERDES_AN_TIMEOUT_5714S 1
- struct tg3_hw_stats *hw_stats;
-#if 0
- dma_addr_t stats_mapping;
-#endif
+ struct tg3_link_config link_config;
+ struct tg3_bufmgr_config bufmgr_config;
+
+ /* cache h/w values, often passed straight to h/w */
+ u32 rx_mode;
+ u32 tx_mode;
+ u32 mac_mode;
+ u32 mi_mode;
+ u32 misc_host_ctrl;
+ u32 grc_mode;
+ u32 grc_local_ctrl;
+ u32 dma_rwctrl;
+ u32 coalesce_mode;
+
+ /* PCI block */
+ u32 pci_chip_rev_id;
+ u16 pci_cmd;
+ u8 pci_cacheline_sz;
+ u8 pci_lat_timer;
- int carrier_ok;
- uint16_t subsystem_vendor;
- uint16_t subsystem_device;
+ int pm_cap;
+ union {
+ int pcix_cap;
+ int pcie_cap;
+ };
+ int pcie_readrq;
+
+ u8 phy_addr;
+
+ /* PHY info */
+ u32 phy_id;
+#define TG3_PHY_ID_MASK 0xfffffff0
+#define TG3_PHY_ID_BCM5400 0x60008040
+#define TG3_PHY_ID_BCM5401 0x60008050
+#define TG3_PHY_ID_BCM5411 0x60008070
+#define TG3_PHY_ID_BCM5701 0x60008110
+#define TG3_PHY_ID_BCM5703 0x60008160
+#define TG3_PHY_ID_BCM5704 0x60008190
+#define TG3_PHY_ID_BCM5705 0x600081a0
+#define TG3_PHY_ID_BCM5750 0x60008180
+#define TG3_PHY_ID_BCM5752 0x60008100
+#define TG3_PHY_ID_BCM5714 0x60008340
+#define TG3_PHY_ID_BCM5780 0x60008350
+#define TG3_PHY_ID_BCM5755 0xbc050cc0
+#define TG3_PHY_ID_BCM5787 0xbc050ce0
+#define TG3_PHY_ID_BCM5756 0xbc050ed0
+#define TG3_PHY_ID_BCM5784 0xbc050fa0
+#define TG3_PHY_ID_BCM5761 0xbc050fd0
+#define TG3_PHY_ID_BCM5718C 0x5c0d8a00
+#define TG3_PHY_ID_BCM5718S 0xbc050ff0
+#define TG3_PHY_ID_BCM57765 0x5c0d8a40
+#define TG3_PHY_ID_BCM5719C 0x5c0d8a20
+#define TG3_PHY_ID_BCM5720C 0x5c0d8b60
+#define TG3_PHY_ID_BCM5906 0xdc00ac40
+#define TG3_PHY_ID_BCM8002 0x60010140
+#define TG3_PHY_ID_INVALID 0xffffffff
+
+#define PHY_ID_RTL8211C 0x001cc910
+#define PHY_ID_RTL8201E 0x00008200
+
+#define TG3_PHY_ID_REV_MASK 0x0000000f
+#define TG3_PHY_REV_BCM5401_B0 0x1
+
+ /* This macro assumes the passed PHY ID is
+ * already masked with TG3_PHY_ID_MASK.
+ */
+#define TG3_KNOWN_PHY_ID(X) \
+ ((X) == TG3_PHY_ID_BCM5400 || (X) == TG3_PHY_ID_BCM5401 || \
+ (X) == TG3_PHY_ID_BCM5411 || (X) == TG3_PHY_ID_BCM5701 || \
+ (X) == TG3_PHY_ID_BCM5703 || (X) == TG3_PHY_ID_BCM5704 || \
+ (X) == TG3_PHY_ID_BCM5705 || (X) == TG3_PHY_ID_BCM5750 || \
+ (X) == TG3_PHY_ID_BCM5752 || (X) == TG3_PHY_ID_BCM5714 || \
+ (X) == TG3_PHY_ID_BCM5780 || (X) == TG3_PHY_ID_BCM5787 || \
+ (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \
+ (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \
+ (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \
+ (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM5719C || \
+ (X) == TG3_PHY_ID_BCM8002)
+
+ u32 phy_flags;
+#define TG3_PHYFLG_IS_LOW_POWER 0x00000001
+#define TG3_PHYFLG_IS_CONNECTED 0x00000002
+#define TG3_PHYFLG_USE_MI_INTERRUPT 0x00000004
+#define TG3_PHYFLG_PHY_SERDES 0x00000010
+#define TG3_PHYFLG_MII_SERDES 0x00000020
+#define TG3_PHYFLG_ANY_SERDES (TG3_PHYFLG_PHY_SERDES | \
+ TG3_PHYFLG_MII_SERDES)
+#define TG3_PHYFLG_IS_FET 0x00000040
+#define TG3_PHYFLG_10_100_ONLY 0x00000080
+#define TG3_PHYFLG_ENABLE_APD 0x00000100
+#define TG3_PHYFLG_CAPACITIVE_COUPLING 0x00000200
+#define TG3_PHYFLG_NO_ETH_WIRE_SPEED 0x00000400
+#define TG3_PHYFLG_JITTER_BUG 0x00000800
+#define TG3_PHYFLG_ADJUST_TRIM 0x00001000
+#define TG3_PHYFLG_ADC_BUG 0x00002000
+#define TG3_PHYFLG_5704_A0_BUG 0x00004000
+#define TG3_PHYFLG_BER_BUG 0x00008000
+#define TG3_PHYFLG_SERDES_PREEMPHASIS 0x00010000
+#define TG3_PHYFLG_PARALLEL_DETECT 0x00020000
+#define TG3_PHYFLG_EEE_CAP 0x00040000
+
+ u32 led_ctrl;
+ u32 phy_otp;
+ u32 setlpicnt;
+
+#define TG3_BPN_SIZE 24
+ char board_part_number[TG3_BPN_SIZE];
+#define TG3_VER_SIZE 32
+ char fw_ver[TG3_VER_SIZE];
+ u32 nic_sram_data_cfg;
+ u32 pci_clock_ctrl;
+ struct pci_device *pdev_peer;
+
+ int nvram_lock_cnt;
+ u32 nvram_size;
+#define TG3_NVRAM_SIZE_2KB 0x00000800
+#define TG3_NVRAM_SIZE_64KB 0x00010000
+#define TG3_NVRAM_SIZE_128KB 0x00020000
+#define TG3_NVRAM_SIZE_256KB 0x00040000
+#define TG3_NVRAM_SIZE_512KB 0x00080000
+#define TG3_NVRAM_SIZE_1MB 0x00100000
+#define TG3_NVRAM_SIZE_2MB 0x00200000
+
+ u32 nvram_pagesize;
+ u32 nvram_jedecnum;
+
+#define JEDEC_ATMEL 0x1f
+#define JEDEC_ST 0x20
+#define JEDEC_SAIFUN 0x4f
+#define JEDEC_SST 0xbf
+
+#define ATMEL_AT24C02_CHIP_SIZE TG3_NVRAM_SIZE_2KB
+#define ATMEL_AT24C02_PAGE_SIZE (8)
+
+#define ATMEL_AT24C64_CHIP_SIZE TG3_NVRAM_SIZE_64KB
+#define ATMEL_AT24C64_PAGE_SIZE (32)
+
+#define ATMEL_AT24C512_CHIP_SIZE TG3_NVRAM_SIZE_512KB
+#define ATMEL_AT24C512_PAGE_SIZE (128)
+
+#define ATMEL_AT45DB0X1B_PAGE_POS 9
+#define ATMEL_AT45DB0X1B_PAGE_SIZE 264
+
+#define ATMEL_AT25F512_PAGE_SIZE 256
+
+#define ST_M45PEX0_PAGE_SIZE 256
+
+#define SAIFUN_SA25F0XX_PAGE_SIZE 256
+
+#define SST_25VF0X0_PAGE_SIZE 4098
+
+ u16 subsystem_vendor;
+ u16 subsystem_device;
};
+#define ARRAY_SIZE(x) ( sizeof(x) / sizeof((x)[0]) )
+
+#define TG3_TX_RING_SIZE 512
+#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1)
+
+/* FIXME: look up alignment requirement in datasheet, page align for now */
+#define TG3_DMA_ALIGNMENT 4096
+
+#define TG3_RX_STD_DMA_SZ (1536 + 64 + 2)
+
+static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
+{
+ tp->write32_mbox(tp, off, val);
+/// if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND))
+/// tp->read32_mbox(tp, off);
+}
+
+u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off);
+void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val);
+u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off);
+void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val);
+
+#define tw32(reg, val) tg3_write_indirect_reg32(tp, reg, val)
+///#define tw32_mailbox(reg, val) tg3_write_indirect_mbox(((val) & 0xffffffff), tp->regs + (reg))
+#define tw32_mailbox(reg, val) tg3_write_indirect_mbox(tp, (reg), (val))
+#define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val))
+#define tw32_f(reg, val) _tw32_flush(tp, (reg), (val), 0)
+#define tw32_wait_f(reg, val, us) _tw32_flush(tp, (reg), (val), (us))
+
+#define tw32_tx_mbox(reg, val) tp->write32_tx_mbox(tp, reg, val)
+#define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val)
+
+#define tr32(reg) tg3_read_indirect_reg32(tp, reg)
+#define tr32_mailbox(reg) tp->read32_mbox(tp, reg)
+
+/* Functions & macros to verify TG3_FLAGS types */
+
+static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
+{
+ int oldbit;
+
+ asm volatile("bt %2,%1\n\t"
+ "sbb %0,%0"
+ : "=r" (oldbit)
+ : "m" (*(unsigned long *)addr), "Ir" (nr));
+
+ return oldbit;
+}
+
+static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits)
+{
+ return variable_test_bit(flag, bits);
+}
+
+#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+ asm volatile("bts %1,%0" : BITOP_ADDR(addr) : "Ir" (nr) : "memory");
+}
+
+static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits)
+{
+ __set_bit(flag, bits);
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+ asm volatile("btr %1,%0" : BITOP_ADDR(addr) : "Ir" (nr));
+}
+
+static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
+{
+ __clear_bit(flag, bits);
+}
+
+#define tg3_flag(tp, flag) \
+ _tg3_flag(TG3_FLAG_##flag, (tp)->tg3_flags)
+#define tg3_flag_set(tp, flag) \
+ _tg3_flag_set(TG3_FLAG_##flag, (tp)->tg3_flags)
+#define tg3_flag_clear(tp, flag) \
+ _tg3_flag_clear(TG3_FLAG_##flag, (tp)->tg3_flags)
+
+/* tg3_main.c forward declarations */
+int tg3_init_rings(struct tg3 *tp);
+void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr);
+///int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);
+
+/* tg3_phy.c forward declarations */
+u32 tg3_read_otp_phycfg(struct tg3 *tp);
+void tg3_mdio_init(struct tg3 *tp);
+int tg3_phy_probe(struct tg3 *tp);
+int tg3_phy_reset(struct tg3 *tp);
+int tg3_setup_phy(struct tg3 *tp, int force_reset);
+int tg3_readphy(struct tg3 *tp, int reg, u32 *val);
+int tg3_writephy(struct tg3 *tp, int reg, u32 val);
+
+/* tg3_hw.c forward declarations */
+void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait);
+void tg3_write_mem(struct tg3 *tp, u32 off, u32 val);
+int tg3_get_invariants(struct tg3 *tp);
+void tg3_init_bufmgr_config(struct tg3 *tp);
+int tg3_get_device_address(struct tg3 *tp);
+int tg3_halt(struct tg3 *tp);
+void tg3_set_txd(struct tg3 *tp, int entry, dma_addr_t mapping, int len, u32 flags);
+void tg3_set_power_state_0(struct tg3 *tp);
+int tg3_alloc_consistent(struct tg3 *tp);
+int tg3_init_hw(struct tg3 *tp, int reset_phy);
+u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val);
+void tg3_poll_link(struct tg3 *tp);
+void tg3_wait_for_event_ack(struct tg3 *tp);
+void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1);
+void tg3_disable_ints(struct tg3 *tp);
+void tg3_enable_ints(struct tg3 *tp);
+
+static inline void tg3_generate_fw_event(struct tg3 *tp)
+{
+ u32 val;
+
+ val = tr32(GRC_RX_CPU_EVENT);
+ val |= GRC_RX_CPU_DRIVER_EVENT;
+ tw32_f(GRC_RX_CPU_EVENT, val);
+}
+
+/* linux-2.6.39, include/linux/mii.h: */
+/**
+ * mii_resolve_flowctrl_fdx
+ * @lcladv: value of MII ADVERTISE register
+ * @rmtadv: value of MII LPA register
+ *
+ * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
+ */
+static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
+{
+ u8 cap = 0;
+
+ if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
+ if (lcladv & ADVERTISE_PAUSE_CAP)
+ cap = FLOW_CTRL_RX;
+ else if (rmtadv & ADVERTISE_PAUSE_CAP)
+ cap = FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+#define ETH_FCS_LEN 4
+
#endif /* !(_T3_H) */
diff --git a/src/drivers/net/tg3/tg3_hw.c b/src/drivers/net/tg3/tg3_hw.c
new file mode 100644
index 00000000..036c2463
--- /dev/null
+++ b/src/drivers/net/tg3/tg3_hw.c
@@ -0,0 +1,2676 @@
+/*
+ * tg3.c: Broadcom Tigon3 ethernet driver.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2005-2011 Broadcom Corporation.
+ *
+ * Firmware is:
+ * Derived from proprietary unpublished source code,
+ * Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware
+ * data in hexadecimal or equivalent format, provided this copyright
+ * notice is accompanying it.
+ */
+
+FILE_LICENCE ( GPL2_ONLY );
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/timer.h>
+#include <ipxe/malloc.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/netdevice.h>
+
+#include "tg3.h"
+
+#define RESET_KIND_SHUTDOWN 0
+#define RESET_KIND_INIT 1
+#define RESET_KIND_SUSPEND 2
+
+#define TG3_DEF_MAC_MODE 0
+
+void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+}
+
+u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+ return val;
+}
+
+static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
+{ DBGP("%s\n", __func__);
+
+ return readl(tp->regs + off + GRCMBOX_BASE);
+}
+
+static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ writel(val, tp->regs + off + GRCMBOX_BASE);
+}
+
+void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+ if (off == TG3_RX_STD_PROD_IDX_REG) {
+ pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+
+ /* In indirect mode when disabling interrupts, we also need
+ * to clear the interrupt bit in the GRC local ctrl register.
+ */
+ if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
+ (val == 0x1)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
+ tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
+ }
+}
+
+u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+
+ return val;
+}
+
+/* usec_wait specifies the wait time in usec when writing to certain registers
+ * where it is unsafe to read back the register without some delay.
+ * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power.
+ * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed.
+ */
+void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait)
+{ DBGP("%s\n", __func__);
+
+ tw32(off, val);
+ if (usec_wait)
+ udelay(usec_wait);
+ tr32(off);
+
+ /* Wait again after the read for the posted method to guarantee that
+ * the wait time is met.
+ */
+ if (usec_wait)
+ udelay(usec_wait);
+}
+
+/* stolen from legacy etherboot tg3 driver */
+void tg3_set_power_state_0(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ uint16_t power_control;
+ int pm = tp->pm_cap;
+
+ /* Make sure register accesses (indirect or otherwise)
+ * will function correctly.
+ */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+
+ pci_read_config_word(tp->pdev, pm + PCI_PM_CTRL, &power_control);
+
+ power_control |= PCI_PM_CTRL_PME_STATUS;
+ power_control &= ~(PCI_PM_CTRL_STATE_MASK);
+ power_control |= 0;
+ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
+
+ tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+
+ return;
+}
+
+void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+ (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
+ *val = 0;
+ return;
+ }
+
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+}
+
+#define PCI_VENDOR_ID_ARIMA 0x161f
+
+static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+ u16 pmcsr;
+
+ /* On some early chips the SRAM cannot be accessed in D3hot state,
+ * so need make sure we're in D0.
+ */
+ pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
+ mdelay(1);
+
+ /* Make sure register accesses (indirect or otherwise)
+ * will function correctly.
+ */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ /* The memory arbiter has to be enabled in order for SRAM accesses
+ * to succeed. Normally on powerup the tg3 chip firmware will make
+ * sure it is enabled, but other entities such as system netboot
+ * code might disable it.
+ */
+ val = tr32(MEMARB_MODE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+ tp->phy_id = TG3_PHY_ID_INVALID;
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+ /* Assume an onboard device by default. */
+ tg3_flag_set(tp, EEPROM_WRITE_PROT);
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
+ if (val == NIC_SRAM_DATA_SIG_MAGIC) {
+ u32 nic_cfg, led_cfg;
+ u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id;
+ int eeprom_phy_serdes = 0;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
+ tp->nic_sram_data_cfg = nic_cfg;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver);
+ ver >>= NIC_SRAM_DATA_VER_SHIFT;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703 &&
+ (ver > 0) && (ver < 0x100))
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4);
+
+ if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
+ NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
+ eeprom_phy_serdes = 1;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+ if (nic_phy_id != 0) {
+ u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+ u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+
+ eeprom_phy_id = (id1 >> 16) << 10;
+ eeprom_phy_id |= (id2 & 0xfc00) << 16;
+ eeprom_phy_id |= (id2 & 0x03ff) << 0;
+ } else
+ eeprom_phy_id = 0;
+
+ tp->phy_id = eeprom_phy_id;
+ if (eeprom_phy_serdes) {
+ if (!tg3_flag(tp, 5705_PLUS))
+ tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+ else
+ tp->phy_flags |= TG3_PHYFLG_MII_SERDES;
+ }
+
+ if (tg3_flag(tp, 5750_PLUS))
+ led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
+ SHASTA_EXT_LED_MODE_MASK);
+ else
+ led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK;
+
+ switch (led_cfg) {
+ default:
+ case NIC_SRAM_DATA_CFG_LED_MODE_PHY_1:
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+ break;
+
+ case NIC_SRAM_DATA_CFG_LED_MODE_PHY_2:
+ tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+ break;
+
+ case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
+ tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+ /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+ * read on some older 5700/5701 bootcode.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5701)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+ break;
+
+ case SHASTA_EXT_LED_SHARED:
+ tp->led_ctrl = LED_CTRL_MODE_SHARED;
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5750_A1)
+ tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+ LED_CTRL_MODE_PHY_2);
+ break;
+
+ case SHASTA_EXT_LED_MAC:
+ tp->led_ctrl = LED_CTRL_MODE_SHASTA_MAC;
+ break;
+
+ case SHASTA_EXT_LED_COMBO:
+ tp->led_ctrl = LED_CTRL_MODE_COMBO;
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)
+ tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+ LED_CTRL_MODE_PHY_2);
+ break;
+
+ }
+
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) &&
+ tp->subsystem_vendor == PCI_VENDOR_ID_DELL)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
+ if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
+ tg3_flag_set(tp, EEPROM_WRITE_PROT);
+ if ((tp->subsystem_vendor ==
+ PCI_VENDOR_ID_ARIMA) &&
+ (tp->subsystem_device == 0x205a ||
+ tp->subsystem_device == 0x2063))
+ tg3_flag_clear(tp, EEPROM_WRITE_PROT);
+ } else {
+ tg3_flag_clear(tp, EEPROM_WRITE_PROT);
+ tg3_flag_set(tp, IS_NIC);
+ }
+
+ if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
+ tg3_flag_set(tp, ENABLE_ASF);
+ if (tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, ASF_NEW_HANDSHAKE);
+ }
+
+ if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+ tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, ENABLE_APE);
+
+ if (cfg2 & (1 << 17))
+ tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
+
+ /* serdes signal pre-emphasis in register 0x590 set by */
+ /* bootcode if bit 18 is set */
+ if (cfg2 & (1 << 18))
+ tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS;
+
+ if ((tg3_flag(tp, 57765_PLUS) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) &&
+ (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
+ tp->phy_flags |= TG3_PHYFLG_ENABLE_APD;
+
+ if (tg3_flag(tp, PCI_EXPRESS) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ !tg3_flag(tp, 57765_PLUS)) {
+ u32 cfg3;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+ }
+
+ if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE)
+ tg3_flag_set(tp, RGMII_INBAND_DISABLE);
+ if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN)
+ tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN);
+ if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
+ tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN);
+ }
+}
+
+static void tg3_switch_clocks(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 clock_ctrl;
+ u32 orig_clock_ctrl;
+
+ if (tg3_flag(tp, CPMU_PRESENT) || tg3_flag(tp, 5780_CLASS))
+ return;
+
+ clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
+
+ orig_clock_ctrl = clock_ctrl;
+ clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
+ CLOCK_CTRL_CLKRUN_OENABLE |
+ 0x1f);
+ tp->pci_clock_ctrl = clock_ctrl;
+
+ if (tg3_flag(tp, 5705_PLUS)) {
+ if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
+ tw32_wait_f(TG3PCI_CLOCK_CTRL,
+ clock_ctrl | CLOCK_CTRL_625_CORE, 40);
+ }
+ } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+ tw32_wait_f(TG3PCI_CLOCK_CTRL,
+ clock_ctrl |
+ (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK),
+ 40);
+ tw32_wait_f(TG3PCI_CLOCK_CTRL,
+ clock_ctrl | (CLOCK_CTRL_ALTCLK),
+ 40);
+ }
+ tw32_wait_f(TG3PCI_CLOCK_CTRL, clock_ctrl, 40);
+}
+
+int tg3_get_invariants(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 misc_ctrl_reg;
+ u32 pci_state_reg, grc_misc_cfg;
+ u32 val;
+ u16 pci_cmd;
+ int err;
+
+ /* Force memory write invalidate off. If we leave it on,
+ * then on 5700_BX chips we have to enable a workaround.
+ * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
+ * to match the cacheline size. The Broadcom driver have this
+ * workaround but turns MWI off all the times so never uses
+ * it. This seems to suggest that the workaround is insufficient.
+ */
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd &= ~PCI_COMMAND_INVALIDATE;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+
+ /* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
+ * has the register indirect write enable bit set before
+ * we try to access any of the MMIO registers. It is also
+ * critical that the PCI-X hw workaround situation is decided
+ * before that as well.
+ */
+ pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ &misc_ctrl_reg);
+
+ tp->pci_chip_rev_id = (misc_ctrl_reg >>
+ MISC_HOST_CTRL_CHIPREV_SHIFT);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
+ u32 prod_id_asic_rev;
+
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
+ pci_read_config_dword(tp->pdev,
+ TG3PCI_GEN2_PRODID_ASICREV,
+ &prod_id_asic_rev);
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
+ pci_read_config_dword(tp->pdev,
+ TG3PCI_GEN15_PRODID_ASICREV,
+ &prod_id_asic_rev);
+ else
+ pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
+ &prod_id_asic_rev);
+
+ tp->pci_chip_rev_id = prod_id_asic_rev;
+ }
+
+ /* Wrong chip ID in 5752 A0. This code can be removed later
+ * as A0 is not in production.
+ */
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
+ tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+
+ /* Initialize misc host control in PCI block. */
+ tp->misc_host_ctrl |= (misc_ctrl_reg &
+ MISC_HOST_CTRL_CHIPREV);
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ tg3_flag_set(tp, 5717_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
+ tg3_flag(tp, 5717_PLUS))
+ tg3_flag_set(tp, 57765_PLUS);
+
+ /* Intentionally exclude ASIC_REV_5906 */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS))
+ tg3_flag_set(tp, 5755_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+ tg3_flag(tp, 5755_PLUS) ||
+ tg3_flag(tp, 5780_CLASS))
+ tg3_flag_set(tp, 5750_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+ tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, 5705_PLUS);
+
+ if (tg3_flag(tp, 5717_PLUS))
+ tg3_flag_set(tp, LRG_PROD_RING_CAP);
+
+ pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+ &pci_state_reg);
+
+ tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+ if (tp->pcie_cap != 0) {
+ u16 lnkctl;
+
+ tg3_flag_set(tp, PCI_EXPRESS);
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_57780_A1)
+ tg3_flag_set(tp, CLKREQ_BUG);
+ } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) {
+ tg3_flag_set(tp, L1PLLPD_EN);
+ }
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ tg3_flag_set(tp, PCI_EXPRESS);
+ } else if (!tg3_flag(tp, 5705_PLUS) ||
+ tg3_flag(tp, 5780_CLASS)) {
+ tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+ if (!tp->pcix_cap) {
+ DBGC(&tp->pdev->dev,
+ "Cannot find PCI-X capability, aborting\n");
+ return -EIO;
+ }
+
+ if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE))
+ tg3_flag_set(tp, PCIX_MODE);
+ }
+
+ /* If we have an AMD 762 or VIA K8T800 chipset, write
+ * reordering to the mailbox registers done by the host
+ * controller can cause major troubles. We read back from
+ * every mailbox register write to force the writes to be
+ * posted to the chip in order.
+ */
+
+ pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ &tp->pci_cacheline_sz);
+ pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ &tp->pci_lat_timer);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+ tp->pci_lat_timer < 64) {
+ tp->pci_lat_timer = 64;
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+ /* 5700 BX chips need to have their TX producer index
+ * mailboxes written twice to workaround a bug.
+ */
+ tg3_flag_set(tp, TXD_MBOX_HWBUG);
+
+ /* If we are in PCI-X mode, enable register write workaround.
+ *
+ * The workaround is to use indirect register accesses
+ * for all chip writes not to mailbox registers.
+ */
+ if (tg3_flag(tp, PCIX_MODE)) {
+ u32 pm_reg;
+
+ tg3_flag_set(tp, PCIX_TARGET_HWBUG);
+
+ /* The chip can have it's power management PCI config
+ * space registers clobbered due to this bug.
+ * So explicitly force the chip into D0 here.
+ */
+ pci_read_config_dword(tp->pdev,
+ tp->pm_cap + PCI_PM_CTRL,
+ &pm_reg);
+ pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
+ pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
+ pci_write_config_dword(tp->pdev,
+ tp->pm_cap + PCI_PM_CTRL,
+ pm_reg);
+
+ /* Also, force SERR#/PERR# in PCI command. */
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+ }
+ }
+
+ if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
+ tg3_flag_set(tp, PCI_HIGH_SPEED);
+ if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
+ tg3_flag_set(tp, PCI_32BIT);
+
+ /* Chip-specific fixup from Broadcom driver */
+ if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&
+ (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) {
+ pci_state_reg |= PCISTATE_RETRY_SAME_DMA;
+ pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
+ }
+
+ tp->write32_mbox = tg3_write_indirect_reg32;
+ tp->write32_rx_mbox = tg3_write_indirect_mbox;
+ tp->write32_tx_mbox = tg3_write_indirect_mbox;
+ tp->read32_mbox = tg3_read_indirect_mbox;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tp->read32_mbox = tg3_read32_mbox_5906;
+ tp->write32_mbox = tg3_write32_mbox_5906;
+ tp->write32_tx_mbox = tg3_write32_mbox_5906;
+ tp->write32_rx_mbox = tg3_write32_mbox_5906;
+ }
+
+ /* Get eeprom hw config before calling tg3_set_power_state().
+ * In particular, the TG3_FLAG_IS_NIC flag must be
+ * determined before calling tg3_set_power_state() so that
+ * we know whether or not to switch out of Vaux power.
+ * When the flag is set, it means that GPIO1 is used for eeprom
+ * write protect and also implies that it is a LOM where GPIOs
+ * are not used to switch power.
+ */
+ tg3_get_eeprom_hw_cfg(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS))
+ tg3_flag_set(tp, CPMU_PRESENT);
+
+ /* Set up tp->grc_local_ctrl before calling tg3_power_up().
+ * GPIO1 driven high will bring 5700's external PHY out of reset.
+ * It is also used as eeprom write protect on LOMs.
+ */
+ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ tg3_flag(tp, EEPROM_WRITE_PROT))
+ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OUTPUT1);
+ /* Unused GPIO3 must be driven as output on 5752 because there
+ * are no pull-up resistors on unused GPIO pins.
+ */
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
+ /* Turn off the debug UART. */
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+ if (tg3_flag(tp, IS_NIC))
+ /* Keep VMain power. */
+ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+ GRC_LCLCTRL_GPIO_OUTPUT0;
+ }
+
+ /* Force the chip into D0. */
+ tg3_set_power_state_0(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ tp->phy_flags |= TG3_PHYFLG_IS_FET;
+
+ /* A few boards don't want Ethernet@WireSpeed phy feature */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
+ (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
+ (tp->phy_flags & TG3_PHYFLG_IS_FET) ||
+ (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+ tp->phy_flags |= TG3_PHYFLG_NO_ETH_WIRE_SPEED;
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
+ tp->phy_flags |= TG3_PHYFLG_ADC_BUG;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
+ tp->phy_flags |= TG3_PHYFLG_5704_A0_BUG;
+
+ if (tg3_flag(tp, 5705_PLUS) &&
+ !(tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 &&
+ !tg3_flag(tp, 57765_PLUS)) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
+ if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
+ tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
+ tp->phy_flags |= TG3_PHYFLG_JITTER_BUG;
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
+ tp->phy_flags |= TG3_PHYFLG_ADJUST_TRIM;
+ } else
+ tp->phy_flags |= TG3_PHYFLG_BER_BUG;
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+ tp->phy_otp = tg3_read_otp_phycfg(tp);
+ if (tp->phy_otp == 0)
+ tp->phy_otp = TG3_OTP_DEFAULT;
+ }
+
+ if (tg3_flag(tp, CPMU_PRESENT))
+ tp->mi_mode = MAC_MI_MODE_500KHZ_CONST;
+ else
+ tp->mi_mode = MAC_MI_MODE_BASE;
+
+ tp->coalesce_mode = 0;
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
+ tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
+
+ /* Set these bits to enable statistics workaround. */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) {
+ tp->coalesce_mode |= HOSTCC_MODE_ATTN;
+ tp->grc_mode |= GRC_MODE_IRQ_ON_FLOW_ATTN;
+ }
+
+ tg3_mdio_init(tp);
+
+ /* Initialize data/descriptor byte/word swapping. */
+ val = tr32(GRC_MODE);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ val &= (GRC_MODE_BYTE_SWAP_B2HRX_DATA |
+ GRC_MODE_WORD_SWAP_B2HRX_DATA |
+ GRC_MODE_B2HRX_ENABLE |
+ GRC_MODE_HTX2B_ENABLE |
+ GRC_MODE_HOST_STACKUP);
+ else
+ val &= GRC_MODE_HOST_STACKUP;
+
+ tw32(GRC_MODE, val | tp->grc_mode);
+
+ tg3_switch_clocks(tp);
+
+ /* Clear this out for sanity. */
+ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+ pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+ &pci_state_reg);
+ if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
+ !tg3_flag(tp, PCIX_TARGET_HWBUG)) {
+ u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl);
+
+ if (chiprevid == CHIPREV_ID_5701_A0 ||
+ chiprevid == CHIPREV_ID_5701_B0 ||
+ chiprevid == CHIPREV_ID_5701_B2 ||
+ chiprevid == CHIPREV_ID_5701_B5) {
+ void *sram_base;
+
+ /* Write some dummy words into the SRAM status block
+ * area, see if it reads back correctly. If the return
+ * value is bad, force enable the PCIX workaround.
+ */
+ sram_base = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_STATS_BLK;
+
+ writel(0x00000000, sram_base);
+ writel(0x00000000, sram_base + 4);
+ writel(0xffffffff, sram_base + 4);
+ if (readl(sram_base) != 0x00000000)
+ tg3_flag_set(tp, PCIX_TARGET_HWBUG);
+ }
+ }
+
+ udelay(50);
+ /* FIXME: do we need nvram access? */
+/// tg3_nvram_init(tp);
+
+ grc_misc_cfg = tr32(GRC_MISC_CFG);
+ grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
+ grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
+ tg3_flag_set(tp, IS_5788);
+
+ if (!tg3_flag(tp, IS_5788) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+ tg3_flag_set(tp, TAGGED_STATUS);
+ if (tg3_flag(tp, TAGGED_STATUS)) {
+ tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD);
+
+ tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+ }
+
+ /* Preserve the APE MAC_MODE bits */
+ if (tg3_flag(tp, ENABLE_APE))
+ tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+ else
+ tp->mac_mode = TG3_DEF_MAC_MODE;
+
+ /* these are limited to 10/100 only */
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+ (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+ (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
+ (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+ (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
+ (tp->phy_flags & TG3_PHYFLG_IS_FET))
+ tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
+
+ err = tg3_phy_probe(tp);
+ if (err) {
+ DBGC(&tp->pdev->dev, "phy probe failed, err: %s\n", strerror(err));
+ /* ... but do not return immediately ... */
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT;
+ } else {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+ tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT;
+ else
+ tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT;
+ }
+
+ /* For all SERDES we poll the MAC status register. */
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
+ tg3_flag_set(tp, POLL_SERDES);
+ else
+ tg3_flag_clear(tp, POLL_SERDES);
+
+ /* Increment the rx prod index on the rx std ring by at most
+ * 8 for these chips to workaround hw errata.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ tp->rx_std_max_post = 8;
+
+ return err;
+}
+
+void tg3_init_bufmgr_config(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 57765_PLUS)) {
+ tp->bufmgr_config.mbuf_read_dma_low_water =
+ DEFAULT_MB_RDMA_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_57765;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_57765;
+
+ tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+ DEFAULT_MB_RDMA_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+ DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765;
+ tp->bufmgr_config.mbuf_high_water_jumbo =
+ DEFAULT_MB_HIGH_WATER_JUMBO_57765;
+ } else if (tg3_flag(tp, 5705_PLUS)) {
+ tp->bufmgr_config.mbuf_read_dma_low_water =
+ DEFAULT_MB_RDMA_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_5705;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_5705;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_5906;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_5906;
+ }
+
+ tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+ DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780;
+ tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+ DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780;
+ tp->bufmgr_config.mbuf_high_water_jumbo =
+ DEFAULT_MB_HIGH_WATER_JUMBO_5780;
+ } else {
+ tp->bufmgr_config.mbuf_read_dma_low_water =
+ DEFAULT_MB_RDMA_LOW_WATER;
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER;
+
+ tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
+ DEFAULT_MB_RDMA_LOW_WATER_JUMBO;
+ tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
+ DEFAULT_MB_MACRX_LOW_WATER_JUMBO;
+ tp->bufmgr_config.mbuf_high_water_jumbo =
+ DEFAULT_MB_HIGH_WATER_JUMBO;
+ }
+
+ tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER;
+ tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
+}
+
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
+
+void tg3_wait_for_event_ack(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+
+ for (i = 0; i < TG3_FW_EVENT_TIMEOUT_USEC / 10; i++) {
+ if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
+ break;
+
+ udelay(10);
+ }
+}
+
+void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
+{ DBGP("%s\n", __func__);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+ (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
+ return;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+}
+
+static void tg3_stop_fw(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) {
+ /* Wait for RX cpu to ACK the previous event. */
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
+
+ tg3_generate_fw_event(tp);
+
+ /* Wait for RX cpu to ACK this event. */
+ tg3_wait_for_event_ack(tp);
+ }
+}
+
+static void tg3_write_sig_pre_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+}
+
+void tg3_disable_ints(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ tw32(TG3PCI_MISC_HOST_CTRL,
+ (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
+
+ tw32_mailbox_f(tp->int_mbox, 0x00000001);
+}
+
+void tg3_enable_ints(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ tw32(TG3PCI_MISC_HOST_CTRL,
+ (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
+
+ tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE;
+
+ tw32_mailbox_f(tp->int_mbox, tp->last_tag << 24);
+
+ /* Force an initial interrupt */
+ if (!tg3_flag(tp, TAGGED_STATUS) &&
+ (tp->hw_status->status & SD_STATUS_UPDATED))
+ tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ else
+ tw32(HOSTCC_MODE, tp->coal_now);
+}
+
+#define MAX_WAIT_CNT 1000
+
+/* To stop a block, clear the enable bit and poll till it clears. */
+static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit)
+{ DBGP("%s\n", __func__);
+
+ unsigned int i;
+ u32 val;
+
+ if (tg3_flag(tp, 5705_PLUS)) {
+ switch (ofs) {
+ case RCVLSC_MODE:
+ case DMAC_MODE:
+ case MBFREE_MODE:
+ case BUFMGR_MODE:
+ case MEMARB_MODE:
+ /* We can't enable/disable these bits of the
+ * 5705/5750, just say success.
+ */
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ val = tr32(ofs);
+ val &= ~enable_bit;
+ tw32_f(ofs, val);
+
+ for (i = 0; i < MAX_WAIT_CNT; i++) {
+ udelay(100);
+ val = tr32(ofs);
+ if ((val & enable_bit) == 0)
+ break;
+ }
+
+ if (i == MAX_WAIT_CNT) {
+ DBGC(&tp->pdev->dev,
+ "tg3_stop_block timed out, ofs=%lx enable_bit=%x\n",
+ ofs, enable_bit);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int tg3_abort_hw(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i, err;
+
+ tg3_disable_ints(tp);
+
+ tp->rx_mode &= ~RX_MODE_ENABLE;
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ udelay(10);
+
+ err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE);
+
+ err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+ err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE);
+
+ tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
+
+ tp->tx_mode &= ~TX_MODE_ENABLE;
+ tw32_f(MAC_TX_MODE, tp->tx_mode);
+
+ for (i = 0; i < MAX_WAIT_CNT; i++) {
+ udelay(100);
+ if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
+ break;
+ }
+ if (i >= MAX_WAIT_CNT) {
+ DBGC(&tp->pdev->dev,
+ "%s timed out, TX_MODE_ENABLE will not clear "
+ "MAC_TX_MODE=%08x\n", __func__, tr32(MAC_TX_MODE));
+ err |= -ENODEV;
+ }
+
+ err |= tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE);
+ err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
+
+ tw32(FTQ_RESET, 0xffffffff);
+ tw32(FTQ_RESET, 0x00000000);
+
+ err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
+ err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
+
+ if (tp->hw_status)
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+ return err;
+}
+
+void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{ DBGP("%s\n", __func__);
+
+ u32 addr_high, addr_low;
+ int i;
+
+ addr_high = ((tp->dev->ll_addr[0] << 8) |
+ tp->dev->ll_addr[1]);
+ addr_low = ((tp->dev->ll_addr[2] << 24) |
+ (tp->dev->ll_addr[3] << 16) |
+ (tp->dev->ll_addr[4] << 8) |
+ (tp->dev->ll_addr[5] << 0));
+ for (i = 0; i < 4; i++) {
+ if (i == 1 && skip_mac_1)
+ continue;
+ tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ for (i = 0; i < 12; i++) {
+ tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+ }
+ }
+
+ addr_high = (tp->dev->ll_addr[0] +
+ tp->dev->ll_addr[1] +
+ tp->dev->ll_addr[2] +
+ tp->dev->ll_addr[3] +
+ tp->dev->ll_addr[4] +
+ tp->dev->ll_addr[5]) &
+ TX_BACKOFF_SEED_MASK;
+ tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+
+ /* Re-enable indirect register accesses. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ /* Set MAX PCI retry to zero. */
+ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ tg3_flag(tp, PCIX_MODE))
+ val |= PCISTATE_RETRY_SAME_DMA;
+
+ pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+ pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+ pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ tp->pci_cacheline_sz);
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
+ }
+
+
+ /* Make sure PCI-X relaxed ordering bit is clear. */
+ if (tg3_flag(tp, PCIX_MODE)) {
+ u16 pcix_cmd;
+
+ pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ &pcix_cmd);
+ pcix_cmd &= ~PCI_X_CMD_ERO;
+ pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ pcix_cmd);
+ }
+}
+
+static int tg3_poll_fw(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+ u32 val;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* Wait up to 20ms for init done. */
+ for (i = 0; i < 200; i++) {
+ if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+ return 0;
+ udelay(100);
+ }
+ return -ENODEV;
+ }
+
+ /* Wait for firmware initialization to complete. */
+ for (i = 0; i < 100000; i++) {
+ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+ if (val == (u32)~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+ break;
+ udelay(10);
+ }
+
+ /* Chip might not be fitted with firmware. Some Sun onboard
+ * parts are configured like that. So don't signal the timeout
+ * of the above loop as an error, but do report the lack of
+ * running firmware once.
+ */
+ if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) {
+ tg3_flag_set(tp, NO_FWARE_REPORTED);
+
+ DBGC(tp->dev, "No firmware running\n");
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+ /* The 57765 A0 needs a little more
+ * time to do some important work.
+ */
+ mdelay(10);
+ }
+
+ return 0;
+}
+
+static int tg3_nvram_lock(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, NVRAM)) {
+ int i;
+
+ if (tp->nvram_lock_cnt == 0) {
+ tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+ for (i = 0; i < 8000; i++) {
+ if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+ break;
+ udelay(20);
+ }
+ if (i == 8000) {
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
+ return -ENODEV;
+ }
+ }
+ tp->nvram_lock_cnt++;
+ }
+ return 0;
+}
+
+static void tg3_nvram_unlock(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, NVRAM)) {
+ if (tp->nvram_lock_cnt > 0)
+ tp->nvram_lock_cnt--;
+ if (tp->nvram_lock_cnt == 0)
+ tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ }
+}
+
+static int tg3_chip_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+ int err;
+
+ tg3_nvram_lock(tp);
+
+
+ /* No matching tg3_nvram_unlock() after this because
+ * chip reset below will undo the nvram lock.
+ */
+ tp->nvram_lock_cnt = 0;
+
+ /* GRC_MISC_CFG core clock reset will clear the memory
+ * enable bit in PCI register 4 and the MSI enable bit
+ * on some chips, so we save relevant registers here.
+ */
+ tg3_save_pci_state(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ tg3_flag(tp, 5755_PLUS))
+ tw32(GRC_FASTBOOT_PC, 0);
+
+#if 0
+ /*
+ * We must avoid the readl() that normally takes place.
+ * It locks machines, causes machine checks, and other
+ * fun things. So, temporarily disable the 5701
+ * hardware workaround, while we do the reset.
+ */
+ write_op = tp->write32;
+ if (write_op == tg3_write_flush_reg32)
+ tp->write32 = tg3_write32;
+#endif
+
+ /* Prevent the irq handler from reading or writing PCI registers
+ * during chip reset when the memory enable bit in the PCI command
+ * register may be cleared. The chip does not generate interrupt
+ * at this time, but the irq handler may still be called due to irq
+ * sharing or irqpoll.
+ */
+ tg3_flag_set(tp, CHIP_RESETTING);
+
+ if (tp->hw_status) {
+ tp->hw_status->status = 0;
+ tp->hw_status->status_tag = 0;
+ }
+ tp->last_tag = 0;
+ tp->last_irq_tag = 0;
+
+ mb();
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+ val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
+ tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
+ }
+
+ /* do the reset */
+ val = GRC_MISC_CFG_CORECLK_RESET;
+
+ if (tg3_flag(tp, PCI_EXPRESS)) {
+ /* Force PCIe 1.0a mode */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ !tg3_flag(tp, 57765_PLUS) &&
+ tr32(TG3_PCIE_PHY_TSTCTL) ==
+ (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM))
+ tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM);
+
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+ tw32(GRC_MISC_CFG, (1 << 29));
+ val |= (1 << 29);
+ }
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET);
+ tw32(GRC_VCPU_EXT_CTRL,
+ tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
+ }
+
+ /* Manage gphy power for all CPMU absent PCIe devices. */
+ if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, CPMU_PRESENT))
+ val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
+
+ tw32(GRC_MISC_CFG, val);
+
+ /* Unfortunately, we have to delay before the PCI read back.
+ * Some 575X chips even will not respond to a PCI cfg access
+ * when the reset command is given to the chip.
+ *
+ * How do these hardware designers expect things to work
+ * properly if the PCI write is posted for a long period
+ * of time? It is always necessary to have some method by
+ * which a register read back can occur to push the write
+ * out which does the reset.
+ *
+ * For most tg3 variants the trick below was working.
+ * Ho hum...
+ */
+ udelay(120);
+
+ /* Flush PCI posted writes. The normal MMIO registers
+ * are inaccessible at this time so this is the only
+ * way to make this reliably (actually, this is no longer
+ * the case, see above). I tried to use indirect
+ * register read/write but this upset some 5701 variants.
+ */
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
+
+ udelay(120);
+
+ if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) {
+ u16 val16;
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
+ int i;
+ u32 cfg_val;
+
+ /* Wait for link training to complete. */
+ for (i = 0; i < 5000; i++)
+ udelay(100);
+
+ pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
+ pci_write_config_dword(tp->pdev, 0xc4,
+ cfg_val | (1 << 15));
+ }
+
+ /* Clear the "no snoop" and "relaxed ordering" bits. */
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVCTL,
+ &val16);
+ val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
+ PCI_EXP_DEVCTL_NOSNOOP_EN);
+ /*
+ * Older PCIe devices only support the 128 byte
+ * MPS setting. Enforce the restriction.
+ */
+ if (!tg3_flag(tp, CPMU_PRESENT))
+ val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVCTL,
+ val16);
+
+ /* Clear error status */
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVSTA,
+ PCI_EXP_DEVSTA_CED |
+ PCI_EXP_DEVSTA_NFED |
+ PCI_EXP_DEVSTA_FED |
+ PCI_EXP_DEVSTA_URD);
+ }
+
+ tg3_restore_pci_state(tp);
+
+ tg3_flag_clear(tp, CHIP_RESETTING);
+ tg3_flag_clear(tp, ERROR_PROCESSED);
+
+ val = 0;
+ if (tg3_flag(tp, 5780_CLASS))
+ val = tr32(MEMARB_MODE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
+ tg3_stop_fw(tp);
+ tw32(0x5000, 0x400);
+ }
+
+ tw32(GRC_MODE, tp->grc_mode);
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
+ val = tr32(0xc4);
+
+ tw32(0xc4, val | (1 << 15));
+ }
+
+ if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)
+ tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN;
+ tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+ val = tp->mac_mode;
+ } else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ val = tp->mac_mode;
+ } else
+ val = 0;
+
+ tw32_f(MAC_MODE, val);
+ udelay(40);
+
+ err = tg3_poll_fw(tp);
+ if (err)
+ return err;
+
+ if (tg3_flag(tp, PCI_EXPRESS) &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ !tg3_flag(tp, 57765_PLUS)) {
+ val = tr32(0x7c00);
+
+ tw32(0x7c00, val | (1 << 25));
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val = tr32(TG3_CPMU_CLCK_ORIDE);
+ tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
+ }
+
+ return 0;
+}
+
+int tg3_halt(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ tg3_stop_fw(tp);
+
+ tg3_write_sig_pre_reset(tp);
+
+ tg3_abort_hw(tp);
+ err = tg3_chip_reset(tp);
+
+ __tg3_set_mac_addr(tp, 0);
+
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
+ u32 offset, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ u32 tmp;
+ int i;
+
+ if (offset > EEPROM_ADDR_ADDR_MASK || (offset % 4) != 0)
+ return -EINVAL;
+
+ tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
+ EEPROM_ADDR_DEVID_MASK |
+ EEPROM_ADDR_READ);
+ tw32(GRC_EEPROM_ADDR,
+ tmp |
+ (0 << EEPROM_ADDR_DEVID_SHIFT) |
+ ((offset << EEPROM_ADDR_ADDR_SHIFT) &
+ EEPROM_ADDR_ADDR_MASK) |
+ EEPROM_ADDR_READ | EEPROM_ADDR_START);
+
+ for (i = 0; i < 1000; i++) {
+ tmp = tr32(GRC_EEPROM_ADDR);
+
+ if (tmp & EEPROM_ADDR_COMPLETE)
+ break;
+ mdelay(1);
+ }
+ if (!(tmp & EEPROM_ADDR_COMPLETE))
+ return -EBUSY;
+
+ tmp = tr32(GRC_EEPROM_DATA);
+
+ /*
+ * The data will always be opposite the native endian
+ * format. Perform a blind byteswap to compensate.
+ */
+ *val = bswap_32(tmp);
+
+ return 0;
+}
+
+static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, NVRAM) &&
+ tg3_flag(tp, NVRAM_BUFFERED) &&
+ tg3_flag(tp, FLASH) &&
+ !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) &&
+ (tp->nvram_jedecnum == JEDEC_ATMEL))
+
+ addr = ((addr / tp->nvram_pagesize) <<
+ ATMEL_AT45DB0X1B_PAGE_POS) +
+ (addr % tp->nvram_pagesize);
+
+ return addr;
+}
+
+static void tg3_enable_nvram_access(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
+ u32 nvaccess = tr32(NVRAM_ACCESS);
+
+ tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+ }
+}
+
+static void tg3_disable_nvram_access(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
+ u32 nvaccess = tr32(NVRAM_ACCESS);
+
+ tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+ }
+}
+
+#define NVRAM_CMD_TIMEOUT 10000
+
+static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
+{ DBGP("%s\n", __func__);
+
+ int i;
+
+ tw32(NVRAM_CMD, nvram_cmd);
+ for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) {
+ udelay(10);
+ if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
+ udelay(10);
+ break;
+ }
+ }
+
+ if (i == NVRAM_CMD_TIMEOUT)
+ return -EBUSY;
+
+ return 0;
+}
+
+/* NOTE: Data read in from NVRAM is byteswapped according to
+ * the byteswapping settings for all other register accesses.
+ * tg3 devices are BE devices, so on a BE machine, the data
+ * returned will be exactly as it is seen in NVRAM. On a LE
+ * machine, the 32-bit value will be byteswapped.
+ */
+static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ int ret;
+
+ if (!tg3_flag(tp, NVRAM))
+ return tg3_nvram_read_using_eeprom(tp, offset, val);
+
+ offset = tg3_nvram_phys_addr(tp, offset);
+
+ if (offset > NVRAM_ADDR_MSK)
+ return -EINVAL;
+
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
+
+ tg3_enable_nvram_access(tp);
+
+ tw32(NVRAM_ADDR, offset);
+ ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO |
+ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+
+ if (ret == 0)
+ *val = tr32(NVRAM_RDDATA);
+
+ tg3_disable_nvram_access(tp);
+
+ tg3_nvram_unlock(tp);
+
+ return ret;
+}
+
+/* Ensures NVRAM data is in bytestream format. */
+static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ u32 v = 0;
+ int res = tg3_nvram_read(tp, offset, &v);
+ if (!res)
+ *val = cpu_to_be32(v);
+ return res;
+}
+
+int tg3_get_device_address(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ struct net_device *dev = tp->dev;
+ u32 hi, lo, mac_offset;
+ int addr_ok = 0;
+
+ mac_offset = 0x7c;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+ tg3_flag(tp, 5780_CLASS)) {
+ if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+ mac_offset = 0xcc;
+ if (tg3_nvram_lock(tp))
+ tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
+ else
+ tg3_nvram_unlock(tp);
+ } else if (tg3_flag(tp, 5717_PLUS)) {
+ if (PCI_FUNC(tp->pdev->busdevfn) & 1)
+ mac_offset = 0xcc;
+ if (PCI_FUNC(tp->pdev->busdevfn) > 1)
+ mac_offset += 0x18c;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ mac_offset = 0x10;
+
+ /* First try to get it from MAC address mailbox. */
+ tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
+ if ((hi >> 16) == 0x484b) {
+ dev->hw_addr[0] = (hi >> 8) & 0xff;
+ dev->hw_addr[1] = (hi >> 0) & 0xff;
+
+ tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo);
+ dev->hw_addr[2] = (lo >> 24) & 0xff;
+ dev->hw_addr[3] = (lo >> 16) & 0xff;
+ dev->hw_addr[4] = (lo >> 8) & 0xff;
+ dev->hw_addr[5] = (lo >> 0) & 0xff;
+
+ /* Some old bootcode may report a 0 MAC address in SRAM */
+ addr_ok = is_valid_ether_addr(&dev->hw_addr[0]);
+ }
+ if (!addr_ok) {
+ /* Next, try NVRAM. */
+ if (!tg3_flag(tp, NO_NVRAM) &&
+ !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) &&
+ !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) {
+ memcpy(&dev->hw_addr[0], ((char *)&hi) + 2, 2);
+ memcpy(&dev->hw_addr[2], (char *)&lo, sizeof(lo));
+ }
+ /* Finally just fetch it out of the MAC control regs. */
+ else {
+ hi = tr32(MAC_ADDR_0_HIGH);
+ lo = tr32(MAC_ADDR_0_LOW);
+
+ dev->hw_addr[5] = lo & 0xff;
+ dev->hw_addr[4] = (lo >> 8) & 0xff;
+ dev->hw_addr[3] = (lo >> 16) & 0xff;
+ dev->hw_addr[2] = (lo >> 24) & 0xff;
+ dev->hw_addr[1] = hi & 0xff;
+ dev->hw_addr[0] = (hi >> 8) & 0xff;
+ }
+ }
+
+ if (!is_valid_ether_addr(&dev->hw_addr[0])) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __tg3_set_rx_mode(struct net_device *dev)
+{ DBGP("%s\n", __func__);
+
+ struct tg3 *tp = netdev_priv(dev);
+ u32 rx_mode;
+
+ rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
+ RX_MODE_KEEP_VLAN_TAG);
+
+ rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+
+ /* Accept all multicast. */
+ tw32(MAC_HASH_REG_0, 0xffffffff);
+ tw32(MAC_HASH_REG_1, 0xffffffff);
+ tw32(MAC_HASH_REG_2, 0xffffffff);
+ tw32(MAC_HASH_REG_3, 0xffffffff);
+
+ if (rx_mode != tp->rx_mode) {
+ tp->rx_mode = rx_mode;
+ tw32_f(MAC_RX_MODE, rx_mode);
+ udelay(10);
+ }
+}
+
+static void __tg3_set_coalesce(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+
+ tw32(HOSTCC_RXCOL_TICKS, 0);
+ tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
+ tw32(HOSTCC_RXMAX_FRAMES, 1);
+ /* FIXME: mix between TXMAX and RXMAX taken from legacy driver */
+ tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
+ tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
+ tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ u32 val = DEFAULT_STAT_COAL_TICKS;
+
+ tw32(HOSTCC_RXCOAL_TICK_INT, DEFAULT_RXCOAL_TICK_INT);
+ tw32(HOSTCC_TXCOAL_TICK_INT, DEFAULT_TXCOAL_TICK_INT);
+
+ if (!netdev_link_ok(tp->dev))
+ val = 0;
+
+ tw32(HOSTCC_STAT_COAL_TICKS, val);
+ }
+}
+
+static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
+ dma_addr_t mapping, u32 maxlen_flags,
+ u32 nic_addr)
+{ DBGP("%s\n", __func__);
+
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
+ ((u64) mapping >> 32));
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
+ ((u64) mapping & 0xffffffff));
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS),
+ maxlen_flags);
+
+ if (!tg3_flag(tp, 5705_PLUS))
+ tg3_write_mem(tp,
+ (bdinfo_addr + TG3_BDINFO_NIC_ADDR),
+ nic_addr);
+}
+
+static void tg3_rings_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+ u32 stblk, txrcb, rxrcb, limit;
+
+ /* Disable all transmit rings but the first. */
+ if (!tg3_flag(tp, 5705_PLUS))
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+ else if (tg3_flag(tp, 5717_PLUS))
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2;
+ else
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+
+ for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+ txrcb < limit; txrcb += TG3_BDINFO_SIZE)
+ tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
+ BDINFO_FLAGS_DISABLED);
+
+
+ /* Disable all receive return rings but the first. */
+ if (tg3_flag(tp, 5717_PLUS))
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17;
+ else if (!tg3_flag(tp, 5705_PLUS))
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4;
+ else
+ limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+
+ for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+ rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
+ tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
+ BDINFO_FLAGS_DISABLED);
+
+ /* Disable interrupts */
+ tw32_mailbox_f(tp->int_mbox, 1);
+
+ tp->tx_prod = 0;
+ tp->tx_cons = 0;
+ tw32_mailbox(tp->prodmbox, 0);
+ tw32_rx_mbox(tp->consmbox, 0);
+
+ /* Make sure the NIC-based send BD rings are disabled. */
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+ for (i = 0; i < 16; i++)
+ tw32_tx_mbox(mbox + i * 8, 0);
+ }
+
+ txrcb = NIC_SRAM_SEND_RCB;
+ rxrcb = NIC_SRAM_RCV_RET_RCB;
+
+ /* Clear status block in ram. */
+ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+ /* Set status block DMA address */
+ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
+ ((u64) tp->status_mapping >> 32));
+ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
+ ((u64) tp->status_mapping & 0xffffffff));
+
+ if (tp->tx_ring) {
+ tg3_set_bdinfo(tp, txrcb, tp->tx_desc_mapping,
+ (TG3_TX_RING_SIZE <<
+ BDINFO_FLAGS_MAXLEN_SHIFT),
+ NIC_SRAM_TX_BUFFER_DESC);
+ txrcb += TG3_BDINFO_SIZE;
+ }
+
+ /* FIXME: will TG3_RX_RET_MAX_SIZE_5705 work on all cards? */
+ if (tp->rx_rcb) {
+ tg3_set_bdinfo(tp, rxrcb, tp->rx_rcb_mapping,
+ TG3_RX_RET_MAX_SIZE_5705 <<
+ BDINFO_FLAGS_MAXLEN_SHIFT, 0);
+ rxrcb += TG3_BDINFO_SIZE;
+ }
+
+ stblk = HOSTCC_STATBLCK_RING1;
+}
+
+static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val, bdcache_maxcnt;
+
+ if (!tg3_flag(tp, 5750_PLUS) ||
+ tg3_flag(tp, 5780_CLASS) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+ bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5700;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5755;
+ else
+ bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5906;
+
+
+ /* NOTE: legacy driver uses RX_PENDING / 8, we only use 4 descriptors
+ * for now, use / 4 so the result is > 0
+ */
+ val = TG3_DEF_RX_RING_PENDING / 4;
+ tw32(RCVBDI_STD_THRESH, val);
+
+ if (tg3_flag(tp, 57765_PLUS))
+ tw32(STD_REPLENISH_LWM, bdcache_maxcnt);
+}
+
+static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
+{ DBGP("%s\n", __func__);
+
+ u32 val, rdmac_mode;
+ int i, err, limit;
+ struct tg3_rx_prodring_set *tpr = &tp->prodring;
+
+ tg3_stop_fw(tp);
+
+ tg3_write_sig_pre_reset(tp);
+
+ if (tg3_flag(tp, INIT_COMPLETE))
+ tg3_abort_hw(tp);
+
+ if (reset_phy)
+ tg3_phy_reset(tp);
+
+ err = tg3_chip_reset(tp);
+ if (err)
+ return err;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+ val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK;
+ val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN |
+ PCIE_PWR_MGMT_L1_THRESH_4MS;
+ tw32(PCIE_PWR_MGMT_THRESH, val);
+
+ val = tr32(TG3_PCIE_EIDLE_DELAY) & ~TG3_PCIE_EIDLE_DELAY_MASK;
+ tw32(TG3_PCIE_EIDLE_DELAY, val | TG3_PCIE_EIDLE_DELAY_13_CLKS);
+
+ tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR);
+
+ val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
+ tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS);
+ }
+
+ if (tg3_flag(tp, L1PLLPD_EN)) {
+ u32 grc_mode = tr32(GRC_MODE);
+
+ /* Access the lower 1K of PL PCIE block registers. */
+ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+ tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+
+ val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1);
+ tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1,
+ val | TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN);
+
+ tw32(GRC_MODE, grc_mode);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+ u32 grc_mode = tr32(GRC_MODE);
+
+ /* Access the lower 1K of PL PCIE block registers. */
+ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+ tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL);
+
+ val = tr32(TG3_PCIE_TLDLPL_PORT +
+ TG3_PCIE_PL_LO_PHYCTL5);
+ tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL5,
+ val | TG3_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ);
+
+ tw32(GRC_MODE, grc_mode);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) {
+ u32 grc_mode = tr32(GRC_MODE);
+
+ /* Access the lower 1K of DL PCIE block registers. */
+ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+ tw32(GRC_MODE, val | GRC_MODE_PCIE_DL_SEL);
+
+ val = tr32(TG3_PCIE_TLDLPL_PORT +
+ TG3_PCIE_DL_LO_FTSMAX);
+ val &= ~TG3_PCIE_DL_LO_FTSMAX_MSK;
+ tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_DL_LO_FTSMAX,
+ val | TG3_PCIE_DL_LO_FTSMAX_VAL);
+
+ tw32(GRC_MODE, grc_mode);
+ }
+
+ val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+ val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+ val |= CPMU_LSPD_10MB_MACCLK_6_25;
+ tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+ }
+
+ /* This works around an issue with Athlon chipsets on
+ * B3 tigon3 silicon. This bit has no effect on any
+ * other revision. But do not set this on PCI Express
+ * chips and don't even touch the clocks if the CPMU is present.
+ */
+ if (!tg3_flag(tp, CPMU_PRESENT)) {
+ if (!tg3_flag(tp, PCI_EXPRESS))
+ tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
+ tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ tg3_flag(tp, PCIX_MODE)) {
+ val = tr32(TG3PCI_PCISTATE);
+ val |= PCISTATE_RETRY_SAME_DMA;
+ tw32(TG3PCI_PCISTATE, val);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
+ /* Enable some hw fixes. */
+ val = tr32(TG3PCI_MSI_DATA);
+ val |= (1 << 26) | (1 << 28) | (1 << 29);
+ tw32(TG3PCI_MSI_DATA, val);
+ }
+
+ /* Descriptor ring init may make accesses to the
+ * NIC SRAM area to setup the TX descriptors, so we
+ * can only do this after the hardware has been
+ * successfully reset.
+ */
+ err = tg3_init_rings(tp);
+ if (err)
+ return err;
+
+ if (tg3_flag(tp, 57765_PLUS)) {
+ val = tr32(TG3PCI_DMA_RW_CTRL) &
+ ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0)
+ val &= ~DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
+ val |= DMA_RWCTRL_TAGGED_STAT_WA;
+ tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl);
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
+ /* This value is determined during the probe time DMA
+ * engine test, tg3_test_dma.
+ */
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
+
+ tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
+ GRC_MODE_4X_NIC_SEND_RINGS |
+ GRC_MODE_NO_TX_PHDR_CSUM |
+ GRC_MODE_NO_RX_PHDR_CSUM);
+ tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
+ tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+ /* Pseudo-header checksum is done by hardware logic and not
+ * the offload processers, so make the chip do the pseudo-
+ * header checksums on receive. For transmit it is more
+ * convenient to do the pseudo-header checksum in software
+ * as Linux does that on transmit for us in all cases.
+ */
+ tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
+
+ tw32(GRC_MODE,
+ tp->grc_mode |
+ (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
+
+ /* Setup the timer prescalar register. Clock is always 66Mhz. */
+ val = tr32(GRC_MISC_CFG);
+ val &= ~0xff;
+ val |= (65 << GRC_MISC_CFG_PRESCALAR_SHIFT);
+ tw32(GRC_MISC_CFG, val);
+
+ /* Initialize MBUF/DESC pool. */
+ if (tg3_flag(tp, 5750_PLUS)) {
+ /* Do nothing. */
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+ tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+ tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
+ else
+ tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
+ tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
+ tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
+ }
+
+ tw32(BUFMGR_MB_RDMA_LOW_WATER,
+ tp->bufmgr_config.mbuf_read_dma_low_water);
+ tw32(BUFMGR_MB_MACRX_LOW_WATER,
+ tp->bufmgr_config.mbuf_mac_rx_low_water);
+ tw32(BUFMGR_MB_HIGH_WATER,
+ tp->bufmgr_config.mbuf_high_water);
+
+ tw32(BUFMGR_DMA_LOW_WATER,
+ tp->bufmgr_config.dma_low_water);
+ tw32(BUFMGR_DMA_HIGH_WATER,
+ tp->bufmgr_config.dma_high_water);
+
+ val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ val |= BUFMGR_MODE_NO_TX_UNDERRUN;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5720_A0)
+ val |= BUFMGR_MODE_MBLOW_ATTN_ENAB;
+ tw32(BUFMGR_MODE, val);
+ for (i = 0; i < 2000; i++) {
+ if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
+ break;
+ udelay(10);
+ }
+ if (i >= 2000) {
+ DBGC(tp->dev, "%s cannot enable BUFMGR\n", __func__);
+ return -ENODEV;
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1)
+ tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2);
+
+ tg3_setup_rxbd_thresholds(tp);
+
+ /* Initialize TG3_BDINFO's at:
+ * RCVDBDI_STD_BD: standard eth size rx ring
+ * RCVDBDI_JUMBO_BD: jumbo frame rx ring
+ * RCVDBDI_MINI_BD: small frame rx ring (??? does not work)
+ *
+ * like so:
+ * TG3_BDINFO_HOST_ADDR: high/low parts of DMA address of ring
+ * TG3_BDINFO_MAXLEN_FLAGS: (rx max buffer size << 16) |
+ * ring attribute flags
+ * TG3_BDINFO_NIC_ADDR: location of descriptors in nic SRAM
+ *
+ * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
+ * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
+ *
+ * The size of each ring is fixed in the firmware, but the location is
+ * configurable.
+ */
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH,
+ ((u64) tpr->rx_std_mapping >> 32));
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
+ ((u64) tpr->rx_std_mapping & 0xffffffff));
+ if (!tg3_flag(tp, 5717_PLUS))
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
+ NIC_SRAM_RX_BUFFER_DESC);
+
+ /* Disable the mini ring */
+ if (!tg3_flag(tp, 5705_PLUS))
+ tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS,
+ BDINFO_FLAGS_DISABLED);
+
+ val = TG3_RX_STD_MAX_SIZE_5700 << BDINFO_FLAGS_MAXLEN_SHIFT;
+
+ tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
+
+ tpr->rx_std_prod_idx = TG3_DEF_RX_RING_PENDING;
+
+ /* std prod index is updated by tg3_refill_prod_ring() */
+ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, 0);
+ tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, 0);
+
+ tg3_rings_reset(tp);
+
+#define TG3_MAX_MTU 1522
+ /* MTU + ethernet header + FCS + optional VLAN tag */
+ tw32(MAC_RX_MTU_SIZE, TG3_MAX_MTU);
+
+ /* The slot time is changed by tg3_setup_phy if we
+ * run at gigabit with half duplex.
+ */
+ val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+ (6 << TX_LENGTHS_IPG_SHIFT) |
+ (32 << TX_LENGTHS_SLOT_TIME_SHIFT);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ val |= tr32(MAC_TX_LENGTHS) &
+ (TX_LENGTHS_JMB_FRM_LEN_MSK |
+ TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+ tw32(MAC_TX_LENGTHS, val);
+
+ /* Receive rules. */
+ tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS);
+ tw32(RCVLPC_CONFIG, 0x0181);
+
+ /* Calculate RDMAC_MODE setting early, we need it to determine
+ * the RCVLPC_STATE_ENABLE mask.
+ */
+ rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
+ RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
+ RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
+ RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
+ RDMAC_MODE_LNGREAD_ENAB);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+ rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+ rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
+ RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
+ RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
+ if (tg3_flag(tp, TSO_CAPABLE) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
+ } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
+ !tg3_flag(tp, IS_5788)) {
+ rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+ }
+ }
+
+ if (tg3_flag(tp, PCI_EXPRESS))
+ rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ rdmac_mode |= tr32(RDMAC_MODE) & RDMAC_MODE_H2BNC_VLAN_DET;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS)) {
+ val = tr32(TG3_RDMA_RSRVCTRL_REG);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK |
+ TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+ TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK);
+ val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B |
+ TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+ TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K;
+ }
+ tw32(TG3_RDMA_RSRVCTRL_REG,
+ val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+ tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val |
+ TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K |
+ TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K);
+ }
+
+ /* Receive/send statistics. */
+ if (tg3_flag(tp, 5750_PLUS)) {
+ val = tr32(RCVLPC_STATS_ENABLE);
+ val &= ~RCVLPC_STATSENAB_DACK_FIX;
+ tw32(RCVLPC_STATS_ENABLE, val);
+ } else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
+ tg3_flag(tp, TSO_CAPABLE)) {
+ val = tr32(RCVLPC_STATS_ENABLE);
+ val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX;
+ tw32(RCVLPC_STATS_ENABLE, val);
+ } else {
+ tw32(RCVLPC_STATS_ENABLE, 0xffffff);
+ }
+ tw32(RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE);
+ tw32(SNDDATAI_STATSENAB, 0xffffff);
+ tw32(SNDDATAI_STATSCTRL,
+ (SNDDATAI_SCTRL_ENABLE |
+ SNDDATAI_SCTRL_FASTUPD));
+
+ /* Setup host coalescing engine. */
+ tw32(HOSTCC_MODE, 0);
+ for (i = 0; i < 2000; i++) {
+ if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
+ break;
+ udelay(10);
+ }
+
+ __tg3_set_coalesce(tp);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ /* Status/statistics block address. See tg3_timer,
+ * the tg3_periodic_fetch_stats call there, and
+ * tg3_get_stats to see how this works for 5705/5750 chips.
+ * NOTE: stats block removed for iPXE
+ */
+ tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK);
+
+ /* Clear statistics and status block memory areas */
+ for (i = NIC_SRAM_STATS_BLK;
+ i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
+ i += sizeof(u32)) {
+ tg3_write_mem(tp, i, 0);
+ udelay(40);
+ }
+ }
+
+ tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode);
+
+ tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE);
+ tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE);
+ if (!tg3_flag(tp, 5705_PLUS))
+ tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
+
+ if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+ tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+ /* reset to prevent losing 1st rx packet intermittently */
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ }
+
+ if (tg3_flag(tp, ENABLE_APE))
+ tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+ else
+ tp->mac_mode = 0;
+ tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+ MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+ if (!tg3_flag(tp, 5705_PLUS) &&
+ !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
+ udelay(40);
+
+ /* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
+ * If TG3_FLAG_IS_NIC is zero, we should read the
+ * register to preserve the GPIO settings for LOMs. The GPIOs,
+ * whether used as inputs or outputs, are set by boot code after
+ * reset.
+ */
+ if (!tg3_flag(tp, IS_NIC)) {
+ u32 gpio_mask;
+
+ gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+ gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
+ GRC_LCLCTRL_GPIO_OUTPUT3;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+ tp->grc_local_ctrl &= ~gpio_mask;
+ tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
+
+ /* GPIO1 must be driven high for eeprom write protect */
+ if (tg3_flag(tp, EEPROM_WRITE_PROT))
+ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OUTPUT1);
+ }
+ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+ udelay(100);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
+ udelay(40);
+ }
+
+ val = (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
+ WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
+ WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
+ WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
+ WDMAC_MODE_LNGREAD_ENAB);
+
+ /* Enable host coalescing bug fix */
+ if (tg3_flag(tp, 5755_PLUS))
+ val |= WDMAC_MODE_STATUS_TAG_FIX;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ val |= WDMAC_MODE_BURST_ALL_DATA;
+
+ tw32_f(WDMAC_MODE, val);
+ udelay(40);
+
+ if (tg3_flag(tp, PCIX_MODE)) {
+ u16 pcix_cmd;
+
+ pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ &pcix_cmd);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
+ pcix_cmd &= ~PCI_X_CMD_MAX_READ;
+ pcix_cmd |= PCI_X_CMD_READ_2K;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ);
+ pcix_cmd |= PCI_X_CMD_READ_2K;
+ }
+ pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ pcix_cmd);
+ }
+
+ tw32_f(RDMAC_MODE, rdmac_mode);
+ udelay(40);
+
+ tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
+ if (!tg3_flag(tp, 5705_PLUS))
+ tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ tw32(SNDDATAC_MODE,
+ SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY);
+ else
+ tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
+ tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
+ tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
+ val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ;
+ if (tg3_flag(tp, LRG_PROD_RING_CAP))
+ val |= RCVDBDI_MODE_LRG_RING_SZ;
+ tw32(RCVDBDI_MODE, val);
+ tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+
+ val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE;
+ if (tg3_flag(tp, ENABLE_TSS))
+ val |= SNDBDI_MODE_MULTI_TXQ_EN;
+ tw32(SNDBDI_MODE, val);
+ tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
+
+
+ /* FIXME: 5701 firmware fix? */
+#if 0
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
+ err = tg3_load_5701_a0_firmware_fix(tp);
+ if (err)
+ return err;
+ }
+#endif
+
+ tp->tx_mode = TX_MODE_ENABLE;
+
+ if (tg3_flag(tp, 5755_PLUS) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+ val = TX_MODE_JMB_FRM_LEN | TX_MODE_CNT_DN_MODE;
+ tp->tx_mode &= ~val;
+ tp->tx_mode |= tr32(MAC_TX_MODE) & val;
+ }
+
+ tw32_f(MAC_TX_MODE, tp->tx_mode);
+ udelay(100);
+
+ tp->rx_mode = RX_MODE_ENABLE;
+
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ udelay(10);
+
+ tw32(MAC_LED_CTRL, tp->led_ctrl);
+
+ tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ }
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ udelay(10);
+
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) &&
+ !(tp->phy_flags & TG3_PHYFLG_SERDES_PREEMPHASIS)) {
+ /* Set drive transmission level to 1.2V */
+ /* only if the signal pre-emphasis bit is not set */
+ val = tr32(MAC_SERDES_CFG);
+ val &= 0xfffff000;
+ val |= 0x880;
+ tw32(MAC_SERDES_CFG, val);
+ }
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
+ tw32(MAC_SERDES_CFG, 0x616000);
+ }
+
+ /* Prevent chip from dropping frames when flow control
+ * is enabled.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ val = 1;
+ else
+ val = 2;
+ tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+ (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
+ /* Use hardware link auto-negotiation */
+ tg3_flag_set(tp, HW_AUTONEG);
+ }
+
+ if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ u32 tmp;
+
+ tmp = tr32(SERDES_RX_CTRL);
+ tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT);
+ tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT;
+ tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT;
+ tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+ }
+
+ err = tg3_setup_phy(tp, 0);
+ if (err)
+ return err;
+
+ if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+ !(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
+ u32 tmp;
+
+ /* Clear CRC stats. */
+ if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
+ tg3_writephy(tp, MII_TG3_TEST1,
+ tmp | MII_TG3_TEST1_CRC_EN);
+ tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &tmp);
+ }
+ }
+
+ __tg3_set_rx_mode(tp->dev);
+
+ /* Initialize receive rules. */
+ tw32(MAC_RCV_RULE_0, 0xc2000000 & RCV_RULE_DISABLE_MASK);
+ tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
+ tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK);
+ tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
+
+ if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS))
+ limit = 8;
+ else
+ limit = 16;
+ if (tg3_flag(tp, ENABLE_ASF))
+ limit -= 4;
+ switch (limit) {
+ case 16:
+ tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0);
+ case 15:
+ tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0);
+ case 14:
+ tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0);
+ case 13:
+ tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0);
+ case 12:
+ tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0);
+ case 11:
+ tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0);
+ case 10:
+ tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0);
+ case 9:
+ tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0);
+ case 8:
+ tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0);
+ case 7:
+ tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0);
+ case 6:
+ tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0);
+ case 5:
+ tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0);
+ case 4:
+ /* tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); */
+ case 3:
+ /* tw32(MAC_RCV_RULE_2, 0); tw32(MAC_RCV_VALUE_2, 0); */
+ case 2:
+ case 1:
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Called at device open time to get the chip ready for
+ * packet processing. Invoked with tp->lock held.
+ */
+int tg3_init_hw(struct tg3 *tp, int reset_phy)
+{ DBGP("%s\n", __func__);
+
+ tg3_switch_clocks(tp);
+
+ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+ return tg3_reset_hw(tp, reset_phy);
+}
+
+void tg3_set_txd(struct tg3 *tp, int entry,
+ dma_addr_t mapping, int len, u32 flags)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
+
+ txd->addr_hi = ((u64) mapping >> 32);
+ txd->addr_lo = ((u64) mapping & 0xffffffff);
+ txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+ txd->vlan_tag = 0;
+}
+
+u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+{ DBGP("%s\n", __func__);
+
+ int cacheline_size;
+ u8 byte;
+
+ pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
+ if (byte == 0)
+ cacheline_size = 1024;
+ else
+ cacheline_size = (int) byte * 4;
+
+ /* On 5703 and later chips, the boundary bits have no
+ * effect.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+ !tg3_flag(tp, PCI_EXPRESS))
+ goto out;
+
+ if (tg3_flag(tp, 57765_PLUS))
+ val = DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
+
+out:
+ return val;
+}
+
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device)
+{ DBGP("%s\n", __func__);
+
+ struct tg3_internal_buffer_desc test_desc;
+ u32 sram_dma_descs;
+ int ret;
+ unsigned int i;
+
+ sram_dma_descs = NIC_SRAM_DMA_DESC_POOL_BASE;
+
+ tw32(FTQ_RCVBD_COMP_FIFO_ENQDEQ, 0);
+ tw32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ, 0);
+ tw32(RDMAC_STATUS, 0);
+ tw32(WDMAC_STATUS, 0);
+
+ tw32(BUFMGR_MODE, 0);
+ tw32(FTQ_RESET, 0);
+
+ test_desc.addr_hi = ((u64) buf_dma) >> 32;
+ test_desc.addr_lo = buf_dma & 0xffffffff;
+ test_desc.nic_mbuf = 0x00002100;
+ test_desc.len = size;
+
+ /*
+ * HP ZX1 was seeing test failures for 5701 cards running at 33Mhz
+ * the *second* time the tg3 driver was getting loaded after an
+ * initial scan.
+ *
+ * Broadcom tells me:
+ * ...the DMA engine is connected to the GRC block and a DMA
+ * reset may affect the GRC block in some unpredictable way...
+ * The behavior of resets to individual blocks has not been tested.
+ *
+ * Broadcom noted the GRC reset will also reset all sub-components.
+ */
+ if (to_device) {
+ test_desc.cqid_sqid = (13 << 8) | 2;
+
+ tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
+ udelay(40);
+ } else {
+ test_desc.cqid_sqid = (16 << 8) | 7;
+
+ tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
+ udelay(40);
+ }
+ test_desc.flags = 0x00000005;
+
+ for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) {
+ u32 val;
+
+ val = *(((u32 *)&test_desc) + i);
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR,
+ sram_dma_descs + (i * sizeof(u32)));
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+ }
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+
+ if (to_device)
+ tw32(FTQ_DMA_HIGH_READ_FIFO_ENQDEQ, sram_dma_descs);
+ else
+ tw32(FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ, sram_dma_descs);
+
+ ret = -ENODEV;
+ for (i = 0; i < 40; i++) {
+ u32 val;
+
+ if (to_device)
+ val = tr32(FTQ_RCVBD_COMP_FIFO_ENQDEQ);
+ else
+ val = tr32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ);
+ if ((val & 0xffff) == sram_dma_descs) {
+ ret = 0;
+ break;
+ }
+
+ udelay(100);
+ }
+
+ return ret;
+}
diff --git a/src/drivers/net/tg3/tg3_phy.c b/src/drivers/net/tg3/tg3_phy.c
new file mode 100644
index 00000000..542e027c
--- /dev/null
+++ b/src/drivers/net/tg3/tg3_phy.c
@@ -0,0 +1,1608 @@
+
+#include <mii.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <ipxe/pci.h>
+
+#include "tg3.h"
+
+static void tg3_link_report(struct tg3 *tp);
+
+void tg3_mdio_init(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (tg3_flag(tp, 5717_PLUS)) {
+ u32 is_serdes;
+
+ tp->phy_addr = PCI_FUNC(tp->pdev->busdevfn) + 1;
+
+ if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
+ is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+ else
+ is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
+ TG3_CPMU_PHY_STRAP_IS_SERDES;
+ if (is_serdes)
+ tp->phy_addr += 7;
+ } else
+ tp->phy_addr = TG3_PHY_MII_ADDR;
+}
+
+static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+{ DBGP("%s\n", __func__);
+
+ int i;
+ u32 val;
+
+ tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
+ tw32(OTP_CTRL, cmd);
+
+ /* Wait for up to 1 ms for command to execute. */
+ for (i = 0; i < 100; i++) {
+ val = tr32(OTP_STATUS);
+ if (val & OTP_STATUS_CMD_DONE)
+ break;
+ udelay(10);
+ }
+
+ return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
+}
+
+/* Read the gphy configuration from the OTP region of the chip. The gphy
+ * configuration is a 32-bit value that straddles the alignment boundary.
+ * We do two 32-bit reads and then shift and merge the results.
+ */
+u32 tg3_read_otp_phycfg(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 bhalf_otp, thalf_otp;
+
+ tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
+ return 0;
+
+ tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+ return 0;
+
+ thalf_otp = tr32(OTP_READ_DATA);
+
+ tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+ return 0;
+
+ bhalf_otp = tr32(OTP_READ_DATA);
+
+ return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
+}
+
+#define PHY_BUSY_LOOPS 5000
+
+int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ u32 frame_val;
+ unsigned int loops;
+ int ret;
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE,
+ (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ udelay(80);
+ }
+
+ *val = 0x0;
+
+ frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
+ MI_COM_PHY_ADDR_MASK);
+ frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
+ MI_COM_REG_ADDR_MASK);
+ frame_val |= (MI_COM_CMD_READ | MI_COM_START);
+
+ tw32_f(MAC_MI_COM, frame_val);
+
+ loops = PHY_BUSY_LOOPS;
+ while (loops != 0) {
+ udelay(10);
+ frame_val = tr32(MAC_MI_COM);
+
+ if ((frame_val & MI_COM_BUSY) == 0) {
+ udelay(5);
+ frame_val = tr32(MAC_MI_COM);
+ break;
+ }
+ loops -= 1;
+ }
+
+ ret = -EBUSY;
+ if (loops != 0) {
+ *val = frame_val & MI_COM_DATA_MASK;
+ ret = 0;
+ }
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE, tp->mi_mode);
+ udelay(80);
+ }
+
+ return ret;
+}
+
+struct subsys_tbl_ent {
+ u16 subsys_vendor, subsys_devid;
+ u32 phy_id;
+};
+
+static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
+ /* Broadcom boards. */
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, TG3_PHY_ID_BCM8002 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9, 0 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7, 0 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, TG3_PHY_ID_BCM5703 },
+ { TG3PCI_SUBVENDOR_ID_BROADCOM,
+ TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, TG3_PHY_ID_BCM5703 },
+
+ /* 3com boards. */
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C996T, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C996BT, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C996SX, 0 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C1000T, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_3COM,
+ TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, TG3_PHY_ID_BCM5701 },
+
+ /* DELL boards. */
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_VIPER, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, TG3_PHY_ID_BCM5401 },
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_MERLOT, TG3_PHY_ID_BCM5411 },
+ { TG3PCI_SUBVENDOR_ID_DELL,
+ TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, TG3_PHY_ID_BCM5411 },
+
+ /* Compaq boards. */
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING, 0 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, TG3_PHY_ID_BCM5701 },
+ { TG3PCI_SUBVENDOR_ID_COMPAQ,
+ TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, TG3_PHY_ID_BCM5701 },
+
+ /* IBM boards. */
+ { TG3PCI_SUBVENDOR_ID_IBM,
+ TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
+};
+
+static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int i;
+
+ DBGC(tp->dev, "Matching with: %x:%x\n", tp->subsystem_vendor, tp->subsystem_device);
+
+ for (i = 0; i < (int) ARRAY_SIZE(subsys_id_to_phy_id); i++) {
+ if ((subsys_id_to_phy_id[i].subsys_vendor ==
+ tp->subsystem_vendor) &&
+ (subsys_id_to_phy_id[i].subsys_devid ==
+ tp->subsystem_device))
+ return &subsys_id_to_phy_id[i];
+ }
+ return NULL;
+}
+
+int tg3_writephy(struct tg3 *tp, int reg, u32 val)
+{ DBGP("%s\n", __func__);
+
+ u32 frame_val;
+ unsigned int loops;
+ int ret;
+
+ if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+ (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+ return 0;
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE,
+ (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ udelay(80);
+ }
+
+ frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
+ MI_COM_PHY_ADDR_MASK);
+ frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
+ MI_COM_REG_ADDR_MASK);
+ frame_val |= (val & MI_COM_DATA_MASK);
+ frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
+
+ tw32_f(MAC_MI_COM, frame_val);
+
+ loops = PHY_BUSY_LOOPS;
+ while (loops != 0) {
+ udelay(10);
+ frame_val = tr32(MAC_MI_COM);
+ if ((frame_val & MI_COM_BUSY) == 0) {
+ udelay(5);
+ frame_val = tr32(MAC_MI_COM);
+ break;
+ }
+ loops -= 1;
+ }
+
+ ret = -EBUSY;
+ if (loops != 0)
+ ret = 0;
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE, tp->mi_mode);
+ udelay(80);
+ }
+
+ return ret;
+}
+
+static int tg3_bmcr_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 phy_control;
+ int limit, err;
+
+ /* OK, reset it, and poll the BMCR_RESET bit until it
+ * clears or we time out.
+ */
+ phy_control = BMCR_RESET;
+ err = tg3_writephy(tp, MII_BMCR, phy_control);
+ if (err != 0)
+ return -EBUSY;
+
+ limit = 5000;
+ while (limit--) {
+ err = tg3_readphy(tp, MII_BMCR, &phy_control);
+ if (err != 0)
+ return -EBUSY;
+
+ if ((phy_control & BMCR_RESET) == 0) {
+ udelay(40);
+ break;
+ }
+ udelay(10);
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int tg3_wait_macro_done(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int limit = 100;
+
+ while (limit--) {
+ u32 tmp32;
+
+ if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) {
+ if ((tmp32 & 0x1000) == 0)
+ break;
+ }
+ }
+ if (limit < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
+{ DBGP("%s\n", __func__);
+
+ static const u32 test_pat[4][6] = {
+ { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
+ { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
+ { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
+ { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
+ };
+ int chan;
+
+ for (chan = 0; chan < 4; chan++) {
+ int i;
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+ (chan * 0x2000) | 0x0200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
+
+ for (i = 0; i < 6; i++)
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
+ test_pat[chan][i]);
+
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
+ if (tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+ (chan * 0x2000) | 0x0200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
+ if (tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802);
+ if (tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+
+ for (i = 0; i < 6; i += 2) {
+ u32 low, high;
+
+ if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
+ tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
+ tg3_wait_macro_done(tp)) {
+ *resetp = 1;
+ return -EBUSY;
+ }
+ low &= 0x7fff;
+ high &= 0x000f;
+ if (low != test_pat[chan][i] ||
+ high != test_pat[chan][i+1]) {
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
+
+ return -EBUSY;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int tg3_phy_reset_chanpat(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int chan;
+
+ for (chan = 0; chan < 4; chan++) {
+ int i;
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+ (chan * 0x2000) | 0x0200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
+ for (i = 0; i < 6; i++)
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
+ if (tg3_wait_macro_done(tp))
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+ if (!err)
+ err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
+
+ return err;
+}
+
+static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
+{ DBGP("%s\n", __func__);
+
+ if (reg == MII_TG3_AUXCTL_SHDWSEL_MISC)
+ set |= MII_TG3_AUXCTL_MISC_WREN;
+
+ return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
+}
+
+#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
+ tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
+ MII_TG3_AUXCTL_ACTL_TX_6DB)
+
+#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
+ tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
+ MII_TG3_AUXCTL_ACTL_TX_6DB);
+
+static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 reg32, phy9_orig;
+ int retries, do_phy_reset, err;
+
+ retries = 10;
+ do_phy_reset = 1;
+ do {
+ if (do_phy_reset) {
+ err = tg3_bmcr_reset(tp);
+ if (err)
+ return err;
+ do_phy_reset = 0;
+ }
+
+ /* Disable transmitter and interrupt. */
+ if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
+ continue;
+
+ reg32 |= 0x3000;
+ tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+
+ /* Set full-duplex, 1000 mbps. */
+ tg3_writephy(tp, MII_BMCR,
+ BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+
+ /* Set to master mode. */
+ if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+ continue;
+
+ tg3_writephy(tp, MII_TG3_CTRL,
+ (MII_TG3_CTRL_AS_MASTER |
+ MII_TG3_CTRL_ENABLE_AS_MASTER));
+
+ err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+ if (err)
+ return err;
+
+ /* Block the PHY control access. */
+ tg3_phydsp_write(tp, 0x8005, 0x0800);
+
+ err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
+ if (!err)
+ break;
+ } while (--retries);
+
+ err = tg3_phy_reset_chanpat(tp);
+ if (err)
+ return err;
+
+ tg3_phydsp_write(tp, 0x8005, 0x0000);
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
+ tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
+
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+
+ tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+
+ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
+ reg32 &= ~0x3000;
+ tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+ } else if (!err)
+ err = -EBUSY;
+
+ return err;
+}
+
+static void tg3_phy_apply_otp(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 otp, phy;
+
+ if (!tp->phy_otp)
+ return;
+
+ otp = tp->phy_otp;
+
+ if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
+ return;
+
+ phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
+ phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT;
+ tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy);
+
+ phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) |
+ ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy);
+
+ phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT);
+ phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ;
+ tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy);
+
+ phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy);
+
+ phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy);
+
+ phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) |
+ ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
+
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+}
+
+static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_AUX_CTRL,
+ (reg << MII_TG3_AUXCTL_MISC_RDSEL_SHIFT) |
+ MII_TG3_AUXCTL_SHDWSEL_MISC);
+ if (!err)
+ err = tg3_readphy(tp, MII_TG3_AUX_CTRL, val);
+
+ return err;
+}
+
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{ DBGP("%s\n", __func__);
+
+ u32 phy;
+
+ if (!tg3_flag(tp, 5705_PLUS) ||
+ (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+ return;
+
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+ u32 ephy;
+
+ if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) {
+ u32 reg = MII_TG3_FET_SHDW_MISCCTRL;
+
+ tg3_writephy(tp, MII_TG3_FET_TEST,
+ ephy | MII_TG3_FET_SHADOW_EN);
+ if (!tg3_readphy(tp, reg, &phy)) {
+ if (enable)
+ phy |= MII_TG3_FET_SHDW_MISCCTRL_MDIX;
+ else
+ phy &= ~MII_TG3_FET_SHDW_MISCCTRL_MDIX;
+ tg3_writephy(tp, reg, phy);
+ }
+ tg3_writephy(tp, MII_TG3_FET_TEST, ephy);
+ }
+ } else {
+ int ret;
+
+ ret = tg3_phy_auxctl_read(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISC, &phy);
+ if (!ret) {
+ if (enable)
+ phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ else
+ phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ tg3_phy_auxctl_write(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISC, phy);
+ }
+ }
+}
+
+static void tg3_phy_set_wirespeed(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int ret;
+ u32 val;
+
+ if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED)
+ return;
+
+ ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val);
+ if (!ret)
+ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_MISC,
+ val | MII_TG3_AUXCTL_MISC_WIRESPD_EN);
+}
+
+/* This will reset the tigon3 PHY if there is no valid
+ * link unless the FORCE argument is non-zero.
+ */
+int tg3_phy_reset(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 val, cpmuctrl;
+ int err;
+
+ DBGCP(&tp->pdev->dev, "%s\n", __func__);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ val = tr32(GRC_MISC_CFG);
+ tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
+ udelay(40);
+ }
+ err = tg3_readphy(tp, MII_BMSR, &val);
+ err |= tg3_readphy(tp, MII_BMSR, &val);
+ if (err != 0)
+ return -EBUSY;
+
+ netdev_link_down(tp->dev);
+ tg3_link_report(tp);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ err = tg3_phy_reset_5703_4_5(tp);
+ if (err)
+ return err;
+ goto out;
+ }
+
+ cpmuctrl = 0;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+ cpmuctrl = tr32(TG3_CPMU_CTRL);
+ if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
+ tw32(TG3_CPMU_CTRL,
+ cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
+ }
+
+ err = tg3_bmcr_reset(tp);
+ if (err)
+ return err;
+
+ if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
+ val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
+
+ tw32(TG3_CPMU_CTRL, cpmuctrl);
+ }
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+ CPMU_LSPD_1000MB_MACCLK_12_5) {
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ udelay(40);
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+ }
+
+ if (tg3_flag(tp, 5717_PLUS) &&
+ (tp->phy_flags & TG3_PHYFLG_MII_SERDES))
+ return 0;
+
+ tg3_phy_apply_otp(tp);
+
+out:
+ if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
+ !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_phydsp_write(tp, 0x201f, 0x2aaa);
+ tg3_phydsp_write(tp, 0x000a, 0x0323);
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+ }
+
+ if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
+ if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_phydsp_write(tp, 0x000a, 0x310b);
+ tg3_phydsp_write(tp, 0x201f, 0x9506);
+ tg3_phydsp_write(tp, 0x401f, 0x14e2);
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+ } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
+ if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+ if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
+ tg3_writephy(tp, MII_TG3_TEST1,
+ MII_TG3_TEST1_TRIM_EN | 0x4);
+ } else
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+
+ TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+ }
+ }
+
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ /* Cannot do read-modify-write on 5401 */
+ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* adjust output voltage */
+ tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
+ }
+
+ tg3_phy_toggle_automdix(tp, 1);
+ tg3_phy_set_wirespeed(tp);
+ return 0;
+}
+
+static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
+{ DBGP("%s\n", __func__);
+
+ u32 adv_reg, all_mask = 0;
+
+ if (mask & ADVERTISED_10baseT_Half)
+ all_mask |= ADVERTISE_10HALF;
+ if (mask & ADVERTISED_10baseT_Full)
+ all_mask |= ADVERTISE_10FULL;
+ if (mask & ADVERTISED_100baseT_Half)
+ all_mask |= ADVERTISE_100HALF;
+ if (mask & ADVERTISED_100baseT_Full)
+ all_mask |= ADVERTISE_100FULL;
+
+ if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
+ return 0;
+
+ if ((adv_reg & all_mask) != all_mask)
+ return 0;
+ if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+ u32 tg3_ctrl;
+
+ all_mask = 0;
+ if (mask & ADVERTISED_1000baseT_Half)
+ all_mask |= ADVERTISE_1000HALF;
+ if (mask & ADVERTISED_1000baseT_Full)
+ all_mask |= ADVERTISE_1000FULL;
+
+ if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
+ return 0;
+
+ if ((tg3_ctrl & all_mask) != all_mask)
+ return 0;
+ }
+ return 1;
+}
+
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{ DBGP("%s\n", __func__);
+
+ u16 miireg;
+
+ if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
+ miireg = ADVERTISE_PAUSE_CAP;
+ else if (flow_ctrl & FLOW_CTRL_TX)
+ miireg = ADVERTISE_PAUSE_ASYM;
+ else if (flow_ctrl & FLOW_CTRL_RX)
+ miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ else
+ miireg = 0;
+
+ return miireg;
+}
+
+static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
+{ DBGP("%s\n", __func__);
+
+ int err = 0;
+ u32 val __unused, new_adv;
+
+ new_adv = ADVERTISE_CSMA;
+ if (advertise & ADVERTISED_10baseT_Half)
+ new_adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ new_adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ new_adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ new_adv |= ADVERTISE_100FULL;
+
+ new_adv |= tg3_advert_flowctrl_1000T(flowctrl);
+
+ err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
+ if (err)
+ goto done;
+
+ if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+ goto done;
+
+ new_adv = 0;
+ if (advertise & ADVERTISED_1000baseT_Half)
+ new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+ if (advertise & ADVERTISED_1000baseT_Full)
+ new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+ new_adv |= (MII_TG3_CTRL_AS_MASTER |
+ MII_TG3_CTRL_ENABLE_AS_MASTER);
+
+ err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+ if (err)
+ goto done;
+
+ if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+ goto done;
+
+done:
+ return err;
+}
+
+static int tg3_init_5401phy_dsp(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ int err;
+
+ /* Turn off tap power management. */
+ /* Set Extended packet length bit */
+ err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
+
+ err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
+ err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
+ err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
+ err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
+ err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
+
+ udelay(40);
+
+ return err;
+}
+
+#define ADVERTISED_Autoneg (1 << 6)
+#define ADVERTISED_Pause (1 << 13)
+#define ADVERTISED_TP (1 << 7)
+#define ADVERTISED_FIBRE (1 << 10)
+
+#define AUTONEG_ENABLE 0x01
+
+static void tg3_phy_init_link_config(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 adv = ADVERTISED_Autoneg |
+ ADVERTISED_Pause;
+
+
+ if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
+ adv |= ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full;
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+ adv |= ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_TP;
+ else
+ adv |= ADVERTISED_FIBRE;
+
+ tp->link_config.advertising = adv;
+ tp->link_config.speed = SPEED_INVALID;
+ tp->link_config.duplex = DUPLEX_INVALID;
+ tp->link_config.autoneg = AUTONEG_ENABLE;
+ tp->link_config.active_speed = SPEED_INVALID;
+ tp->link_config.active_duplex = DUPLEX_INVALID;
+ tp->link_config.orig_speed = SPEED_INVALID;
+ tp->link_config.orig_duplex = DUPLEX_INVALID;
+ tp->link_config.orig_autoneg = AUTONEG_INVALID;
+}
+
+int tg3_phy_probe(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 hw_phy_id_1, hw_phy_id_2;
+ u32 hw_phy_id, hw_phy_id_masked;
+ int err;
+
+ /* flow control autonegotiation is default behavior */
+ tg3_flag_set(tp, PAUSE_AUTONEG);
+ tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+
+ /* Reading the PHY ID register can conflict with ASF
+ * firmware access to the PHY hardware.
+ */
+ err = 0;
+ if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)) {
+ hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID;
+ } else {
+ /* Now read the physical PHY_ID from the chip and verify
+ * that it is sane. If it doesn't look good, we fall back
+ * to either the hard-coded table based PHY_ID and failing
+ * that the value found in the eeprom area.
+ */
+ err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
+ err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
+
+ hw_phy_id = (hw_phy_id_1 & 0xffff) << 10;
+ hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
+ hw_phy_id |= (hw_phy_id_2 & 0x03ff) << 0;
+
+ hw_phy_id_masked = hw_phy_id & TG3_PHY_ID_MASK;
+ }
+
+ if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) {
+ tp->phy_id = hw_phy_id;
+ if (hw_phy_id_masked == TG3_PHY_ID_BCM8002)
+ tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+ else
+ tp->phy_flags &= ~TG3_PHYFLG_PHY_SERDES;
+ } else {
+ if (tp->phy_id != TG3_PHY_ID_INVALID) {
+ /* Do nothing, phy ID already set up in
+ * tg3_get_eeprom_hw_cfg().
+ */
+ } else {
+ struct subsys_tbl_ent *p;
+
+ /* No eeprom signature? Try the hardcoded
+ * subsys device table.
+ */
+ p = tg3_lookup_by_subsys(tp);
+ if (!p) {
+ DBGC(&tp->pdev->dev, "lookup by subsys failed\n");
+ return -ENODEV;
+ }
+
+ tp->phy_id = p->phy_id;
+ if (!tp->phy_id ||
+ tp->phy_id == TG3_PHY_ID_BCM8002)
+ tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
+ }
+ }
+
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+ ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
+ tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+
+ tg3_phy_init_link_config(tp);
+
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+ !tg3_flag(tp, ENABLE_APE) &&
+ !tg3_flag(tp, ENABLE_ASF)) {
+ u32 bmsr;
+ u32 mask;
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS))
+ goto skip_phy_reset;
+
+ err = tg3_phy_reset(tp);
+ if (err)
+ return err;
+
+ tg3_phy_set_wirespeed(tp);
+
+ mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
+ if (!tg3_copper_is_advertising_all(tp, mask)) {
+ tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+ tp->link_config.flowctrl);
+
+ tg3_writephy(tp, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART);
+ }
+ }
+
+skip_phy_reset:
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ err = tg3_init_5401phy_dsp(tp);
+ if (err)
+ return err;
+
+ err = tg3_init_5401phy_dsp(tp);
+ }
+
+ return err;
+}
+
+void tg3_poll_link(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 mac_stat;
+
+ mac_stat = tr32(MAC_STATUS);
+
+ if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)
+ tg3_setup_phy(tp, 0);
+}
+
+static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
+{ DBGP("%s\n", __func__);
+
+ switch (val & MII_TG3_AUX_STAT_SPDMASK) {
+ case MII_TG3_AUX_STAT_10HALF:
+ *speed = SPEED_10;
+ *duplex = DUPLEX_HALF;
+ break;
+
+ case MII_TG3_AUX_STAT_10FULL:
+ *speed = SPEED_10;
+ *duplex = DUPLEX_FULL;
+ break;
+
+ case MII_TG3_AUX_STAT_100HALF:
+ *speed = SPEED_100;
+ *duplex = DUPLEX_HALF;
+ break;
+
+ case MII_TG3_AUX_STAT_100FULL:
+ *speed = SPEED_100;
+ *duplex = DUPLEX_FULL;
+ break;
+
+ case MII_TG3_AUX_STAT_1000HALF:
+ *speed = SPEED_1000;
+ *duplex = DUPLEX_HALF;
+ break;
+
+ case MII_TG3_AUX_STAT_1000FULL:
+ *speed = SPEED_1000;
+ *duplex = DUPLEX_FULL;
+ break;
+
+ default:
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+ *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+ SPEED_10;
+ *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+ DUPLEX_HALF;
+ break;
+ }
+ *speed = SPEED_INVALID;
+ *duplex = DUPLEX_INVALID;
+ break;
+ }
+}
+
+static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
+{ DBGP("%s\n", __func__);
+
+ u32 curadv, reqadv;
+
+ if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
+ return 1;
+
+ curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+ reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
+ if (tp->link_config.active_duplex == DUPLEX_FULL) {
+ if (curadv != reqadv)
+ return 0;
+
+ if (tg3_flag(tp, PAUSE_AUTONEG))
+ tg3_readphy(tp, MII_LPA, rmtadv);
+ } else {
+ /* Reprogram the advertisement register, even if it
+ * does not affect the current link. If the link
+ * gets renegotiated in the future, we can save an
+ * additional renegotiation cycle by advertising
+ * it correctly in the first place.
+ */
+ if (curadv != reqadv) {
+ *lcladv &= ~(ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
+ }
+ }
+
+ return 1;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{ DBGP("%s\n", __func__);
+
+ u8 cap = 0;
+
+ if (lcladv & ADVERTISE_1000XPAUSE) {
+ if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+ if (rmtadv & LPA_1000XPAUSE)
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ else if (rmtadv & LPA_1000XPAUSE_ASYM)
+ cap = FLOW_CTRL_RX;
+ } else {
+ if (rmtadv & LPA_1000XPAUSE)
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+ if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+ cap = FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
+{ DBGP("%s\n", __func__);
+
+ u8 autoneg;
+ u8 flowctrl = 0;
+ u32 old_rx_mode = tp->rx_mode;
+ u32 old_tx_mode = tp->tx_mode;
+
+ autoneg = tp->link_config.autoneg;
+
+ if (tg3_flag(tp, PAUSE_AUTONEG)) {
+ if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
+ flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
+ else
+ flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+ } else
+ flowctrl = tp->link_config.flowctrl;
+
+ tp->link_config.active_flowctrl = flowctrl;
+
+ if (flowctrl & FLOW_CTRL_RX)
+ tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
+ else
+ tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
+
+ if (old_rx_mode != tp->rx_mode)
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+
+ if (flowctrl & FLOW_CTRL_TX)
+ tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
+ else
+ tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
+
+ if (old_tx_mode != tp->tx_mode)
+ tw32_f(MAC_TX_MODE, tp->tx_mode);
+}
+
+static void tg3_phy_copper_begin(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 new_adv;
+
+ if (tp->link_config.speed == SPEED_INVALID) {
+ if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+ tp->link_config.advertising &=
+ ~(ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full);
+
+ tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+ tp->link_config.flowctrl);
+ } else {
+ /* Asking for a specific link mode. */
+ if (tp->link_config.speed == SPEED_1000) {
+ if (tp->link_config.duplex == DUPLEX_FULL)
+ new_adv = ADVERTISED_1000baseT_Full;
+ else
+ new_adv = ADVERTISED_1000baseT_Half;
+ } else if (tp->link_config.speed == SPEED_100) {
+ if (tp->link_config.duplex == DUPLEX_FULL)
+ new_adv = ADVERTISED_100baseT_Full;
+ else
+ new_adv = ADVERTISED_100baseT_Half;
+ } else {
+ if (tp->link_config.duplex == DUPLEX_FULL)
+ new_adv = ADVERTISED_10baseT_Full;
+ else
+ new_adv = ADVERTISED_10baseT_Half;
+ }
+
+ tg3_phy_autoneg_cfg(tp, new_adv,
+ tp->link_config.flowctrl);
+ }
+
+ tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+}
+
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{ DBGP("%s\n", __func__);
+
+ if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+ return 1;
+ else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) {
+ if (speed != SPEED_10)
+ return 1;
+ } else if (speed == SPEED_10)
+ return 1;
+
+ return 0;
+}
+
+#if 1
+
+static void tg3_ump_link_report(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ u32 reg;
+ u32 val;
+
+ if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
+ return;
+
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+
+ val = 0;
+ if (!tg3_readphy(tp, MII_BMCR, &reg))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_BMSR, &reg))
+ val |= (reg & 0xffff);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+
+ val = 0;
+ if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_LPA, &reg))
+ val |= (reg & 0xffff);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+
+ val = 0;
+ if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
+ if (!tg3_readphy(tp, MII_CTRL1000, &reg))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_STAT1000, &reg))
+ val |= (reg & 0xffff);
+ }
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+
+ if (!tg3_readphy(tp, MII_PHYADDR, &reg))
+ val = reg << 16;
+ else
+ val = 0;
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+
+ tg3_generate_fw_event(tp);
+}
+
+/* NOTE: Debugging only code */
+static void tg3_link_report(struct tg3 *tp)
+{ DBGP("%s\n", __func__);
+
+ if (!netdev_link_ok(tp->dev)) {
+ DBGC(tp->dev, "Link is down\n");
+ tg3_ump_link_report(tp);
+ } else {
+ DBGC(tp->dev, "Link is up at %d Mbps, %s duplex\n",
+ (tp->link_config.active_speed == SPEED_1000 ?
+ 1000 :
+ (tp->link_config.active_speed == SPEED_100 ?
+ 100 : 10)),
+ (tp->link_config.active_duplex == DUPLEX_FULL ?
+ "full" : "half"));
+
+ DBGC(tp->dev, "Flow control is %s for TX and %s for RX\n",
+ (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
+ "on" : "off",
+ (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
+ "on" : "off");
+
+ if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
+ DBGC(tp->dev, "EEE is %s\n",
+ tp->setlpicnt ? "enabled" : "disabled");
+
+ tg3_ump_link_report(tp);
+ }
+}
+#endif
+
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
+{ DBGP("%s\n", __func__);
+
+ int current_link_up;
+ u32 bmsr, val;
+ u32 lcl_adv, rmt_adv;
+ u16 current_speed;
+ u8 current_duplex;
+ int i, err;
+
+ tw32(MAC_EVENT, 0);
+
+ tw32_f(MAC_STATUS,
+ (MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED |
+ MAC_STATUS_MI_COMPLETION |
+ MAC_STATUS_LNKSTATE_CHANGED));
+ udelay(40);
+
+ if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+ tw32_f(MAC_MI_MODE,
+ (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+ udelay(80);
+ }
+
+ tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
+
+ /* Some third-party PHYs need to be reset on link going
+ * down.
+ */
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
+ netdev_link_ok(tp->dev)) {
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ !(bmsr & BMSR_LSTATUS))
+ force_reset = 1;
+ }
+ if (force_reset)
+ tg3_phy_reset(tp);
+
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
+ !tg3_flag(tp, INIT_COMPLETE))
+ bmsr = 0;
+
+ if (!(bmsr & BMSR_LSTATUS)) {
+ err = tg3_init_5401phy_dsp(tp);
+ if (err)
+ return err;
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ for (i = 0; i < 1000; i++) {
+ udelay(10);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS)) {
+ udelay(40);
+ break;
+ }
+ }
+
+ if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
+ TG3_PHY_REV_BCM5401_B0 &&
+ !(bmsr & BMSR_LSTATUS) &&
+ tp->link_config.active_speed == SPEED_1000) {
+ err = tg3_phy_reset(tp);
+ if (!err)
+ err = tg3_init_5401phy_dsp(tp);
+ if (err)
+ return err;
+ }
+ }
+ } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
+ /* 5701 {A0,B0} CRC bug workaround */
+ tg3_writephy(tp, 0x15, 0x0a75);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
+ }
+
+ /* Clear pending interrupts... */
+ tg3_readphy(tp, MII_TG3_ISTAT, &val);
+ tg3_readphy(tp, MII_TG3_ISTAT, &val);
+
+ if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
+ tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
+ else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
+ tg3_writephy(tp, MII_TG3_IMASK, ~0);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+ if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+ else
+ tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
+ }
+
+ current_link_up = 0;
+ current_speed = SPEED_INVALID;
+ current_duplex = DUPLEX_INVALID;
+
+ if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
+ err = tg3_phy_auxctl_read(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+ &val);
+ if (!err && !(val & (1 << 10))) {
+ tg3_phy_auxctl_write(tp,
+ MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
+ val | (1 << 10));
+ goto relink;
+ }
+ }
+
+ bmsr = 0;
+ for (i = 0; i < 100; i++) {
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS))
+ break;
+ udelay(40);
+ }
+
+ if (bmsr & BMSR_LSTATUS) {
+ u32 aux_stat, bmcr;
+
+ tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
+ for (i = 0; i < 2000; i++) {
+ udelay(10);
+ if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
+ aux_stat)
+ break;
+ }
+
+ tg3_aux_stat_to_speed_duplex(tp, aux_stat,
+ &current_speed,
+ &current_duplex);
+
+ bmcr = 0;
+ for (i = 0; i < 200; i++) {
+ tg3_readphy(tp, MII_BMCR, &bmcr);
+ if (tg3_readphy(tp, MII_BMCR, &bmcr))
+ continue;
+ if (bmcr && bmcr != 0x7fff)
+ break;
+ udelay(10);
+ }
+
+ lcl_adv = 0;
+ rmt_adv = 0;
+
+ tp->link_config.active_speed = current_speed;
+ tp->link_config.active_duplex = current_duplex;
+
+ if ((bmcr & BMCR_ANENABLE) &&
+ tg3_copper_is_advertising_all(tp,
+ tp->link_config.advertising)) {
+ if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
+ &rmt_adv)) {
+ current_link_up = 1;
+ }
+ }
+
+ if (current_link_up == 1 &&
+ tp->link_config.active_duplex == DUPLEX_FULL)
+ tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
+ }
+
+relink:
+ if (current_link_up == 0) {
+ tg3_phy_copper_begin(tp);
+
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
+ (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
+ current_link_up = 1;
+ }
+
+ tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
+ if (current_link_up == 1) {
+ if (tp->link_config.active_speed == SPEED_100 ||
+ tp->link_config.active_speed == SPEED_10)
+ tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+ else
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+ tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+ else
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
+ tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
+ if (tp->link_config.active_duplex == DUPLEX_HALF)
+ tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+ if (current_link_up == 1 &&
+ tg3_5700_link_polarity(tp, tp->link_config.active_speed))
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ else
+ tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ }
+
+ /* ??? Without this setting Netgear GA302T PHY does not
+ * ??? send/receive packets...
+ */
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
+ tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
+ tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
+ tw32_f(MAC_MI_MODE, tp->mi_mode);
+ udelay(80);
+ }
+
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
+
+ /* We always use the link change register */
+ /* NOTE: this freezes for mdc? */
+ tw32_f(MAC_EVENT, 0);
+ udelay(40);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
+ current_link_up == 1 &&
+ tp->link_config.active_speed == SPEED_1000 &&
+ (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
+ udelay(120);
+ /* NOTE: this freezes for mdc? */
+ tw32_f(MAC_STATUS,
+ (MAC_STATUS_SYNC_CHANGED |
+ MAC_STATUS_CFG_CHANGED));
+ udelay(40);
+ tg3_write_mem(tp,
+ NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
+ }
+
+ /* Prevent send BD corruption. */
+ if (tg3_flag(tp, CLKREQ_BUG)) {
+ u16 oldlnkctl, newlnkctl;
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &oldlnkctl);
+ if (tp->link_config.active_speed == SPEED_100 ||
+ tp->link_config.active_speed == SPEED_10)
+ newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ else
+ newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+ if (newlnkctl != oldlnkctl)
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ newlnkctl);
+ }
+
+ if (current_link_up != netdev_link_ok(tp->dev)) {
+ if (current_link_up)
+ netdev_link_up(tp->dev);
+ else
+ netdev_link_down(tp->dev);
+ tg3_link_report(tp);
+ }
+
+ return 0;
+}
+
+int tg3_setup_phy(struct tg3 *tp, int force_reset)
+{ DBGP("%s\n", __func__);
+
+ u32 val;
+ int err;
+
+#if 0
+ if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)
+ err = tg3_setup_fiber_phy(tp, force_reset);
+ else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+ err = tg3_setup_fiber_mii_phy(tp, force_reset);
+ else
+#endif
+ /* FIXME: add only copper phy variants for now */
+ err = tg3_setup_copper_phy(tp, force_reset);
+
+ val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+ (6 << TX_LENGTHS_IPG_SHIFT);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ val |= tr32(MAC_TX_LENGTHS) &
+ (TX_LENGTHS_JMB_FRM_LEN_MSK |
+ TX_LENGTHS_CNT_DWN_VAL_MSK);
+
+ if (tp->link_config.active_speed == SPEED_1000 &&
+ tp->link_config.active_duplex == DUPLEX_HALF)
+ tw32(MAC_TX_LENGTHS, val |
+ (0xff << TX_LENGTHS_SLOT_TIME_SHIFT));
+ else
+ tw32(MAC_TX_LENGTHS, val |
+ (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ if (netdev_link_ok(tp->dev)) {
+ tw32(HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS);
+ } else {
+ tw32(HOSTCC_STAT_COAL_TICKS, 0);
+ }
+ }
+
+ val = tr32(PCIE_PWR_MGMT_THRESH);
+ if (!netdev_link_ok(tp->dev))
+ val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK);
+ else
+ val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+ tw32(PCIE_PWR_MGMT_THRESH, val);
+
+ return err;
+}