drivers/net/phy/intel-xway.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/intel-xway.c
Extension
.c
Size
25571 bytes
Lines
790
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 xway_gphy_priv {
	u64 rx_errors;
};

static const int xway_internal_delay[] = {0, 500, 1000, 1500, 2000, 2500,
					 3000, 3500};

static int xway_gphy_rgmii_init(struct phy_device *phydev)
{
	unsigned int delay_size = ARRAY_SIZE(xway_internal_delay);
	s32 int_delay;
	int val = 0;

	if (!phy_interface_is_rgmii(phydev))
		return 0;

	/* Existing behavior was to use default pin strapping delay in rgmii
	 * mode, but rgmii should have meant no delay.  Warn existing users,
	 * but do not change anything at the moment.
	 */
	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
		u16 txskew, rxskew;

		val = phy_read(phydev, XWAY_MDIO_MIICTRL);
		if (val < 0)
			return val;

		txskew = FIELD_GET(XWAY_MDIO_MIICTRL_TXSKEW_MASK, val);
		rxskew = FIELD_GET(XWAY_MDIO_MIICTRL_RXSKEW_MASK, val);

		if (txskew > 0 || rxskew > 0)
			phydev_warn(phydev,
				    "PHY has delays (e.g. via pin strapping), but phy-mode = 'rgmii'\n"
				    "Should be 'rgmii-id' to use internal delays txskew:%d ps rxskew:%d ps\n",
				    xway_internal_delay[txskew],
				    xway_internal_delay[rxskew]);
		return 0;
	}

	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
		int_delay = phy_get_internal_delay(phydev, xway_internal_delay,
						   delay_size, true);

		/* if rx-internal-delay-ps is missing, use default of 2.0 ns */
		if (int_delay < 0)
			int_delay = 4; /* 2000 ps */

		val |= FIELD_PREP(XWAY_MDIO_MIICTRL_RXSKEW_MASK, int_delay);
	}

	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
		int_delay = phy_get_internal_delay(phydev, xway_internal_delay,
						   delay_size, false);

		/* if tx-internal-delay-ps is missing, use default of 2.0 ns */
		if (int_delay < 0)
			int_delay = 4; /* 2000 ps */

		val |= FIELD_PREP(XWAY_MDIO_MIICTRL_TXSKEW_MASK, int_delay);
	}

	return phy_modify(phydev, XWAY_MDIO_MIICTRL,
			  XWAY_MDIO_MIICTRL_RXSKEW_MASK |
			  XWAY_MDIO_MIICTRL_TXSKEW_MASK, val);
}

static int xway_gphy_init_leds(struct phy_device *phydev)
{
	int err;
	u32 ledxh;
	u32 ledxl;

	/* Ensure that integrated led function is enabled for all leds */
	err = phy_write(phydev, XWAY_MDIO_LED,
			XWAY_MDIO_LED_LED0_EN |
			XWAY_MDIO_LED_LED1_EN |
			XWAY_MDIO_LED_LED2_EN |
			XWAY_MDIO_LED_LED3_EN);
	if (err)
		return err;

	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCH,
		      XWAY_MMD_LEDCH_NACS_NONE |
		      XWAY_MMD_LEDCH_SBF_F02HZ |
		      XWAY_MMD_LEDCH_FBF_F16HZ);
	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCL,
		      XWAY_MMD_LEDCH_CBLINK_NONE |
		      XWAY_MMD_LEDCH_SCAN_NONE);

Annotation

Implementation Notes