drivers/net/phy/qcom/qca83xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/qcom/qca83xx.c
Extension
.c
Size
7018 bytes
Lines
270
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 qca83xx_priv {
	u64 stats[ARRAY_SIZE(qca83xx_hw_stats)];
};

MODULE_DESCRIPTION("Qualcomm Atheros QCA83XX PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
MODULE_LICENSE("GPL");

static int qca83xx_get_sset_count(struct phy_device *phydev)
{
	return ARRAY_SIZE(qca83xx_hw_stats);
}

static void qca83xx_get_strings(struct phy_device *phydev, u8 *data)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
		ethtool_puts(&data, qca83xx_hw_stats[i].string);
}

static u64 qca83xx_get_stat(struct phy_device *phydev, int i)
{
	struct at803x_hw_stat stat = qca83xx_hw_stats[i];
	struct qca83xx_priv *priv = phydev->priv;
	int val;
	u64 ret;

	if (stat.access_type == MMD)
		val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg);
	else
		val = phy_read(phydev, stat.reg);

	if (val < 0) {
		ret = U64_MAX;
	} else {
		val = val & stat.mask;
		priv->stats[i] += val;
		ret = priv->stats[i];
	}

	return ret;
}

static void qca83xx_get_stats(struct phy_device *phydev,
			      struct ethtool_stats *stats, u64 *data)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
		data[i] = qca83xx_get_stat(phydev, i);
}

static int qca83xx_probe(struct phy_device *phydev)
{
	struct device *dev = &phydev->mdio.dev;
	struct qca83xx_priv *priv;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	phydev->priv = priv;

	return 0;
}

static int qca83xx_config_init(struct phy_device *phydev)
{
	u8 switch_revision;

	switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK;

	switch (switch_revision) {
	case 1:
		/* For 100M waveform */
		at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea);
		/* Turn on Gigabit clock */
		at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0);
		break;

	case 2:
		phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);
		fallthrough;
	case 4:
		phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f);
		at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860);
		at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46);
		at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000);

Annotation

Implementation Notes