// SPDX-License-Identifier: GPL-2.0-only /**************************************************************************** * Driver for Solarflare network controllers and boards * Copyright 2006-2012 Solarflare Communications Inc.
*/ /* * Driver for AMCC QT202x SFP+ and XFP adapters; see www.amcc.com for details
*/
/* Wait for firmware heartbeat to start */ for (;;) { int counter;
reg = ef4_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG); if (reg < 0) return reg;
counter = ((reg >> PCS_FW_HEARTB_LBN) &
((1 << PCS_FW_HEARTB_WIDTH) - 1)); if (old_counter == 0)
old_counter = counter; elseif (counter != old_counter) break; if (time_after(jiffies, timeout)) { /* Some cables have EEPROMs that conflict with the
* PHY's on-board EEPROM so it cannot load firmware */
netif_err(efx, hw, efx->net_dev, "If an SFP+ direct attach cable is" " connected, please check that it complies" " with the SFP+ specification\n"); return -ETIMEDOUT;
}
msleep(QT2025C_HEARTB_WAIT);
}
/* The PHY can get stuck in a state where it reports PHY_XS and PMA/PMD * layers up, but PCS down (no block_lock). If we notice this state * persisting for a couple of seconds, we switch PMA/PMD loopback * briefly on and then off again, which is normally sufficient to * recover it.
*/ if (efx->link_state.up ||
!ef4_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) {
phy_data->bug17190_in_bad_state = false; return;
}
/* Only 2.0.1.0+ PHY firmware supports the more optimal SFP+ * Self-Configure mode. Don't attempt any switching if we encounter
* older firmware. */ if (phy_data->firmware_ver < 0x02000100) return 0;
/* In general we will get optimal behaviour in "SFP+ Self-Configure" * mode; however, that powers down most of the PHY when no module is * present, so we must use a different mode (any fixed mode will do)
* to be sure that loopbacks will work. */
phy_op_mode = (efx->loopback_mode == LOOPBACK_NONE) ? 0x0038 : 0x0020;
/* Only change mode if really necessary */
reg = ef4_mdio_read(efx, 1, 0xc319); if ((reg & 0x0038) == phy_op_mode) return 0;
netif_dbg(efx, hw, efx->net_dev, "Switching PHY to mode 0x%04x\n",
phy_op_mode);
/* This sequence replicates the register writes configured in the boot * EEPROM (including the differences between board revisions), except * that the operating mode is changed, and the PHY is prevented from
* unnecessarily reloading the main firmware image again. */
ef4_mdio_write(efx, 1, 0xc300, 0x0000); /* (Note: this portion of the boot EEPROM sequence, which bit-bashes 9 * STOPs onto the firmware/module I2C bus to reset it, varies across * board revisions, as the bus is connected to different GPIO/LED
* outputs on the PHY.) */ if (board->major == 0 && board->minor < 2) {
ef4_mdio_write(efx, 1, 0xc303, 0x4498); for (i = 0; i < 9; i++) {
ef4_mdio_write(efx, 1, 0xc303, 0x4488);
ef4_mdio_write(efx, 1, 0xc303, 0x4480);
ef4_mdio_write(efx, 1, 0xc303, 0x4490);
ef4_mdio_write(efx, 1, 0xc303, 0x4498);
}
} else {
ef4_mdio_write(efx, 1, 0xc303, 0x0920);
ef4_mdio_write(efx, 1, 0xd008, 0x0004); for (i = 0; i < 9; i++) {
ef4_mdio_write(efx, 1, 0xc303, 0x0900);
ef4_mdio_write(efx, 1, 0xd008, 0x0005);
ef4_mdio_write(efx, 1, 0xc303, 0x0920);
ef4_mdio_write(efx, 1, 0xd008, 0x0004);
}
ef4_mdio_write(efx, 1, 0xc303, 0x4900);
}
ef4_mdio_write(efx, 1, 0xc303, 0x4900);
ef4_mdio_write(efx, 1, 0xc302, 0x0004);
ef4_mdio_write(efx, 1, 0xc316, 0x0013);
ef4_mdio_write(efx, 1, 0xc318, 0x0054);
ef4_mdio_write(efx, 1, 0xc319, phy_op_mode);
ef4_mdio_write(efx, 1, 0xc31a, 0x0098);
ef4_mdio_write(efx, 3, 0x0026, 0x0e00);
ef4_mdio_write(efx, 3, 0x0027, 0x0013);
ef4_mdio_write(efx, 3, 0x0028, 0xa528);
ef4_mdio_write(efx, 1, 0xd006, 0x000a);
ef4_mdio_write(efx, 1, 0xd007, 0x0009);
ef4_mdio_write(efx, 1, 0xd008, 0x0004); /* This additional write is not present in the boot EEPROM. It * prevents the PHY's internal boot ROM doing another pointless (and * slow) reload of the firmware image (the microcontroller's code
* memory is not affected by the microcontroller reset). */
ef4_mdio_write(efx, 1, 0xc317, 0x00ff); /* PMA/PMD loopback sets RXIN to inverse polarity and the firmware
* restart doesn't reset it. We need to do that ourselves. */
ef4_mdio_set_flag(efx, 1, PMA_PMD_MODE_REG,
1 << PMA_PMD_RXIN_SEL_LBN, false);
ef4_mdio_write(efx, 1, 0xc300, 0x0002);
msleep(20);
/* Restart microcontroller execution of firmware from RAM */
qt2025c_restart_firmware(efx);
/* Wait for the microcontroller to be ready again */
rc = qt2025c_wait_reset(efx); if (rc < 0) {
netif_err(efx, hw, efx->net_dev, "PHY microcontroller reset during mode switch " "timed out\n"); return rc;
}
return 0;
}
staticint qt202x_reset_phy(struct ef4_nic *efx)
{ int rc;
if (efx->phy_type == PHY_TYPE_QT2025C) { /* Wait for the reset triggered by falcon_reset_hw()
* to complete */
rc = qt2025c_wait_reset(efx); if (rc < 0) goto fail;
} else { /* Reset the PHYXS MMD. This is documented as doing
* a complete soft reset. */
rc = ef4_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
QT2022C2_MAX_RESET_TIME /
QT2022C2_RESET_WAIT,
QT2022C2_RESET_WAIT); if (rc < 0) goto fail;
}
/* Wait 250ms for the PHY to complete bootup */
msleep(250);
if (efx->phy_type == PHY_TYPE_QT2025C) { int rc = qt2025c_select_phy_mode(efx); if (rc) return rc;
/* There are several different register bits which can * disable TX (and save power) on direct-attach cables * or optical transceivers, varying somewhat between * firmware versions. Only 'static mode' appears to
* cover everything. */
mdio_set_flag(
&efx->mdio, efx->mdio.prtad, MDIO_MMD_PMAPMD,
PMA_PMD_FTX_CTRL2_REG, 1 << PMA_PMD_FTX_STATIC_LBN,
efx->phy_mode & PHY_MODE_TX_DISABLED ||
efx->phy_mode & PHY_MODE_LOW_POWER ||
efx->loopback_mode == LOOPBACK_PCS ||
efx->loopback_mode == LOOPBACK_PMAPMD);
} else { /* Reset the PHY when moving from tx off to tx on */ if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) &&
(phy_data->phy_mode & PHY_MODE_TX_DISABLED))
qt202x_reset_phy(efx);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.