drivers/net/ethernet/sfc/falcon/txc43128_phy.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/falcon/txc43128_phy.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sfc/falcon/txc43128_phy.c
Extension
.c
Size
16156 bytes
Lines
559
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct txc43128_data {
	unsigned long bug10934_timer;
	enum ef4_phy_mode phy_mode;
	enum ef4_loopback_mode loopback_mode;
};

/* The PHY sometimes needs a reset to bring the link back up.  So long as
 * it reports link down, we reset it every 5 seconds.
 */
#define BUG10934_RESET_INTERVAL (5 * HZ)

/* Perform a reset that doesn't clear configuration changes */
static void txc_reset_logic(struct ef4_nic *efx);

/* Set the output value of a gpio */
void falcon_txc_set_gpio_val(struct ef4_nic *efx, int pin, int on)
{
	ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on);
}

/* Set up the GPIO direction register */
void falcon_txc_set_gpio_dir(struct ef4_nic *efx, int pin, int dir)
{
	ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir);
}

/* Reset the PMA/PMD MMD. The documentation is explicit that this does a
 * global reset (it's less clear what reset of other MMDs does).*/
static int txc_reset_phy(struct ef4_nic *efx)
{
	int rc = ef4_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD,
				    TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
				    TXC_RESET_WAIT);
	if (rc < 0)
		goto fail;

	/* Check that all the MMDs we expect are present and responding. */
	rc = ef4_mdio_check_mmds(efx, TXC_REQUIRED_DEVS);
	if (rc < 0)
		goto fail;

	return 0;

fail:
	netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n");
	return rc;
}

/* Run a single BIST on one MMD */
static int txc_bist_one(struct ef4_nic *efx, int mmd, int test)
{
	int ctrl, bctl;
	int lane;
	int rc = 0;

	/* Set PMA to test into loopback using Mt Diablo reg as per app note */
	ctrl = ef4_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
	ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
	ef4_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);
	ef4_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);
	ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);

	/* Set the BSTRT bit in the BIST Control register */
	ef4_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);
	ef4_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 = ef4_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 = ef4_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
		if (count != 0) {
			netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "

Annotation

Implementation Notes