From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qk1-f170.google.com (mail-qk1-f170.google.com [209.85.222.170]) (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 5B779398902 for ; Mon, 19 Oct 2026 03:01:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792378900; cv=none; b=cIrbp1T9byvjQvx/WU1aVU6HljQgHDEF1tqCjU++fFnRp31gUN3AMLZrsNbwLg/a5u3R8jwp138ywdkBUBxCB+ltutW94ANBMjABN90GaQnB+8PDK1aiVPh+ojXR5BJrGDHMsZ0SoQ1lbi1ngsHC7VtPG0CCUqdU/p3uZR9eV5s= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792378900; c=relaxed/simple; bh=g3I5FYgIeX7uxb/Cfoc/AEAx7kZPkkJbAgv5X7Cg99s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lamMPlAeuw9INSl8f3vM/4k/t8tn8W3YpfmpXydbdwB6aVvk8fdE8IGDdJ8taZhuwUYAqKIqFJD6jBQKz/oJSLbxNFvMnpwhV71yFytG0XzCxfV89VNEmpP/TMEx8KrDkT5FR96rqET5sIuK0yVM6nA7ldV8C5CSpc1Or2crXoM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=riscstar.com; spf=pass smtp.mailfrom=riscstar.com; dkim=pass (2048-bit key) header.d=riscstar-com.20251104.gappssmtp.com header.i=@riscstar-com.20251104.gappssmtp.com header.b=Rd0JfPaD; arc=none smtp.client-ip=209.85.222.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=riscstar.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=riscstar.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=riscstar-com.20251104.gappssmtp.com header.i=@riscstar-com.20251104.gappssmtp.com header.b="Rd0JfPaD" Received: by mail-qk1-f170.google.com with SMTP id af79cd13be357-93f079a63b8so157622585a.3 for ; Sun, 18 Oct 2026 20:01:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=riscstar-com.20251104.gappssmtp.com; s=20251104; t=1792378897; x=1792983697; 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=R5TeWWNtJggGTTz6M8A9FjvcqNzl7loaYSyNhUw4yhc=; b=Rd0JfPaDo5lXdChKvRJbyuRl1KfFof78opAI5/2c++af0OTYTN0XVBu3Jh90Eu6wBt 6aCskj8ElMhWcRWjkdUbJ0N41Rlrn9B8Lmnl6zwyFHWA+jlyu8XfmZdvkwd5Z7oppRIi IMiPg2aFBzJStBMGbS/Z/GhdWM76IiU2CtcBO8jb/GExL4K12pg8Ox+gBG1XRXZh8D9G vx55m7Zm0rpfWFgj/qsuCoDUDGZBlQbIbRvJ+P7NXE0FBKduXDt1PE9BXVfU9nsqdKcx FRvUUUiZyEf3ACjNlmIztRmuAwBRgBaEYC76sizfAmAReGYe5nMaFqLi7mnDK8EszsSm R4Bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792378897; x=1792983697; 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=R5TeWWNtJggGTTz6M8A9FjvcqNzl7loaYSyNhUw4yhc=; b=wLM+YxDMbSuKVIh/7anUkHMecOgjyq8WUTVsA/bGwnysvfLYCfuOb3sOJt8+480HXF ktm5GAH+g8cjaNX+kbWI/346zdDD2372Zz9IUb/BVnebM0l6ykItQJV0plJDA4LdGr8k bzyMRaNRNnfXP8NHMbnSC6k26KCJgM4fKgNt8fC6HyxBUZkcrqSG+dbfDcCKGlUX1sxA k2rIqalyfj2l7/sb6aNi8E6R7kne9S5pHxZsXwSDql0MM4R8UbzLERKgoXY/LJQK9AQC esSc0pJN+2hIcKTgOO+f8Ut5pqd5EdRuhgP3CwZEMsr7daao4eC3ZwQfrzAN85DKEptX d34g== X-Forwarded-Encrypted: i=1; AKwUvByX9XT4mFyG7SPpvCLrVeZEwNCVxBvbOFsjJEVw/gOgKPlevXRbMyHvZk3C0wcAIZ33sKY//z1tuDz2@vger.kernel.org X-Gm-Message-State: AFq9FYJvRKfqbYfKPJyX0mfAWepsJYeNP3BmgW5M2cLfnvxN6Lxz5RWm qtThdy8xL7dKF0/zA7AFuJxOde966fAClGbQigQvV+1Srt2uvaYBrV9nJqFozBfjdsU= X-Gm-Gg: AYBFou2A+s6bSRzfYLHAWNBChIxpgY0HlbgZvJc2zi4ut2CeqDz4YQzDKtZ9yGykQXX drvPi2j0kgClaP6eWL7QWDZCvT1qUZaSMXRCS3OXZXVeCJ6bAZbDEL/vbOiMdeXNvlzDes+b6+M TwBo+3oimYKEvhVO8o3BehdYV+amrISLoovnnFX/BNgt7khewlWI1izWFL5w/q9U4vV3SYajsJm yD5G8IrtHsxYu2b7BXLaSQVmBSVaon+xMJvgWBwFl+5zHFM4YYIlicIR7LEvzIpZFH2O1j+s1Sr Xd5XKXAKd9A7FfYMgD/f7G6u7b5cehbOsNuWOBYNf4EsHEs/X+FfE/LLeBVNnBBH8rxjyo2rCUE LV82EeIBrxFWGTxoJmtS5q5bDiBpGfiO3I0Nin2Fn9BKlKrxaVu4QYO5w3lWCK544wxJxy76GmR LRnKp1kYxVbEGF3GUvsEAFTHYlHsprvZAhc8cTZvwMUzpxEpQBQnb2T1cLQ1EsbJE+/wOFX3NlP wQ2I5HK+oo9wA== X-Received: by 2002:a05:620a:8812:b0:93e:fa30:f1dd with SMTP id af79cd13be357-93f29dac9e9mr998353385a.70.1792378897136; Sun, 18 Oct 2026 20:01:37 -0700 (PDT) Received: from zippy.localdomain ([73.62.185.64]) by smtp.gmail.com with ESMTPSA id af79cd13be357-93f3c61c440sm216840185a.10.2026.10.18.20.01.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 18 Oct 2026 20:01:36 -0700 (PDT) From: Alex Elder To: maxime.chevallier@bootlin.com, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@kernel.org, kuba@kernel.org, pabeni@redhat.com, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: Daniel Thompson , mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, hkallweit1@gmail.com, linux@armlinux.org.uk, richardcochran@gmail.com, p.zabel@pengutronix.de, peppe.cavallaro@st.com, joabreu@synopsys.com, mohd.anwar@oss.qualcomm.com, lorenzo.bianconi@oss.qualcomm.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 2/5] net: pcs: pcs-xpcs-regmap: support XPCS memory-mapped MDIO bus via regmap Date: Sun, 18 Oct 2026 22:01:25 -0500 Message-ID: <20261019030129.1470307-3-elder@riscstar.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261019030129.1470307-1-elder@riscstar.com> References: <20261019030129.1470307-1-elder@riscstar.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Daniel Thompson In some DesignWare XPCS implementations the memory-mapped MDIO bus is allocated to a register window that does not align to a page boundary. This makes iomapping the registers problematic. For example the Toshiba TC9564 (a PCIe Ethernet-AVB/TSN bridge) provides an "eMAC" subsystem with the XPCS base address cuddled up to XGMAC registers. Let's introduce helpers to allow the driver that owns the eMAC to register an XPCS using is regmap for the memory-mapped MDIO bus. Signed-off-by: Daniel Thompson Co-developed-by: Alex Elder Signed-off-by: Alex Elder --- MAINTAINERS | 2 + drivers/net/pcs/Makefile | 3 +- drivers/net/pcs/pcs-xpcs-regmap.c | 169 ++++++++++++++++++++++++++++ include/linux/pcs/pcs-xpcs-regmap.h | 13 +++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 drivers/net/pcs/pcs-xpcs-regmap.c create mode 100644 include/linux/pcs/pcs-xpcs-regmap.h diff --git a/MAINTAINERS b/MAINTAINERS index 55ead3d1007a8..972c9faead5b3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -27148,8 +27148,10 @@ F: drivers/net/ethernet/synopsys/ SYNOPSYS DESIGNWARE ETHERNET XPCS DRIVER L: netdev@vger.kernel.org S: Orphan +F: drivers/net/pcs/pcs-xpcs-regmap.c F: drivers/net/pcs/pcs-xpcs.c F: drivers/net/pcs/pcs-xpcs.h +F: include/linux/pcs/pcs-xpcs-regmap.h F: include/linux/pcs/pcs-xpcs.h SYNOPSYS DESIGNWARE HDMI RX CONTROLLER DRIVER diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile index 4f7920618b900..088d35f21a4c3 100644 --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile @@ -2,7 +2,8 @@ # Makefile for Linux PCS drivers pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-plat.o \ - pcs-xpcs-nxp.o pcs-xpcs-wx.o + pcs-xpcs-nxp.o pcs-xpcs-regmap.o \ + pcs-xpcs-wx.o obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o diff --git a/drivers/net/pcs/pcs-xpcs-regmap.c b/drivers/net/pcs/pcs-xpcs-regmap.c new file mode 100644 index 0000000000000..f3f3aaaf0b75a --- /dev/null +++ b/drivers/net/pcs/pcs-xpcs-regmap.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Synopsys DesignWare XPCS regmap helpers + * + * Copyright (C) 2026 RISCstar Solutions. + * Copyright (C) 2024 Serge Semin + */ + +#include +#include +#include +#include +#include +#include + +#include "pcs-xpcs.h" + +/* Page select register for the indirect MMIO CSRs access */ +#define DW_VR_CSR_VIEWPORT 0xff + +static ptrdiff_t xpcs_regmap_addr_format(int dev, int reg) +{ + return FIELD_PREP(0x1f0000, dev) | FIELD_PREP(0xffff, reg); +} + +static u16 xpcs_regmap_addr_page(ptrdiff_t csr) +{ + return FIELD_GET(0x1fff00, csr); +} + +static ptrdiff_t xpcs_regmap_addr_offset(ptrdiff_t csr) +{ + return FIELD_GET(0xff, csr); +} + +static int +xpcs_regmap_read_reg_indirect(struct regmap *regmap, int dev, int reg) +{ + ptrdiff_t csr, ofs; + unsigned int val; + u16 page; + int res; + + csr = xpcs_regmap_addr_format(dev, reg); + page = xpcs_regmap_addr_page(csr); + ofs = xpcs_regmap_addr_offset(csr); + + res = regmap_write(regmap, DW_VR_CSR_VIEWPORT, page); + if (res < 0) + return res; + + res = regmap_read(regmap, ofs, &val); + if (res < 0) + return res; + + return val & 0xffff; +} + +static int +xpcs_regmap_write_reg_indirect(struct regmap *regmap, int dev, int reg, u16 val) +{ + ptrdiff_t csr, ofs; + u16 page; + int res; + + csr = xpcs_regmap_addr_format(dev, reg); + page = xpcs_regmap_addr_page(csr); + ofs = xpcs_regmap_addr_offset(csr); + + res = regmap_write(regmap, DW_VR_CSR_VIEWPORT, page); + if (res < 0) + return res; + + return regmap_write(regmap, ofs, val); +} + +static int xpcs_regmap_read_c22(struct mii_bus *bus, int addr, int reg) +{ + struct regmap *regmap = bus->priv; + + if (addr != 0) + return -ENODEV; + + return xpcs_regmap_read_reg_indirect(regmap, MDIO_MMD_VEND2, reg); +} + +static int +xpcs_regmap_write_c22(struct mii_bus *bus, int addr, int reg, u16 val) +{ + struct regmap *regmap = bus->priv; + + if (addr != 0) + return -ENODEV; + + return xpcs_regmap_write_reg_indirect(regmap, MDIO_MMD_VEND2, reg, val); +} + +static int xpcs_regmap_read_c45(struct mii_bus *bus, int addr, int dev, int reg) +{ + struct regmap *regmap = bus->priv; + + if (addr != 0) + return -ENODEV; + + return xpcs_regmap_read_reg_indirect(regmap, dev, reg); +} + +static int xpcs_regmap_write_c45(struct mii_bus *bus, int addr, int dev, + int reg, u16 val) +{ + struct regmap *regmap = bus->priv; + + if (addr != 0) + return -ENODEV; + + return xpcs_regmap_write_reg_indirect(regmap, dev, reg, val); +} + +static void devm_xpcs_regmap_destroy(void *data) +{ + struct dw_xpcs *xpcs = data; + + xpcs_destroy(xpcs); +} + +struct dw_xpcs *devm_xpcs_regmap_register(struct device *dev, + struct regmap *regmap) +{ + static atomic_t id = ATOMIC_INIT(-1); + struct dw_xpcs *xpcs; + struct mii_bus *bus; + int ret; + + bus = devm_mdiobus_alloc_size(dev, 0); + if (!bus) + return ERR_PTR(-ENOMEM); + + bus->name = "DW XPCS MCI/APB3"; + bus->read = xpcs_regmap_read_c22; + bus->write = xpcs_regmap_write_c22; + bus->read_c45 = xpcs_regmap_read_c45; + bus->write_c45 = xpcs_regmap_write_c45; + bus->phy_mask = ~0; + bus->parent = dev; + bus->priv = regmap; + + snprintf(bus->id, sizeof(bus->id), "dwxpcs-%x", atomic_inc_return(&id)); + + /* MDIO-bus here serves as just a back-end engine abstracting out + * the MDIO and MCI/APB3 IO interfaces utilized for the DW XPCS CSRs + * access. + */ + ret = devm_mdiobus_register(dev, bus); + if (ret) { + dev_err(dev, "failed to create MDIO bus\n"); + return ERR_PTR(ret); + } + + xpcs = xpcs_create_mdiodev(bus, 0); + if (IS_ERR(xpcs)) + return xpcs; + + ret = devm_add_action_or_reset(dev, devm_xpcs_regmap_destroy, xpcs); + if (ret) + return ERR_PTR(ret); + + return xpcs; +} +EXPORT_SYMBOL_GPL(devm_xpcs_regmap_register); diff --git a/include/linux/pcs/pcs-xpcs-regmap.h b/include/linux/pcs/pcs-xpcs-regmap.h new file mode 100644 index 0000000000000..c6d934b1054ed --- /dev/null +++ b/include/linux/pcs/pcs-xpcs-regmap.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __LINUX_PCS_XPCS_REGMAP_H +#define __LINUX_PCS_XPCS_REGMAP_H + +struct device; +struct regmap; +struct dw_xpcs; + +struct dw_xpcs *devm_xpcs_regmap_register(struct device *dev, + struct regmap *regmap); + +#endif /* __LINUX_PCS_XPCS_REGMAP_H */ -- 2.53.0