blob: 6f97b7bbcbf13a29b9f2c567eb317a12ec51609c [file] [log] [blame]
/*
* 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-2010 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 <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/stringify.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/brcmphy.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/workqueue.h>
#include <linux/prefetch.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <net/checksum.h>
#include <net/ip.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#ifdef CONFIG_SPARC
#include <asm/idprom.h>
#include <asm/prom.h>
#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 TG3_MAJ_NUM 3
#define TG3_MIN_NUM 115
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
#define DRV_MODULE_RELDATE "October 14, 2010"
#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_STD_RING_SIZE(tp) \
((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
RX_STD_MAX_SIZE_5717 : 512)
#define TG3_DEF_RX_RING_PENDING 200
#define TG3_RX_JMB_RING_SIZE(tp) \
((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
1024 : 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_TX_RING_SIZE 512
#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1)
#define TG3_RX_STD_RING_BYTES(tp) \
(sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_RING_SIZE(tp))
#define TG3_RX_JMB_RING_BYTES(tp) \
(sizeof(struct tg3_ext_rx_buffer_desc) * TG3_RX_JMB_RING_SIZE(tp))
#define TG3_RX_RCB_RING_BYTES(tp) \
(sizeof(struct tg3_rx_buffer_desc) * (tp->rx_ret_ring_mask + 1))
#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_RX_DMA_ALIGN 16
#define TG3_RX_HEADROOM ALIGN(VLAN_HLEN, TG3_RX_DMA_ALIGN)
#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)
#define TG3_RX_STD_BUFF_RING_SIZE(tp) \
(sizeof(struct ring_info) * TG3_RX_STD_RING_SIZE(tp))
#define TG3_RX_JMB_BUFF_RING_SIZE(tp) \
(sizeof(struct ring_info) * TG3_RX_JMB_RING_SIZE(tp))
/* Due to a hardware bug, the 5701 can only DMA to memory addresses
* that are at least dword aligned when used in PCIX mode. The driver
* works around this bug by double copying the packet. This workaround
* is built into the normal double copy length check for efficiency.
*
* However, the double copy is only necessary on those architectures
* where unaligned memory accesses are inefficient. For those architectures
* where unaligned memory accesses incur little penalty, we can reintegrate
* the 5701 in the normal rx path. Doing so saves a device structure
* dereference by hardcoding the double copy threshold in place.
*/
#define TG3_RX_COPY_THRESHOLD 256
#if NET_IP_ALIGN == 0 || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
#define TG3_RX_COPY_THRESH(tp) TG3_RX_COPY_THRESHOLD
#else
#define TG3_RX_COPY_THRESH(tp) ((tp)->rx_copy_thresh)
#endif
/* 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 TG3_FW_UPDATE_TIMEOUT_SEC 5
#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 ")";
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);
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 DEFINE_PCI_DEVICE_TABLE(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_5721)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
{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_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
{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 == TG3_RX_STD_PROD_IDX_REG) {
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;
u32 regbase;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
regbase = TG3_APE_LOCK_GRANT;
else
regbase = TG3_APE_PER_LOCK_GRANT;
/* Make sure the driver hasn't any stale locks. */
for (i = 0; i < 8; i++)
tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER);
}
static int tg3_ape_lock(struct tg3 *tp, int locknum)
{
int i, off;
int ret = 0;
u32 status, req, gnt;
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;
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
req = TG3_APE_LOCK_REQ;
gnt = TG3_APE_LOCK_GRANT;
} else {
req = TG3_APE_PER_LOCK_REQ;
gnt = TG3_APE_PER_LOCK_GRANT;
}
off = 4 * locknum;
tg3_ape_write32(tp, 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, gnt + off);
if (status == APE_LOCK_GRANT_DRIVER)
break;
udelay(10);
}
if (status != APE_LOCK_GRANT_DRIVER) {
/* Revoke the lock request. */
tg3_ape_write32(tp, gnt + off,
APE_LOCK_GRANT_DRIVER);
ret = -EBUSY;
}
return ret;
}
static void tg3_ape_unlock(struct tg3 *tp, int locknum)
{
u32 gnt;
if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;
switch (locknum) {
case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
break;
default:
return;
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
gnt = TG3_APE_LOCK_GRANT;
else
gnt = TG3_APE_PER_LOCK_GRANT;
tg3_ape_write32(tp, gnt + 4 * locknum, 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;
tp->irq_sync = 0;
wmb();
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE;
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);
tp->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->coal_now);
tp->coal_now &= ~(tp->napi[0].coal_now | tp->napi[1].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_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->phy_flags & TG3_PHYFLG_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[TG3_PHY_MII_ADDR];
switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
case PHY_ID_BCM50610:
case PHY_ID_BCM50610M:
val = MAC_PHYCFG2_50610_LED_MODES;
break;
case PHY_ID_BCMAC131:
val = MAC_PHYCFG2_AC131_LED_MODES;
break;
case PHY_ID_RTL8211C:
val = MAC_PHYCFG2_RTL8211C_LED_MODES;
break;
case 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_INBAND_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_INBAND_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_INBAND_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 ((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;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
u32 is_serdes;
tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1;
if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
else
is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
TG3_CPMU_PHY_STRAP_IS_SERDES;
if (is_serdes)
tp->phy_addr += 7;
} else
tp->phy_addr = TG3_PHY_MII_ADDR;
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 << TG3_PHY_MII_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) || (reg & BMCR_PDOWN))
tg3_bmcr_reset(tp);
i = mdiobus_register(tp->mdio_bus);
if (i) {
dev_warn(&tp->pdev->dev, "mdiobus_reg failed (0x%x)\n", i);
mdiobus_free(tp->mdio_bus);
return i;
}
phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
if (!phydev || !phydev->drv) {
dev_warn(&tp->pdev->dev, "No PHY devices\n");
mdiobus_unregister(tp->mdio_bus);
mdiobus_free(tp->mdio_bus);
return -ENODEV;
}
switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
case PHY_ID_BCM57780:
phydev->interface = PHY_INTERFACE_MODE_GMII;
phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE;
break;
case PHY_ID_BCM50610:
case PHY_ID_BCM50610M:
phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE |
PHY_BRCM_RX_REFCLK_UNUSED |
PHY_BRCM_DIS_TXCRXC_NOENRGY |
PHY_BRCM_AUTO_PWRDWN_ENABLE;
if (tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_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 PHY_ID_RTL8211C:
phydev->interface = PHY_INTERFACE_MODE_RGMII;
break;
case PHY_ID_RTL8201E:
case PHY_ID_BCMAC131:
phydev->interface = PHY_INTERFACE_MODE_MII;
phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE;
tp->phy_flags |= TG3_PHYFLG_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);
}
}
static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val)
{
int err;
err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
if (err)
goto done;
err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
if (err)
goto done;
err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
MII_TG3_MMD_CTRL_DATA_NOINC | devad);
if (err)
goto done;
err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val);
done:
return err;
}
static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val)
{
int err;
err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
if (err)
goto done;
err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
if (err)
goto done;
err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
MII_TG3_MMD_CTRL_DATA_NOINC | devad);
if (err)
goto done;
err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val);
done:
return err;
}
/* 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, &reg))
val = reg << 16;
if (!tg3_readphy(tp, MII_BMSR, &reg))
val |= (reg & 0xffff);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
val = 0;
if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
val = reg << 16;
if (!tg3_readphy(tp, MII_LPA, &reg))
val |= (reg & 0xffff);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
val = 0;
if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
if (!tg3_readphy(tp, MII_CTRL1000, &reg))
val = reg << 16;
if (!tg3_readphy(tp, MII_STAT1000, &reg))
val |= (reg & 0xffff);
}
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
if (!tg3_readphy(tp, MII_PHYADDR, &reg))
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)) {
netif_info(tp, link, tp->dev, "Link is down\n");
tg3_ump_link_report(tp);
} else if (netif_msg_link(tp)) {
netdev_info(tp->dev, "Link is up at %d Mbps, %s duplex\n",
(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"));
netdev_info(tp->dev, "Flow control is %s for TX and %s for RX\n",
(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[TG3_PHY_MII_ADDR]->autoneg;
else
autoneg = tp->link_config.autoneg;
if (autoneg == AUTONEG_ENABLE &&
(tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) {
if (tp->phy_flags & TG3_PHYFLG_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[TG3_PHY_MII_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 if (phydev->speed == SPEED_1000 ||
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785)
mac_mode |= MAC_MODE_PORT_MODE_GMII;
else
mac_mode |= MAC_MODE_PORT_MODE_MII;
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->phy_flags & TG3_PHYFLG_IS_CONNECTED)
return 0;
/* Bring the PHY back to a known state. */
tg3_bmcr_reset(tp);
phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_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)) {
dev_err(&tp->pdev->dev, "Could not attach to PHY\n");
return PTR_ERR(phydev);
}
/* Mask with MAC supported features. */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_RGMII:
if (!(tp->phy_flags & TG3_PHYFLG_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[TG3_PHY_MII_ADDR]);
return -EINVAL;
}
tp->phy_flags |= TG3_PHYFLG_IS_CONNECTED;
phydev->advertising = phydev->supported;
return 0;
}
static void tg3_phy_start(struct tg3 *tp)
{
struct phy_device *phydev;
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return;
phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
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->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return;
phy_stop(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]);
}
static void tg3_phy_fini(struct tg3 *tp)
{
if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) {
phy_disconnect(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]);
tp->phy_flags &= ~TG3_PHYFLG_IS_CONNECTED;
}
}
static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val)
{
int err;
err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
if (!err)
err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val);
return err;
}
static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
{
int err;
err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
if (!err)
err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
return err;
}
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) ||
((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) &&
(tp->phy_flags & TG3_PHYFLG_MII_SERDES)))
return;
if (tp->phy_flags & TG3_PHYFLG_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->phy_flags & TG3_PHYFLG_ANY_SERDES))
return;
if (tp->phy_flags & TG3_PHYFLG_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->phy_flags & TG3_PHYFLG_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 void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
{
u32 val;
if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
return;
tp->setlpicnt = 0;
if (tp->link_config.autoneg == AUTONEG_ENABLE &&
current_link_up == 1 &&
(tp->link_config.active_speed == SPEED_1000 ||
(tp->link_config.active_speed == SPEED_100 &&
tp->link_config.active_duplex == DUPLEX_FULL))) {
u32 eeectl;
if (tp->link_config.active_speed == SPEED_1000)
eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US;
else
eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US;
tw32(TG3_CPMU_EEE_CTRL, eeectl);
tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val);
if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
tp->setlpicnt = 2;
}
if (!tp->setlpicnt) {
val = tr32(TG3_CPMU_EEE_MODE);
tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE);
}
}
static int tg3_wait_macro_done(struct tg3 *tp)
{
int limit = 100;
while (limit--) {
u32 tmp32;
if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &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, MII_TG3_DSP_CONTROL, 0x0002);
for (i = 0; i < 6; i++)
tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
test_pat[chan][i]);
tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
if (tg3_wait_macro_done(tp)) {
*resetp = 1;
return -EBUSY;
}
tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
(chan * 0x2000) | 0x0200);
tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
if (tg3_wait_macro_done(tp)) {
*resetp = 1;
return -EBUSY;
}
tg3_writephy(tp, MII_TG3_DSP_CONTROL, 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, MII_TG3_DSP_CONTROL, 0x0002);
for (i = 0; i < 6; i++)
tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
tg3_writephy(tp, MII_TG3_DSP_CONTROL, 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, &reg32))
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_phydsp_write(tp, 0x8005, 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_phydsp_write(tp, 0x8005, 0x0000);
tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
tg3_writephy(tp, MII_TG3_DSP_CONTROL, 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, &reg32)) {
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 val, cpmuctrl;
int err;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
udelay(40);
}
err = tg3_readphy(tp, MII_BMSR, &val);
err |= tg3_readphy(tp, MII_BMSR, &val);
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) {
val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
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) {
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);
}
}
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) &&
(tp->phy_flags & TG3_PHYFLG_MII_SERDES))
return 0;
tg3_phy_apply_otp(tp);
if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
tg3_phy_toggle_apd(tp, true);
else
tg3_phy_toggle_apd(tp, false);
out:
if (tp->phy_flags & TG3_PHYFLG_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
tg3_phydsp_write(tp, 0x201f, 0x2aaa);
tg3_phydsp_write(tp, 0x000a, 0x0323);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
}
if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
}
if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
tg3_phydsp_write(tp, 0x000a, 0x310b);
tg3_phydsp_write(tp, 0x201f, 0x9506);
tg3_phydsp_write(tp, 0x401f, 0x14e2);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
} else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
if (tp->phy_flags & TG3_PHYFLG_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 & TG3_PHY_ID_MASK) == TG3_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) {
/* 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, &val))
tg3_writephy(tp, MII_TG3_AUX_CTRL, val | 0x4000);
}
/* Set phy register 0x10 bit 0 to high fifo elasticity to support
* jumbo frames transmission.
*/
if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &val))
tg3_writephy(tp, MII_TG3_EXT_CTRL,
val | 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;
/* The GPIOs do something completely different on 57765. */
if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
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 & TG3_PHY_ID_MASK) == TG3_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->phy_flags & TG3_PHYFLG_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->phy_flags & TG3_PHYFLG_IS_FET) {
u32 phytest;
if (!tg3_readphy(tp, MII_TG3_FET_TEST, &phytest)) {
u32 phy;
tg3_writephy(tp, MII_ADVERTISE, 0);
tg3_writephy(tp, MII_BMCR,
BMCR_ANENABLE | BMCR_ANRESTART);
tg3_writephy(tp, MII_TG3_FET_TEST,
phytest | MII_TG3_FET_SHADOW_EN);
if (!tg3_readphy(tp, MII_TG3_FET_SHDW_AUXMODE4, &phy)) {
phy |= MII_TG3_FET_SHDW_AUXMODE4_SBPD;
tg3_writephy(tp,
MII_TG3_FET_SHDW_AUXMODE4,
phy);
}
tg3_writephy(tp, MII_TG3_FET_TEST, phytest);
}
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->phy_flags & TG3_PHYFLG_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_flags3 & TG3_FLG3_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_flags3 & TG3_FLG3_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->dev_addr[1] +
tp->dev->dev_addr[2] +
tp->dev->dev_addr[3] +
tp->dev->dev_addr[4] +
tp->dev->dev_addr[5]) &
TX_BACKOFF_SEED_MASK;
tw32(MAC_TX_BACKOFF_SEED, addr_high);
}
static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
{
u32 misc_host_ctrl;
bool device_should_wake, do_low_power;
/* 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:
netdev_err(tp->dev, "Invalid power state (D%d) requested\n",
state);
return -EINVAL;
}
/* Restore the CLKREQ setting. */
if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
u16 lnkctl;
pci_read_config_word(tp->pdev,
tp->pcie_cap + PCI_EXP_LNKCTL,
&lnkctl);
lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
pci_write_config_word(tp->pdev,
tp->pcie_cap + PCI_EXP_LNKCTL,
lnkctl);
}
misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
tw32(TG3PCI_MISC_HOST_CTRL,
misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
device_should_wake = pci_pme_capable(tp->pdev, state) &&
device_may_wakeup(&tp->pdev->dev) &&
(tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
do_low_power = false;
if ((tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) &&
!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
struct phy_device *phydev;
u32 phyid, advertising;
phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
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) ||
device_should_wake) {
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);
phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
if (phyid != PHY_ID_BCMAC131) {
phyid &= PHY_BCM_OUI_MASK;
if (phyid == PHY_BCM_OUI_1 ||
phyid == PHY_BCM_OUI_2 ||
phyid == PHY_BCM_OUI_3)
do_low_power = true;
}
}
} else {
do_low_power = true;
if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
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->phy_flags & TG3_PHYFLG_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 (device_should_wake) {
u32 mac_mode;
if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
if (do_low_power) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
udelay(40);
}
if (tp->phy_flags & TG3_PHYFLG_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);
mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) &&
((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)))
mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
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 (!(device_should_wake) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
tg3_power_down_phy(tp, do_low_power);
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 (device_should_wake)
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 (tp->phy_flags & TG3_PHYFLG_IS_FET) {
*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->phy_flags & TG3_PHYFLG_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->phy_flags & TG3_PHYFLG_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->phy_flags & TG3_PHYFLG_10_100_ONLY) &&
(tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
tp->pci_chip_rev_id == CHIPREV_ID_5701_B0))
new_adv |= (MII_TG3_CTRL_AS_MASTER |
MII_TG3_CTRL_ENABLE_AS_MASTER);
tg3_writephy(tp, MII_TG3_CTRL, new_adv);
} else {
tg3_writephy(tp, MII_TG3_CTRL, 0);
}
} else {
new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
new_adv |= ADVERTISE_CSMA;
/* Asking for a specific link mode. */
if (tp->link_config.speed == SPEED_1000) {
tg3_writephy(tp, MII_ADVERTISE, new_adv);
if (tp->link_config.duplex == DUPLEX_FULL)
new_adv = MII_TG3_CTRL_ADV_1000_FULL;
else
new_adv = MII_TG3_CTRL_ADV_1000_HALF;
if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
new_adv |= (MII_TG3_CTRL_AS_MASTER |
MII_TG3_CTRL_ENABLE_AS_MASTER);
} else {
if (tp->link_config.speed == SPEED_100) {
if (tp->link_config.duplex == DUPLEX_FULL)
new_adv |= ADVERTISE_100FULL;
else
new_adv |= ADVERTISE_100HALF;
} else {
if (tp->link_config.duplex == DUPLEX_FULL)
new_adv |= ADVERTISE_10FULL;
else
new_adv |= ADVERTISE_10HALF;
}
tg3_writephy(tp, MII_ADVERTISE, new_adv);
new_adv = 0;
}
tg3_writephy(tp, MII_TG3_CTRL, new_adv);
}
if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
u32 val = 0;
tw32(TG3_CPMU_EEE_MODE,
tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
/* Enable SM_DSP clock and tx 6dB coding. */
val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
MII_TG3_AUXCTL_ACTL_TX_6DB;
tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2,
val | MII_TG3_DSP_CH34TP2_HIBW01);
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
/* Advertise 100-BaseTX EEE ability */
if (tp->link_config.advertising &
(ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full))
val |= TG3_CL45_D7_EEEADV_CAP_100TX;
/* Advertise 1000-BaseT EEE ability */
if (tp->link_config.advertising &
(ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full))
val |= TG3_CL45_D7_EEEADV_CAP_1000T;
}
tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val);
/* Turn off SM_DSP clock. */
val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |