drivers/net/mdio/mdio-mux-mmioreg.c

Source file repositories/reference/linux-study-clean/drivers/net/mdio/mdio-mux-mmioreg.c

File Facts

System
Linux kernel
Corpus path
drivers/net/mdio/mdio-mux-mmioreg.c
Extension
.c
Size
4716 bytes
Lines
191
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 mdio_mux_mmioreg_state {
	void *mux_handle;
	phys_addr_t phys;
	unsigned int iosize;
	unsigned int mask;
};

/*
 * MDIO multiplexing switch function
 *
 * This function is called by the mdio-mux layer when it thinks the mdio bus
 * multiplexer needs to switch.
 *
 * 'current_child' is the current value of the mux register (masked via
 * s->mask).
 *
 * 'desired_child' is the value of the 'reg' property of the target child MDIO
 * node.
 *
 * The first time this function is called, current_child == -1.
 *
 * If current_child == desired_child, then the mux is already set to the
 * correct bus.
 */
static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child,
				      void *data)
{
	struct mdio_mux_mmioreg_state *s = data;

	if (current_child ^ desired_child) {
		void __iomem *p = ioremap(s->phys, s->iosize);
		if (!p)
			return -ENOMEM;

		switch (s->iosize) {
		case sizeof(uint8_t): {
			uint8_t x, y;

			x = ioread8(p);
			y = (x & ~s->mask) | desired_child;
			if (x != y) {
				iowrite8((x & ~s->mask) | desired_child, p);
				pr_debug("%s: %02x -> %02x\n", __func__, x, y);
			}

			break;
		}
		case sizeof(uint16_t): {
			uint16_t x, y;

			x = ioread16(p);
			y = (x & ~s->mask) | desired_child;
			if (x != y) {
				iowrite16((x & ~s->mask) | desired_child, p);
				pr_debug("%s: %04x -> %04x\n", __func__, x, y);
			}

			break;
		}
		case sizeof(uint32_t): {
			uint32_t x, y;

			x = ioread32(p);
			y = (x & ~s->mask) | desired_child;
			if (x != y) {
				iowrite32((x & ~s->mask) | desired_child, p);
				pr_debug("%s: %08x -> %08x\n", __func__, x, y);
			}

			break;
		}
		}

		iounmap(p);
	}

	return 0;
}

static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct mdio_mux_mmioreg_state *s;
	struct resource res;
	const __be32 *iprop;
	int len, ret;

	dev_dbg(&pdev->dev, "probing node %pOF\n", np);

	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);

Annotation

Implementation Notes