mirror of https://github.com/ipxe/ipxe.git
2675 lines
76 KiB
C
2675 lines
76 KiB
C
/*
|
|
* 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, ENABLE_ASF))
|
|
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_57762 ||
|
|
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 ||
|
|
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 ||
|
|
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 ||
|
|
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766 ||
|
|
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);
|
|
}
|
|
|
|
if (tg3_flag(tp, CPMU_PRESENT)) {
|
|
tw32(TG3_CPMU_D0_CLCK_POLICY, 0);
|
|
val = tr32(TG3_CPMU_CLCK_ORIDE_EN);
|
|
tw32(TG3_CPMU_CLCK_ORIDE_EN,
|
|
val | CPMU_CLCK_ORIDE_MAC_CLCK_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 = dev->priv;
|
|
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 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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
if (tg3_flag(tp, 57765_PLUS))
|
|
val |= (RX_STD_MAX_SIZE << 2);
|
|
|
|
tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
|
|
|
|
tpr->rx_std_prod_idx = 0;
|
|
|
|
/* 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);
|
|
|
|
__tg3_set_mac_addr(tp,0);
|
|
|
|
#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);
|
|
/* Fall through */
|
|
case 15:
|
|
tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0);
|
|
/* Fall through */
|
|
case 14:
|
|
tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0);
|
|
/* Fall through */
|
|
case 13:
|
|
tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0);
|
|
/* Fall through */
|
|
case 12:
|
|
tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0);
|
|
/* Fall through */
|
|
case 11:
|
|
tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0);
|
|
/* Fall through */
|
|
case 10:
|
|
tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0);
|
|
/* Fall through */
|
|
case 9:
|
|
tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0);
|
|
/* Fall through */
|
|
case 8:
|
|
tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0);
|
|
/* Fall through */
|
|
case 7:
|
|
tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0);
|
|
/* Fall through */
|
|
case 6:
|
|
tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0);
|
|
/* Fall through */
|
|
case 5:
|
|
tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0);
|
|
/* Fall through */
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|