drivers/net/mdio/mdio-realtek-rtl9300.c

Source file repositories/reference/linux-study-clean/drivers/net/mdio/mdio-realtek-rtl9300.c

File Facts

System
Linux kernel
Corpus path
drivers/net/mdio/mdio-realtek-rtl9300.c
Extension
.c
Size
23685 bytes
Lines
766
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 otto_emdio_cmd_regs {
	u32 c22_data;
	u32 c45_data;
	u32 io_data;
	u32 port_mask_low;
	/* additional registers for high port count models RTL839x/RTL931x */
	u32 port_mask_high;
	u32 broadcast;
	u32 ext_page;
};

struct otto_emdio_priv {
	const struct otto_emdio_info *info;
	struct regmap *regmap;
	struct mutex lock; /* protect HW access */
	DECLARE_BITMAP(valid_ports, MAX_PORTS);
	u8 smi_bus[MAX_PORTS];
	u8 smi_addr[MAX_PORTS];
	bool smi_bus_is_c45[MAX_SMI_BUSSES];
	struct mii_bus *bus[MAX_SMI_BUSSES];
};

struct otto_emdio_info {
	u32 addr_map_base;
	u32 bus_map_base;
	u32 cmd_fail;
	u32 cmd_read;
	u32 cmd_write;
	struct otto_emdio_cmd_regs cmd_regs;
	u8 num_buses;
	u8 num_ports;
	u16 num_pages;
	int (*setup_controller)(struct otto_emdio_priv *priv);
	int (*read_c22)(struct mii_bus *bus, int port, int regnum, u32 *value);
	int (*read_c45)(struct mii_bus *bus, int port, int dev_addr, int regnum, u32 *value);
	int (*write_c22)(struct mii_bus *bus, int port, int regnum, u16 value);
	int (*write_c45)(struct mii_bus *bus, int port, int dev_addr, int regnum, u16 value);
};

struct otto_emdio_chan {
	struct otto_emdio_priv *priv;
	u8 mdio_bus;
};

static int otto_emdio_phy_to_port(struct mii_bus *bus, int phy_id)
{
	struct otto_emdio_chan *chan = bus->priv;
	struct otto_emdio_priv *priv;
	int i;

	priv = chan->priv;

	for_each_set_bit(i, priv->valid_ports, priv->info->num_ports)
		if (priv->smi_bus[i] == chan->mdio_bus &&
		    priv->smi_addr[i] == phy_id)
			return i;

	return -ENOENT;
}

static struct otto_emdio_priv *otto_emdio_bus_to_priv(struct mii_bus *bus)
{
	struct otto_emdio_chan *chan = bus->priv;

	return chan->priv;
}

static int otto_emdio_run_cmd(struct mii_bus *bus, u32 cmd,
			      struct otto_emdio_cmd_regs *cmd_data)
{
	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
	const struct otto_emdio_info *info = priv->info;
	u32 cmdstate;
	int ret;

	/* Defensive pre check just in case something goes horrible wrong */
	ret = regmap_read_poll_timeout(priv->regmap, info->cmd_regs.c22_data,
				       cmdstate, !(cmdstate & PHY_CTRL_CMD), 10, 1000);
	if (ret)
		return ret;

	/* Fill all registers. Hardware will read only the needed bits depending on command */
	if (info->cmd_regs.port_mask_high) {
		/* Fill extra registers for high port count models */
		ret = regmap_write(priv->regmap, info->cmd_regs.broadcast, cmd_data->broadcast);
		if (ret)
			return ret;

		ret = regmap_write(priv->regmap, info->cmd_regs.ext_page, cmd_data->ext_page);
		if (ret)

Annotation

Implementation Notes