* [PATCH 2/4] net: cpsw: Remove compat string argument
2026-04-10 11:04 [PATCH 0/4] net: cpsw: Add cpsw-switch DT binding support Markus Schneider-Pargmann (TI)
2026-04-10 11:04 ` [PATCH 1/4] net: cpsw: Fix error message Markus Schneider-Pargmann (TI)
@ 2026-04-10 11:04 ` Markus Schneider-Pargmann (TI)
2026-04-13 9:00 ` Maarten Brock
2026-04-10 11:04 ` [PATCH 3/4] net: cpsw: Use driver data for phy_sel Markus Schneider-Pargmann (TI)
2026-04-10 11:04 ` [PATCH 4/4] net: cpsw: Support new cpsw-switch DT bindings Markus Schneider-Pargmann (TI)
3 siblings, 1 reply; 10+ messages in thread
From: Markus Schneider-Pargmann (TI) @ 2026-04-10 11:04 UTC (permalink / raw)
To: u-boot; +Cc: Jerome Forissier, Tom Rini, Markus Schneider-Pargmann (TI)
The string is already in the priv struct, remove it from the argument
list.
Signed-off-by: Markus Schneider-Pargmann (TI) <msp@baylibre.com>
---
drivers/net/ti/cpsw.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c
index 6bfdbb60091ac1cb7ef5a0bb3ad5221c2c11206f..c844416d50ca3db9bb0d9ffe56cd9c352b8c58b0 100644
--- a/drivers/net/ti/cpsw.c
+++ b/drivers/net/ti/cpsw.c
@@ -1064,9 +1064,10 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
writel(reg, priv->data->gmii_sel);
}
-static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
- phy_interface_t phy_mode)
+static void cpsw_phy_sel(struct cpsw_priv *priv, phy_interface_t phy_mode)
{
+ const char *compat = priv->data->phy_sel_compat;
+
if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
cpsw_gmii_sel_am3352(priv, phy_mode);
if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel"))
@@ -1084,8 +1085,7 @@ static int cpsw_eth_probe(struct udevice *dev)
priv->data = pdata->priv_pdata;
ti_cm_get_macid(dev, priv->data, pdata->enetaddr);
/* Select phy interface in control module */
- cpsw_phy_sel(priv, priv->data->phy_sel_compat,
- pdata->phy_interface);
+ cpsw_phy_sel(priv, pdata->phy_interface);
return _cpsw_register(priv);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 3/4] net: cpsw: Use driver data for phy_sel
2026-04-10 11:04 [PATCH 0/4] net: cpsw: Add cpsw-switch DT binding support Markus Schneider-Pargmann (TI)
2026-04-10 11:04 ` [PATCH 1/4] net: cpsw: Fix error message Markus Schneider-Pargmann (TI)
2026-04-10 11:04 ` [PATCH 2/4] net: cpsw: Remove compat string argument Markus Schneider-Pargmann (TI)
@ 2026-04-10 11:04 ` Markus Schneider-Pargmann (TI)
2026-04-13 8:57 ` Maarten Brock
2026-04-10 11:04 ` [PATCH 4/4] net: cpsw: Support new cpsw-switch DT bindings Markus Schneider-Pargmann (TI)
3 siblings, 1 reply; 10+ messages in thread
From: Markus Schneider-Pargmann (TI) @ 2026-04-10 11:04 UTC (permalink / raw)
To: u-boot; +Cc: Jerome Forissier, Tom Rini, Markus Schneider-Pargmann (TI)
Use driver data to pass the correct gmii_sel function. This way new
compatibles don't need manual compatible matching as is done in
cpsw_phy_sel().
Signed-off-by: Markus Schneider-Pargmann (TI) <msp@baylibre.com>
---
drivers/net/ti/cpsw.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c
index c844416d50ca3db9bb0d9ffe56cd9c352b8c58b0..b1fb009822e9586886e5487e4fbeee115eec9a59 100644
--- a/drivers/net/ti/cpsw.c
+++ b/drivers/net/ti/cpsw.c
@@ -216,6 +216,10 @@ struct cpsw_priv {
u32 phy_mask;
};
+struct cpsw_driver_data {
+ void (*gmii_sel)(struct cpsw_priv *priv, phy_interface_t phy_mode);
+};
+
static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
{
int idx;
@@ -1067,6 +1071,13 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
static void cpsw_phy_sel(struct cpsw_priv *priv, phy_interface_t phy_mode)
{
const char *compat = priv->data->phy_sel_compat;
+ const struct cpsw_driver_data *drv_data =
+ (const struct cpsw_driver_data *)dev_get_driver_data(priv->dev);
+
+ if (drv_data && drv_data->gmii_sel) {
+ drv_data->gmii_sel(priv, phy_mode);
+ return;
+ }
if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
cpsw_gmii_sel_am3352(priv, phy_mode);
@@ -1222,13 +1233,6 @@ static int cpsw_eth_of_to_plat(struct udevice *dev)
if (ofnode_read_bool(subnode, "rmii-clock-ext"))
data->rmii_clock_external = true;
-
- data->phy_sel_compat = ofnode_read_string(subnode,
- "compatible");
- if (!data->phy_sel_compat) {
- pr_err("Not able to get gmii_sel compatible\n");
- return -ENOENT;
- }
}
}
@@ -1253,9 +1257,19 @@ static int cpsw_eth_of_to_plat(struct udevice *dev)
return 0;
}
+static const struct cpsw_driver_data cpsw_data_am3352 = {
+ .gmii_sel = cpsw_gmii_sel_am3352,
+};
+
+static const struct cpsw_driver_data cpsw_data_dra7xx = {
+ .gmii_sel = cpsw_gmii_sel_dra7xx,
+};
+
static const struct udevice_id cpsw_eth_ids[] = {
- { .compatible = "ti,cpsw" },
- { .compatible = "ti,am335x-cpsw" },
+ { .compatible = "ti,cpsw", .data = (ulong)&cpsw_data_am3352 },
+ { .compatible = "ti,am335x-cpsw", .data = (ulong)&cpsw_data_am3352 },
+ { .compatible = "ti,am4372-cpsw", .data = (ulong)&cpsw_data_am3352 },
+ { .compatible = "ti,dra7-cpsw", .data = (ulong)&cpsw_data_dra7xx },
{ }
};
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 4/4] net: cpsw: Support new cpsw-switch DT bindings
2026-04-10 11:04 [PATCH 0/4] net: cpsw: Add cpsw-switch DT binding support Markus Schneider-Pargmann (TI)
` (2 preceding siblings ...)
2026-04-10 11:04 ` [PATCH 3/4] net: cpsw: Use driver data for phy_sel Markus Schneider-Pargmann (TI)
@ 2026-04-10 11:04 ` Markus Schneider-Pargmann (TI)
3 siblings, 0 replies; 10+ messages in thread
From: Markus Schneider-Pargmann (TI) @ 2026-04-10 11:04 UTC (permalink / raw)
To: u-boot; +Cc: Jerome Forissier, Tom Rini, Markus Schneider-Pargmann (TI)
Upstream devicetrees use a newer DT binding using cpsw-switch
compatibles. The bindings are a bit different, so two functions are
introduced to capture the differences, cpsw_eth_of_to_plat_switch() and
cpsw_eth_of_to_plat_legacy().
Signed-off-by: Markus Schneider-Pargmann (TI) <msp@baylibre.com>
---
drivers/net/ti/cpsw.c | 148 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 115 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c
index b1fb009822e9586886e5487e4fbeee115eec9a59..7a7cb83bd9847bc79ed21b2786ef6fe869e3fc0d 100644
--- a/drivers/net/ti/cpsw.c
+++ b/drivers/net/ti/cpsw.c
@@ -33,6 +33,7 @@
#define PKT_MAX (1500 + 14 + 4 + 4)
#define CLEAR_BIT 1
#define GIGABITEN BIT(7)
+#define GMII_EN BIT(5)
#define FULLDUPLEXEN BIT(0)
#define MIIEN BIT(15)
#define CTL_EXT_EN BIT(18)
@@ -1133,33 +1134,13 @@ static void cpsw_eth_of_parse_slave(struct cpsw_platform_data *data,
"max-speed", 0);
}
-static int cpsw_eth_of_to_plat(struct udevice *dev)
+static int cpsw_eth_of_to_plat_legacy(struct udevice *dev,
+ struct cpsw_platform_data *data)
{
- struct eth_pdata *pdata = dev_get_plat(dev);
- struct cpsw_platform_data *data;
- struct gpio_desc *mode_gpios;
int slave_index = 0;
- int num_mode_gpios;
ofnode subnode;
int ret;
- data = calloc(1, sizeof(struct cpsw_platform_data));
- if (!data)
- return -ENOMEM;
-
- pdata->priv_pdata = data;
- pdata->iobase = dev_read_addr(dev);
- data->version = CPSW_CTRL_VERSION_2;
- data->bd_ram_ofs = CPSW_BD_OFFSET;
- data->ale_reg_ofs = CPSW_ALE_OFFSET;
- data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET;
- data->mdio_div = CPSW_MDIO_DIV;
- data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET,
-
- pdata->phy_interface = -1;
-
- data->cpsw_base = pdata->iobase;
-
ret = dev_read_s32(dev, "cpdma_channels", &data->channels);
if (ret) {
printf("error: cpdma_channels not found in dt\n");
@@ -1192,17 +1173,6 @@ static int cpsw_eth_of_to_plat(struct udevice *dev)
return ret;
}
- num_mode_gpios = gpio_get_list_count(dev, "mode-gpios");
- if (num_mode_gpios > 0) {
- mode_gpios = malloc(sizeof(struct gpio_desc) *
- num_mode_gpios);
- gpio_request_list_by_name(dev, "mode-gpios", mode_gpios,
- num_mode_gpios, GPIOD_IS_OUT);
- free(mode_gpios);
- }
-
- data->active_slave = dev_read_u32_default(dev, "active_slave", 0);
-
ofnode_for_each_subnode(subnode, dev_ofnode(dev)) {
const char *name;
@@ -1236,6 +1206,115 @@ static int cpsw_eth_of_to_plat(struct udevice *dev)
}
}
+ return 0;
+}
+
+static int cpsw_eth_of_to_plat_switch(struct udevice *dev,
+ struct cpsw_platform_data *data)
+{
+ ofnode eth_ports_node, subnode;
+ int ret;
+
+ data->channels = 8;
+ data->ale_entries = 1024;
+ data->mac_control = GMII_EN;
+
+ eth_ports_node = ofnode_find_subnode(dev_ofnode(dev), "ethernet-ports");
+ data->slaves = ofnode_get_child_count(eth_ports_node);
+ if (!data->slaves) {
+ pr_err("cpsw: No ethernet-ports defined\n");
+ return -EINVAL;
+ }
+
+ data->slave_data = malloc(sizeof(struct cpsw_slave_data) * data->slaves);
+ if (!data->slave_data)
+ return -ENOMEM;
+
+ ofnode_for_each_subnode(subnode, eth_ports_node) {
+ struct ofnode_phandle_args args;
+ u32 port_id;
+
+ ret = ofnode_read_u32(subnode, "reg", &port_id);
+ if (ret || !port_id || port_id > data->slaves) {
+ pr_err("cpsw: invalid or missing reg in port node\n");
+ return -EINVAL;
+ }
+
+ cpsw_eth_of_parse_slave(data, port_id - 1, subnode);
+
+ if (!data->gmii_sel) {
+ ret = ofnode_parse_phandle_with_args(subnode, "phys", "#phy-cells",
+ 0, 0, &args);
+ if (!ret)
+ data->gmii_sel = ofnode_get_addr(args.node);
+ }
+ }
+
+ if (!data->gmii_sel) {
+ pr_err("No port specified phys correctly\n");
+ return -ENOENT;
+ }
+
+ ofnode_for_each_subnode(subnode, dev_ofnode(dev)) {
+ const char *name = ofnode_get_name(subnode);
+
+ if (strncmp(name, "mdio", 4))
+ continue;
+
+ data->mdio_base = ofnode_get_addr(subnode);
+ if (data->mdio_base == FDT_ADDR_T_NONE) {
+ pr_err("Not able to get MDIO address space\n");
+ return -ENOENT;
+ }
+ }
+
+ return 0;
+}
+
+static int cpsw_eth_of_to_plat(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct cpsw_platform_data *data;
+ struct gpio_desc *mode_gpios;
+ int num_mode_gpios;
+ int ret;
+ bool switch_dt_bindings =
+ ofnode_valid(ofnode_find_subnode(dev_ofnode(dev), "ethernet-ports"));
+
+ data = calloc(1, sizeof(struct cpsw_platform_data));
+ if (!data)
+ return -ENOMEM;
+
+ pdata->priv_pdata = data;
+ pdata->iobase = dev_read_addr(dev);
+ data->version = CPSW_CTRL_VERSION_2;
+ data->bd_ram_ofs = CPSW_BD_OFFSET;
+ data->ale_reg_ofs = CPSW_ALE_OFFSET;
+ data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET;
+ data->mdio_div = CPSW_MDIO_DIV;
+ data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET;
+
+ pdata->phy_interface = -1;
+
+ data->cpsw_base = pdata->iobase;
+
+ num_mode_gpios = gpio_get_list_count(dev, "mode-gpios");
+ if (num_mode_gpios > 0) {
+ mode_gpios = malloc(sizeof(struct gpio_desc) * num_mode_gpios);
+ gpio_request_list_by_name(dev, "mode-gpios", mode_gpios,
+ num_mode_gpios, GPIOD_IS_OUT);
+ free(mode_gpios);
+ }
+
+ data->active_slave = dev_read_u32_default(dev, "active_slave", 0);
+
+ if (switch_dt_bindings)
+ ret = cpsw_eth_of_to_plat_switch(dev, data);
+ else
+ ret = cpsw_eth_of_to_plat_legacy(dev, data);
+ if (ret)
+ return ret;
+
data->slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET;
data->slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET;
@@ -1270,6 +1349,9 @@ static const struct udevice_id cpsw_eth_ids[] = {
{ .compatible = "ti,am335x-cpsw", .data = (ulong)&cpsw_data_am3352 },
{ .compatible = "ti,am4372-cpsw", .data = (ulong)&cpsw_data_am3352 },
{ .compatible = "ti,dra7-cpsw", .data = (ulong)&cpsw_data_dra7xx },
+ { .compatible = "ti,am335x-cpsw-switch", .data = (ulong)&cpsw_data_am3352 },
+ { .compatible = "ti,am4372-cpsw-switch", .data = (ulong)&cpsw_data_am3352 },
+ { .compatible = "ti,dra7-cpsw-switch", .data = (ulong)&cpsw_data_dra7xx },
{ }
};
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread