[PATCH v2 15/24] net: mdio: Add ZTE ZX279128S MDIO controller

Andrew Lunn andrew at lunn.ch
Wed Oct 14 05:13:38 PDT 2026


> +static int zx279128s_mdio_xfer(struct mii_bus *bus, u32 op, int addr,
> +			       int regnum, u16 data)
> +{
> +	struct zx279128s_mdio *priv = bus->priv;
> +	void __iomem *base = priv->base;
> +	u32 cmd, val;
> +	int ret;
> +
> +	/* Clear the previous command and its status */
> +	writel(readl(base + ZX_MDIO_CMD) & ~ZX_MDIO_CMD_START,
> +	       base + ZX_MDIO_CMD);
> +	writel(0, base + ZX_MDIO_STATUS);
> +
> +	cmd = readl(base + ZX_MDIO_CMD);
> +	cmd &= ~(ZX_MDIO_CMD_WR | ZX_MDIO_CMD_RD | ZX_MDIO_CMD_ADDR |
> +		 ZX_MDIO_CMD_REG);
> +	cmd |= op | FIELD_PREP(ZX_MDIO_CMD_ADDR, addr) |
> +	       FIELD_PREP(ZX_MDIO_CMD_REG, regnum);
> +
> +	if (op == ZX_MDIO_CMD_WR)
> +		writel(data, base + ZX_MDIO_DATA_WR);
> +	writel(cmd | ZX_MDIO_CMD_START, base + ZX_MDIO_CMD);
> +
> +	ret = readl_poll_timeout(base + ZX_MDIO_STATUS, val,
> +				 val & ZX_MDIO_STATUS_DONE, ZX_MDIO_POLL_US,
> +				 ZX_MDIO_TIMEOUT_US);
> +	if (ret) {
> +		dev_err_ratelimited(&bus->dev, "timeout (addr %d, reg %d)\n",
> +				    addr, regnum);
> +		return ret;
> +	}
> +
> +	writel(0, base + ZX_MDIO_STATUS);
> +	writel(readl(base + ZX_MDIO_CMD) & ~ZX_MDIO_CMD_START,
> +	       base + ZX_MDIO_CMD);

This is the same as what you did at the beginning, but in the opposite
order. Is it actually needed, and can the same order be used?

> +static int zx279128s_mdio_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct zx279128s_mdio *priv;
> +	struct mii_bus *bus;
> +	struct clk *clk;
> +	u32 val;
> +
> +	bus = devm_mdiobus_alloc_size(dev, sizeof(*priv));
> +	if (!bus)
> +		return -ENOMEM;
> +
> +	priv = bus->priv;
> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(priv->base))
> +		return PTR_ERR(priv->base);
> +
> +	clk = devm_clk_get_enabled(dev, "pclk");
> +	if (IS_ERR(clk))
> +		return dev_err_probe(dev, PTR_ERR(clk),
> +				     "failed to get the register clock\n");
> +	clk = devm_clk_get_enabled(dev, "wclk");
> +	if (IS_ERR(clk))
> +		return dev_err_probe(dev, PTR_ERR(clk),
> +				     "failed to get the work clock\n");
> +

Is this the bus clock? Does it need setting to 2.5Mhz?

> +static const struct of_device_id zx279128s_mdio_of_match[] = {
> +	{ .compatible = "zte,zx279128s-mdio" },
> +	{ }

It needs a device tree binding. But that is mostly boilerplate.

   Andrew



More information about the linux-arm-kernel mailing list