drivers/net/phy/microchip.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/microchip.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/microchip.c
Extension
.c
Size
16231 bytes
Lines
602
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 lan88xx_priv {
	int	chip_id;
	int	chip_rev;
	__u32	wolopts;
	u8	downshift_cnt;
};

static int lan88xx_read_page(struct phy_device *phydev)
{
	return __phy_read(phydev, LAN88XX_EXT_PAGE_ACCESS);
}

static int lan88xx_write_page(struct phy_device *phydev, int page)
{
	return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page);
}

static int lan88xx_suspend(struct phy_device *phydev)
{
	struct lan88xx_priv *priv = phydev->priv;

	/* do not power down PHY when WOL is enabled */
	if (!priv->wolopts)
		genphy_suspend(phydev);

	return 0;
}

static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
			      u32 data)
{
	int val, save_page, ret = 0;
	u16 buf;

	/* Save current page */
	save_page = phy_save_page(phydev);
	if (save_page < 0) {
		phydev_warn(phydev, "Failed to get current page\n");
		goto err;
	}

	/* Switch to TR page */
	lan88xx_write_page(phydev, LAN88XX_EXT_PAGE_ACCESS_TR);

	ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_LOW_DATA,
			  (data & 0xFFFF));
	if (ret < 0) {
		phydev_warn(phydev, "Failed to write TR low data\n");
		goto err;
	}

	ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_HIGH_DATA,
			  (data & 0x00FF0000) >> 16);
	if (ret < 0) {
		phydev_warn(phydev, "Failed to write TR high data\n");
		goto err;
	}

	/* Config control bits [15:13] of register */
	buf = (regaddr & ~(0x3 << 13));/* Clr [14:13] to write data in reg */
	buf |= 0x8000; /* Set [15] to Packet transmit */

	ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_CR, buf);
	if (ret < 0) {
		phydev_warn(phydev, "Failed to write data in reg\n");
		goto err;
	}

	usleep_range(1000, 2000);/* Wait for Data to be written */
	val = __phy_read(phydev, LAN88XX_EXT_PAGE_TR_CR);
	if (!(val & 0x8000))
		phydev_warn(phydev, "TR Register[0x%X] configuration failed\n",
			    regaddr);
err:
	return phy_restore_page(phydev, save_page, ret);
}

static void lan88xx_config_TR_regs(struct phy_device *phydev)
{
	int err;

	/* Get access to Channel 0x1, Node 0xF , Register 0x01.
	 * Write 24-bit value 0x12B00A to register. Setting MrvlTrFix1000Kf,
	 * MrvlTrFix1000Kp, MasterEnableTR bits.
	 */
	err = lan88xx_TR_reg_set(phydev, 0x0F82, 0x12B00A);
	if (err < 0)
		phydev_warn(phydev, "Failed to Set Register[0x0F82]\n");

	/* Get access to Channel b'10, Node b'1101, Register 0x06.

Annotation

Implementation Notes