diff options
author | Michael Chan <mchan@broadcom.com> | 2006-09-27 19:10:14 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-28 21:01:42 -0400 |
commit | b16250e3d1c55820f08f0296624a423122ea9805 (patch) | |
tree | 9559f4acd5e740b727c42e635699b7427f21d3c3 /drivers/net | |
parent | 715116a12610b67c1d301a9b845ce95f7247dad3 (diff) |
[TG3]: Add 5709 self-test support.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/tg3.c | 123 | ||||
-rw-r--r-- | drivers/net/tg3.h | 4 |
2 files changed, 111 insertions, 16 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 23f5744bdffa..21843de4a88a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -3615,8 +3615,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, | |||
3615 | 3615 | ||
3616 | if ((sblk->status & SD_STATUS_UPDATED) || | 3616 | if ((sblk->status & SD_STATUS_UPDATED) || |
3617 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { | 3617 | !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { |
3618 | tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, | 3618 | tg3_disable_ints(tp); |
3619 | 0x00000001); | ||
3620 | return IRQ_RETVAL(1); | 3619 | return IRQ_RETVAL(1); |
3621 | } | 3620 | } |
3622 | return IRQ_RETVAL(0); | 3621 | return IRQ_RETVAL(0); |
@@ -6860,8 +6859,7 @@ static int tg3_request_irq(struct tg3 *tp) | |||
6860 | static int tg3_test_interrupt(struct tg3 *tp) | 6859 | static int tg3_test_interrupt(struct tg3 *tp) |
6861 | { | 6860 | { |
6862 | struct net_device *dev = tp->dev; | 6861 | struct net_device *dev = tp->dev; |
6863 | int err, i; | 6862 | int err, i, intr_ok = 0; |
6864 | u32 int_mbox = 0; | ||
6865 | 6863 | ||
6866 | if (!netif_running(dev)) | 6864 | if (!netif_running(dev)) |
6867 | return -ENODEV; | 6865 | return -ENODEV; |
@@ -6882,10 +6880,18 @@ static int tg3_test_interrupt(struct tg3 *tp) | |||
6882 | HOSTCC_MODE_NOW); | 6880 | HOSTCC_MODE_NOW); |
6883 | 6881 | ||
6884 | for (i = 0; i < 5; i++) { | 6882 | for (i = 0; i < 5; i++) { |
6883 | u32 int_mbox, misc_host_ctrl; | ||
6884 | |||
6885 | int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 + | 6885 | int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 + |
6886 | TG3_64BIT_REG_LOW); | 6886 | TG3_64BIT_REG_LOW); |
6887 | if (int_mbox != 0) | 6887 | misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); |
6888 | |||
6889 | if ((int_mbox != 0) || | ||
6890 | (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) { | ||
6891 | intr_ok = 1; | ||
6888 | break; | 6892 | break; |
6893 | } | ||
6894 | |||
6889 | msleep(10); | 6895 | msleep(10); |
6890 | } | 6896 | } |
6891 | 6897 | ||
@@ -6898,7 +6904,7 @@ static int tg3_test_interrupt(struct tg3 *tp) | |||
6898 | if (err) | 6904 | if (err) |
6899 | return err; | 6905 | return err; |
6900 | 6906 | ||
6901 | if (int_mbox != 0) | 6907 | if (intr_ok) |
6902 | return 0; | 6908 | return 0; |
6903 | 6909 | ||
6904 | return -EIO; | 6910 | return -EIO; |
@@ -8288,6 +8294,8 @@ static void tg3_get_ethtool_stats (struct net_device *dev, | |||
8288 | 8294 | ||
8289 | #define NVRAM_TEST_SIZE 0x100 | 8295 | #define NVRAM_TEST_SIZE 0x100 |
8290 | #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 | 8296 | #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 |
8297 | #define NVRAM_SELFBOOT_HW_SIZE 0x20 | ||
8298 | #define NVRAM_SELFBOOT_DATA_SIZE 0x1c | ||
8291 | 8299 | ||
8292 | static int tg3_test_nvram(struct tg3 *tp) | 8300 | static int tg3_test_nvram(struct tg3 *tp) |
8293 | { | 8301 | { |
@@ -8299,12 +8307,14 @@ static int tg3_test_nvram(struct tg3 *tp) | |||
8299 | 8307 | ||
8300 | if (magic == TG3_EEPROM_MAGIC) | 8308 | if (magic == TG3_EEPROM_MAGIC) |
8301 | size = NVRAM_TEST_SIZE; | 8309 | size = NVRAM_TEST_SIZE; |
8302 | else if ((magic & 0xff000000) == 0xa5000000) { | 8310 | else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { |
8303 | if ((magic & 0xe00000) == 0x200000) | 8311 | if ((magic & 0xe00000) == 0x200000) |
8304 | size = NVRAM_SELFBOOT_FORMAT1_SIZE; | 8312 | size = NVRAM_SELFBOOT_FORMAT1_SIZE; |
8305 | else | 8313 | else |
8306 | return 0; | 8314 | return 0; |
8307 | } else | 8315 | } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) |
8316 | size = NVRAM_SELFBOOT_HW_SIZE; | ||
8317 | else | ||
8308 | return -EIO; | 8318 | return -EIO; |
8309 | 8319 | ||
8310 | buf = kmalloc(size, GFP_KERNEL); | 8320 | buf = kmalloc(size, GFP_KERNEL); |
@@ -8323,7 +8333,8 @@ static int tg3_test_nvram(struct tg3 *tp) | |||
8323 | goto out; | 8333 | goto out; |
8324 | 8334 | ||
8325 | /* Selfboot format */ | 8335 | /* Selfboot format */ |
8326 | if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) { | 8336 | if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) == |
8337 | TG3_EEPROM_MAGIC_FW) { | ||
8327 | u8 *buf8 = (u8 *) buf, csum8 = 0; | 8338 | u8 *buf8 = (u8 *) buf, csum8 = 0; |
8328 | 8339 | ||
8329 | for (i = 0; i < size; i++) | 8340 | for (i = 0; i < size; i++) |
@@ -8338,6 +8349,51 @@ static int tg3_test_nvram(struct tg3 *tp) | |||
8338 | goto out; | 8349 | goto out; |
8339 | } | 8350 | } |
8340 | 8351 | ||
8352 | if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) == | ||
8353 | TG3_EEPROM_MAGIC_HW) { | ||
8354 | u8 data[NVRAM_SELFBOOT_DATA_SIZE]; | ||
8355 | u8 parity[NVRAM_SELFBOOT_DATA_SIZE]; | ||
8356 | u8 *buf8 = (u8 *) buf; | ||
8357 | int j, k; | ||
8358 | |||
8359 | /* Separate the parity bits and the data bytes. */ | ||
8360 | for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) { | ||
8361 | if ((i == 0) || (i == 8)) { | ||
8362 | int l; | ||
8363 | u8 msk; | ||
8364 | |||
8365 | for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1) | ||
8366 | parity[k++] = buf8[i] & msk; | ||
8367 | i++; | ||
8368 | } | ||
8369 | else if (i == 16) { | ||
8370 | int l; | ||
8371 | u8 msk; | ||
8372 | |||
8373 | for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1) | ||
8374 | parity[k++] = buf8[i] & msk; | ||
8375 | i++; | ||
8376 | |||
8377 | for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1) | ||
8378 | parity[k++] = buf8[i] & msk; | ||
8379 | i++; | ||
8380 | } | ||
8381 | data[j++] = buf8[i]; | ||
8382 | } | ||
8383 | |||
8384 | err = -EIO; | ||
8385 | for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) { | ||
8386 | u8 hw8 = hweight8(data[i]); | ||
8387 | |||
8388 | if ((hw8 & 0x1) && parity[i]) | ||
8389 | goto out; | ||
8390 | else if (!(hw8 & 0x1) && !parity[i]) | ||
8391 | goto out; | ||
8392 | } | ||
8393 | err = 0; | ||
8394 | goto out; | ||
8395 | } | ||
8396 | |||
8341 | /* Bootstrap checksum at offset 0x10 */ | 8397 | /* Bootstrap checksum at offset 0x10 */ |
8342 | csum = calc_crc((unsigned char *) buf, 0x10); | 8398 | csum = calc_crc((unsigned char *) buf, 0x10); |
8343 | if(csum != cpu_to_le32(buf[0x10/4])) | 8399 | if(csum != cpu_to_le32(buf[0x10/4])) |
@@ -8384,7 +8440,7 @@ static int tg3_test_link(struct tg3 *tp) | |||
8384 | /* Only test the commonly used registers */ | 8440 | /* Only test the commonly used registers */ |
8385 | static int tg3_test_registers(struct tg3 *tp) | 8441 | static int tg3_test_registers(struct tg3 *tp) |
8386 | { | 8442 | { |
8387 | int i, is_5705; | 8443 | int i, is_5705, is_5750; |
8388 | u32 offset, read_mask, write_mask, val, save_val, read_val; | 8444 | u32 offset, read_mask, write_mask, val, save_val, read_val; |
8389 | static struct { | 8445 | static struct { |
8390 | u16 offset; | 8446 | u16 offset; |
@@ -8392,6 +8448,7 @@ static int tg3_test_registers(struct tg3 *tp) | |||
8392 | #define TG3_FL_5705 0x1 | 8448 | #define TG3_FL_5705 0x1 |
8393 | #define TG3_FL_NOT_5705 0x2 | 8449 | #define TG3_FL_NOT_5705 0x2 |
8394 | #define TG3_FL_NOT_5788 0x4 | 8450 | #define TG3_FL_NOT_5788 0x4 |
8451 | #define TG3_FL_NOT_5750 0x8 | ||
8395 | u32 read_mask; | 8452 | u32 read_mask; |
8396 | u32 write_mask; | 8453 | u32 write_mask; |
8397 | } reg_tbl[] = { | 8454 | } reg_tbl[] = { |
@@ -8502,9 +8559,9 @@ static int tg3_test_registers(struct tg3 *tp) | |||
8502 | 0xffffffff, 0x00000000 }, | 8559 | 0xffffffff, 0x00000000 }, |
8503 | 8560 | ||
8504 | /* Buffer Manager Control Registers. */ | 8561 | /* Buffer Manager Control Registers. */ |
8505 | { BUFMGR_MB_POOL_ADDR, 0x0000, | 8562 | { BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750, |
8506 | 0x00000000, 0x007fff80 }, | 8563 | 0x00000000, 0x007fff80 }, |
8507 | { BUFMGR_MB_POOL_SIZE, 0x0000, | 8564 | { BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750, |
8508 | 0x00000000, 0x007fffff }, | 8565 | 0x00000000, 0x007fffff }, |
8509 | { BUFMGR_MB_RDMA_LOW_WATER, 0x0000, | 8566 | { BUFMGR_MB_RDMA_LOW_WATER, 0x0000, |
8510 | 0x00000000, 0x0000003f }, | 8567 | 0x00000000, 0x0000003f }, |
@@ -8530,10 +8587,12 @@ static int tg3_test_registers(struct tg3 *tp) | |||
8530 | { 0xffff, 0x0000, 0x00000000, 0x00000000 }, | 8587 | { 0xffff, 0x0000, 0x00000000, 0x00000000 }, |
8531 | }; | 8588 | }; |
8532 | 8589 | ||
8533 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) | 8590 | is_5705 = is_5750 = 0; |
8591 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { | ||
8534 | is_5705 = 1; | 8592 | is_5705 = 1; |
8535 | else | 8593 | if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) |
8536 | is_5705 = 0; | 8594 | is_5750 = 1; |
8595 | } | ||
8537 | 8596 | ||
8538 | for (i = 0; reg_tbl[i].offset != 0xffff; i++) { | 8597 | for (i = 0; reg_tbl[i].offset != 0xffff; i++) { |
8539 | if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705)) | 8598 | if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705)) |
@@ -8546,6 +8605,9 @@ static int tg3_test_registers(struct tg3 *tp) | |||
8546 | (reg_tbl[i].flags & TG3_FL_NOT_5788)) | 8605 | (reg_tbl[i].flags & TG3_FL_NOT_5788)) |
8547 | continue; | 8606 | continue; |
8548 | 8607 | ||
8608 | if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750)) | ||
8609 | continue; | ||
8610 | |||
8549 | offset = (u32) reg_tbl[i].offset; | 8611 | offset = (u32) reg_tbl[i].offset; |
8550 | read_mask = reg_tbl[i].read_mask; | 8612 | read_mask = reg_tbl[i].read_mask; |
8551 | write_mask = reg_tbl[i].write_mask; | 8613 | write_mask = reg_tbl[i].write_mask; |
@@ -8637,6 +8699,13 @@ static int tg3_test_memory(struct tg3 *tp) | |||
8637 | { 0x00008000, 0x02000}, | 8699 | { 0x00008000, 0x02000}, |
8638 | { 0x00010000, 0x0c000}, | 8700 | { 0x00010000, 0x0c000}, |
8639 | { 0xffffffff, 0x00000} | 8701 | { 0xffffffff, 0x00000} |
8702 | }, mem_tbl_5906[] = { | ||
8703 | { 0x00000200, 0x00008}, | ||
8704 | { 0x00004000, 0x00400}, | ||
8705 | { 0x00006000, 0x00400}, | ||
8706 | { 0x00008000, 0x01000}, | ||
8707 | { 0x00010000, 0x01000}, | ||
8708 | { 0xffffffff, 0x00000} | ||
8640 | }; | 8709 | }; |
8641 | struct mem_entry *mem_tbl; | 8710 | struct mem_entry *mem_tbl; |
8642 | int err = 0; | 8711 | int err = 0; |
@@ -8646,6 +8715,8 @@ static int tg3_test_memory(struct tg3 *tp) | |||
8646 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || | 8715 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || |
8647 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) | 8716 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) |
8648 | mem_tbl = mem_tbl_5755; | 8717 | mem_tbl = mem_tbl_5755; |
8718 | else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) | ||
8719 | mem_tbl = mem_tbl_5906; | ||
8649 | else | 8720 | else |
8650 | mem_tbl = mem_tbl_5705; | 8721 | mem_tbl = mem_tbl_5705; |
8651 | } else | 8722 | } else |
@@ -8691,6 +8762,21 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) | |||
8691 | } else if (loopback_mode == TG3_PHY_LOOPBACK) { | 8762 | } else if (loopback_mode == TG3_PHY_LOOPBACK) { |
8692 | u32 val; | 8763 | u32 val; |
8693 | 8764 | ||
8765 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { | ||
8766 | u32 phytest; | ||
8767 | |||
8768 | if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) { | ||
8769 | u32 phy; | ||
8770 | |||
8771 | tg3_writephy(tp, MII_TG3_EPHY_TEST, | ||
8772 | phytest | MII_TG3_EPHY_SHADOW_EN); | ||
8773 | if (!tg3_readphy(tp, 0x1b, &phy)) | ||
8774 | tg3_writephy(tp, 0x1b, phy & ~0x20); | ||
8775 | if (!tg3_readphy(tp, 0x10, &phy)) | ||
8776 | tg3_writephy(tp, 0x10, phy & ~0x4000); | ||
8777 | tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest); | ||
8778 | } | ||
8779 | } | ||
8694 | val = BMCR_LOOPBACK | BMCR_FULLDPLX; | 8780 | val = BMCR_LOOPBACK | BMCR_FULLDPLX; |
8695 | if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) | 8781 | if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) |
8696 | val |= BMCR_SPEED100; | 8782 | val |= BMCR_SPEED100; |
@@ -8699,6 +8785,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) | |||
8699 | 8785 | ||
8700 | tg3_writephy(tp, MII_BMCR, val); | 8786 | tg3_writephy(tp, MII_BMCR, val); |
8701 | udelay(40); | 8787 | udelay(40); |
8788 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) | ||
8789 | tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800); | ||
8790 | |||
8702 | /* reset to prevent losing 1st rx packet intermittently */ | 8791 | /* reset to prevent losing 1st rx packet intermittently */ |
8703 | if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { | 8792 | if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { |
8704 | tw32_f(MAC_RX_MODE, RX_MODE_RESET); | 8793 | tw32_f(MAC_RX_MODE, RX_MODE_RESET); |
@@ -9112,7 +9201,9 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) | |||
9112 | if (tg3_nvram_read_swab(tp, 0, &magic) != 0) | 9201 | if (tg3_nvram_read_swab(tp, 0, &magic) != 0) |
9113 | return; | 9202 | return; |
9114 | 9203 | ||
9115 | if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000)) | 9204 | if ((magic != TG3_EEPROM_MAGIC) && |
9205 | ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) && | ||
9206 | ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW)) | ||
9116 | return; | 9207 | return; |
9117 | 9208 | ||
9118 | /* | 9209 | /* |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 9259d12fabd9..92f53000bce6 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -1507,6 +1507,10 @@ | |||
1507 | 1507 | ||
1508 | 1508 | ||
1509 | #define TG3_EEPROM_MAGIC 0x669955aa | 1509 | #define TG3_EEPROM_MAGIC 0x669955aa |
1510 | #define TG3_EEPROM_MAGIC_FW 0xa5000000 | ||
1511 | #define TG3_EEPROM_MAGIC_FW_MSK 0xff000000 | ||
1512 | #define TG3_EEPROM_MAGIC_HW 0xabcd | ||
1513 | #define TG3_EEPROM_MAGIC_HW_MSK 0xffff | ||
1510 | 1514 | ||
1511 | /* 32K Window into NIC internal memory */ | 1515 | /* 32K Window into NIC internal memory */ |
1512 | #define NIC_SRAM_WIN_BASE 0x00008000 | 1516 | #define NIC_SRAM_WIN_BASE 0x00008000 |