* [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