The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] net: dsa: sja1105: Add rev-rmii support sja1110 devices
@ 2026-06-08 14:16 Martijn de Gouw
  2026-06-10  1:59 ` Jakub Kicinski
  0 siblings, 1 reply; 3+ messages in thread
From: Martijn de Gouw @ 2026-06-08 14:16 UTC (permalink / raw)
  To: Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Martijn de Gouw, linux-kernel, netdev

When a rmii port is used in phy-mode (rev-rmii), the ref_clk is an input on
the rx clk pin. Configure both the rx and tx clock source to use the
rx_clk as external clock source input.

Signed-off-by: Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com>
---
 drivers/net/dsa/sja1105/sja1105.h          |   1 +
 drivers/net/dsa/sja1105/sja1105_clocking.c | 197 +++++++++++++++++++++
 drivers/net/dsa/sja1105/sja1105_spi.c      |   8 +-
 3 files changed, 204 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index dceb96ae9c83d..012632533cb68 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -368,6 +368,7 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port);
 int sja1110_setup_rgmii_delay(const void *ctx, int port);
 int sja1105_clocking_setup_port(struct sja1105_private *priv, int port);
 int sja1105_clocking_setup(struct sja1105_private *priv);
+int sja1110_clocking_setup(struct sja1105_private *priv);
 int sja1110_disable_microcontroller(struct sja1105_private *priv);
 
 /* From sja1105_ethtool.c */
diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c
index 08a3e7b962541..826bfd01e0b71 100644
--- a/drivers/net/dsa/sja1105/sja1105_clocking.c
+++ b/drivers/net/dsa/sja1105/sja1105_clocking.c
@@ -6,6 +6,7 @@
 #include "sja1105.h"
 
 #define SJA1105_SIZE_CGU_CMD	4
+#define SJA1105_SIZE_ACU_CMD	4
 #define SJA1110_BASE_MCSS_CLK	SJA1110_CGU_ADDR(0x70)
 #define SJA1110_BASE_TIMER_CLK	SJA1110_CGU_ADDR(0x74)
 
@@ -36,6 +37,29 @@ struct sja1105_cfg_pad_mii_id {
 	u64 txc_pd;
 };
 
+struct sja1110_pin_cfg_mii_tx {
+	u64 d32_ods;
+	u64 d32_pupd;
+	u64 d10_ods;
+	u64 d10_pupd;
+	u64 ctrl_ods;
+	u64 ctrl_pupd;
+	u64 clk_pol;
+	u64 clk_src;
+	u64 clk_ods;
+	u64 clk_pupd;
+};
+
+struct sja1110_pin_cfg_mii_rx {
+	u64 d32_pupd;
+	u64 d10_pupd;
+	u64 ctrl_pupd;
+	u64 clk_pol;
+	u64 clk_src;
+	u64 clk_ods;
+	u64 clk_pupd;
+};
+
 /* UM10944 Table 82.
  * IDIV_0_C to IDIV_4_C control registers
  * (addr. 10000Bh to 10000Fh)
@@ -820,6 +844,179 @@ int sja1105_clocking_setup(struct sja1105_private *priv)
 	return 0;
 }
 
+static void
+sja1110_acu_pin_cfg_mii_tx_packing(void *buf, struct sja1110_pin_cfg_mii_tx *cmd,
+				   enum packing_op op)
+{
+	const int size = 4;
+
+	sja1105_packing(buf, &cmd->d32_ods,   28, 27, size, op);
+	sja1105_packing(buf, &cmd->d32_pupd,  25, 24, size, op);
+	sja1105_packing(buf, &cmd->d10_ods,   20, 19, size, op);
+	sja1105_packing(buf, &cmd->d10_pupd,  17, 16, size, op);
+	sja1105_packing(buf, &cmd->ctrl_ods,  12, 11, size, op);
+	sja1105_packing(buf, &cmd->ctrl_pupd,  9,  8, size, op);
+	sja1105_packing(buf, &cmd->clk_pol,    7,  7, size, op);
+	sja1105_packing(buf, &cmd->clk_src,    6,  5, size, op);
+	sja1105_packing(buf, &cmd->clk_ods,    4,  3, size, op);
+	sja1105_packing(buf, &cmd->clk_pupd,   1,  0, size, op);
+}
+
+static int sja1110_acu_rmii_ext_tx_clk_config(struct sja1105_private *priv,
+					      int port)
+{
+	const struct sja1105_regs *regs = priv->info->regs;
+	struct sja1110_pin_cfg_mii_tx pin_cfg_mii_tx = {0};
+	u8 packed_buf[SJA1105_SIZE_ACU_CMD] = {0};
+
+	if (regs->pad_mii_tx[port] == SJA1105_RSV_ADDR)
+		return 0;
+
+	/* Payload */
+	pin_cfg_mii_tx.d32_ods   = 2; /* TXD[3:2] output stage drive-strength: */
+				      /*   FAST Medium noise / Fast speed (default) */
+	pin_cfg_mii_tx.d32_pupd  = 2; /* TXD[3:2] pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	pin_cfg_mii_tx.d10_ods   = 2; /* TXD[1:0] output stage drive-strength: */
+				      /*   FAST Medium noise / Fast speed (default) */
+	pin_cfg_mii_tx.d10_pupd  = 2; /* TXD[1:0] pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	pin_cfg_mii_tx.ctrl_ods  = 2; /* TX_EN / TX_ER output stage drive-strength: */
+				      /*   FAST Medium noise / Fast speed (default) */
+	pin_cfg_mii_tx.ctrl_pupd = 2; /* TX_EN / TX_ER (weak) pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	pin_cfg_mii_tx.clk_pol   = 0; /* TX_CLK output polarity: */
+				      /*   NORMAL Not inverted (default) */
+	pin_cfg_mii_tx.clk_src   = 3; /* TX_CLK source: */
+				      /*   RXC RX_CLK used */
+	pin_cfg_mii_tx.clk_ods   = 2; /* TX_CLK output stage drive-strength: */
+				      /*   FAST Medium noise / Fast speed (default) */
+	pin_cfg_mii_tx.clk_pupd  = 2; /* TX_CLK (weak) pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	sja1110_acu_pin_cfg_mii_tx_packing(packed_buf, &pin_cfg_mii_tx, PACK);
+
+	return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_tx[port],
+				packed_buf, SJA1105_SIZE_ACU_CMD);
+}
+
+static void
+sja1110_acu_pin_cfg_mii_rx_packing(void *buf, struct sja1110_pin_cfg_mii_rx *cmd,
+				   enum packing_op op)
+{
+	const int size = 4;
+
+	sja1105_packing(buf, &cmd->d32_pupd,  25, 24, size, op);
+	sja1105_packing(buf, &cmd->d10_pupd,  17, 16, size, op);
+	sja1105_packing(buf, &cmd->ctrl_pupd,  9,  8, size, op);
+	sja1105_packing(buf, &cmd->clk_pol,    7,  7, size, op);
+	sja1105_packing(buf, &cmd->clk_src,    6,  5, size, op);
+	sja1105_packing(buf, &cmd->clk_ods,    4,  3, size, op);
+	sja1105_packing(buf, &cmd->clk_pupd,   1,  0, size, op);
+}
+
+static int sja1110_acu_rmii_ext_rx_clk_config(struct sja1105_private *priv,
+					      int port)
+{
+	const struct sja1105_regs *regs = priv->info->regs;
+	struct sja1110_pin_cfg_mii_rx pin_cfg_mii_rx = {0};
+	u8 packed_buf[SJA1105_SIZE_ACU_CMD] = {0};
+
+	if (regs->pad_mii_rx[port] == SJA1105_RSV_ADDR)
+		return 0;
+
+	/* Payload */
+	pin_cfg_mii_rx.d32_pupd  = 2; /* RXD[3:2] pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	pin_cfg_mii_rx.d10_pupd  = 2; /* RXD[1:0] pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	pin_cfg_mii_rx.ctrl_pupd = 2; /* RX_DV / RX_ER pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	pin_cfg_mii_rx.clk_pol   = 0; /* RX_CLK output polarity: */
+				      /*   NORMAL Not inverted (default) */
+	pin_cfg_mii_rx.clk_src   = 1; /* RX_CLK source: */
+				      /*   EXTERNAL Clock sourced from external*/
+	pin_cfg_mii_rx.clk_ods   = 2; /* RX_CLK output stage drive-strength: */
+				      /*   FAST Medium noise / Fast speed (default) */
+	pin_cfg_mii_rx.clk_pupd  = 2; /* RX_CLK pull-up/-down: */
+				      /*   PLAIN Pull-up/-down disabled (default) */
+	sja1110_acu_pin_cfg_mii_rx_packing(packed_buf, &pin_cfg_mii_rx, PACK);
+
+	return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_rx[port],
+				packed_buf, SJA1105_SIZE_ACU_CMD);
+}
+
+static int sja1110_rmii_clocking_setup(struct sja1105_private *priv, int port,
+				       sja1105_mii_role_t role)
+{
+	struct device *dev = priv->ds->dev;
+	int rc;
+
+	dev_dbg(dev, "Configuring RMII-%s clocking\n",
+		(role == XMII_MAC) ? "MAC" : "PHY");
+	if (role == XMII_PHY) {
+		rc = sja1110_acu_rmii_ext_tx_clk_config(priv, port);
+		if (rc)
+			return rc;
+
+		rc = sja1110_acu_rmii_ext_rx_clk_config(priv, port);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+int sja1110_clocking_setup_port(struct sja1105_private *priv, int port)
+{
+	struct sja1105_xmii_params_entry *mii;
+	struct device *dev = priv->ds->dev;
+	sja1105_phy_interface_t phy_mode;
+	sja1105_mii_role_t role;
+	int rc;
+
+	mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries;
+
+	/* RGMII etc */
+	phy_mode = mii->xmii_mode[port];
+	/* MAC or PHY, for applicable types (not RGMII) */
+	role = mii->phy_mac[port];
+
+	switch (phy_mode) {
+	case XMII_MODE_RMII:
+		rc = sja1110_rmii_clocking_setup(priv, port, role);
+		break;
+	case XMII_MODE_MII:
+	case XMII_MODE_RGMII:
+	case XMII_MODE_SGMII:
+		/* Nothing to do in the CGU/ACU for MII/RGMII/SGMII */
+		rc = 0;
+		break;
+	default:
+		dev_err(dev, "Invalid interface mode specified: %d\n",
+			phy_mode);
+		return -EINVAL;
+	}
+	if (rc) {
+		dev_err(dev, "Clocking setup for port %d failed: %d\n",
+			port, rc);
+	}
+
+	return rc;
+}
+
+int sja1110_clocking_setup(struct sja1105_private *priv)
+{
+	struct dsa_switch *ds = priv->ds;
+	int port, rc;
+
+	for (port = 0; port < ds->num_ports; port++) {
+		rc = sja1110_clocking_setup_port(priv, port);
+		if (rc < 0)
+			return rc;
+	}
+	return 0;
+}
+
 static void
 sja1110_cgu_outclk_packing(void *buf, struct sja1110_cgu_outclk *outclk,
 			   enum packing_op op)
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index 834b5c1b4db0c..fcc675a269edb 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -495,13 +495,13 @@ static const struct sja1105_regs sja1110_regs = {
 	 * configure in the CGU/ACU for them.
 	 */
 	.pad_mii_tx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
-		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
+		       SJA1110_ACU_ADDR(0x10), SJA1110_ACU_ADDR(0x20),
 		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
 		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
 		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
 		       SJA1105_RSV_ADDR},
 	.pad_mii_rx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
-		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
+		       SJA1110_ACU_ADDR(0x14), SJA1110_ACU_ADDR(0x24),
 		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
 		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
 		       SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
@@ -794,6 +794,7 @@ const struct sja1105_info sja1110a_info = {
 	.ptp_cmd_packing	= sja1105pqrs_ptp_cmd_packing,
 	.rxtstamp		= sja1110_rxtstamp,
 	.txtstamp		= sja1110_txtstamp,
+	.clocking_setup		= sja1110_clocking_setup,
 	.disable_microcontroller = sja1110_disable_microcontroller,
 	.pcs_mdio_read_c45	= sja1110_pcs_mdio_read_c45,
 	.pcs_mdio_write_c45	= sja1110_pcs_mdio_write_c45,
@@ -845,6 +846,7 @@ const struct sja1105_info sja1110b_info = {
 	.ptp_cmd_packing	= sja1105pqrs_ptp_cmd_packing,
 	.rxtstamp		= sja1110_rxtstamp,
 	.txtstamp		= sja1110_txtstamp,
+	.clocking_setup		= sja1110_clocking_setup,
 	.disable_microcontroller = sja1110_disable_microcontroller,
 	.pcs_mdio_read_c45	= sja1110_pcs_mdio_read_c45,
 	.pcs_mdio_write_c45	= sja1110_pcs_mdio_write_c45,
@@ -896,6 +898,7 @@ const struct sja1105_info sja1110c_info = {
 	.ptp_cmd_packing	= sja1105pqrs_ptp_cmd_packing,
 	.rxtstamp		= sja1110_rxtstamp,
 	.txtstamp		= sja1110_txtstamp,
+	.clocking_setup		= sja1110_clocking_setup,
 	.disable_microcontroller = sja1110_disable_microcontroller,
 	.pcs_mdio_read_c45	= sja1110_pcs_mdio_read_c45,
 	.pcs_mdio_write_c45	= sja1110_pcs_mdio_write_c45,
@@ -947,6 +950,7 @@ const struct sja1105_info sja1110d_info = {
 	.ptp_cmd_packing	= sja1105pqrs_ptp_cmd_packing,
 	.rxtstamp		= sja1110_rxtstamp,
 	.txtstamp		= sja1110_txtstamp,
+	.clocking_setup		= sja1110_clocking_setup,
 	.disable_microcontroller = sja1110_disable_microcontroller,
 	.pcs_mdio_read_c45	= sja1110_pcs_mdio_read_c45,
 	.pcs_mdio_write_c45	= sja1110_pcs_mdio_write_c45,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] net: dsa: sja1105: Add rev-rmii support sja1110 devices
  2026-06-08 14:16 [PATCH] net: dsa: sja1105: Add rev-rmii support sja1110 devices Martijn de Gouw
@ 2026-06-10  1:59 ` Jakub Kicinski
  2026-06-10 10:00   ` Martijn de Gouw
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Kicinski @ 2026-06-10  1:59 UTC (permalink / raw)
  To: Martijn de Gouw
  Cc: Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, linux-kernel, netdev

On Mon, 8 Jun 2026 16:16:51 +0200 Martijn de Gouw wrote:
> When a rmii port is used in phy-mode (rev-rmii), the ref_clk is an input on
> the rx clk pin. Configure both the rx and tx clock source to use the
> rx_clk as external clock source input.

drivers/net/dsa/sja1105/sja1105_clocking.c:969:5: warning: no previous prototype for function 'sja1110_clocking_setup_port' [-Wmissing-prototypes]
  969 | int sja1110_clocking_setup_port(struct sja1105_private *priv, int port)
      |     ^
drivers/net/dsa/sja1105/sja1105_clocking.c:969:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
  969 | int sja1110_clocking_setup_port(struct sja1105_private *priv, int port)
      | ^
      | static 
-- 
pw-bot: cr

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] net: dsa: sja1105: Add rev-rmii support sja1110 devices
  2026-06-10  1:59 ` Jakub Kicinski
@ 2026-06-10 10:00   ` Martijn de Gouw
  0 siblings, 0 replies; 3+ messages in thread
From: Martijn de Gouw @ 2026-06-10 10:00 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, linux-kernel, netdev

Hi

On 10/06/2026 03:59, Jakub Kicinski wrote:
> On Mon, 8 Jun 2026 16:16:51 +0200 Martijn de Gouw wrote:
>> When a rmii port is used in phy-mode (rev-rmii), the ref_clk is an input on
>> the rx clk pin. Configure both the rx and tx clock source to use the
>> rx_clk as external clock source input.
> 
> drivers/net/dsa/sja1105/sja1105_clocking.c:969:5: warning: no previous prototype for function 'sja1110_clocking_setup_port' [-Wmissing-prototypes]
>    969 | int sja1110_clocking_setup_port(struct sja1105_private *priv, int port)
>        |     ^
> drivers/net/dsa/sja1105/sja1105_clocking.c:969:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
>    969 | int sja1110_clocking_setup_port(struct sja1105_private *priv, int port)
>        | ^
>        | static

Looking into why sja1105_clocking_setup_port is not declared static as 
well reveals that sja1105_clocking_setup_port is called directly from 
sja1105_set_port_speed() in sja1105_main.c as well. I think this should 
also be handled via the struct sja1105_info. If this port specific 
function is available via the info struct, there is also no longer a 
need to have a sja1105/sja1110 specific clocking_setup() function.

Unless there are additional comments I'll try to form a patch-series 
that implements this.

Regards, Martijn

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-06-10 10:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-08 14:16 [PATCH] net: dsa: sja1105: Add rev-rmii support sja1110 devices Martijn de Gouw
2026-06-10  1:59 ` Jakub Kicinski
2026-06-10 10:00   ` Martijn de Gouw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox