예제 #1
0
static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
{
	int rc = 0, rc2, i, ctrl_reg, res_reg;

	/* Initialise cable diagnostic results to unknown failure */
	for (i = 1; i < 9; ++i)
		results[i] = -1;

	/* Run cable diagnostics; wait up to 5 seconds for them to complete.
	 * A cable fault is not a self-test failure, but a timeout is. */
	ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) |
		    (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
	if (flags & ETH_TEST_FL_OFFLINE) {
		/* Break the link in order to run full diagnostics.  We
		 * must reset the PHY to resume normal service. */
		ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN);
	}
	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG,
		       ctrl_reg);
	i = 0;
	while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) &
	       (1 << CDIAG_CTRL_IN_PROG_LBN)) {
		if (++i == 50) {
			rc = -ETIMEDOUT;
			goto out;
		}
		msleep(100);
	}
	res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG);
	for (i = 0; i < 4; i++) {
		int pair_res =
			(res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
			& ((1 << CDIAG_RES_WIDTH) - 1);
		int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
					    PMA_PMD_CDIAG_LEN_REG + i);
		if (pair_res == CDIAG_RES_OK)
			results[1 + i] = 1;
		else if (pair_res == CDIAG_RES_INVALID)
			results[1 + i] = -1;
		else
			results[1 + i] = -pair_res;
		if (pair_res != CDIAG_RES_INVALID &&
		    pair_res != CDIAG_RES_OPEN &&
		    len_reg != 0xffff)
			results[5 + i] = len_reg;
	}

out:
	if (flags & ETH_TEST_FL_OFFLINE) {
		/* Reset, running the BIST and then resuming normal service. */
		rc2 = tenxpress_special_reset(efx);
		results[0] = rc2 ? -1 : 1;
		if (!rc)
			rc = rc2;

		efx_mdio_an_reconfigure(efx);
	}

	return rc;
}
예제 #2
0
static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests)
{
	int rc = 0;
	int devad = __ffs(efx->mdio.mmds);
	u16 physid1, physid2;

	if (efx->phy_type == PHY_TYPE_NONE)
		return 0;

	mutex_lock(&efx->mac_lock);
	tests->mdio = -1;

	physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
	physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);

	if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
	    (physid2 == 0x0000) || (physid2 == 0xffff)) {
		EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
			efx->mdio.prtad);
		rc = -EINVAL;
		goto out;
	}

	if (EFX_IS10G(efx)) {
		rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
		if (rc)
			goto out;
	}

out:
	mutex_unlock(&efx->mac_lock);
	tests->mdio = rc ? -1 : 1;
	return rc;
}
예제 #3
0
static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
{
	int val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
	int tries = 50;
	val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
	efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
	while (tries--) {
		val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
		if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
			break;
		udelay(1);
	}
	if (!tries)
		EFX_INFO(efx, TXCNAME " Logic reset timed out!\n");
}
static int tenxpress_special_reset(struct efx_nic *efx)
{
	int rc, reg;

	falcon_stop_nic_stats(efx);

	
	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
	reg |= (1 << PMA_PMD_EXT_SSR_LBN);
	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);

	mdelay(200);

	
	rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
	if (rc < 0)
		goto out;

	
	rc = tenxpress_init(efx);
	if (rc < 0)
		goto out;

	
	mdelay(10);
out:
	falcon_start_nic_stats(efx);
	return rc;
}
예제 #5
0
/* Poll for link state changes */
static bool tenxpress_phy_poll(struct efx_nic *efx)
{
	struct efx_link_state old_state = efx->link_state;

	if (efx->phy_type == PHY_TYPE_SFX7101) {
		efx->link_state.up = sfx7101_link_ok(efx);
		efx->link_state.speed = 10000;
		efx->link_state.fd = true;
		efx->link_state.fc = efx_mdio_get_pause(efx);

		sfx7101_check_bad_lp(efx, efx->link_state.up);
	} else {
		struct ethtool_cmd ecmd;

		/* Check the LASI alarm first */
		if (efx->loopback_mode == LOOPBACK_NONE &&
		    !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
		      MDIO_PMA_LASI_LSALARM))
			return false;

		tenxpress_get_settings(efx, &ecmd);

		efx->link_state.up = sft9001_link_ok(efx, &ecmd);
		efx->link_state.speed = ecmd.speed;
		efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
		efx->link_state.fc = efx_mdio_get_pause(efx);
	}

	return !efx_link_state_equal(&efx->link_state, &old_state);
}
예제 #6
0
/* Perform a "special software reset" on the PHY. The caller is
 * responsible for saving and restoring the PHY hardware registers
 * properly, and masking/unmasking LASI */
static int tenxpress_special_reset(struct efx_nic *efx)
{
	int rc, reg;

	/* The XGMAC clock is driven from the SFX7101 312MHz clock, so
	 * a special software reset can glitch the XGMAC sufficiently for stats
	 * requests to fail. */
	falcon_stop_nic_stats(efx);

	/* Initiate reset */
	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
	reg |= (1 << PMA_PMD_EXT_SSR_LBN);
	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);

	mdelay(200);

	/* Wait for the blocks to come out of reset */
	rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
	if (rc < 0)
		goto out;

	/* Try and reconfigure the device */
	rc = tenxpress_init(efx);
	if (rc < 0)
		goto out;

	/* Wait for the XGXS state machine to churn */
	mdelay(10);
out:
	falcon_start_nic_stats(efx);
	return rc;
}
예제 #7
0
static int tenxpress_init(struct efx_nic *efx)
{
	int reg;

	if (efx->phy_type == PHY_TYPE_SFX7101) {
		/* Enable 312.5 MHz clock */
		efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
			       1 << CLK312_EN_LBN);
	} else {
		/* Enable 312.5 MHz clock and GMII */
		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
		reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
			(1 << PMA_PMD_EXT_CLK_OUT_LBN) |
			(1 << PMA_PMD_EXT_CLK312_LBN) |
			(1 << PMA_PMD_EXT_ROBUST_LBN));

		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
		efx_mdio_set_flag(efx, MDIO_MMD_C22EXT,
			      GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN,
			      false);
	}

	/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
	if (efx->phy_type == PHY_TYPE_SFX7101) {
		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
				  1 << PMA_PMA_LED_ACTIVITY_LBN, true);
		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
			       SFX7101_PMA_PMD_LED_DEFAULT);
	}

	return 0;
}
예제 #8
0
/* Initialisation entry point for this PHY driver */
static int txc43128_phy_init(struct efx_nic *efx)
{
	u32 devid;
	int rc;

	devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
	EFX_INFO(efx, ""TXCNAME ": PHY ID reg %x (OUI %06x model %02x "
		 "revision %x)\n", devid, efx_mdio_id_oui(devid),
		 efx_mdio_id_model(devid), efx_mdio_id_rev(devid));

	EFX_INFO(efx, ""TXCNAME ": Silicon ID %x\n",
		 efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_GLRGS_SLID) &
		 TXC_GLRGS_SLID_MASK);

	rc = txc_reset_phy(efx);
	if (rc < 0)
		return rc;

	rc = txc_bist(efx);
	if (rc < 0)
		return rc;

	txc_apply_defaults(efx);

	return 0;
}
static void
tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
	u32 adv = 0, lpa = 0;
	int reg;

	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
	if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
		adv |= ADVERTISED_10000baseT_Full;
	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
	if (reg & MDIO_AN_10GBT_STAT_LP10G)
		lpa |= ADVERTISED_10000baseT_Full;

	mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);

	if (LOOPBACK_EXTERNAL(efx))
		ethtool_cmd_speed_set(ecmd, SPEED_10000);
}
예제 #10
0
static ssize_t show_phy_short_reach(struct device *dev,
				    struct device_attribute *attr, char *buf)
{
	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
	int reg;

	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR);
	return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT));
}
예제 #11
0
static void
tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
	u32 adv = 0, lpa = 0;
	int reg;

	if (efx->phy_type != PHY_TYPE_SFX7101) {
		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL);
		if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
			adv |= ADVERTISED_1000baseT_Full;
		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS);
		if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
			lpa |= ADVERTISED_1000baseT_Half;
		if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
			lpa |= ADVERTISED_1000baseT_Full;
	}
	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
	if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
		adv |= ADVERTISED_10000baseT_Full;
	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
	if (reg & MDIO_AN_10GBT_STAT_LP10G)
		lpa |= ADVERTISED_10000baseT_Full;

	mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);

	if (efx->phy_type != PHY_TYPE_SFX7101) {
		ecmd->supported |= (SUPPORTED_100baseT_Full |
				    SUPPORTED_1000baseT_Full);
		if (ecmd->speed != SPEED_10000) {
			ecmd->eth_tp_mdix =
				(efx_mdio_read(efx, MDIO_MMD_PMAPMD,
					       PMA_PMD_XSTATUS_REG) &
				 (1 << PMA_PMD_XSTAT_MDIX_LBN))
				? ETH_TP_MDI_X : ETH_TP_MDI;
		}
	}

	/* In loopback, the PHY automatically brings up the correct interface,
	 * but doesn't advertise the correct speed. So override it */
	if (efx->loopback_mode == LOOPBACK_GPHY)
		ecmd->speed = SPEED_1000;
	else if (LOOPBACK_EXTERNAL(efx))
		ecmd->speed = SPEED_10000;
}
예제 #12
0
static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
{
	struct tenxpress_phy_data *pd = efx->phy_data;
	bool bad_lp;
	int reg;

	if (link_ok) {
		bad_lp = false;
	} else {
		/* Check that AN has started but not completed. */
		reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1);
		if (!(reg & MDIO_AN_STAT1_LPABLE))
			return; /* LP status is unknown */
		bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE);
		if (bad_lp)
			pd->bad_lp_tries++;
	}

	/* Nothing to do if all is well and was previously so. */
	if (!pd->bad_lp_tries)
		return;

	/* Use the RX (red) LED as an error indicator once we've seen AN
	 * failure several times in a row, and also log a message. */
	if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
				    PMA_PMD_LED_OVERR_REG);
		reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN);
		if (!bad_lp) {
			reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN;
		} else {
			reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN;
			netif_err(efx, link, efx->net_dev,
				  "appears to be plugged into a port"
				  " that is not 10GBASE-T capable. The PHY"
				  " supports 10GBASE-T ONLY, so no link can"
				  " be established\n");
		}
		efx_mdio_write(efx, MDIO_MMD_PMAPMD,
			       PMA_PMD_LED_OVERR_REG, reg);
		pd->bad_lp_tries = bad_lp;
	}
}
예제 #13
0
/* Set the lane power down state in the analog control registers */
static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
{
	int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
		| (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
	int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN)
		| (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN);
	int txctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL);
	int rxctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL);

	if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) {
		txctl &= ~txpd;
		rxctl &= ~rxpd;
	} else {
		txctl |= txpd;
		rxctl |= rxpd;
	}

	efx_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl);
	efx_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl);
}
예제 #14
0
static void
tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
	u32 adv = 0, lpa = 0;
	int reg;

	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
	if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
		adv |= ADVERTISED_10000baseT_Full;
	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
	if (reg & MDIO_AN_10GBT_STAT_LP10G)
		lpa |= ADVERTISED_10000baseT_Full;

	mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);

	/* In loopback, the PHY automatically brings up the correct interface,
	 * but doesn't advertise the correct speed. So override it */
	if (LOOPBACK_EXTERNAL(efx))
		ethtool_cmd_speed_set(ecmd, SPEED_10000);
}
static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
{
	struct tenxpress_phy_data *pd = efx->phy_data;
	bool bad_lp;
	int reg;

	if (link_ok) {
		bad_lp = false;
	} else {
		
		reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1);
		if (!(reg & MDIO_AN_STAT1_LPABLE))
			return; 
		bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE);
		if (bad_lp)
			pd->bad_lp_tries++;
	}

	
	if (!pd->bad_lp_tries)
		return;

	if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
				    PMA_PMD_LED_OVERR_REG);
		reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN);
		if (!bad_lp) {
			reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN;
		} else {
			reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN;
			netif_err(efx, link, efx->net_dev,
				  "appears to be plugged into a port"
				  " that is not 10GBASE-T capable. The PHY"
				  " supports 10GBASE-T ONLY, so no link can"
				  " be established\n");
		}
		efx_mdio_write(efx, MDIO_MMD_PMAPMD,
			       PMA_PMD_LED_OVERR_REG, reg);
		pd->bad_lp_tries = bad_lp;
	}
}
예제 #16
0
/* Set the lane power down state in the global registers */
static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
{
	int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
	int ctl = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);

	if (!(efx->phy_mode & PHY_MODE_LOW_POWER))
		ctl &= ~pd;
	else
		ctl |= pd;

	efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl);
}
예제 #17
0
int sft9001_wait_boot(struct efx_nic *efx)
{
	unsigned long timeout = jiffies + HZ + 1;
	int boot_stat;

	for (;;) {
		boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS,
					  PCS_BOOT_STATUS_REG);
		if (boot_stat >= 0) {
			EFX_LOG(efx, "PHY boot status = %#x\n", boot_stat);
			switch (boot_stat &
				((1 << PCS_BOOT_FATAL_ERROR_LBN) |
				 (3 << PCS_BOOT_PROGRESS_LBN) |
				 (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
				 (1 << PCS_BOOT_CODE_STARTED_LBN))) {
			case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
			      (PCS_BOOT_PROGRESS_CHECKSUM <<
			       PCS_BOOT_PROGRESS_LBN)):
			case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
			      (PCS_BOOT_PROGRESS_INIT <<
			       PCS_BOOT_PROGRESS_LBN) |
			      (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
				return -EINVAL;
			case ((PCS_BOOT_PROGRESS_WAIT_MDIO <<
			       PCS_BOOT_PROGRESS_LBN) |
			      (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
				return (efx->phy_mode & PHY_MODE_SPECIAL) ?
					0 : -EIO;
			case ((PCS_BOOT_PROGRESS_JUMP <<
			       PCS_BOOT_PROGRESS_LBN) |
			      (1 << PCS_BOOT_CODE_STARTED_LBN)):
			case ((PCS_BOOT_PROGRESS_JUMP <<
			       PCS_BOOT_PROGRESS_LBN) |
			      (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
			      (1 << PCS_BOOT_CODE_STARTED_LBN)):
				return (efx->phy_mode & PHY_MODE_SPECIAL) ?
					-EIO : 0;
			default:
				if (boot_stat & (1 << PCS_BOOT_FATAL_ERROR_LBN))
					return -EIO;
				break;
			}
		}

		if (time_after_eq(jiffies, timeout))
			return -ETIMEDOUT;

		msleep(50);
	}
}
예제 #18
0
static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
	u32 reg;

	if (efx_phy_mode_disabled(efx->phy_mode))
		return false;
	else if (efx->loopback_mode == LOOPBACK_GPHY)
		return true;
	else if (efx->loopback_mode)
		return efx_mdio_links_ok(efx,
					 MDIO_DEVS_PMAPMD |
					 MDIO_DEVS_PHYXS);

	/* We must use the same definition of link state as LASI,
	 * otherwise we can miss a link state transition
	 */
	if (ecmd->speed == 10000) {
		reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
		return reg & MDIO_PCS_10GBRT_STAT1_BLKLK;
	} else {
		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG);
		return reg & (1 << C22EXT_STATUS_LINK_LBN);
	}
}
예제 #19
0
/* Push the non-configurable defaults into the PHY. This must be
 * done after every full reset */
static void txc_apply_defaults(struct efx_nic *efx)
{
	int mctrl;

	/* Turn amplitude down and preemphasis off on the host side
	 * (PHY<->MAC) as this is believed less likely to upset Falcon
	 * and no adverse effects have been noted. It probably also
	 * saves a picowatt or two */

	/* Turn off preemphasis */
	efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
	efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);

	/* Turn down the amplitude */
	efx_mdio_write(efx, MDIO_MMD_PHYXS,
		       TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
	efx_mdio_write(efx, MDIO_MMD_PHYXS,
		       TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);

	/* Set the line side amplitude and preemphasis to the databook
	 * defaults as an erratum causes them to be 0 on at least some
	 * PHY rev.s */
	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
		       TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
		       TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
		       TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
		       TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);

	/* Set up the LEDs  */
	mctrl = efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL);

	/* Set the Green and Red LEDs to their default modes */
	mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
	efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);

	/* Databook recommends doing this after configuration changes */
	txc_reset_logic(efx);

	falcon_board(efx)->type->init_phy(efx);
}
예제 #20
0
static int tenxpress_phy_init(struct efx_nic *efx)
{
	int rc;

	falcon_board(efx)->type->init_phy(efx);

	if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
		if (efx->phy_type == PHY_TYPE_SFT9001A) {
			int reg;
			reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
					    PMA_PMD_XCONTROL_REG);
			reg |= (1 << PMA_PMD_EXT_SSR_LBN);
			efx_mdio_write(efx, MDIO_MMD_PMAPMD,
				       PMA_PMD_XCONTROL_REG, reg);
			mdelay(200);
		}

		rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
		if (rc < 0)
			return rc;

		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
		if (rc < 0)
			return rc;
	}

	rc = tenxpress_init(efx);
	if (rc < 0)
		return rc;

	/* Reinitialise flow control settings */
	efx_link_set_wanted_fc(efx, efx->wanted_fc);
	efx_mdio_an_reconfigure(efx);

	schedule_timeout_uninterruptible(HZ / 5); /* 200ms */

	/* Let XGXS and SerDes out of reset */
	falcon_reset_xaui(efx);

	return 0;
}
예제 #21
0
/* Run a single BIST on one MMD*/
static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
{
	int ctrl, bctl;
	int lane;
	int rc = 0;

	EFX_INFO(efx, "" TXCNAME ": running BIST on %s MMD\n",
		 efx_mdio_mmd_name(mmd));

	/* Set PMA to test into loopback using Mt Diablo reg as per app note */
	ctrl = efx_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
	ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
	efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);

	/* The BIST app. note lists these  as 3 distinct steps. */
	/* Set the BIST type */
	bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
	efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);

	/* Set the BSTEN bit in the BIST Control register to enable */
	bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
	efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);

	/* Set the BSTRT bit in the BIST Control register */
	efx_mdio_write(efx, mmd, TXC_BIST_CTL,
		       bctl | (1 << TXC_BIST_CTRL_STRT_LBN));

	/* Wait. */
	udelay(TXC_BIST_DURATION);

	/* Set the BSTOP bit in the BIST Control register */
	bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
	efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);

	/* The STOP bit should go off when things have stopped */
	while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
		bctl = efx_mdio_read(efx, mmd, TXC_BIST_CTL);

	/* Check all the error counts are 0 and all the frame counts are
	   non-zero */
	for (lane = 0; lane < 4; lane++) {
		int count = efx_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
		if (count != 0) {
			EFX_ERR(efx, ""TXCNAME": BIST error. "
				"Lane %d had %d errs\n", lane, count);
			rc = -EIO;
		}
		count = efx_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane);
		if (count == 0) {
			EFX_ERR(efx, ""TXCNAME": BIST error. "
				"Lane %d got 0 frames\n", lane);
			rc = -EIO;
		}
	}

	if (rc == 0)
		EFX_INFO(efx, ""TXCNAME": BIST pass\n");

	/* Disable BIST */
	efx_mdio_write(efx, mmd, TXC_BIST_CTL, 0);

	/* Turn off loopback */
	ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
	efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);

	return rc;
}