Netdev List
 help / color / mirror / Atom feed
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
To: Alex Elder <elder@riscstar.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 <daniel@riscstar.com>,
	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: Re: [PATCH net-next 5/5] net: stmmac: support the TC9564 SoC
Date: Mon, 19 Oct 2026 09:52:58 +0200	[thread overview]
Message-ID: <3d0b17c6-3b94-4e36-b7bc-700211c83273@bootlin.com> (raw)
In-Reply-To: <20261019030129.1470307-6-elder@riscstar.com>

Hi Alex,

On 10/19/26 05:01, Alex Elder wrote:
> From: Daniel Thompson <daniel@riscstar.com>
> 
> Add support for the Ethernet XGMAC functionality present in the
> Toshiba TC9564 SoC.
> 
> The TC9564 is a fairly complex chip that attaches to a host via
> the upstream port of a PCIe switch it implements.  That switch
> has three downstream ports, and one of those has an embedded PCI
> endpoint.  The PCI endpoint implements two PCI functions, and a
> 10 Gbps-capable XGMAC interface is attached to each.
> 
> The TC9564 implements additional peripherals, and access to them
> is provided by a PCI endpoint bus associated with BAR 4 of the
> first PCI function.  A PCI driver sets up the PCI function for
> use, and peripherals using the bus use platform drivers, matched
> by compatible string.
> 
> We use the pci-ep-bus approach for the stmmac driver as well, with
> each PCI function exposing access to its BAR 4 via an endpoint bus.
> The XGMAC device is defined within a pci-ep-bus node, and is bound
> to the platform driver based on its compatible string.
> 
> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
> Co-developed-by: Alex Elder <elder@riscstar.com>
> Signed-off-by: Alex Elder <elder@riscstar.com>
> ---
>  MAINTAINERS                                   |   1 +
>  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
>  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
>  .../ethernet/stmicro/stmmac/dwmac-tc9564.c    | 590 ++++++++++++++++++
>  4 files changed, 603 insertions(+)
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-tc9564.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 972c9faead5b3..69f301aa26eb9 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -28313,6 +28313,7 @@ M:	Alex Elder <elder@kernel.org>
>  M:	Daniel Thompson <danielt@kernel.org>
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/net/toshiba,tc9564-dwmac.yaml
> +F:	drivers/net/ethernet/stmicro/stmmac/dwmac-tc9564.c
>  
>  TOSHIBA WMI HOTKEYS DRIVER
>  M:	Azael Avalos <coproscefalo@gmail.com>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index ab3c4cf964239..5613921188df4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -363,6 +363,17 @@ config DWMAC_LOONGSON1
>  	  device driver. This driver is used for Loongson1-based boards
>  	  like Loongson LS1B/LS1C.
>  
> +config DWMAC_TC9564
> +	tristate "Toshiba TC9564 DWMAC support"
> +	depends on OF && COMMON_CLK && TC9564_PCI
> +	default TC9564_PCI
> +	help
> +	  Support for the Ethernet controllers on the Toshiba TC9564.
> +
> +	  This enables glue layer support in the stmmac driver support
> +	  for the Toshiba TC9564.  This chip implements two embedded
> +	  PCIe functions, each of which has an XGMAC interface.
> +
>  config DWMAC_TEGRA
>  	tristate "NVIDIA Tegra MGBE support"
>  	depends on ARCH_TEGRA || COMPILE_TEST
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index b16a456b730ec..c4de25db93715 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -52,4 +52,5 @@ obj-$(CONFIG_STMMAC_PCI)	+= stmmac-pci.o
>  obj-$(CONFIG_DWMAC_INTEL)	+= dwmac-intel.o
>  obj-$(CONFIG_DWMAC_LOONGSON)	+= dwmac-loongson.o
>  obj-$(CONFIG_DWMAC_MOTORCOMM)	+= dwmac-motorcomm.o
> +obj-$(CONFIG_DWMAC_TC9564)	+= dwmac-tc9564.o
>  stmmac-pci-objs:= stmmac_pci.o
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tc9564.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tc9564.c
> new file mode 100644
> index 0000000000000..21098f91e3bbf
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tc9564.c
> @@ -0,0 +1,590 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Copyright (C) 2026 by RISCstar Solutions Corporation.  All rights reserved.
> + *
> + * Derived from code having the following copyrights:
> + * Copyright (C) 2011-2012  Vayavya Labs Pvt Ltd
> + * Copyright (C) 2025 Toshiba Electronic Devices & Storage Corporation
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/iopoll.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/pcs/pcs-xpcs-regmap.h>
> +#include <linux/pcs/pcs-xpcs.h>
> +#include <linux/phy.h>
> +#include <linux/regmap.h>
> +#include <linux/stmmac.h>
> +#include <linux/types.h>
> +#include <linux/units.h>
> +
> +#include "common.h"
> +#include "dwxgmac2.h"
> +#include "stmmac.h"
> +#include "stmmac_platform.h"
> +
> +#define DRIVER_NAME			"dwmac-tc9564"
> +
> +/* Start of range representing PCI space on the TC9564 internal bus */
> +#define TC9564_SLV00_SRC_ADDR		0x0000001000000000ULL
> +
> +#define TC9564_PTP_CLOCK_RATE		(250 * HZ_PER_MHZ)
> +
> +#define TC9564_RX_FIFO_SIZE		(46 * SZ_1K)
> +#define TC9564_TX_FIFO_SIZE		(46 * SZ_1K)
> +
> +/* Fields and values for the EMACTL registers */
> +#define EMAC_SP_SEL_MASK		GENMASK(3, 0)
> +#define SP_SEL_2500BASEX		4
> +#define SP_SEL_SGMII_1000M		5
> +#define SP_SEL_SGMII_100M		6
> +#define SP_SEL_SGMII_10M		7
> +#define EMAC_PHY_INF_SEL_MASK		GENMASK(5, 4)
> +#define PCS_CLK_PHY			1	/* Clock from PHY */
> +#define EMAC_INV_SGM_SIG_DET		BIT(6)	/* 1 = polarity inverted */
> +#define EMAC_LPIHWCLKEN			BIT(8)	/* 1 = low power mode */
> +#define EMAC_INIT_DONE			BIT(21)
> +
> +/* Offset to the XPCS memory block, relative to the EMAC address range */
> +#define DWMAC_XPCS_OFFSET		0x3a00
> +
> +/* Offset to the PMATOP memory block, relative to the EMAC address range */
> +#define DWMAC_PMATOP_OFFSET			0x4000
> +
> +#define PMA_CML_GL_PM_CFG0			0x01b8
> +
> +/*
> + * Five sets three registers must be configured for PMA.  The HWT_REFCLK
> + * registers are each separated by 0x14 bytes.  The Common0 configuration
> + * registers are separated by 0x8 bytes.
> + */
> +#define PMA_REG_COUNT				5
> +
> +#define PMA_HWT_REFCK_R_EN			0x1080
> +#define PMA_HWT_REFCK_TERM_EN			0x1090
> +#define PMA_HWT_REFCK_STRIDE			0x0014
> +
> +#define PMA_COMM_CFG_0_1			0x1888
> +#define PMA_COMM_CFG_0_1_STRIDE			0x0008
> +
> +/* PMA_COMM_CFG_0_1 fields (WRITE_MASK is a field name) */
> +#define COMM_CFG_WRITE_MASK_MASK		GENMASK(16, 9)
> +#define WRITE_MASK_VALUE			0xf7	/* Power-on value */
> +#define COMM_CFG_ENABLE				BIT(8)
> +#define COMM_CFG_WRITE_DATA_MASK		GENMASK(7, 0)
> +#define WRITE_DATA_VALUE			0x04	/* Power-on value */
> +
> +enum {
> +	RESET_ID_MAC,
> +	RESET_ID_XPCS,
> +	RESET_ID_PMA,
> +};
> +
> +static const char * const tc9564_reset_names[] = {
> +	[RESET_ID_MAC] = "mac",
> +	[RESET_ID_XPCS] = "xpcs",
> +	[RESET_ID_PMA] = "pma",
> +};
> +
> +/**
> + * struct tc9564_data - Toshiba-specific platform data
> + * @dev:		Device pointer
> + * @ioaddr:		Pointer to mapped eMAC memory
> + * @plat:		Pointer to our stmmac platform data
> + * @resets:		Reset controller bulk array
> + * @clocks:		Clock controller bulk array
> + * @clock_count:	Number of valid elements in the clock array
> + * @config_regmap:	Regmap used to access eMAC configuration registers
> + * @emac_ctl_offset:	Offset of the eMAC control register within the regmap
> + * @res:		Structure passed to stmmac_dvr_probe()
> + * @desc:		DMA descriptor data used by mac_device_info
> + * @dma:		DMA operations data used by mac_device_info
> + */
> +struct tc9564_data {
> +	struct device *dev;
> +	void __iomem *ioaddr;
> +	struct plat_stmmacenet_data *plat;
> +	struct reset_control_bulk_data resets[ARRAY_SIZE(tc9564_reset_names)];
> +	struct clk_bulk_data *clocks;
> +	u32 clock_count;
> +
> +	struct regmap *config_regmap;
> +	u32 emac_ctl_offset;
> +
> +	/* This field is data passed to stmmac_dvr_probe() */
> +	struct stmmac_resources res;
> +
> +	/* These two fields are used by the mac_device_info structure */
> +	struct stmmac_desc_ops desc;
> +	struct stmmac_dma_ops dma;
> +};
> +
> +struct tc9564_mac_speed {
> +	phy_interface_t phy_interface;
> +	int speed;
> +	u32 sp_sel;
> +};
> +
> +static struct tc9564_mac_speed mac_speed[] = {
> +	{ PHY_INTERFACE_MODE_2500BASEX,	SPEED_2500,  SP_SEL_2500BASEX },
> +	{ PHY_INTERFACE_MODE_SGMII,	SPEED_1000,  SP_SEL_SGMII_1000M },
> +	{ PHY_INTERFACE_MODE_SGMII,	SPEED_100,   SP_SEL_SGMII_100M },
> +	{ PHY_INTERFACE_MODE_SGMII,	SPEED_10,    SP_SEL_SGMII_10M },
> +};
> +
> +/* TC9564 uses indirect addressing so this need only describe a 1KiB range */
> +static const struct regmap_config xpcs_regmap_config = {
> +	.reg_bits	= 32,
> +	.val_bits	= 32,
> +	.reg_base	= 0x00,		/* Minimum XPCS reg offset */
> +	.max_register	= 0xff,		/* Register DW_VR_CSR_VIEWPORT */
> +	.reg_shift	= REGMAP_UPSHIFT(2),
> +};
> +
> +/**
> + * tc9564_pma_init() - Initialize PMA
> + * @td:	bsp_priv pointer
> + *
> + * Initialize (or re-initialize) the PMA, configure the clocks and wait for the
> + * eMAC to be ready.
> + */
> +static void tc9564_pma_init(struct tc9564_data *td)
> +{
> +	struct reset_control *rstc = td->resets[RESET_ID_PMA].rstc;
> +	struct regmap *regmap = td->config_regmap;
> +	void __iomem *pmatop;
> +	u32 val;
> +	int ret;
> +	u32 i;
> +
> +	/*
> +	 * When we re-initialize the PMA then the reset will already have
> +	 * been deasserted. We must make sure the PMA reset is asserted
> +	 * before we change the clock settings.
> +	 */
> +	WARN_ON(reset_control_assert(rstc));
> +
> +	pmatop = td->res.addr + DWMAC_PMATOP_OFFSET;
> +
> +	/* Power on CML buffer (0 = normal mode, 1 = power down) */
> +	writel(0, pmatop + PMA_CML_GL_PM_CFG0);
> +
> +	/* This value switches clock from C0_REFCK to CLK_REF_I */
> +	val = u32_encode_bits(WRITE_MASK_VALUE, COMM_CFG_WRITE_MASK_MASK);
> +	val |= COMM_CFG_ENABLE;
> +	val |= u32_encode_bits(WRITE_DATA_VALUE, COMM_CFG_WRITE_DATA_MASK);
> +
> +	for (i = 0; i < PMA_REG_COUNT; i++) {
> +		u32 offset =  i * PMA_HWT_REFCK_STRIDE;
> +
> +		/* Disable C0_REFCK and 100 ohm termination */
> +		writel(0, pmatop + PMA_HWT_REFCK_R_EN + offset);
> +		writel(0, pmatop + PMA_HWT_REFCK_TERM_EN + offset);
> +
> +		/* Switch clock from C0_REFCK to CLK_REF_I */
> +		offset =  i * PMA_COMM_CFG_0_1_STRIDE;
> +		writel(val, pmatop + PMA_COMM_CFG_0_1 + offset);
> +	}
> +
> +	WARN_ON(reset_control_deassert(rstc));
> +
> +	ret = regmap_read_poll_timeout(regmap, td->emac_ctl_offset,
> +				       val, val & EMAC_INIT_DONE, 50, 1000000);
> +	WARN(ret, "timeout waiting for MAC init done\n");

This is too many WARN_ON / WARN, there's 3 just in this function. At least use
WARN_ON_ONCE, or maybe better 	print a log with pr_warn / dev_warn ?

> +}
> +
> +static int tc9564_mac_speed_select(struct tc9564_data *td,
> +				   phy_interface_t interface, int speed)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(mac_speed); i++) {
> +		if (mac_speed[i].phy_interface != interface)
> +			continue;
> +
> +		if (speed == mac_speed[i].speed || speed == SPEED_UNKNOWN)
> +			return mac_speed[i].sp_sel;
> +	}
> +	dev_err(td->dev, "%s/%d unsupported\n", phy_modes(interface), speed);

Is that "mac_speed" lookup table actually needed ? maybe a simpler switch/case
based on the speed alone would be enough, or do we really need to validate
the phy_interface_t each time ?

> +
> +	return -EOPNOTSUPP;
> +}
> +
> +static void tc9564_mac_configure(struct tc9564_data *td,
> +				 phy_interface_t interface, int speed)
> +{
> +	struct regmap *regmap = td->config_regmap;
> +	u32 offset = td->emac_ctl_offset;
> +	int sp_sel;
> +	u32 val;
> +
> +	sp_sel = tc9564_mac_speed_select(td, interface, speed);
> +	if (sp_sel < 0)
> +		return;
> +
> +	/* No error checking needed for MMIO regmap */
> +	regmap_read(regmap, offset, &val);
> +	val |= EMAC_LPIHWCLKEN;
> +	val &= ~EMAC_INV_SGM_SIG_DET;
> +	val = u32_replace_bits(val, PCS_CLK_PHY, EMAC_PHY_INF_SEL_MASK);
> +	val = u32_replace_bits(val, sp_sel, EMAC_SP_SEL_MASK);
> +	regmap_write(regmap, offset, val);
> +}
> +
> +static void tc9564_mac_enable(struct tc9564_data *td)
> +{
> +	WARN_ON(clk_bulk_prepare_enable(td->clock_count, td->clocks));
> +
> +	WARN_ON(reset_control_deassert(td->resets[RESET_ID_MAC].rstc));
> +
> +	tc9564_mac_configure(td, td->plat->phy_interface, SPEED_UNKNOWN);
> +	tc9564_pma_init(td);
> +
> +	WARN_ON(reset_control_deassert(td->resets[RESET_ID_XPCS].rstc));

Too many warns :)

> +}
> +
> +static void tc9564_mac_disable(struct tc9564_data *td)
> +{
> +	WARN_ON(reset_control_bulk_assert(ARRAY_SIZE(td->resets), td->resets));

same

Maxime

  reply	other threads:[~2026-10-19  7:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-19  3:01 [PATCH net-next 0/5] net: stmmac: enable Toshiba TC9564 Alex Elder
2026-10-19  3:01 ` [PATCH net-next 1/5] dt-bindings: net: add support for " Alex Elder
2026-10-19 12:41   ` Andrew Lunn
2026-10-19  3:01 ` [PATCH net-next 2/5] net: pcs: pcs-xpcs-regmap: support XPCS memory-mapped MDIO bus via regmap Alex Elder
2026-10-19  3:01 ` [PATCH net-next 3/5] net: stmmac: dwxgmac2: Add XGMAC 3.01a support Alex Elder
2026-10-19  7:58   ` Maxime Chevallier
2026-10-19  3:01 ` [PATCH net-next 4/5] net: stmmac: dwxgmac2: export symbols for XGMAC 3.01a DMA Alex Elder
2026-10-19  3:01 ` [PATCH net-next 5/5] net: stmmac: support the TC9564 SoC Alex Elder
2026-10-19  7:52   ` Maxime Chevallier [this message]
2026-10-19  9:14   ` Mohd Ayaan Anwar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3d0b17c6-3b94-4e36-b7bc-700211c83273@bootlin.com \
    --to=maxime.chevallier@bootlin.com \
    --cc=alexandre.torgue@foss.st.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=conor+dt@kernel.org \
    --cc=daniel@riscstar.com \
    --cc=davem@davemloft.net \
    --cc=devicetree@vger.kernel.org \
    --cc=edumazet@kernel.org \
    --cc=elder@riscstar.com \
    --cc=hkallweit1@gmail.com \
    --cc=joabreu@synopsys.com \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=linux@armlinux.org.uk \
    --cc=lorenzo.bianconi@oss.qualcomm.com \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=mohd.anwar@oss.qualcomm.com \
    --cc=netdev@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=pabeni@redhat.com \
    --cc=peppe.cavallaro@st.com \
    --cc=richardcochran@gmail.com \
    --cc=robh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox