/* * 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-2007 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_SPARC #include #include #endif #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define TG3_VLAN_TAG_USED 1 #else #define TG3_VLAN_TAG_USED 0 #endif #define TG3_TSO_SUPPORT 1 #include "tg3.h" #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "3.94" #define DRV_MODULE_RELDATE "August 14, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 #define TG3_DEF_TX_MODE 0 #define TG3_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK | \ NETIF_MSG_TIMER | \ NETIF_MSG_IFDOWN | \ NETIF_MSG_IFUP | \ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) /* length of time before we decide the hardware is borked, * and dev->tx_timeout() should be called to fix the problem */ #define TG3_TX_TIMEOUT (5 * HZ) /* hardware minimum and maximum for a single frame's data payload */ #define TG3_MIN_MTU 60 #define TG3_MAX_MTU(tp) \ ((tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) ? 9000 : 1500) /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place * them in the NIC onboard memory. */ #define TG3_RX_RING_SIZE 512 #define TG3_DEF_RX_RING_PENDING 200 #define TG3_RX_JUMBO_RING_SIZE 256 #define TG3_DEF_RX_JUMBO_RING_PENDING 100 /* Do not place this n-ring entries value into the tp struct itself, * we really want to expose these constants to GCC so that modulo et * al. operations are done with shifts and masks instead of with * hw multiply/modulo instructions. Another solution would be to * replace things like '% foo' with '& (foo - 1)'. */ #define TG3_RX_RCB_RING_SIZE(tp) \ ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 512 : 1024) #define TG3_TX_RING_SIZE 512 #define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) #define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_RING_SIZE) #define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_JUMBO_RING_SIZE) #define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) #define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) /* minimum number of free TX descriptors required to wake up TX process */ #define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4) /* number of ETHTOOL_GSTATS u64's */ #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) #define TG3_NUM_TEST 6 static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5785)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)}, {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)}, {} }; MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); static const struct { const char string[ETH_GSTRING_LEN]; } ethtool_stats_keys[TG3_NUM_STATS] = { { "rx_octets" }, { "rx_fragments" }, { "rx_ucast_packets" }, { "rx_mcast_packets" }, { "rx_bcast_packets" }, { "rx_fcs_errors" }, { "rx_align_errors" }, { "rx_xon_pause_rcvd" }, { "rx_xoff_pause_rcvd" }, { "rx_mac_ctrl_rcvd" }, { "rx_xoff_entered" }, { "rx_frame_too_long_errors" }, { "rx_jabbers" }, { "rx_undersize_packets" }, { "rx_in_length_errors" }, { "rx_out_length_errors" }, { "rx_64_or_less_octet_packets" }, { "rx_65_to_127_octet_packets" }, { "rx_128_to_255_octet_packets" }, { "rx_256_to_511_octet_packets" }, { "rx_512_to_1023_octet_packets" }, { "rx_1024_to_1522_octet_packets" }, { "rx_1523_to_2047_octet_packets" }, { "rx_2048_to_4095_octet_packets" }, { "rx_4096_to_8191_octet_packets" }, { "rx_8192_to_9022_octet_packets" }, { "tx_octets" }, { "tx_collisions" }, { "tx_xon_sent" }, { "tx_xoff_sent" }, { "tx_flow_control" }, { "tx_mac_errors" }, { "tx_single_collisions" }, { "tx_mult_collisions" }, { "tx_deferred" }, { "tx_excessive_collisions" }, { "tx_late_collisions" }, { "tx_collide_2times" }, { "tx_collide_3times" }, { "tx_collide_4times" }, { "tx_collide_5times" }, { "tx_collide_6times" }, { "tx_collide_7times" }, { "tx_collide_8times" }, { "tx_collide_9times" }, { "tx_collide_10times" }, { "tx_collide_11times" }, { "tx_collide_12times" }, { "tx_collide_13times" }, { "tx_collide_14times" }, { "tx_collide_15times" }, { "tx_ucast_packets" }, { "tx_mcast_packets" }, { "tx_bcast_packets" }, { "tx_carrier_sense_errors" }, { "tx_discards" }, { "tx_errors" }, { "dma_writeq_full" }, { "dma_write_prioq_full" }, { "rxbds_empty" }, { "rx_discards" }, { "rx_errors" }, { "rx_threshold_hit" }, { "dma_readq_full" }, { "dma_read_prioq_full" }, { "tx_comp_queue_full" }, { "ring_set_send_prod_index" }, { "ring_status_update" }, { "nic_irqs" }, { "nic_avoided_irqs" }, { "nic_tx_threshold_hit" } }; static const struct { const char string[ETH_GSTRING_LEN]; } ethtool_test_keys[TG3_NUM_TEST] = { { "nvram test (online) " }, { "link test (online) " }, { "register test (offline)" }, { "memory test (offline)" }, { "loopback test (offline)" }, { "interrupt test (offline)" }, }; static void tg3_write32(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->regs + off); } static u32 tg3_read32(struct tg3 *tp, u32 off) { return (readl(tp->regs + off)); } static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->aperegs + off); } static u32 tg3_ape_read32(struct tg3 *tp, u32 off) { return (readl(tp->aperegs + off)); } static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->regs + off); readl(tp->regs + off); } static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off) { unsigned long flags; u32 val; spin_lock_irqsave(&tp->indirect_lock, flags); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val); spin_unlock_irqrestore(&tp->indirect_lock, flags); return val; } static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; 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 == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) { pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW, val); return; } spin_lock_irqsave(&tp->indirect_lock, flags); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600); pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); spin_unlock_irqrestore(&tp->indirect_lock, flags); /* 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); } } static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off) { unsigned long flags; u32 val; spin_lock_irqsave(&tp->indirect_lock, flags); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600); pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val); spin_unlock_irqrestore(&tp->indirect_lock, flags); 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. */ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait) { if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) || (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) /* Non-posted methods */ tp->write32(tp, off, val); else { /* Posted method */ tg3_write32(tp, off, val); if (usec_wait) udelay(usec_wait); tp->read32(tp, off); } /* Wait again after the read for the posted method to guarantee that * the wait time is met. */ if (usec_wait) udelay(usec_wait); } static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) { tp->write32_mbox(tp, off, val); if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) && !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) tp->read32_mbox(tp, off); } static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) { void __iomem *mbox = tp->regs + off; writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) readl(mbox); } static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off) { return (readl(tp->regs + off + GRCMBOX_BASE)); } static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->regs + off + GRCMBOX_BASE); } #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val) #define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val)) #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val) #define tw32_tx_mbox(reg, val) tp->write32_tx_mbox(tp, reg, val) #define tr32_mailbox(reg) tp->read32_mbox(tp, reg) #define tw32(reg,val) tp->write32(tp, reg, val) #define tw32_f(reg,val) _tw32_flush(tp,(reg),(val), 0) #define tw32_wait_f(reg,val,us) _tw32_flush(tp,(reg),(val), (us)) #define tr32(reg) tp->read32(tp, reg) static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) return; spin_lock_irqsave(&tp->indirect_lock, flags); if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { 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); } else { tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); tw32_f(TG3PCI_MEM_WIN_DATA, val); /* Always leave this as zero. */ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); } spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) { unsigned long flags; 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; } spin_lock_irqsave(&tp->indirect_lock, flags); if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { 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); } else { tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); *val = tr32(TG3PCI_MEM_WIN_DATA); /* Always leave this as zero. */ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); } spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_ape_lock_init(struct tg3 *tp) { int i; /* Make sure the driver hasn't any stale locks. */ for (i = 0; i < 8; i++) tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i, APE_LOCK_GRANT_DRIVER); } static int tg3_ape_lock(struct tg3 *tp, int locknum) { int i, off; int ret = 0; u32 status; if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) return 0; switch (locknum) { case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: return -EINVAL; } off = 4 * locknum; tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER); /* Wait for up to 1 millisecond to acquire lock. */ for (i = 0; i < 100; i++) { status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off); if (status == APE_LOCK_GRANT_DRIVER) break; udelay(10); } if (status != APE_LOCK_GRANT_DRIVER) { /* Revoke the lock request. */ tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER); ret = -EBUSY; } return ret; } static void tg3_ape_unlock(struct tg3 *tp, int locknum) { int off; if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) return; switch (locknum) { case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: return; } off = 4 * locknum; tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER); } static void tg3_disable_ints(struct tg3 *tp) { tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT)); tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); } static inline void tg3_cond_int(struct tg3 *tp) { if (!(tp->tg3_flags & TG3_FLAG_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->coalesce_mode | (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); } static void tg3_enable_ints(struct tg3 *tp) { tp->irq_sync = 0; wmb(); tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, (tp->last_tag << 24)); if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, (tp->last_tag << 24)); tg3_cond_int(tp); } static inline unsigned int tg3_has_work(struct tg3 *tp) { struct tg3_hw_status *sblk = tp->hw_status; unsigned int work_exists = 0; /* check for phy events */ if (!(tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES))) { if (sblk->status & SD_STATUS_LINK_CHG) work_exists = 1; } /* check for RX/TX work to do */ if (sblk->idx[0].tx_consumer != tp->tx_cons || sblk->idx[0].rx_producer != tp->rx_rcb_ptr) work_exists = 1; return work_exists; } /* tg3_restart_ints * similar to tg3_enable_ints, but it accurately determines whether there * is new work pending and can return without flushing the PIO write * which reenables interrupts */ static void tg3_restart_ints(struct tg3 *tp) { tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, tp->last_tag << 24); mmiowb(); /* When doing tagged status, this work check is unnecessary. * The last_tag we write above tells the chip which piece of * work we've completed. */ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && tg3_has_work(tp)) tw32(HOSTCC_MODE, tp->coalesce_mode | (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); } static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ napi_disable(&tp->napi); netif_tx_disable(tp->dev); } static inline void tg3_netif_start(struct tg3 *tp) { netif_wake_queue(tp->dev); /* NOTE: unconditional netif_wake_queue is only appropriate * so long as all callers are assured to have free tx slots * (such as after tg3_init_hw) */ napi_enable(&tp->napi); tp->hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); } static void tg3_switch_clocks(struct tg3 *tp) { u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); u32 orig_clock_ctrl; if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) return; orig_clock_ctrl = clock_ctrl; clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE | 0x1f); tp->pci_clock_ctrl = clock_ctrl; if (tp->tg3_flags2 & TG3_FLG2_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); } #define PHY_BUSY_LOOPS 5000 static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) { u32 frame_val; unsigned int loops; int ret; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); udelay(80); } *val = 0x0; frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); frame_val |= (MI_COM_CMD_READ | MI_COM_START); tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; while (loops != 0) { udelay(10); frame_val = tr32(MAC_MI_COM); if ((frame_val & MI_COM_BUSY) == 0) { udelay(5); frame_val = tr32(MAC_MI_COM); break; } loops -= 1; } ret = -EBUSY; if (loops != 0) { *val = frame_val & MI_COM_DATA_MASK; ret = 0; } if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); } return ret; } static int tg3_writephy(struct tg3 *tp, int reg, u32 val) { u32 frame_val; unsigned int loops; int ret; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 && (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL)) return 0; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); udelay(80); } frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); frame_val |= (val & MI_COM_DATA_MASK); frame_val |= (MI_COM_CMD_WRITE | MI_COM_START); tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; while (loops != 0) { udelay(10); frame_val = tr32(MAC_MI_COM); if ((frame_val & MI_COM_BUSY) == 0) { udelay(5); frame_val = tr32(MAC_MI_COM); break; } loops -= 1; } ret = -EBUSY; if (loops != 0) ret = 0; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); } return ret; } static int tg3_bmcr_reset(struct tg3 *tp) { u32 phy_control; int limit, err; /* OK, reset it, and poll the BMCR_RESET bit until it * clears or we time out. */ phy_control = BMCR_RESET; err = tg3_writephy(tp, MII_BMCR, phy_control); if (err != 0) return -EBUSY; limit = 5000; while (limit--) { err = tg3_readphy(tp, MII_BMCR, &phy_control); if (err != 0) return -EBUSY; if ((phy_control & BMCR_RESET) == 0) { udelay(40); break; } udelay(10); } if (limit <= 0) return -EBUSY; return 0; } static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) { struct tg3 *tp = (struct tg3 *)bp->priv; u32 val; if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) return -EAGAIN; if (tg3_readphy(tp, reg, &val)) return -EIO; return val; } static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) { struct tg3 *tp = (struct tg3 *)bp->priv; if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) return -EAGAIN; if (tg3_writephy(tp, reg, val)) return -EIO; return 0; } static int tg3_mdio_reset(struct mii_bus *bp) { return 0; } static void tg3_mdio_config(struct tg3 *tp) { u32 val; if (tp->mdio_bus->phy_map[PHY_ADDR]->interface != PHY_INTERFACE_MODE_RGMII) return; val = tr32(MAC_PHYCFG1) & ~(MAC_PHYCFG1_RGMII_EXT_RX_DEC | MAC_PHYCFG1_RGMII_SND_STAT_EN); if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) { if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) val |= MAC_PHYCFG1_RGMII_SND_STAT_EN; } tw32(MAC_PHYCFG1, val | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV); val = tr32(MAC_PHYCFG2) & ~(MAC_PHYCFG2_INBAND_ENABLE); if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) val |= MAC_PHYCFG2_INBAND_ENABLE; tw32(MAC_PHYCFG2, val); val = tr32(MAC_EXT_RGMII_MODE); val &= ~(MAC_RGMII_MODE_RX_INT_B | MAC_RGMII_MODE_RX_QUALITY | MAC_RGMII_MODE_RX_ACTIVITY | MAC_RGMII_MODE_RX_ENG_DET | MAC_RGMII_MODE_TX_ENABLE | MAC_RGMII_MODE_TX_LOWPWR | MAC_RGMII_MODE_TX_RESET); if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) { if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) val |= MAC_RGMII_MODE_RX_INT_B | MAC_RGMII_MODE_RX_QUALITY | MAC_RGMII_MODE_RX_ACTIVITY | MAC_RGMII_MODE_RX_ENG_DET; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) val |= MAC_RGMII_MODE_TX_ENABLE | MAC_RGMII_MODE_TX_LOWPWR | MAC_RGMII_MODE_TX_RESET; } tw32(MAC_EXT_RGMII_MODE, val); } static void tg3_mdio_start(struct tg3 *tp) { if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { mutex_lock(&tp->mdio_bus->mdio_lock); tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; mutex_unlock(&tp->mdio_bus->mdio_lock); } tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) tg3_mdio_config(tp); } static void tg3_mdio_stop(struct tg3 *tp) { if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { mutex_lock(&tp->mdio_bus->mdio_lock); tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED; mutex_unlock(&tp->mdio_bus->mdio_lock); } } static int tg3_mdio_init(struct tg3 *tp) { int i; u32 reg; struct phy_device *phydev; tg3_mdio_start(tp); if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) || (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED)) return 0; tp->mdio_bus = mdiobus_alloc(); if (tp->mdio_bus == NULL) return -ENOMEM; tp->mdio_bus->name = "tg3 mdio bus"; snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x", (tp->pdev->bus->number << 8) | tp->pdev->devfn); tp->mdio_bus->priv = tp; tp->mdio_bus->parent = &tp->pdev->dev; tp->mdio_bus->read = &tg3_mdio_read; tp->mdio_bus->write = &tg3_mdio_write; tp->mdio_bus->reset = &tg3_mdio_reset; tp->mdio_bus->phy_mask = ~(1 << PHY_ADDR); tp->mdio_bus->irq = &tp->mdio_irq[0]; for (i = 0; i < PHY_MAX_ADDR; i++) tp->mdio_bus->irq[i] = PHY_POLL; /* The bus registration will look for all the PHYs on the mdio bus. * Unfortunately, it does not ensure the PHY is powered up before * accessing the PHY ID registers. A chip reset is the * quickest way to bring the device back to an operational state.. */ if (tg3_readphy(tp, MII_BMCR, ®) || (reg & BMCR_PDOWN)) tg3_bmcr_reset(tp); i = mdiobus_register(tp->mdio_bus); if (i) { printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", tp->dev->name, i); return i; } tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; phydev = tp->mdio_bus->phy_map[PHY_ADDR]; switch (phydev->phy_id) { case TG3_PHY_ID_BCM50610: phydev->interface = PHY_INTERFACE_MODE_RGMII; if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE; break; case TG3_PHY_ID_BCMAC131: phydev->interface = PHY_INTERFACE_MODE_MII; break; } tg3_mdio_config(tp); return 0; } static void tg3_mdio_fini(struct tg3 *tp) { if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED; mdiobus_unregister(tp->mdio_bus); mdiobus_free(tp->mdio_bus); tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; } } /* tp->lock is held. */ static inline void tg3_generate_fw_event(struct tg3 *tp) { u32 val; val = tr32(GRC_RX_CPU_EVENT); val |= GRC_RX_CPU_DRIVER_EVENT; tw32_f(GRC_RX_CPU_EVENT, val); tp->last_event_jiffies = jiffies; } #define TG3_FW_EVENT_TIMEOUT_USEC 2500 /* tp->lock is held. */ static void tg3_wait_for_event_ack(struct tg3 *tp) { int i; unsigned int delay_cnt; long time_remain; /* If enough time has passed, no wait is necessary. */ time_remain = (long)(tp->last_event_jiffies + 1 + usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) - (long)jiffies; if (time_remain < 0) return; /* Check if we can shorten the wait time. */ delay_cnt = jiffies_to_usecs(time_remain); if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC) delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC; delay_cnt = (delay_cnt >> 3) + 1; for (i = 0; i < delay_cnt; i++) { if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) break; udelay(8); } } /* tp->lock is held. */ static void tg3_ump_link_report(struct tg3 *tp) { u32 reg; u32 val; if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) return; tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); val = 0; if (!tg3_readphy(tp, MII_BMCR, ®)) val = reg << 16; if (!tg3_readphy(tp, MII_BMSR, ®)) val |= (reg & 0xffff); tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val); val = 0; if (!tg3_readphy(tp, MII_ADVERTISE, ®)) val = reg << 16; if (!tg3_readphy(tp, MII_LPA, ®)) val |= (reg & 0xffff); tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val); val = 0; if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) { if (!tg3_readphy(tp, MII_CTRL1000, ®)) val = reg << 16; if (!tg3_readphy(tp, MII_STAT1000, ®)) val |= (reg & 0xffff); } tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val); if (!tg3_readphy(tp, MII_PHYADDR, ®)) val = reg << 16; else val = 0; tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); tg3_generate_fw_event(tp); } static void tg3_link_report(struct tg3 *tp) { if (!netif_carrier_ok(tp->dev)) { if (netif_msg_link(tp)) printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name); tg3_ump_link_report(tp); } else if (netif_msg_link(tp)) { printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", tp->dev->name, (tp->link_config.active_speed == SPEED_1000 ? 1000 : (tp->link_config.active_speed == SPEED_100 ? 100 : 10)), (tp->link_config.active_duplex == DUPLEX_FULL ? "full" : "half")); printk(KERN_INFO PFX "%s: Flow control is %s for TX and %s for RX.\n", tp->dev->name, (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ? "on" : "off", (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ? "on" : "off"); tg3_ump_link_report(tp); } } static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl) { u16 miireg; if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) miireg = ADVERTISE_PAUSE_CAP; else if (flow_ctrl & TG3_FLOW_CTRL_TX) miireg = ADVERTISE_PAUSE_ASYM; else if (flow_ctrl & TG3_FLOW_CTRL_RX) miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; else miireg = 0; return miireg; } static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) { u16 miireg; if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) miireg = ADVERTISE_1000XPAUSE; else if (flow_ctrl & TG3_FLOW_CTRL_TX) miireg = ADVERTISE_1000XPSE_ASYM; else if (flow_ctrl & TG3_FLOW_CTRL_RX) miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; else miireg = 0; return miireg; } static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) { u8 cap = 0; if (lcladv & ADVERTISE_PAUSE_CAP) { if (lcladv & ADVERTISE_PAUSE_ASYM) { if (rmtadv & LPA_PAUSE_CAP) cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; else if (rmtadv & LPA_PAUSE_ASYM) cap = TG3_FLOW_CTRL_RX; } else { if (rmtadv & LPA_PAUSE_CAP) cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; } } else if (lcladv & ADVERTISE_PAUSE_ASYM) { if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) cap = TG3_FLOW_CTRL_TX; } return cap; } static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) { u8 cap = 0; if (lcladv & ADVERTISE_1000XPAUSE) { if (lcladv & ADVERTISE_1000XPSE_ASYM) { if (rmtadv & LPA_1000XPAUSE) cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; else if (rmtadv & LPA_1000XPAUSE_ASYM) cap = TG3_FLOW_CTRL_RX; } else { if (rmtadv & LPA_1000XPAUSE) cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; } } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) cap = TG3_FLOW_CTRL_TX; } return cap; } static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv) { u8 autoneg; u8 flowctrl = 0; u32 old_rx_mode = tp->rx_mode; u32 old_tx_mode = tp->tx_mode; if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) autoneg = tp->mdio_bus->phy_map[PHY_ADDR]->autoneg; else autoneg = tp->link_config.autoneg; if (autoneg == AUTONEG_ENABLE && (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) { if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv); else flowctrl = tg3_resolve_flowctrl_1000T(lcladv, rmtadv); } else flowctrl = tp->link_config.flowctrl; tp->link_config.active_flowctrl = flowctrl; if (flowctrl & TG3_FLOW_CTRL_RX) tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; else tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; if (old_rx_mode != tp->rx_mode) tw32_f(MAC_RX_MODE, tp->rx_mode); if (flowctrl & TG3_FLOW_CTRL_TX) tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; else tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; if (old_tx_mode != tp->tx_mode) tw32_f(MAC_TX_MODE, tp->tx_mode); } static void tg3_adjust_link(struct net_device *dev) { u8 oldflowctrl, linkmesg = 0; u32 mac_mode, lcl_adv, rmt_adv; struct tg3 *tp = netdev_priv(dev); struct phy_device *phydev = tp->mdio_bus->phy_map[PHY_ADDR]; spin_lock(&tp->lock); mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); oldflowctrl = tp->link_config.active_flowctrl; if (phydev->link) { lcl_adv = 0; rmt_adv = 0; if (phydev->speed == SPEED_100 || phydev->speed == SPEED_10) mac_mode |= MAC_MODE_PORT_MODE_MII; else mac_mode |= MAC_MODE_PORT_MODE_GMII; if (phydev->duplex == DUPLEX_HALF) mac_mode |= MAC_MODE_HALF_DUPLEX; else { lcl_adv = tg3_advert_flowctrl_1000T( tp->link_config.flowctrl); if (phydev->pause) rmt_adv = LPA_PAUSE_CAP; if (phydev->asym_pause) rmt_adv |= LPA_PAUSE_ASYM; } tg3_setup_flow_control(tp, lcl_adv, rmt_adv); } else mac_mode |= MAC_MODE_PORT_MODE_GMII; if (mac_mode != tp->mac_mode) { tp->mac_mode = mac_mode; tw32_f(MAC_MODE, tp->mac_mode); udelay(40); } if (phydev->speed == SPEED_1000 && phydev->duplex == DUPLEX_HALF) tw32(MAC_TX_LENGTHS, ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | (6 << TX_LENGTHS_IPG_SHIFT) | (0xff << TX_LENGTHS_SLOT_TIME_SHIFT))); else tw32(MAC_TX_LENGTHS, ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | (6 << TX_LENGTHS_IPG_SHIFT) | (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) || (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) || phydev->speed != tp->link_config.active_speed || phydev->duplex != tp->link_config.active_duplex || oldflowctrl != tp->link_config.active_flowctrl) linkmesg = 1; tp->link_config.active_speed = phydev->speed; tp->link_config.active_duplex = phydev->duplex; spin_unlock(&tp->lock); if (linkmesg) tg3_link_report(tp); } static int tg3_phy_init(struct tg3 *tp) { struct phy_device *phydev; if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) return 0; /* Bring the PHY back to a known state. */ tg3_bmcr_reset(tp); phydev = tp->mdio_bus->phy_map[PHY_ADDR]; /* Attach the MAC to the PHY. */ phydev = phy_connect(tp->dev, phydev->dev.bus_id, tg3_adjust_link, phydev->dev_flags, phydev->interface); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", tp->dev->name); return PTR_ERR(phydev); } tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED; /* Mask with MAC supported features. */ phydev->supported &= (PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause); phydev->advertising = phydev->supported; printk(KERN_INFO "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", tp->dev->name, phydev->drv->name, phydev->dev.bus_id); return 0; } static void tg3_phy_start(struct tg3 *tp) { struct phy_device *phydev; if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) return; phydev = tp->mdio_bus->phy_map[PHY_ADDR]; if (tp->link_config.phy_is_low_power) { tp->link_config.phy_is_low_power = 0; phydev->speed = tp->link_config.orig_speed; phydev->duplex = tp->link_config.orig_duplex; phydev->autoneg = tp->link_config.orig_autoneg; phydev->advertising = tp->link_config.orig_advertising; } phy_start(phydev); phy_start_aneg(phydev); } static void tg3_phy_stop(struct tg3 *tp) { if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) return; phy_stop(tp->mdio_bus->phy_map[PHY_ADDR]); } static void tg3_phy_fini(struct tg3 *tp) { if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]); tp->tg3_flags3 &= ~TG3_FLG3_PHY_CONNECTED; } } static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); } static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) { u32 phy; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) return; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u32 ephy; if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) { tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy | MII_TG3_EPHY_SHADOW_EN); if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) { if (enable) phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX; else phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX; tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy); } tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy); } } else { phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC | MII_TG3_AUXCTL_SHDWSEL_MISC; if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) && !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) { if (enable) phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX; else phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX; phy |= MII_TG3_AUXCTL_MISC_WREN; tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); } } } static void tg3_phy_set_wirespeed(struct tg3 *tp) { u32 val; if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) return; if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) && !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val)) tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); } static void tg3_phy_apply_otp(struct tg3 *tp) { u32 otp, phy; if (!tp->phy_otp) return; otp = tp->phy_otp; /* Enable SM_DSP clock and tx 6dB coding. */ phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | MII_TG3_AUXCTL_ACTL_SMDSP_ENA | MII_TG3_AUXCTL_ACTL_TX_6DB; tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT; tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy); phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) | ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy); phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT); phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ; tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy); phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy); phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy); phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) | ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); /* Turn off SM_DSP clock. */ phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | MII_TG3_AUXCTL_ACTL_TX_6DB; tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); } static int tg3_wait_macro_done(struct tg3 *tp) { int limit = 100; while (limit--) { u32 tmp32; if (!tg3_readphy(tp, 0x16, &tmp32)) { if ((tmp32 & 0x1000) == 0) break; } } if (limit <= 0) return -EBUSY; return 0; } static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) { static const u32 test_pat[4][6] = { { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 }, { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 }, { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 }, { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 } }; int chan; for (chan = 0; chan < 4; chan++) { int i; tg3_writephy(tp, MII_TG3_DSP_ADDRESS, (chan * 0x2000) | 0x0200); tg3_writephy(tp, 0x16, 0x0002); for (i = 0; i < 6; i++) tg3_writephy(tp, MII_TG3_DSP_RW_PORT, test_pat[chan][i]); tg3_writephy(tp, 0x16, 0x0202); if (tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; } tg3_writephy(tp, MII_TG3_DSP_ADDRESS, (chan * 0x2000) | 0x0200); tg3_writephy(tp, 0x16, 0x0082); if (tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; } tg3_writephy(tp, 0x16, 0x0802); if (tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; } for (i = 0; i < 6; i += 2) { u32 low, high; if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) || tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) || tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; } low &= 0x7fff; high &= 0x000f; if (low != test_pat[chan][i] || high != test_pat[chan][i+1]) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005); return -EBUSY; } } } return 0; } static int tg3_phy_reset_chanpat(struct tg3 *tp) { int chan; for (chan = 0; chan < 4; chan++) { int i; tg3_writephy(tp, MII_TG3_DSP_ADDRESS, (chan * 0x2000) | 0x0200); tg3_writephy(tp, 0x16, 0x0002); for (i = 0; i < 6; i++) tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000); tg3_writephy(tp, 0x16, 0x0202); if (tg3_wait_macro_done(tp)) return -EBUSY; } return 0; } static int tg3_phy_reset_5703_4_5(struct tg3 *tp) { u32 reg32, phy9_orig; int retries, do_phy_reset, err; retries = 10; do_phy_reset = 1; do { if (do_phy_reset) { err = tg3_bmcr_reset(tp); if (err) return err; do_phy_reset = 0; } /* Disable transmitter and interrupt. */ if (tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) continue; reg32 |= 0x3000; tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); /* Set full-duplex, 1000 mbps. */ tg3_writephy(tp, MII_BMCR, BMCR_FULLDPLX | TG3_BMCR_SPEED1000); /* Set to master mode. */ if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig)) continue; tg3_writephy(tp, MII_TG3_CTRL, (MII_TG3_CTRL_AS_MASTER | MII_TG3_CTRL_ENABLE_AS_MASTER)); /* Enable SM_DSP_CLOCK and 6dB. */ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); /* Block the PHY control access. */ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800); err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset); if (!err) break; } while (--retries); err = tg3_phy_reset_chanpat(tp); if (err) return err; tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, 0x16, 0x0000); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { /* Set Extended packet length bit for jumbo frames */ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4400); } else { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); } tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) { reg32 &= ~0x3000; tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); } else if (!err) err = -EBUSY; return err; } /* This will reset the tigon3 PHY if there is no valid * link unless the FORCE argument is non-zero. */ static int tg3_phy_reset(struct tg3 *tp) { u32 cpmuctrl; u32 phy_status; int err; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u32 val; val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ); udelay(40); } err = tg3_readphy(tp, MII_BMSR, &phy_status); err |= tg3_readphy(tp, MII_BMSR, &phy_status); if (err != 0) return -EBUSY; if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) { netif_carrier_off(tp->dev); tg3_link_report(tp); } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { err = tg3_phy_reset_5703_4_5(tp); if (err) return err; goto out; } cpmuctrl = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) { cpmuctrl = tr32(TG3_CPMU_CTRL); if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) tw32(TG3_CPMU_CTRL, cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY); } err = tg3_bmcr_reset(tp); if (err) return err; if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) { u32 phy; phy = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz; tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, phy); tw32(TG3_CPMU_CTRL, cpmuctrl); } 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); } tg3_phy_apply_otp(tp); out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); } if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) { tg3_writephy(tp, 0x1c, 0x8d68); tg3_writephy(tp, 0x1c, 0x8d68); } if (tp->tg3_flags2 & TG3_FLG2_PHY_BER_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x310b); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x9506); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x401f); tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); } else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->tg3_flags2 & TG3_FLG2_PHY_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); tg3_writephy(tp, MII_TG3_TEST1, MII_TG3_TEST1_TRIM_EN | 0x4); } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); } /* Set Extended packet length bit (bit 14) on all chips that */ /* support jumbo frames */ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { /* Cannot do read-modify-write on 5401 */ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); } else if (tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) { u32 phy_reg; /* Set bit 14 with read-modify-write to preserve other bits */ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) && !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg)) tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); } /* Set phy register 0x10 bit 0 to high fifo elasticity to support * jumbo frames transmission. */ if (tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) { u32 phy_reg; if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg)) tg3_writephy(tp, MII_TG3_EXT_CTRL, phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC); } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { /* adjust output voltage */ tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12); } tg3_phy_toggle_automdix(tp, 1); tg3_phy_set_wirespeed(tp); return 0; } static void tg3_frob_aux_power(struct tg3 *tp) { struct tg3 *tp_peer = tp; if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0) return; if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) { struct net_device *dev_peer; dev_peer = pci_get_drvdata(tp->pdev_peer); /* remove_one() may have been run on the peer. */ if (!dev_peer) tp_peer = tp; else tp_peer = netdev_priv(dev_peer); } if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 || (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */ u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1 | tp->grc_local_ctrl; tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2; tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0; tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); } else { u32 no_gpio2; u32 grc_local_ctrl = 0; if (tp_peer != tp && (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; /* Workaround to prevent overdrawing Amps. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl, 100); } /* On 5753 and variants, GPIO2 cannot be used. */ no_gpio2 = tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_NO_GPIO2; grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2; if (no_gpio2) { grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT2); } tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl, 100); grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl, 100); if (!no_gpio2) { grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl, 100); } } } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { if (tp_peer != tp && (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_GPIO_OE1, 100); tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); } } } static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed) { if (tp->led_ctrl == LED_CTRL_MODE_PHY_2) return 1; else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) { if (speed != SPEED_10) return 1; } else if (speed == SPEED_10) return 1; return 0; } static int tg3_setup_phy(struct tg3 *, int); #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 #define RESET_KIND_SUSPEND 2 static void tg3_write_sig_post_reset(struct tg3 *, int); static int tg3_halt_cpu(struct tg3 *, u32); static int tg3_nvram_lock(struct tg3 *); static void tg3_nvram_unlock(struct tg3 *); 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); u32 serdes_cfg = tr32(MAC_SERDES_CFG); sg_dig_ctrl |= SG_DIG_USING_HW_AUTONEG | SG_DIG_SOFT_RESET; tw32(SG_DIG_CTRL, sg_dig_ctrl); tw32(MAC_SERDES_CFG, serdes_cfg | (1 << 15)); } return; } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tg3_bmcr_reset(tp); val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); udelay(40); return; } else if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); } /* The PHY should not be powered down on some chips because * of bugs. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || (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); } static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) { u32 misc_host_ctrl; /* Make sure register accesses (indirect or otherwise) * will function correctly. */ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); switch (state) { case PCI_D0: pci_enable_wake(tp->pdev, state, false); pci_set_power_state(tp->pdev, PCI_D0); /* Switch out of Vaux if it is a NIC */ if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100); return 0; case PCI_D1: case PCI_D2: case PCI_D3hot: break; default: printk(KERN_ERR PFX "%s: Invalid power state (D%d) requested\n", tp->dev->name, state); return -EINVAL; } misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); tw32(TG3PCI_MISC_HOST_CTRL, misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT); if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) && !tp->link_config.phy_is_low_power) { struct phy_device *phydev; u32 advertising; phydev = tp->mdio_bus->phy_map[PHY_ADDR]; tp->link_config.phy_is_low_power = 1; tp->link_config.orig_speed = phydev->speed; tp->link_config.orig_duplex = phydev->duplex; tp->link_config.orig_autoneg = phydev->autoneg; tp->link_config.orig_advertising = phydev->advertising; advertising = ADVERTISED_TP | ADVERTISED_Pause | ADVERTISED_Autoneg | ADVERTISED_10baseT_Half; if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) { if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) advertising |= ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_10baseT_Full; else advertising |= ADVERTISED_10baseT_Full; } phydev->advertising = advertising; phy_start_aneg(phydev); } } else { if (tp->link_config.phy_is_low_power == 0) { tp->link_config.phy_is_low_power = 1; tp->link_config.orig_speed = tp->link_config.speed; tp->link_config.orig_duplex = tp->link_config.duplex; tp->link_config.orig_autoneg = tp->link_config.autoneg; } if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { tp->link_config.speed = SPEED_10; tp->link_config.duplex = DUPLEX_HALF; tp->link_config.autoneg = AUTONEG_ENABLE; tg3_setup_phy(tp, 0); } } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u32 val; val = tr32(GRC_VCPU_EXT_CTRL); tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL); } else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { int i; u32 val; for (i = 0; i < 200; i++) { tg3_read_mem(tp, NIC_SRAM_FW_ASF_STATUS_MBOX, &val); if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) break; msleep(1); } } if (tp->tg3_flags & TG3_FLAG_WOL_CAP) tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE | WOL_DRV_STATE_SHUTDOWN | WOL_DRV_WOL | WOL_SET_MAGIC_PKT); if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { u32 mac_mode; if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); udelay(40); } if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) mac_mode = MAC_MODE_PORT_MODE_GMII; else mac_mode = MAC_MODE_PORT_MODE_MII; mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { u32 speed = (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) ? SPEED_100 : SPEED_10; if (tg3_5700_link_polarity(tp, speed)) mac_mode |= MAC_MODE_LINK_POLARITY; else mac_mode &= ~MAC_MODE_LINK_POLARITY; } } else { mac_mode = MAC_MODE_PORT_MODE_TBI; } if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) tw32(MAC_LED_CTRL, tp->led_ctrl); if (pci_pme_capable(tp->pdev, state) && (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { mac_mode |= tp->mac_mode & (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); if (mac_mode & MAC_MODE_APE_TX_EN) mac_mode |= MAC_MODE_TDE_ENABLE; } tw32_f(MAC_MODE, mac_mode); udelay(100); tw32_f(MAC_RX_MODE, RX_MODE_ENABLE); udelay(10); } if (!(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { u32 base_val; base_val = tp->pci_clock_ctrl; base_val |= (CLOCK_CTRL_RXCLK_DISABLE | CLOCK_CTRL_TXCLK_DISABLE); tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK | CLOCK_CTRL_PWRDOWN_PLL133, 40); } else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) { /* do nothing */ } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) { u32 newbits1, newbits2; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { newbits1 = (CLOCK_CTRL_RXCLK_DISABLE | CLOCK_CTRL_TXCLK_DISABLE | CLOCK_CTRL_ALTCLK); newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { newbits1 = CLOCK_CTRL_625_CORE; newbits2 = newbits1 | CLOCK_CTRL_ALTCLK; } else { newbits1 = CLOCK_CTRL_ALTCLK; newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; } tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1, 40); tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2, 40); if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { u32 newbits3; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { newbits3 = (CLOCK_CTRL_RXCLK_DISABLE | CLOCK_CTRL_TXCLK_DISABLE | CLOCK_CTRL_44MHZ_CORE); } else { newbits3 = CLOCK_CTRL_44MHZ_CORE; } tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3, 40); } } if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) tg3_power_down_phy(tp); tg3_frob_aux_power(tp); /* Workaround for unstable PLL clock */ if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) || (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) { u32 val = tr32(0x7d00); val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); tw32(0x7d00, val); if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { int err; err = tg3_nvram_lock(tp); tg3_halt_cpu(tp, RX_CPU_BASE); if (!err) tg3_nvram_unlock(tp); } } tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) pci_enable_wake(tp->pdev, state, true); /* Finally, set the new power state. */ pci_set_power_state(tp->pdev, state); return 0; } static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) { switch (val & MII_TG3_AUX_STAT_SPDMASK) { case MII_TG3_AUX_STAT_10HALF: *speed = SPEED_10; *duplex = DUPLEX_HALF; break; case MII_TG3_AUX_STAT_10FULL: *speed = SPEED_10; *duplex = DUPLEX_FULL; break; case MII_TG3_AUX_STAT_100HALF: *speed = SPEED_100; *duplex = DUPLEX_HALF; break; case MII_TG3_AUX_STAT_100FULL: *speed = SPEED_100; *duplex = DUPLEX_FULL; break; case MII_TG3_AUX_STAT_1000HALF: *speed = SPEED_1000; *duplex = DUPLEX_HALF; break; case MII_TG3_AUX_STAT_1000FULL: *speed = SPEED_1000; *duplex = DUPLEX_FULL; break; default: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 : SPEED_10; *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL : DUPLEX_HALF; break; } *speed = SPEED_INVALID; *duplex = DUPLEX_INVALID; break; } } static void tg3_phy_copper_begin(struct tg3 *tp) { u32 new_adv; int i; if (tp->link_config.phy_is_low_power) { /* Entering low power mode. Disable gigabit and * 100baseT advertisements. */ tg3_writephy(tp, MII_TG3_CTRL, 0); new_adv = (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) new_adv |= (ADVERTISE_100HALF | ADVERTISE_100FULL); tg3_writephy(tp, MII_ADVERTISE, new_adv); } else if (tp->link_config.speed == SPEED_INVALID) { if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) tp->link_config.advertising &= ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); new_adv = ADVERTISE_CSMA; if (tp->link_config.advertising & ADVERTISED_10baseT_Half) new_adv |= ADVERTISE_10HALF; if (tp->link_config.advertising & ADVERTISED_10baseT_Full) new_adv |= ADVERTISE_10FULL; if (tp->link_config.advertising & ADVERTISED_100baseT_Half) new_adv |= ADVERTISE_100HALF; if (tp->link_config.advertising & ADVERTISED_100baseT_Full) new_adv |= ADVERTISE_100FULL; new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); tg3_writephy(tp, MII_ADVERTISE, new_adv); if (tp->link_config.advertising & (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) { new_adv = 0; if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) new_adv |= MII_TG3_CTRL_ADV_1000_HALF; if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) new_adv |= MII_TG3_CTRL_ADV_1000_FULL; if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) && (t