drivers/net/dsa/lan9303_mdio.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/lan9303_mdio.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/lan9303_mdio.c
Extension
.c
Size
4807 bytes
Lines
178
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 lan9303_mdio {
	struct mdio_device *device;
	struct lan9303 chip;
};

static void lan9303_mdio_real_write(struct mdio_device *mdio, int reg, u16 val)
{
	mdio->bus->write(mdio->bus, PHY_ADDR(reg), PHY_REG(reg), val);
}

static int lan9303_mdio_write(void *ctx, uint32_t reg, uint32_t val)
{
	struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;

	reg <<= 2; /* reg num to offset */
	mutex_lock_nested(&sw_dev->device->bus->mdio_lock, MDIO_MUTEX_NESTED);
	lan9303_mdio_real_write(sw_dev->device, reg, val & 0xffff);
	lan9303_mdio_real_write(sw_dev->device, reg + 2, (val >> 16) & 0xffff);
	mutex_unlock(&sw_dev->device->bus->mdio_lock);

	return 0;
}

static u16 lan9303_mdio_real_read(struct mdio_device *mdio, int reg)
{
	return mdio->bus->read(mdio->bus, PHY_ADDR(reg), PHY_REG(reg));
}

static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
{
	struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;

	reg <<= 2; /* reg num to offset */
	mutex_lock_nested(&sw_dev->device->bus->mdio_lock, MDIO_MUTEX_NESTED);
	*val = lan9303_mdio_real_read(sw_dev->device, reg);
	*val |= (lan9303_mdio_real_read(sw_dev->device, reg + 2) << 16);
	mutex_unlock(&sw_dev->device->bus->mdio_lock);

	return 0;
}

static int lan9303_mdio_phy_write(struct lan9303 *chip, int addr, int reg,
				  u16 val)
{
	struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);

	return mdiobus_write_nested(sw_dev->device->bus, addr, reg, val);
}

static int lan9303_mdio_phy_read(struct lan9303 *chip, int addr, int reg)
{
	struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);

	return mdiobus_read_nested(sw_dev->device->bus, addr, reg);
}

static const struct lan9303_phy_ops lan9303_mdio_phy_ops = {
	.phy_read = lan9303_mdio_phy_read,
	.phy_write = lan9303_mdio_phy_write,
};

static const struct regmap_config lan9303_mdio_regmap_config = {
	.reg_bits = 8,
	.val_bits = 32,
	.reg_stride = 1,
	.can_multi_write = true,
	.max_register = 0x0ff, /* address bits 0..1 are not used */
	.reg_format_endian = REGMAP_ENDIAN_LITTLE,

	.volatile_table = &lan9303_register_set,
	.wr_table = &lan9303_register_set,
	.rd_table = &lan9303_register_set,

	.reg_read = lan9303_mdio_read,
	.reg_write = lan9303_mdio_write,

	.cache_type = REGCACHE_NONE,
};

static int lan9303_mdio_probe(struct mdio_device *mdiodev)
{
	struct lan9303_mdio *sw_dev;
	int ret;

	sw_dev = devm_kzalloc(&mdiodev->dev, sizeof(struct lan9303_mdio),
			      GFP_KERNEL);
	if (!sw_dev)
		return -ENOMEM;

	sw_dev->chip.regmap = devm_regmap_init(&mdiodev->dev, NULL, sw_dev,

Annotation

Implementation Notes