net: dsa: lantiq_gswip: prepare for more CPU port options

The MaxLinear GSW1xx series of switches support using either the
(R)(G)MII interface on port 5 or the SGMII interface on port 4 to be
used as CPU port. Prepare for supporting them by defining a mask of
allowed CPU ports instead of a single port.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Link: https://patch.msgid.link/879c66672d26fe49c1f5d9aa40d8ebc0f31885ab.1755878232.git.daniel@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Daniel Golle 2025-08-22 17:11:39 +01:00 committed by Jakub Kicinski
parent fa1439a865
commit 2bec1c3836

View File

@ -253,7 +253,7 @@
struct gswip_hw_info {
int max_ports;
int cpu_port;
unsigned int allowed_cpu_ports;
void (*phylink_get_caps)(struct dsa_switch *ds, int port,
struct phylink_config *config);
};
@ -655,7 +655,6 @@ static int gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add)
{
struct gswip_pce_table_entry vlan_active = {0,};
struct gswip_pce_table_entry vlan_mapping = {0,};
unsigned int cpu_port = priv->hw_info->cpu_port;
int err;
vlan_active.index = port + 1;
@ -675,7 +674,7 @@ static int gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add)
vlan_mapping.index = port + 1;
vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
vlan_mapping.val[0] = 0 /* vid */;
vlan_mapping.val[1] = BIT(port) | BIT(cpu_port);
vlan_mapping.val[1] = BIT(port) | dsa_cpu_ports(priv->ds);
vlan_mapping.val[2] = 0;
err = gswip_pce_table_entry_write(priv, &vlan_mapping);
if (err) {
@ -805,10 +804,10 @@ static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port,
static int gswip_setup(struct dsa_switch *ds)
{
unsigned int cpu_ports = dsa_cpu_ports(ds);
struct gswip_priv *priv = ds->priv;
unsigned int cpu_port = priv->hw_info->cpu_port;
int i;
int err;
struct dsa_port *cpu_dp;
int err, i;
gswip_switch_w(priv, GSWIP_SWRES_R0, GSWIP_SWRES);
usleep_range(5000, 10000);
@ -830,9 +829,9 @@ static int gswip_setup(struct dsa_switch *ds)
}
/* Default unknown Broadcast/Multicast/Unicast port maps */
gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP1);
gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP2);
gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP3);
gswip_switch_w(priv, cpu_ports, GSWIP_PCE_PMAP1);
gswip_switch_w(priv, cpu_ports, GSWIP_PCE_PMAP2);
gswip_switch_w(priv, cpu_ports, GSWIP_PCE_PMAP3);
/* Deactivate MDIO PHY auto polling. Some PHYs as the AR8030 have an
* interoperability problem with this auto polling mechanism because
@ -861,13 +860,15 @@ static int gswip_setup(struct dsa_switch *ds)
GSWIP_MII_CFG_EN | GSWIP_MII_CFG_ISOLATE,
0, i);
/* enable special tag insertion on cpu port */
gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN,
GSWIP_FDMA_PCTRLp(cpu_port));
dsa_switch_for_each_cpu_port(cpu_dp, ds) {
/* enable special tag insertion on cpu port */
gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN,
GSWIP_FDMA_PCTRLp(cpu_dp->index));
/* accept special tag in ingress direction */
gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
GSWIP_PCE_PCTRL_0p(cpu_port));
/* accept special tag in ingress direction */
gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
GSWIP_PCE_PCTRL_0p(cpu_dp->index));
}
gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
GSWIP_BM_QUEUE_GCTRL);
@ -963,7 +964,6 @@ static int gswip_vlan_add_unaware(struct gswip_priv *priv,
{
struct gswip_pce_table_entry vlan_mapping = {0,};
unsigned int max_ports = priv->hw_info->max_ports;
unsigned int cpu_port = priv->hw_info->cpu_port;
bool active_vlan_created = false;
int idx = -1;
int i;
@ -1003,7 +1003,7 @@ static int gswip_vlan_add_unaware(struct gswip_priv *priv,
}
/* Update the VLAN mapping entry and write it to the switch */
vlan_mapping.val[1] |= BIT(cpu_port);
vlan_mapping.val[1] |= dsa_cpu_ports(priv->ds);
vlan_mapping.val[1] |= BIT(port);
err = gswip_pce_table_entry_write(priv, &vlan_mapping);
if (err) {
@ -1025,7 +1025,7 @@ static int gswip_vlan_add_aware(struct gswip_priv *priv,
{
struct gswip_pce_table_entry vlan_mapping = {0,};
unsigned int max_ports = priv->hw_info->max_ports;
unsigned int cpu_port = priv->hw_info->cpu_port;
unsigned int cpu_ports = dsa_cpu_ports(priv->ds);
bool active_vlan_created = false;
int idx = -1;
int fid = -1;
@ -1072,8 +1072,8 @@ static int gswip_vlan_add_aware(struct gswip_priv *priv,
vlan_mapping.val[0] = vid;
/* Update the VLAN mapping entry and write it to the switch */
vlan_mapping.val[1] |= BIT(cpu_port);
vlan_mapping.val[2] |= BIT(cpu_port);
vlan_mapping.val[1] |= cpu_ports;
vlan_mapping.val[2] |= cpu_ports;
vlan_mapping.val[1] |= BIT(port);
if (untagged)
vlan_mapping.val[2] &= ~BIT(port);
@ -1100,7 +1100,6 @@ static int gswip_vlan_remove(struct gswip_priv *priv,
{
struct gswip_pce_table_entry vlan_mapping = {0,};
unsigned int max_ports = priv->hw_info->max_ports;
unsigned int cpu_port = priv->hw_info->cpu_port;
int idx = -1;
int i;
int err;
@ -1136,7 +1135,7 @@ static int gswip_vlan_remove(struct gswip_priv *priv,
}
/* In case all ports are removed from the bridge, remove the VLAN */
if ((vlan_mapping.val[1] & ~BIT(cpu_port)) == 0) {
if (!(vlan_mapping.val[1] & ~dsa_cpu_ports(priv->ds))) {
err = gswip_vlan_active_remove(priv, idx);
if (err) {
dev_err(priv->dev, "failed to write active VLAN: %d\n",
@ -2078,6 +2077,30 @@ static int gswip_gphy_fw_list(struct gswip_priv *priv,
return err;
}
static int gswip_validate_cpu_port(struct dsa_switch *ds)
{
struct gswip_priv *priv = ds->priv;
struct dsa_port *cpu_dp;
int cpu_port = -1;
dsa_switch_for_each_cpu_port(cpu_dp, ds) {
if (cpu_port != -1)
return dev_err_probe(ds->dev, -EINVAL,
"only a single CPU port is supported\n");
cpu_port = cpu_dp->index;
}
if (cpu_port == -1)
return dev_err_probe(ds->dev, -EINVAL, "no CPU port defined\n");
if (BIT(cpu_port) & ~priv->hw_info->allowed_cpu_ports)
return dev_err_probe(ds->dev, -EINVAL,
"unsupported CPU port defined\n");
return 0;
}
static int gswip_probe(struct platform_device *pdev)
{
struct device_node *np, *gphy_fw_np;
@ -2160,12 +2183,10 @@ static int gswip_probe(struct platform_device *pdev)
dev_err_probe(dev, err, "dsa switch registration failed\n");
goto gphy_fw_remove;
}
if (!dsa_is_cpu_port(priv->ds, priv->hw_info->cpu_port)) {
err = dev_err_probe(dev, -EINVAL,
"wrong CPU port defined, HW only supports port: %i\n",
priv->hw_info->cpu_port);
err = gswip_validate_cpu_port(priv->ds);
if (err)
goto disable_switch;
}
platform_set_drvdata(pdev, priv);
@ -2214,13 +2235,13 @@ static void gswip_shutdown(struct platform_device *pdev)
static const struct gswip_hw_info gswip_xrx200 = {
.max_ports = 7,
.cpu_port = 6,
.allowed_cpu_ports = BIT(6),
.phylink_get_caps = gswip_xrx200_phylink_get_caps,
};
static const struct gswip_hw_info gswip_xrx300 = {
.max_ports = 7,
.cpu_port = 6,
.allowed_cpu_ports = BIT(6),
.phylink_get_caps = gswip_xrx300_phylink_get_caps,
};