/* * 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-2009 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 #include #ifdef CONFIG_SPARC #include #include #endif #define BAR_0 0 #define BAR_2 2 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define TG3_VLAN_TAG_USED 1 #else #define TG3_VLAN_TAG_USED 0 #endif #include "tg3.h" #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "3.102" #define DRV_MODULE_RELDATE "September 1, 2009" #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_flags & TG3_FLAG_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 #define TG3_RSS_INDIR_TBL_SIZE 128 /* 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_flags & TG3_FLAG_JUMBO_CAPABLE) && \ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) ? 1024 : 512) #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_ext_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 TG3_DMA_BYTE_ENAB 64 #define TG3_RX_STD_DMA_SZ 1536 #define TG3_RX_JMB_DMA_SZ 9046 #define TG3_RX_DMA_TO_MAP_SZ(x) ((x) + TG3_DMA_BYTE_ENAB) #define TG3_RX_STD_MAP_SZ TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ) #define TG3_RX_JMB_MAP_SZ TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ) /* minimum number of free TX descriptors required to wake up TX process */ #define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4) #define TG3_RAW_IP_ALIGN 2 /* number of ETHTOOL_GSTATS u64's */ #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) #define TG3_NUM_TEST 6 #define FIRMWARE_TG3 "tigon/tg3.bin" #define FIRMWARE_TG3TSO "tigon/tg3_tso.bin" #define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin" 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); MODULE_FIRMWARE(FIRMWARE_TG3); MODULE_FIRMWARE(FIRMWARE_TG3TSO); MODULE_FIRMWARE(FIRMWARE_TG3TSO5); #define TG3_RSS_MIN_NUM_MSIX_VECS 2 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, TG3PCI_DEVICE_TIGON3_5761S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)}, {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) { int i; tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT)); for (i = 0; i < tp->irq_max; i++) tw32_mailbox_f(tp->napi[i].int_mbox, 0x00000001); } static void tg3_enable_ints(struct tg3 *tp) { int i; u32 coal_now = 0; tp->irq_sync = 0; wmb(); tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); for (i = 0; i < tp->irq_cnt; i++) { struct tg3_napi *tnapi = &tp->napi[i]; tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); coal_now |= tnapi->coal_now; } /* Force an initial interrupt */ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && (tp->napi[0].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 | coal_now); } static inline unsigned int tg3_has_work(struct tg3_napi *tnapi) { struct tg3 *tp = tnapi->tp; struct tg3_hw_status *sblk = tnapi->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 != tnapi->tx_cons || *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr) work_exists = 1; return work_exists; } /* tg3_int_reenable * 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_int_reenable(struct tg3_napi *tnapi) { struct tg3 *tp = tnapi->tp; tw32_mailbox(tnapi->int_mbox, tnapi->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(tnapi)) tw32(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | tnapi->coal_now); } static void tg3_napi_disable(struct tg3 *tp) { int i; for (i = tp->irq_cnt - 1; i >= 0; i--) napi_disable(&tp->napi[i].napi); } static void tg3_napi_enable(struct tg3 *tp) { int i; for (i = 0; i < tp->irq_cnt; i++) napi_enable(&tp->napi[i].napi); } static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ tg3_napi_disable(tp); netif_tx_disable(tp->dev); } static inline void tg3_netif_start(struct tg3 *tp) { /* NOTE: unconditional netif_tx_wake_all_queues is only * appropriate so long as all callers are assured to * have free tx slots (such as after tg3_init_hw) */ netif_tx_wake_all_queues(tp->dev); tg3_napi_enable(tp); tp->napi[0].hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); } static void tg3_switch_clocks(struct tg3 *tp) { u32 clock_ctrl; u32 orig_clock_ctrl; if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || (tp->tg3_flags2 & TG3_FLG2_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 (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 = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); frame_val |= (MI_COM_CMD_READ | MI_COM_START); tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; while (loops != 0) { udelay(10); frame_val = tr32(MAC_MI_COM); if ((frame_val & MI_COM_BUSY) == 0) { udelay(5); frame_val = tr32(MAC_MI_COM); break; } loops -= 1; } ret = -EBUSY; if (loops != 0) { *val = frame_val & MI_COM_DATA_MASK; ret = 0; } if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); } return ret; } static int tg3_writephy(struct tg3 *tp, int reg, u32 val) { u32 frame_val; unsigned int loops; int ret; if ((tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) && (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL)) return 0; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); udelay(80); } frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); frame_val |= (val & MI_COM_DATA_MASK); frame_val |= (MI_COM_CMD_WRITE | MI_COM_START); tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; while (loops != 0) { udelay(10); frame_val = tr32(MAC_MI_COM); if ((frame_val & MI_COM_BUSY) == 0) { udelay(5); frame_val = tr32(MAC_MI_COM); break; } loops -= 1; } ret = -EBUSY; if (loops != 0) ret = 0; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); } return ret; } static int tg3_bmcr_reset(struct tg3 *tp) { 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 = bp->priv; u32 val; spin_lock_bh(&tp->lock); if (tg3_readphy(tp, reg, &val)) val = -EIO; spin_unlock_bh(&tp->lock); return val; } static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) { struct tg3 *tp = bp->priv; u32 ret = 0; spin_lock_bh(&tp->lock); if (tg3_writephy(tp, reg, val)) ret = -EIO; spin_unlock_bh(&tp->lock); return ret; } static int tg3_mdio_reset(struct mii_bus *bp) { return 0; } static void tg3_mdio_config_5785(struct tg3 *tp) { u32 val; struct phy_device *phydev; phydev = tp->mdio_bus->phy_map[PHY_ADDR]; switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { case TG3_PHY_ID_BCM50610: val = MAC_PHYCFG2_50610_LED_MODES; break; case TG3_PHY_ID_BCMAC131: val = MAC_PHYCFG2_AC131_LED_MODES; break; case TG3_PHY_ID_RTL8211C: val = MAC_PHYCFG2_RTL8211C_LED_MODES; break; case TG3_PHY_ID_RTL8201E: val = MAC_PHYCFG2_RTL8201E_LED_MODES; break; default: return; } if (phydev->interface != PHY_INTERFACE_MODE_RGMII) { tw32(MAC_PHYCFG2, val); val = tr32(MAC_PHYCFG1); val &= ~(MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK); val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT; tw32(MAC_PHYCFG1, val); return; } if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) val |= MAC_PHYCFG2_EMODE_MASK_MASK | MAC_PHYCFG2_FMODE_MASK_MASK | MAC_PHYCFG2_GMODE_MASK_MASK | MAC_PHYCFG2_ACT_MASK_MASK | MAC_PHYCFG2_QUAL_MASK_MASK | MAC_PHYCFG2_INBAND_ENABLE; tw32(MAC_PHYCFG2, val); val = tr32(MAC_PHYCFG1); val &= ~(MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK | 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; } val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV; tw32(MAC_PHYCFG1, 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) { tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { u32 funcnum, is_serdes; funcnum = tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC; if (funcnum) tp->phy_addr = 2; else tp->phy_addr = 1; is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; if (is_serdes) tp->phy_addr += 7; } else tp->phy_addr = PHY_ADDR; if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tg3_mdio_config_5785(tp); } 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); mdiobus_free(tp->mdio_bus); return i; } phydev = tp->mdio_bus->phy_map[PHY_ADDR]; if (!phydev || !phydev->drv) { printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name); mdiobus_unregister(tp->mdio_bus); mdiobus_free(tp->mdio_bus); return -ENODEV; } switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { case TG3_PHY_ID_BCM57780: phydev->interface = PHY_INTERFACE_MODE_GMII; break; case TG3_PHY_ID_BCM50610: 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; /* fallthru */ case TG3_PHY_ID_RTL8211C: phydev->interface = PHY_INTERFACE_MODE_RGMII; break; case TG3_PHY_ID_RTL8201E: case TG3_PHY_ID_BCMAC131: phydev->interface = PHY_INTERFACE_MODE_MII; tp->tg3_flags3 |= TG3_FLG3_PHY_IS_FET; break; } tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tg3_mdio_config_5785(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->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 & FLOW_CTRL_TX) ? "on" : "off", (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ? "on" : "off"); tg3_ump_link_report(tp); } } static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl) { u16 miireg; if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX)) miireg = ADVERTISE_PAUSE_CAP; else if (flow_ctrl & FLOW_CTRL_TX) miireg = ADVERTISE_PAUSE_ASYM; else if (flow_ctrl & FLOW_CTRL_RX) miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; else miireg = 0; return miireg; } static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) { u16 miireg; if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX)) miireg = ADVERTISE_1000XPAUSE; else if (flow_ctrl & FLOW_CTRL_TX) miireg = ADVERTISE_1000XPSE_ASYM; else if (flow_ctrl & FLOW_CTRL_RX) miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; else miireg = 0; return miireg; } 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 = FLOW_CTRL_TX | FLOW_CTRL_RX; else if (rmtadv & LPA_1000XPAUSE_ASYM) cap = FLOW_CTRL_RX; } else { if (rmtadv & LPA_1000XPAUSE) cap = FLOW_CTRL_TX | FLOW_CTRL_RX; } } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) cap = FLOW_CTRL_TX; } return cap; } static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv) { 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 = mii_resolve_flowctrl_fdx(lcladv, rmtadv); } else flowctrl = tp->link_config.flowctrl; tp->link_config.active_flowctrl = flowctrl; if (flowctrl & FLOW_CTRL_RX) tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; else tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; if (old_rx_mode != tp->rx_mode) tw32_f(MAC_RX_MODE, tp->rx_mode); if (flowctrl & FLOW_CTRL_TX) tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; else tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; if (old_tx_mode != tp->tx_mode) tw32_f(MAC_TX_MODE, tp->tx_mode); } static void tg3_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_bh(&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 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { if (phydev->speed == SPEED_10) tw32(MAC_MI_STAT, MAC_MI_STAT_10MBPS_MODE | MAC_MI_STAT_LNKSTAT_ATTN_ENAB); else tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); } 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_bh(&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, dev_name(&phydev->dev), 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); } /* Mask with MAC supported features. */ switch (phydev->interface) { case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RGMII: if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { phydev->supported &= (PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause); break; } /* fallthru */ case PHY_INTERFACE_MODE_MII: phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause); break; default: phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]); return -EINVAL; } tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED; phydev->advertising = phydev->supported; 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_fet_toggle_apd(struct tg3 *tp, bool enable) { u32 phytest; if (!tg3_readphy(tp, MII_TG3_FET_TEST, &phytest)) { u32 phy; tg3_writephy(tp, MII_TG3_FET_TEST, phytest | MII_TG3_FET_SHADOW_EN); if (!tg3_readphy(tp, MII_TG3_FET_SHDW_AUXSTAT2, &phy)) { if (enable) phy |= MII_TG3_FET_SHDW_AUXSTAT2_APD; else phy &= ~MII_TG3_FET_SHDW_AUXSTAT2_APD; tg3_writephy(tp, MII_TG3_FET_SHDW_AUXSTAT2, phy); } tg3_writephy(tp, MII_TG3_FET_TEST, phytest); } } static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) { u32 reg; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) return; if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { tg3_phy_fet_toggle_apd(tp, enable); return; } reg = MII_TG3_MISC_SHDW_WREN | MII_TG3_MISC_SHDW_SCR5_SEL | MII_TG3_MISC_SHDW_SCR5_LPED | MII_TG3_MISC_SHDW_SCR5_DLPTLM | MII_TG3_MISC_SHDW_SCR5_SDTL | MII_TG3_MISC_SHDW_SCR5_C125OE; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable) reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD; tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); reg = MII_TG3_MISC_SHDW_WREN | MII_TG3_MISC_SHDW_APD_SEL | MII_TG3_MISC_SHDW_APD_WKTM_84MS; if (enable) reg |= MII_TG3_MISC_SHDW_APD_ENABLE; tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); } 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 (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { u32 ephy; if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) { u32 reg = MII_TG3_FET_SHDW_MISCCTRL; tg3_writephy(tp, MII_TG3_FET_TEST, ephy | MII_TG3_FET_SHADOW_EN); if (!tg3_readphy(tp, reg, &phy)) { if (enable) phy |= MII_TG3_FET_SHDW_MISCCTRL_MDIX; else phy &= ~MII_TG3_FET_SHDW_MISCCTRL_MDIX; tg3_writephy(tp, reg, phy); } tg3_writephy(tp, MII_TG3_FET_TEST, ephy); } } else { 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 (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) { 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); } } tg3_phy_apply_otp(tp); if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) tg3_phy_toggle_apd(tp, true); else tg3_phy_toggle_apd(tp, false); 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_flags & TG3_FLAG_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_flags & TG3_FLAG_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_FET_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 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { 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 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) { /* 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 void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) { 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 (do_low_power) { tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); tg3_writephy(tp, MII_TG3_AUX_CTRL, MII_TG3_AUXCTL_SHDWSEL_PWRCTL | MII_TG3_AUXCTL_PCTL_100TX_LPWR | MII_TG3_AUXCTL_PCTL_SPR_ISOLATE | MII_TG3_AUXCTL_PCTL_VREG_11V); } /* 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 (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) { val = tr32(TG3_CPMU_LSPD_1000MB_CLK); 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); } /* tp->lock is held. */ static int tg3_nvram_lock(struct tg3 *tp) { if (tp->tg3_flags & TG3_FLAG_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; } /* tp->lock is held. */ static void tg3_nvram_unlock(struct tg3 *tp) { if (tp->tg3_flags & TG3_FLAG_NVRAM) { if (tp->nvram_lock_cnt > 0) tp->nvram_lock_cnt--; if (tp->nvram_lock_cnt == 0) tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1); } } /* tp->lock is held. */ static void tg3_enable_nvram_access(struct tg3 *tp) { if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) { u32 nvaccess = tr32(NVRAM_ACCESS); tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); } } /* tp->lock is held. */ static void tg3_disable_nvram_access(struct tg3 *tp) { if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) { u32 nvaccess = tr32(NVRAM_ACCESS); tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); } } static int tg3_nvram_read_using_eeprom(struct tg3 *tp, u32 offset, u32 *val) { 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; msleep(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 = swab32(tmp); return 0; } #define NVRAM_CMD_TIMEOUT 10000 static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) { 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; } static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr) { if ((tp->tg3_flags & TG3_FLAG_NVRAM) && (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && (tp->tg3_flags2 & TG3_FLG2_FLASH) && !(tp->tg3_flags3 & TG3_FLG3_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 u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr) { if ((tp->tg3_flags & TG3_FLAG_NVRAM) && (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && (tp->tg3_flags2 & TG3_FLG2_FLASH) && !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) && (tp->nvram_jedecnum == JEDEC_ATMEL)) addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) * tp->nvram_pagesize) + (addr & ((1 << ATMEL_AT45DB0X1B_PAGE_POS) - 1)); return addr; } /* 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) { int ret; if (!(tp->tg3_flags & TG3_FLAG_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, __be32 *val) { u32 v; int res = tg3_nvram_read(tp, offset, &v); if (!res) *val = cpu_to_be32(v); return res; } /* tp->lock is held. */ static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1) { u32 addr_high, addr_low; int i; addr_high = ((tp->dev->dev_addr[0] << 8) | tp->dev->dev_addr[1]); addr_low = ((tp->dev->dev_addr[2] << 24) | (tp->dev->dev_addr[3] << 16) | (tp->dev->dev_addr[4] << 8) | (tp->dev->dev_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->dev_addr[0] + tp->dev->de