drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c
Extension
.c
Size
6165 bytes
Lines
228
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 spacmit_dwmac {
	struct regmap *apmu;
	unsigned int ctrl_offset;
	unsigned int dline_offset;
};

static int spacemit_dwmac_set_delay(struct spacmit_dwmac *dwmac,
				    unsigned int tx_code, unsigned int rx_code)
{
	unsigned int mask, val;

	mask = RGMII_TX_DLINE_STEP | RGMII_TX_DLINE_CODE | RGMII_TX_DLINE_EN |
	       RGMII_RX_DLINE_STEP | RGMII_RX_DLINE_CODE | RGMII_RX_DLINE_EN;

	/*
	 * Since the delay step provided by config 0 is small enough, and
	 * it can cover the range of the valid delay, so there is no needed
	 * to use other step config.
	 */
	val = FIELD_PREP(RGMII_TX_DLINE_STEP, 0) |
	      FIELD_PREP(RGMII_TX_DLINE_CODE, tx_code) | RGMII_TX_DLINE_EN |
	      FIELD_PREP(RGMII_RX_DLINE_STEP, 0) |
	      FIELD_PREP(RGMII_RX_DLINE_CODE, rx_code) | RGMII_RX_DLINE_EN;

	return regmap_update_bits(dwmac->apmu, dwmac->dline_offset,
				  mask, val);
}

static int spacemit_dwmac_detected_delay_value(unsigned int delay)
{
	if (delay == 0)
		return 0;

	if (delay > MAX_WORKED_DELAY)
		return -EINVAL;

	/*
	 * Note K3 require a specific factor for calculate
	 * the delay, in this scenario it is 0.9. So the
	 * formula is code * step / 10 * 0.9
	 */
	return DIV_ROUND_CLOSEST(delay * 10 * 10, K3_DELAY_STEP * 9);
}

static int spacemit_dwmac_fix_delay(struct spacmit_dwmac *dwmac,
				    unsigned int tx_delay,
				    unsigned int rx_delay)
{
	int rx_code;
	int tx_code;

	rx_code = spacemit_dwmac_detected_delay_value(rx_delay);
	if (rx_code < 0)
		return rx_code;

	tx_code = spacemit_dwmac_detected_delay_value(tx_delay);
	if (tx_code < 0)
		return tx_code;

	return spacemit_dwmac_set_delay(dwmac, tx_code, rx_code);
}

static int spacemit_dwmac_update_irq_config(struct spacmit_dwmac *dwmac,
					    struct stmmac_resources *stmmac_res)
{
	unsigned int val = stmmac_res->wol_irq >= 0 ? CTRL_WAKE_IRQ_EN : 0;
	unsigned int mask = CTRL_WAKE_IRQ_EN;

	return regmap_update_bits(dwmac->apmu, dwmac->ctrl_offset,
				  mask, val);
}

static void spacemit_get_interfaces(struct stmmac_priv *priv, void *bsp_priv,
				    unsigned long *interfaces)
{
	__set_bit(PHY_INTERFACE_MODE_MII, interfaces);
	__set_bit(PHY_INTERFACE_MODE_RMII, interfaces);
	phy_interface_set_rgmii(interfaces);
}

static int spacemit_set_phy_intf_sel(void *bsp_priv, u8 phy_intf_sel)
{
	unsigned int mask = CTRL_PHY_INTF_MII | CTRL_PHY_INTF_RGMII;
	struct spacmit_dwmac *dwmac = bsp_priv;
	unsigned int val = 0;

	switch (phy_intf_sel) {
	case PHY_INTF_SEL_GMII_MII:
		val = CTRL_PHY_INTF_MII;
		break;

Annotation

Implementation Notes