#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.84"
-#define DRV_MODULE_RELDATE "October 12, 2007"
+#define DRV_MODULE_VERSION "3.86"
+#define DRV_MODULE_RELDATE "November 9, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
if (err)
return err;
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ u32 val;
+
+ 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);
+ }
+
+ /* Disable GPHY autopowerdown. */
+ tg3_writephy(tp, MII_TG3_MISC_SHDW,
+ MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_APD_SEL |
+ MII_TG3_MISC_SHDW_APD_WKTM_84MS);
+ }
+
out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
static void tg3_power_down_phy(struct tg3 *tp)
{
+ u32 val;
+
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 val;
-
tg3_bmcr_reset(tp);
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
+
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
}
err = tg3_setup_copper_phy(tp, force_reset);
}
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+ u32 val, scale;
+
+ val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+ if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+ scale = 65;
+ else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+ scale = 6;
+ else
+ scale = 12;
+
+ val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+ val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+ tw32(GRC_MISC_CFG, val);
+ }
+
if (tp->link_config.active_speed == SPEED_1000 &&
tp->link_config.active_duplex == DUPLEX_HALF)
tw32(MAC_TX_LENGTHS,
pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
- if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+ pcie_set_readrq(tp->pdev, 4096);
+ else {
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 (tp->pcix_cap) {
u16 pcix_cmd;
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
+
+ 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);
+
+ val = tr32(TG3_CPMU_LNK_AWARE_PWRMD);
+ val &= ~CPMU_LNK_AWARE_MACCLK_MASK;
+ val |= CPMU_LNK_AWARE_MACCLK_6_25;
+ tw32(TG3_CPMU_LNK_AWARE_PWRMD, val);
+
+ val = tr32(TG3_CPMU_HST_ACC);
+ val &= ~CPMU_HST_ACC_MACCLK_MASK;
+ val |= CPMU_HST_ACC_MACCLK_6_25;
+ tw32(TG3_CPMU_HST_ACC, val);
}
/* This works around an issue with Athlon chipsets on
} else if (pci_enable_msi(tp->pdev) == 0) {
u32 msi_mode;
- /* Hardware bug - MSI won't work if INTX disabled. */
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
- pci_intx(tp->pdev, 1);
-
msi_mode = tr32(MSGINT_MODE);
tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
}
static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val);
+static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val);
static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val);
static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
struct tg3 *tp = netdev_priv(dev);
int ret;
u8 *pd;
- u32 i, offset, len, val, b_offset, b_count;
+ u32 i, offset, len, b_offset, b_count;
+ __le32 val;
if (tp->link_config.phy_is_low_power)
return -EAGAIN;
/* i.e. offset=1 len=2 */
b_count = len;
}
- ret = tg3_nvram_read(tp, offset-b_offset, &val);
+ ret = tg3_nvram_read_le(tp, offset-b_offset, &val);
if (ret)
return ret;
- val = cpu_to_le32(val);
memcpy(data, ((char*)&val) + b_offset, b_count);
len -= b_count;
offset += b_count;
/* read bytes upto the last 4 byte boundary */
pd = &data[eeprom->len];
for (i = 0; i < (len - (len & 3)); i += 4) {
- ret = tg3_nvram_read(tp, offset + i, &val);
+ ret = tg3_nvram_read_le(tp, offset + i, &val);
if (ret) {
eeprom->len += i;
return ret;
}
- val = cpu_to_le32(val);
memcpy(pd + i, &val, 4);
}
eeprom->len += i;
pd = &data[eeprom->len];
b_count = len & 3;
b_offset = offset + len - b_count;
- ret = tg3_nvram_read(tp, b_offset, &val);
+ ret = tg3_nvram_read_le(tp, b_offset, &val);
if (ret)
return ret;
- val = cpu_to_le32(val);
- memcpy(pd, ((char*)&val), b_count);
+ memcpy(pd, &val, b_count);
eeprom->len += b_count;
}
return 0;
{
struct tg3 *tp = netdev_priv(dev);
int ret;
- u32 offset, len, b_offset, odd_len, start, end;
+ u32 offset, len, b_offset, odd_len;
u8 *buf;
+ __le32 start, end;
if (tp->link_config.phy_is_low_power)
return -EAGAIN;
if ((b_offset = (offset & 3))) {
/* adjustments to start on required 4 byte boundary */
- ret = tg3_nvram_read(tp, offset-b_offset, &start);
+ ret = tg3_nvram_read_le(tp, offset-b_offset, &start);
if (ret)
return ret;
- start = cpu_to_le32(start);
len += b_offset;
offset &= ~3;
if (len < 4)
/* adjustments to end on required 4 byte boundary */
odd_len = 1;
len = (len + 3) & ~3;
- ret = tg3_nvram_read(tp, offset+len-4, &end);
+ ret = tg3_nvram_read_le(tp, offset+len-4, &end);
if (ret)
return ret;
- end = cpu_to_le32(end);
}
buf = data;
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;
}
#define NVRAM_TEST_SIZE 0x100
-#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
+#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c
#define NVRAM_SELFBOOT_HW_SIZE 0x20
#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
static int tg3_test_nvram(struct tg3 *tp)
{
- u32 *buf, csum, magic;
+ u32 csum, magic;
+ __le32 *buf;
int i, j, k, err = 0, size;
if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
if (magic == TG3_EEPROM_MAGIC)
size = NVRAM_TEST_SIZE;
else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
- if ((magic & 0xe00000) == 0x200000)
- size = NVRAM_SELFBOOT_FORMAT1_SIZE;
- else
+ if ((magic & TG3_EEPROM_SB_FORMAT_MASK) ==
+ TG3_EEPROM_SB_FORMAT_1) {
+ switch (magic & TG3_EEPROM_SB_REVISION_MASK) {
+ case TG3_EEPROM_SB_REVISION_0:
+ size = NVRAM_SELFBOOT_FORMAT1_0_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_2:
+ size = NVRAM_SELFBOOT_FORMAT1_2_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_3:
+ size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
+ break;
+ default:
+ return 0;
+ }
+ } else
return 0;
} else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
size = NVRAM_SELFBOOT_HW_SIZE;
err = -EIO;
for (i = 0, j = 0; i < size; i += 4, j++) {
- u32 val;
-
- if ((err = tg3_nvram_read(tp, i, &val)) != 0)
+ if ((err = tg3_nvram_read_le(tp, i, &buf[j])) != 0)
break;
- buf[j] = cpu_to_le32(val);
}
if (i < size)
goto out;
/* Selfboot format */
- if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) ==
+ magic = swab32(le32_to_cpu(buf[0]));
+ if ((magic & TG3_EEPROM_MAGIC_FW_MSK) ==
TG3_EEPROM_MAGIC_FW) {
u8 *buf8 = (u8 *) buf, csum8 = 0;
- for (i = 0; i < size; i++)
- csum8 += buf8[i];
+ if ((magic & TG3_EEPROM_SB_REVISION_MASK) ==
+ TG3_EEPROM_SB_REVISION_2) {
+ /* For rev 2, the csum doesn't include the MBA. */
+ for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++)
+ csum8 += buf8[i];
+ for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++)
+ csum8 += buf8[i];
+ } else {
+ for (i = 0; i < size; i++)
+ csum8 += buf8[i];
+ }
if (csum8 == 0) {
err = 0;
goto out;
}
- if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) ==
+ if ((magic & TG3_EEPROM_MAGIC_HW_MSK) ==
TG3_EEPROM_MAGIC_HW) {
u8 data[NVRAM_SELFBOOT_DATA_SIZE];
u8 parity[NVRAM_SELFBOOT_DATA_SIZE];
/* Bootstrap checksum at offset 0x10 */
csum = calc_crc((unsigned char *) buf, 0x10);
- if(csum != cpu_to_le32(buf[0x10/4]))
+ if(csum != le32_to_cpu(buf[0x10/4]))
goto out;
/* Manufacturing block starts at offset 0x74, checksum at 0xfc */
csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
- if (csum != cpu_to_le32(buf[0xfc/4]))
+ if (csum != le32_to_cpu(buf[0xfc/4]))
goto out;
err = 0;
if (err)
return TG3_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
int i;
u32 status;
if (status != CPMU_MUTEX_GNT_DRIVER)
return TG3_LOOPBACK_FAILED;
- cpmuctrl = tr32(TG3_CPMU_CTRL);
-
/* Turn off power management based on link speed. */
+ cpmuctrl = tr32(TG3_CPMU_CTRL);
tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE);
+ cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
+ CPMU_CTRL_LINK_AWARE_MODE));
}
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
/* Release the mutex */
return ret;
}
+static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val)
+{
+ u32 v;
+ int res = tg3_nvram_read(tp, offset, &v);
+ if (!res)
+ *val = cpu_to_le32(v);
+ return res;
+}
+
static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val)
{
int err;
u32 val;
for (i = 0; i < len; i += 4) {
- u32 addr, data;
+ u32 addr;
+ __le32 data;
addr = offset + i;
memcpy(&data, buf + i, 4);
- tw32(GRC_EEPROM_DATA, cpu_to_le32(data));
+ tw32(GRC_EEPROM_DATA, le32_to_cpu(data));
val = tr32(GRC_EEPROM_ADDR);
tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
phy_addr = offset & ~pagemask;
for (j = 0; j < pagesize; j += 4) {
- if ((ret = tg3_nvram_read(tp, phy_addr + j,
- (u32 *) (tmp + j))))
+ if ((ret = tg3_nvram_read_le(tp, phy_addr + j,
+ (__le32 *) (tmp + j))))
break;
}
if (ret)
break;
for (j = 0; j < pagesize; j += 4) {
- u32 data;
+ __be32 data;
- data = *((u32 *) (tmp + j));
- tw32(NVRAM_WRDATA, cpu_to_be32(data));
+ data = *((__be32 *) (tmp + j));
+ /* swab32(le32_to_cpu(data)), actually */
+ tw32(NVRAM_WRDATA, be32_to_cpu(data));
tw32(NVRAM_ADDR, phy_addr + j);
int i, ret = 0;
for (i = 0; i < len; i += 4, offset += 4) {
- u32 data, page_off, phy_addr, nvram_cmd;
+ u32 page_off, phy_addr, nvram_cmd;
+ __be32 data;
memcpy(&data, buf + i, 4);
- tw32(NVRAM_WRDATA, cpu_to_be32(data));
+ tw32(NVRAM_WRDATA, be32_to_cpu(data));
page_off = offset % tp->nvram_pagesize;
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1)
+ tp->led_ctrl = LED_CTRL_MODE_MAC;
+
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if ((tp->pdev->subsystem_vendor ==
vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD);
for (i = 0; i < 256; i += 4) {
u32 tmp, j = 0;
+ __le32 v;
u16 tmp16;
pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR,
pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
&tmp);
- tmp = cpu_to_le32(tmp);
- memcpy(&vpd_data[i], &tmp, 4);
+ v = cpu_to_le32(tmp);
+ memcpy(&vpd_data[i], &v, 4);
}
}
offset = offset + ver_offset - start;
for (i = 0; i < 16; i += 4) {
- if (tg3_nvram_read(tp, offset + i, &val))
+ __le32 v;
+ if (tg3_nvram_read_le(tp, offset + i, &v))
return;
- val = le32_to_cpu(val);
- memcpy(tp->fw_ver + i, &val, 4);
+ memcpy(tp->fw_ver + i, &v, 4);
}
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
- (tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;
for (offset = TG3_NVM_DIR_START;
tp->fw_ver[bcnt++] = ' ';
for (i = 0; i < 4; i++) {
- if (tg3_nvram_read(tp, offset, &val))
+ __le32 v;
+ if (tg3_nvram_read_le(tp, offset, &v))
return;
- val = le32_to_cpu(val);
- offset += sizeof(val);
+ offset += sizeof(v);
- if (bcnt > TG3_VER_SIZE - sizeof(val)) {
- memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt);
+ if (bcnt > TG3_VER_SIZE - sizeof(v)) {
+ memcpy(&tp->fw_ver[bcnt], &v, TG3_VER_SIZE - bcnt);
break;
}
- memcpy(&tp->fw_ver[bcnt], &val, sizeof(val));
- bcnt += sizeof(val);
+ memcpy(&tp->fw_ver[bcnt], &v, sizeof(v));
+ bcnt += sizeof(v);
}
tp->fw_ver[TG3_VER_SIZE - 1] = 0;
pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
if (pcie_cap != 0) {
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+
+ pcie_set_readrq(tp->pdev, 4096);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u16 lnkctl;
}
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_5761) {
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
+ tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
+ }
+
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
* GPIO1 driven high will bring 5700's external PHY out of reset.
* It is also used as eeprom write protect on LOMs.
goto err_out_iounmap;
}
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+ if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX "Cannot find proper PCI device "
+ "base address for APE, aborting.\n");
+ err = -ENODEV;
+ goto err_out_iounmap;
+ }
+
+ tg3reg_base = pci_resource_start(pdev, 2);
+ tg3reg_len = pci_resource_len(pdev, 2);
+
+ tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
+ if (tp->aperegs == 0UL) {
+ printk(KERN_ERR PFX "Cannot map APE registers, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ tg3_ape_lock_init(tp);
+ }
+
/*
* Reset chip in case UNDI or EFI driver did not shutdown
* DMA self test will enable WDMAC and we'll see (spurious)
err = tg3_test_dma(tp);
if (err) {
printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
- goto err_out_iounmap;
+ goto err_out_apeunmap;
}
/* Tigon3 can do ipv4 only... and some chips have buggy
tg3_init_coal(tp);
- if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
- if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find proper PCI device "
- "base address for APE, aborting.\n");
- err = -ENODEV;
- goto err_out_iounmap;
- }
-
- tg3reg_base = pci_resource_start(pdev, 2);
- tg3reg_len = pci_resource_len(pdev, 2);
-
- tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
- if (tp->aperegs == 0UL) {
- printk(KERN_ERR PFX "Cannot map APE registers, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_out_iounmap;
- }
-
- tg3_ape_lock_init(tp);
- }
-
pci_set_drvdata(pdev, dev);
err = register_netdev(dev);
if (err)
return err;
- /* Hardware bug - MSI won't work if INTX disabled. */
- if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
- (tp->tg3_flags2 & TG3_FLG2_USING_MSI))
- pci_intx(tp->pdev, 1);
-
netif_device_attach(dev);
tg3_full_lock(tp, 0);