#include <linux/seq_file.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
+#include <linux/mii.h>
#include "net_driver.h"
#include "bitfield.h"
#include "efx.h"
#include "mac.h"
-#include "gmii.h"
#include "spi.h"
#include "falcon.h"
#include "falcon_hwdefs.h"
#endif
if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
- efx->phy_type == PHY_TYPE_10XPRESS))
+ efx->phy_type == PHY_TYPE_SFX7101))
tenxpress_crc_err(efx);
}
efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
- bool is_phy_event = false, handled = false;
+ bool handled = false;
- /* Check for interrupt on either port. Some boards have a
- * single PHY wired to the interrupt line for port 1. */
if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
- EFX_QWORD_FIELD(*event, XG_PHY_INTR))
- is_phy_event = true;
+ EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
+ EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
+ efx->phy_op->clear_interrupt(efx);
+ queue_work(efx->workqueue, &efx->phy_work);
+ handled = true;
+ }
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
- EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0))
- is_phy_event = true;
-
- if (is_phy_event) {
- efx->phy_op->clear_interrupt(efx);
- queue_work(efx->workqueue, &efx->reconfigure_work);
+ EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
+ queue_work(efx->workqueue, &efx->mac_work);
handled = true;
}
falcon_generate_event(channel, &test_event);
}
+void falcon_sim_phy_event(struct efx_nic *efx)
+{
+ efx_qword_t phy_event;
+
+ EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE);
+ if (EFX_IS10G(efx))
+ EFX_SET_OWORD_FIELD(phy_event, XG_PHY_INTR, 1);
+ else
+ EFX_SET_OWORD_FIELD(phy_event, G_PHY0_INTR, 1);
+
+ falcon_generate_event(&efx->channel[0], &phy_event);
+}
+
/**************************************************************************
*
* Flush handling
*
**************************************************************************
*/
-void falcon_drain_tx_fifo(struct efx_nic *efx)
+
+static int falcon_reset_macs(struct efx_nic *efx)
{
- efx_oword_t temp;
+ efx_oword_t reg;
int count;
- if ((falcon_rev(efx) < FALCON_REV_B0) ||
- (efx->loopback_mode != LOOPBACK_NONE))
- return;
+ if (falcon_rev(efx) < FALCON_REV_B0) {
+ /* It's not safe to use GLB_CTL_REG to reset the
+ * macs, so instead use the internal MAC resets
+ */
+ if (!EFX_IS10G(efx)) {
+ EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1);
+ falcon_write(efx, ®, GM_CFG1_REG);
+ udelay(1000);
+
+ EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0);
+ falcon_write(efx, ®, GM_CFG1_REG);
+ udelay(1000);
+ return 0;
+ } else {
+ EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1);
+ falcon_write(efx, ®, XM_GLB_CFG_REG);
+
+ for (count = 0; count < 10000; count++) {
+ falcon_read(efx, ®, XM_GLB_CFG_REG);
+ if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0)
+ return 0;
+ udelay(10);
+ }
- falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
- /* There is no point in draining more than once */
- if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
- return;
+ EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
+ return -ETIMEDOUT;
+ }
+ }
/* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */
spin_lock(&efx->stats_lock);
- EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1);
- falcon_write(efx, &temp, MAC0_CTRL_REG_KER);
+ falcon_read(efx, ®, MAC0_CTRL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
+ falcon_write(efx, ®, MAC0_CTRL_REG_KER);
- /* Reset the MAC and EM block. */
- falcon_read(efx, &temp, GLB_CTL_REG_KER);
- EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1);
- EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1);
- EFX_SET_OWORD_FIELD(temp, RST_EM, 1);
- falcon_write(efx, &temp, GLB_CTL_REG_KER);
+ falcon_read(efx, ®, GLB_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1);
+ EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1);
+ EFX_SET_OWORD_FIELD(reg, RST_EM, 1);
+ falcon_write(efx, ®, GLB_CTL_REG_KER);
count = 0;
while (1) {
- falcon_read(efx, &temp, GLB_CTL_REG_KER);
- if (!EFX_OWORD_FIELD(temp, RST_XGTX) &&
- !EFX_OWORD_FIELD(temp, RST_XGRX) &&
- !EFX_OWORD_FIELD(temp, RST_EM)) {
+ falcon_read(efx, ®, GLB_CTL_REG_KER);
+ if (!EFX_OWORD_FIELD(reg, RST_XGTX) &&
+ !EFX_OWORD_FIELD(reg, RST_XGRX) &&
+ !EFX_OWORD_FIELD(reg, RST_EM)) {
EFX_LOG(efx, "Completed MAC reset after %d loops\n",
count);
break;
/* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */
- if (efx->link_up && EFX_WORKAROUND_5147(efx))
+ if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
falcon_reset_xaui(efx);
+
+ return 0;
+}
+
+void falcon_drain_tx_fifo(struct efx_nic *efx)
+{
+ efx_oword_t reg;
+
+ if ((falcon_rev(efx) < FALCON_REV_B0) ||
+ (efx->loopback_mode != LOOPBACK_NONE))
+ return;
+
+ falcon_read(efx, ®, MAC0_CTRL_REG_KER);
+ /* There is no point in draining more than once */
+ if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0))
+ return;
+
+ falcon_reset_macs(efx);
}
void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
{
- efx_oword_t temp;
+ efx_oword_t reg;
if (falcon_rev(efx) < FALCON_REV_B0)
return;
/* Isolate the MAC -> RX */
- falcon_read(efx, &temp, RX_CFG_REG_KER);
- EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0);
- falcon_write(efx, &temp, RX_CFG_REG_KER);
+ falcon_read(efx, ®, RX_CFG_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0);
+ falcon_write(efx, ®, RX_CFG_REG_KER);
if (!efx->link_up)
falcon_drain_tx_fifo(efx);
int link_speed;
bool tx_fc;
- if (efx->link_options & GM_LPA_10000)
- link_speed = 0x3;
- else if (efx->link_options & GM_LPA_1000)
- link_speed = 0x2;
- else if (efx->link_options & GM_LPA_100)
- link_speed = 0x1;
- else
- link_speed = 0x0;
+ switch (efx->link_speed) {
+ case 10000: link_speed = 3; break;
+ case 1000: link_speed = 2; break;
+ case 100: link_speed = 1; break;
+ default: link_speed = 0; break;
+ }
/* MAC_LINK_STATUS controls MAC backpressure but doesn't work
* as advertised. Disable to ensure packets are not
* indefinitely held and TX queue can be flushed at any point
/* Transmission of pause frames when RX crosses the threshold is
* covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
* Action on receipt of pause frames is controller by XM_DIS_FCNTL */
- tx_fc = !!(efx->flow_control & EFX_FC_TX);
+ tx_fc = !!(efx->link_fc & EFX_FC_TX);
falcon_read(efx, ®, RX_CFG_REG_KER);
EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
efx_dword_t md_stat;
int count;
- for (count = 0; count < 1000; count++) { /* wait upto 10ms */
+ /* wait upto 50ms - taken max from datasheet */
+ for (count = 0; count < 5000; count++) {
falcon_readl(efx, &md_stat, MD_STAT_REG_KER);
if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) {
if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 ||
static int falcon_probe_phy(struct efx_nic *efx)
{
switch (efx->phy_type) {
- case PHY_TYPE_10XPRESS:
- efx->phy_op = &falcon_tenxpress_phy_ops;
+ case PHY_TYPE_SFX7101:
+ efx->phy_op = &falcon_sfx7101_phy_ops;
+ break;
+ case PHY_TYPE_SFT9001A:
+ case PHY_TYPE_SFT9001B:
+ efx->phy_op = &falcon_sft9001_phy_ops;
break;
case PHY_TYPE_XFP:
efx->phy_op = &falcon_xfp_phy_ops;
return -1;
}
- efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks;
+ if (efx->phy_op->macs & EFX_XMAC)
+ efx->loopback_modes |= ((1 << LOOPBACK_XGMII) |
+ (1 << LOOPBACK_XGXS) |
+ (1 << LOOPBACK_XAUI));
+ if (efx->phy_op->macs & EFX_GMAC)
+ efx->loopback_modes |= (1 << LOOPBACK_GMAC);
+ efx->loopback_modes |= efx->phy_op->loopbacks;
+
return 0;
}
+int falcon_switch_mac(struct efx_nic *efx)
+{
+ struct efx_mac_operations *old_mac_op = efx->mac_op;
+ efx_oword_t nic_stat;
+ unsigned strap_val;
+
+ /* Internal loopbacks override the phy speed setting */
+ if (efx->loopback_mode == LOOPBACK_GMAC) {
+ efx->link_speed = 1000;
+ efx->link_fd = true;
+ } else if (LOOPBACK_INTERNAL(efx)) {
+ efx->link_speed = 10000;
+ efx->link_fd = true;
+ }
+
+ efx->mac_op = (EFX_IS10G(efx) ?
+ &falcon_xmac_operations : &falcon_gmac_operations);
+ if (old_mac_op == efx->mac_op)
+ return 0;
+
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
+ /* Not all macs support a mac-level link state */
+ efx->mac_up = true;
+
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+ strap_val = EFX_IS10G(efx) ? 5 : 3;
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
+ EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1);
+ EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val);
+ falcon_write(efx, &nic_stat, NIC_STAT_REG);
+ } else {
+ /* Falcon A1 does not support 1G/10G speed switching
+ * and must not be used with a PHY that does. */
+ BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val);
+ }
+
+
+ EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
+ return falcon_reset_macs(efx);
+}
+
/* This call is responsible for hooking in the MAC and PHY operations */
int falcon_probe_port(struct efx_nic *efx)
{
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
if (falcon_rev(efx) >= FALCON_REV_B0)
- efx->flow_control = EFX_FC_RX | EFX_FC_TX;
+ efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
else
- efx->flow_control = EFX_FC_RX;
+ efx->wanted_fc = EFX_FC_RX;
/* Allocate buffer for stats */
rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
{ DP_CTRL_REG,
EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
+ { GM_CFG2_REG,
+ EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) },
+ { GMF_CFG0_REG,
+ EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) },
{ XM_GLB_CFG_REG,
EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
{ XM_TX_CFG_REG,
static int falcon_probe_nic_variant(struct efx_nic *efx)
{
efx_oword_t altera_build;
+ efx_oword_t nic_stat;
falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
if (EFX_OWORD_FIELD(altera_build, VER_ALL)) {
return -ENODEV;
}
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+
switch (falcon_rev(efx)) {
case FALCON_REV_A0:
case 0xff:
EFX_ERR(efx, "Falcon rev A0 not supported\n");
return -ENODEV;
- case FALCON_REV_A1:{
- efx_oword_t nic_stat;
-
- falcon_read(efx, &nic_stat, NIC_STAT_REG);
-
+ case FALCON_REV_A1:
if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) {
EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
return -ENODEV;
}
- if (!EFX_OWORD_FIELD(nic_stat, STRAP_10G)) {
- EFX_ERR(efx, "1G mode not supported\n");
- return -ENODEV;
- }
break;
- }
case FALCON_REV_B0:
break;
return -ENODEV;
}
+ /* Initial assumed speed */
+ efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000;
+
return 0;
}
EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
falcon_write(efx, &temp, NIC_STAT_REG);
+ /* Set the source of the GMAC clock */
+ if (falcon_rev(efx) == FALCON_REV_B0) {
+ falcon_read(efx, &temp, GPIO_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true);
+ falcon_write(efx, &temp, GPIO_CTL_REG_KER);
+ }
+
/* Set buffer table mode */
EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL);
falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER);