[PATCH net-next v2 08/12] net: dsa: rzn1-a5psw: Get switch info via OF data
From: Prabhakar
Date: Thu Oct 01 2026 - 11:54:45 EST
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
The driver previously assumed a fixed 5-port layout and derived the CPU
port and number of PCS instances from this. Newer Renesas variants use
different port counts. Although the CPU port remains the last port, the
fixed port/PCS topology hard coded in the driver no longer matches all
hardware.
Introduce an a5psw_of_data struct holding the per SoC swicth info, and
use this match data in place of the previously embedded constants. This
makes the port loops, PCS allocation, management-port setup, and other
topology dependent code reflect the switch layout selected by the
compatible string.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v1->v2:
- Updated commit message
- Renamed A5PSW_MAX_PORTS macro to A5PSW_MAX_NUM_PCS
---
drivers/net/dsa/rzn1_a5psw.c | 27 ++++++++++++++++++---------
drivers/net/dsa/rzn1_a5psw.h | 20 +++++++++++++++++---
2 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c
index bdfa84745eda..c8197ef62fd2 100644
--- a/drivers/net/dsa/rzn1_a5psw.c
+++ b/drivers/net/dsa/rzn1_a5psw.c
@@ -382,13 +382,14 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
struct dsa_bridge bridge)
{
struct a5psw *a5psw = ds->priv;
+ unsigned int cpu_port = a5psw->of_data->cpu_port;
a5psw->bridged_ports &= ~BIT(port);
a5psw_port_set_standalone(a5psw, port, true);
/* No more ports bridged */
- if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT))
+ if (a5psw->bridged_ports == BIT(cpu_port))
a5psw->br_dev = NULL;
}
@@ -924,20 +925,21 @@ static void a5psw_vlan_setup(struct a5psw *a5psw, int port)
static int a5psw_setup(struct dsa_switch *ds)
{
struct a5psw *a5psw = ds->priv;
+ unsigned int cpu_port = a5psw->of_data->cpu_port;
int port, vlan, ret;
struct dsa_port *dp;
u32 reg;
- /* Validate that there is only 1 CPU port with index A5PSW_CPU_PORT */
+ /* Validate that there is only 1 CPU port with index matching cpu_port */
dsa_switch_for_each_cpu_port(dp, ds) {
- if (dp->index != A5PSW_CPU_PORT) {
+ if (dp->index != cpu_port) {
dev_err(a5psw->dev, "Invalid CPU port\n");
return -EINVAL;
}
}
/* Configure management port */
- reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_ENABLE;
+ reg = cpu_port | A5PSW_MGMT_CFG_ENABLE;
a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg);
/* Set pattern 0 to forward all frame to mgmt port */
@@ -1149,7 +1151,7 @@ static void a5psw_pcs_free(struct a5psw *a5psw)
{
int i;
- for (i = 0; i < ARRAY_SIZE(a5psw->pcs); i++) {
+ for (i = 0; i < a5psw->of_data->npcs; i++) {
if (a5psw->pcs[i])
miic_destroy(a5psw->pcs[i]);
}
@@ -1176,7 +1178,7 @@ static int a5psw_pcs_get(struct a5psw *a5psw)
goto free_pcs;
}
- if (reg >= ARRAY_SIZE(a5psw->pcs)) {
+ if (reg >= a5psw->of_data->npcs) {
ret = -ENODEV;
goto free_pcs;
}
@@ -1226,7 +1228,8 @@ static int a5psw_probe(struct platform_device *pdev)
if (IS_ERR(a5psw->base))
return PTR_ERR(a5psw->base);
- a5psw->bridged_ports = BIT(A5PSW_CPU_PORT);
+ a5psw->of_data = of_device_get_match_data(dev);
+ a5psw->bridged_ports = BIT(a5psw->of_data->cpu_port);
ret = a5psw_pcs_get(a5psw);
if (ret)
@@ -1271,7 +1274,7 @@ static int a5psw_probe(struct platform_device *pdev)
ds = &a5psw->ds;
ds->dev = dev;
- ds->num_ports = A5PSW_PORTS_NUM;
+ ds->num_ports = a5psw->of_data->nports;
ds->ops = &a5psw_switch_ops;
ds->phylink_mac_ops = &a5psw_phylink_mac_ops;
ds->priv = a5psw;
@@ -1313,8 +1316,14 @@ static void a5psw_shutdown(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
}
+static const struct a5psw_of_data rzn1_of_data = {
+ .nports = 5,
+ .npcs = 4,
+ .cpu_port = 4,
+};
+
static const struct of_device_id a5psw_of_mtable[] = {
- { .compatible = "renesas,rzn1-a5psw", },
+ { .compatible = "renesas,rzn1-a5psw", .data = &rzn1_of_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, a5psw_of_mtable);
diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h
index d54acedac194..197ff5916578 100644
--- a/drivers/net/dsa/rzn1_a5psw.h
+++ b/drivers/net/dsa/rzn1_a5psw.h
@@ -195,8 +195,8 @@
#define A5PSW_aCarrierSenseErrors 0x924
#define A5PSW_VLAN_TAG(prio, id) (((prio) << 12) | (id))
-#define A5PSW_PORTS_NUM 5
-#define A5PSW_CPU_PORT (A5PSW_PORTS_NUM - 1)
+/* Maximum number of PCS instances (excludes CPU port) */
+#define A5PSW_MAX_NUM_PCS 4
#define A5PSW_MDIO_DEF_FREQ 2500000
#define A5PSW_MDIO_TIMEOUT 100
#define A5PSW_JUMBO_LEN (10 * SZ_1K)
@@ -231,12 +231,25 @@ union lk_data {
struct fdb_entry entry;
};
+/**
+ * struct a5psw_of_data - OF data structure
+ * @nports: Number of ports in the switch
+ * @npcs: Number of PCS connected to the switch
+ * @cpu_port: CPU port number
+ */
+struct a5psw_of_data {
+ unsigned int nports;
+ unsigned int npcs;
+ unsigned int cpu_port;
+};
+
/**
* struct a5psw - switch struct
* @base: Base address of the switch
* @hclk: hclk_switch clock
* @clk: clk_switch clock
* @dev: Device associated to the switch
+ * @of_data: Pointer to OF data
* @mii_bus: MDIO bus struct
* @mdio_freq: MDIO bus frequency requested
* @pcs: Array of PCS connected to the switch ports (not for the CPU)
@@ -252,8 +265,9 @@ struct a5psw {
struct clk *hclk;
struct clk *clk;
struct device *dev;
+ const struct a5psw_of_data *of_data;
struct mii_bus *mii_bus;
- struct phylink_pcs *pcs[A5PSW_PORTS_NUM - 1];
+ struct phylink_pcs *pcs[A5PSW_MAX_NUM_PCS];
struct dsa_switch ds;
struct mutex lk_lock;
spinlock_t reg_lock;
--
2.55.0