From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A847748B37B for ; Wed, 14 Oct 2026 07:23:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791962595; cv=none; b=pMj5vhwUb3O9SEyodkjLdLACrtcm0wlyijDAABBOBYrSU6x86f0FenFwle/VstbwvYqktQLYPl+YLbPMAdxT0PRRxOOZXCKrNLBZSzA6IzvhRazFuYS9zKeK1ScRqmWkE/w2wM0BsU0yXAEgOrYfB60seyjoAeM7izdBH3P3b6M= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791962595; c=relaxed/simple; bh=4TA+L1CPkCZuDbEq9Cory5nOrbbxEIllqqfFp5BOn0o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WbZDflBFyw+mCNYu4xEC+BXv73J9yQuC686DRexawJaFV4XKMZsB5HcbOzrgkRGszND7mp5SDs0/pzzfExyVZN5wyTfIpqas3wp1kJMqpUxK2k9rcBB1SuBdLaZiZpR6Krd20kPClSKQkLheBWdtYZb99NITnFrfB5KjzXjdHf0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hJ3i3mq9; arc=none smtp.client-ip=209.85.221.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hJ3i3mq9" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-48afbd2c386so2162158f8f.3 for ; Wed, 14 Oct 2026 00:23:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791962588; x=1792567388; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=F1UhGspZt3n8d7AimaUoaUHhmKl1e/RrKismBjq1j3Q=; b=hJ3i3mq9xMJOEIshQOfF3pinETtMasu42yMcXw04owp32ZWeIqya7OYAv8trLOPtPf 1k3DYIW1FVRN/Zi2L0RorJP9XjJIuy+Fp4UWy6jNxngtPerHRvqpswWqcSSIbZc+QFSt Z3CetxcDl/vWSIMA9maBB9plEkWL83+btTaiuoLmpJIn3O77uZIqWh3WfEthH9/xCj4S V3lKLxFV8Jh+oeAJn/BEyiVJYJD/uJknZ0B89kZLmSMznq8xET56j0nSqXMUtj1lQmBl Ib22usbz9Fc9VItbfJWnaAEdKbwpediDRKDX8AidU4orJ34duj82Afgu5bFga8PClSou Ddmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791962588; x=1792567388; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=F1UhGspZt3n8d7AimaUoaUHhmKl1e/RrKismBjq1j3Q=; b=OREy6FX8mfuPJBgaspQIixmEgBnO0tpwtUu6fZgearveIpOQrfzguXmdxbT2VT4LEf kz4UBQI7xu7L7NDX7LrffNPY/bp0M5TAA3QWPL4NWu9hNy0aXA1hr/6rFEq5Mkkaetxw lLLdYExX/PkvhqbYvG/NBUDImtjbX5ivS3Mb9LV6mmc7I3xSW85AiUgpH2s5csk3GAbd Yq0svTjU0DwY66XriPePn8cj/vm+G0SW9f4VOjJ85dvCreRuCjdVGGYf+ugXFi5bRYQT dMpN5yk9iR7VZpiglev33S+4biJzDzPAa53D3pJqJmeGzEp9RiiTeQFZdjhLm7QwRBw+ cdcQ== X-Forwarded-Encrypted: i=1; AKwUvBxosBEU2f0E+dVh9PnRo8dOoIZ5FTxJglwhysv7uYbjRbGZp8b9SCeKCPoZUpcWmBCCysOXXQCNbBKqSHg=@vger.kernel.org X-Gm-Message-State: AFq9FYI/6byKU4LRYxZ1nPwt4nlfb1U4QzrEtYwfisOnIYidNqq4ZCkz mI8fF13NEVwI+1sWWblnWH6HF4ctTjycWmbDv6BZAvVj8SoOxh2ZtKNS X-Gm-Gg: AYBFou2VUzY56YwP63syMY3DSVHTx0M4xjzuwPgUOH17pJQpnrPQWiJ6sVQnOM37yqf ix/vrsB0IXz0fGyg6mWWJcwl1d1c/DGh9m3IH6mcmG/7kd7ilF8ULzVEjLLpisoFNjEIoMO4tfb 0tB/c6H9TnP4s+uw/jgRfQFEPZGWQLejz11nLwlMRtYFxZ+h0tmihpoWKoQQzwPQQfF03xWSZ6v yCwozzUclq3M+nLJh28irV0/gAI4dfmZ2S7hIdDCsEIMWZaPqV7fkYzDkVXiAej3fGpxHAeZwq7 coIhHZAuxmWsPrf2BuBgbRjgY5OcDj9yy1hJP6HL/MnhR4mUfzuKWaVaSW3FJvEOQ8Z42NPJIm2 lvwYAGIKJunAG5U75CsQHpr7ih6EtUfVYCTRmsvTG/7X6VDpoRIbgjxhXeVRyN/FbRHfSUxpm18 39VQuA3hJCu2UM0VEQ1ocx1oYiSl6xRzIFfOYVXZnVPo3ImyfQh/pI47TOGanHt1J99+mQ3Eg75 WjLPmExy/doexMLIIl5b5aRX/No7pt4BjqDIWanILA7ZHEXjc4nPYO8Hi7d676sT5tdI1iNUECF SO6zIF84J9PLha66OkEvzmfjeWk5WHWLY1+kynGSOTq3RdKMqQB9NRPsrVPTJdWjl0WAmXOx X-Received: by 2002:a05:6000:2c06:b0:48d:ed3c:4cdd with SMTP id ffacd0b85a97d-48ded3c5789mr1068940f8f.49.1791962588408; Wed, 14 Oct 2026 00:23:08 -0700 (PDT) Received: from navid-pc ([2a01:4b00:a856:6220::a11]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48de3f7f8b8sm8500933f8f.35.2026.10.14.00.23.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 00:23:07 -0700 (PDT) From: Navid Ghahremani To: linux-arm-kernel@lists.infradead.org Cc: arnd@arndb.de, stefandoesinger@gmail.com, krzk@kernel.org, Navid Ghahremani , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH v2 15/24] net: mdio: Add ZTE ZX279128S MDIO controller Date: Wed, 14 Oct 2026 08:20:55 +0100 Message-ID: <20261014072109.1759502-16-ghahramani.navid@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261014072109.1759502-1-ghahramani.navid@gmail.com> References: <20261014072109.1759502-1-ghahramani.navid@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Provide bounded Clause 22 transactions and managed clock and MDIO-bus registration. Signed-off-by: Navid Ghahremani --- drivers/net/mdio/Kconfig | 11 +++ drivers/net/mdio/Makefile | 1 + drivers/net/mdio/mdio-zx279128s.c | 157 ++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 drivers/net/mdio/mdio-zx279128s.c diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig index a05229838c..59812a082a 100644 --- a/drivers/net/mdio/Kconfig +++ b/drivers/net/mdio/Kconfig @@ -199,6 +199,17 @@ config MDIO_THUNDER ThunderX SoCs when the MDIO bus device appears as a PCI device. +config MDIO_ZX279128S + tristate "ZTE zx279128s MDIO bus controller" + depends on ARCH_ZTE || COMPILE_TEST + depends on HAS_IOMEM && OF_MDIO + help + This driver supports the MDIO controller of the ZTE zx279128s + SoC. It reaches the PHYs of the integrated switch and, on boards + such as the ZTE ZXHN H3600, an external PHY. + + To compile this driver as a module, choose M here. + menu "MDIO Multiplexers" config MDIO_BUS_MUX diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile index 0485867460..ce21e1496c 100644 --- a/drivers/net/mdio/Makefile +++ b/drivers/net/mdio/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o +obj-$(CONFIG_MDIO_ZX279128S) += mdio-zx279128s.o obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_BCM6368) += mdio-mux-bcm6368.o diff --git a/drivers/net/mdio/mdio-zx279128s.c b/drivers/net/mdio/mdio-zx279128s.c new file mode 100644 index 0000000000..fa0aab5b28 --- /dev/null +++ b/drivers/net/mdio/mdio-zx279128s.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ZTE zx279128s MDIO controller + * + * Copyright (C) 2026 Navid Ghahremani + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ZX_MDIO_DATA_WR 0x04 +#define ZX_MDIO_DATA_RD 0x08 +#define ZX_MDIO_CFG 0x0c +#define ZX_MDIO_STATUS 0x10 +#define ZX_MDIO_STATUS_DONE BIT(0) +#define ZX_MDIO_CMD 0x14 +#define ZX_MDIO_CMD_REG GENMASK(4, 0) +#define ZX_MDIO_CMD_ADDR GENMASK(9, 5) +#define ZX_MDIO_CMD_WR BIT(10) +#define ZX_MDIO_CMD_RD BIT(11) +#define ZX_MDIO_CMD_CLK_DIV BIT(12) +#define ZX_MDIO_CMD_BIT13 BIT(13) +#define ZX_MDIO_CMD_START BIT(14) +#define ZX_MDIO_CMD_BIT15 BIT(15) + +#define ZX_MDIO_POLL_US 10 +#define ZX_MDIO_TIMEOUT_US 2000 + +struct zx279128s_mdio { + void __iomem *base; +}; + +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); + + return 0; +} + +static int zx279128s_mdio_read(struct mii_bus *bus, int addr, int regnum) +{ + struct zx279128s_mdio *priv = bus->priv; + int ret; + + ret = zx279128s_mdio_xfer(bus, ZX_MDIO_CMD_RD, addr, regnum, 0); + if (ret) + return ret; + + return readl(priv->base + ZX_MDIO_DATA_RD) & 0xffff; +} + +static int zx279128s_mdio_write(struct mii_bus *bus, int addr, int regnum, + u16 val) +{ + return zx279128s_mdio_xfer(bus, ZX_MDIO_CMD_WR, addr, regnum, val); +} + +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"); + + val = readl(priv->base + ZX_MDIO_CMD); + val &= ~(ZX_MDIO_CMD_START | ZX_MDIO_CMD_BIT15 | ZX_MDIO_CMD_BIT13); + val |= ZX_MDIO_CMD_CLK_DIV; + writel(val, priv->base + ZX_MDIO_CMD); + writel(0, priv->base + ZX_MDIO_STATUS); + writel(0, priv->base + ZX_MDIO_CFG); + + bus->name = "zx279128s-mdio"; + bus->read = zx279128s_mdio_read; + bus->write = zx279128s_mdio_write; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); + bus->parent = dev; + + return devm_of_mdiobus_register(dev, bus, dev->of_node); +} + +static const struct of_device_id zx279128s_mdio_of_match[] = { + { .compatible = "zte,zx279128s-mdio" }, + { } +}; +MODULE_DEVICE_TABLE(of, zx279128s_mdio_of_match); + +static struct platform_driver zx279128s_mdio_driver = { + .probe = zx279128s_mdio_probe, + .driver = { + .name = "zx279128s-mdio", + .of_match_table = zx279128s_mdio_of_match, + }, +}; +module_platform_driver(zx279128s_mdio_driver); + +MODULE_AUTHOR("Navid Ghahremani "); +MODULE_DESCRIPTION("ZTE zx279128s MDIO controller driver"); +MODULE_LICENSE("GPL"); -- 2.55.0