diff mbox series

[1/2] net: dsa: lantiq: allow to use all GPHYs on xRX300 and xRX330

Message ID 20201203220347.13691-1-olek2@wp.pl
State New
Headers show
Series [1/2] net: dsa: lantiq: allow to use all GPHYs on xRX300 and xRX330 | expand

Commit Message

Aleksander Jan Bajkowski Dec. 3, 2020, 10:03 p.m. UTC
From: Aleksander Jan Bajkowski <A.Bajkowski@stud.elka.pw.edu.pl>

This patch allows you to use all phs on GRX300 and GRX330. The ARX300 has 3
and the GRX330 has 4 integrated PHYs connected to different ports compared
to VRX200.

Port configurations:

xRX200:
GMAC0: RGMII port
GMAC1: RGMII port
GMAC2: GPHY0 (GMII)
GMAC3: GPHY0 (MII)
GMAC4: GPHY1 (GMII)
GMAC5: GPHY1 (MII) or RGMII port

xRX300:
GMAC0: RGMII port
GMAC1: GPHY2 (GMII)
GMAC2: GPHY0 (GMII)
GMAC3: GPHY0 (MII)
GMAC4: GPHY1 (GMII)
GMAC5: GPHY1 (MII) or RGMII port

xRX330:
GMAC0: RGMII port
GMAC1: GPHY2 (GMII)
GMAC2: GPHY0 (GMII)
GMAC3: GPHY3 (GMII)
GMAC4: GPHY1 (GMII)
GMAC5: GPHY1 (MII) or RGMII port

Tested on D-Link DWR966 with OpenWRT.

Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
---
 drivers/net/dsa/lantiq_gswip.c | 110 +++++++++++++++++++++++++++++++--
 1 file changed, 104 insertions(+), 6 deletions(-)

Comments

Hauke Mehrtens Dec. 4, 2020, 12:31 a.m. UTC | #1
Hi,

This looks good.

I haven't checked all the differences between the SoCs, but found some 
minor problems in the code for the port configuration.


On 12/3/20 11:03 PM, Aleksander Jan Bajkowski wrote:
> From: Aleksander Jan Bajkowski <A.Bajkowski@stud.elka.pw.edu.pl>
> 
> This patch allows you to use all phs on GRX300 and GRX330. The ARX300 has 3
> and the GRX330 has 4 integrated PHYs connected to different ports compared
> to VRX200.
> 
> Port configurations:
> 
> xRX200:
> GMAC0: RGMII port
> GMAC1: RGMII port
> GMAC2: GPHY0 (GMII)
> GMAC3: GPHY0 (MII)
> GMAC4: GPHY1 (GMII)
> GMAC5: GPHY1 (MII) or RGMII port
> 
> xRX300:
> GMAC0: RGMII port
> GMAC1: GPHY2 (GMII)
> GMAC2: GPHY0 (GMII)
> GMAC3: GPHY0 (MII)
> GMAC4: GPHY1 (GMII)
> GMAC5: GPHY1 (MII) or RGMII port
> 
> xRX330:
> GMAC0: RGMII port
> GMAC1: GPHY2 (GMII)
> GMAC2: GPHY0 (GMII)
> GMAC3: GPHY3 (GMII)
GMAC3: GPHY3 (GMII) or GPHY0 (MII)
This can be changed in GSWIP_MII_CFG3 (0xc3)

> GMAC4: GPHY1 (GMII)
> GMAC5: GPHY1 (MII) or RGMII port

You also have to change gswip_mii_mask_cfg() it only supports port 0, 1 
and 5, but this SoC can not change port 1 (always connected to internal 
GPHY, but it can change port 3 (change between GPHY0/MII/0x0 and 
PHY3/GMII/0x1)

> 
> Tested on D-Link DWR966 with OpenWRT.
> 
> Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
> ---
>   drivers/net/dsa/lantiq_gswip.c | 110 +++++++++++++++++++++++++++++++--
>   1 file changed, 104 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
> index 09701c17f3f6..540cf99ad7fe 100644
> --- a/drivers/net/dsa/lantiq_gswip.c
> +++ b/drivers/net/dsa/lantiq_gswip.c
> @@ -222,6 +222,7 @@
>   struct gswip_hw_info {
>   	int max_ports;
>   	int cpu_port;
> +	struct dsa_switch_ops *ops;
>   };
>   
>   struct xway_gphy_match_data {
> @@ -1409,9 +1410,9 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
>   	return 0;
>   }
>   
> -static void gswip_phylink_validate(struct dsa_switch *ds, int port,
> -				   unsigned long *supported,
> -				   struct phylink_link_state *state)
> +static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port,
> +					  unsigned long *supported,
> +					  struct phylink_link_state *state)
>   {
>   	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
>   
> @@ -1471,7 +1472,70 @@ static void gswip_phylink_validate(struct dsa_switch *ds, int port,
>   	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
>   	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
>   		phy_modes(state->interface), port);
> +}
> +
> +static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port,
> +					  unsigned long *supported,
> +					  struct phylink_link_state *state)
> +{
> +	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
> +
> +	switch (port) {
> +	case 0:
> +		if (!phy_interface_mode_is_rgmii(state->interface) &&
> +		    state->interface != PHY_INTERFACE_MODE_MII &

MII is not support on port 0

> +		    state->interface != PHY_INTERFACE_MODE_REVMII &&

REVMII is not support on port 0

> +		    state->interface != PHY_INTERFACE_MODE_RMII)

GMII is now supported with 0x9

> +			goto unsupported;
> +		break;
> +	case 1:
> +	case 2:
> +	case 3:
> +	case 4:
> +		if (state->interface != PHY_INTERFACE_MODE_INTERNAL)
> +			goto unsupported;
> +		break;
> +	case 5:
> +		if (!phy_interface_mode_is_rgmii(state->interface) &&
> +		    state->interface != PHY_INTERFACE_MODE_INTERNAL)
> +			goto unsupported;
port 5 also supports RMIIM with bit 0x3 on xrx300 and xrx330

> +		break;
> +	default:
> +		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
> +		dev_err(ds->dev, "Unsupported port: %i\n", port);
> +		return;
> +	}
> +
> +	/* Allow all the expected bits */
> +	phylink_set(mask, Autoneg);
> +	phylink_set_port_modes(mask);
> +	phylink_set(mask, Pause);
> +	phylink_set(mask, Asym_Pause);
> +
> +	/* With the exclusion of MII and Reverse MII, we support Gigabit,
> +	 * including Half duplex
> +	 */
> +	if (state->interface != PHY_INTERFACE_MODE_MII &&
> +	    state->interface != PHY_INTERFACE_MODE_REVMII) {
> +		phylink_set(mask, 1000baseT_Full);
> +		phylink_set(mask, 1000baseT_Half);
> +	}
> +
> +	phylink_set(mask, 10baseT_Half);
> +	phylink_set(mask, 10baseT_Full);
> +	phylink_set(mask, 100baseT_Half);
> +	phylink_set(mask, 100baseT_Full);
> +
> +	bitmap_and(supported, supported, mask,
> +		   __ETHTOOL_LINK_MODE_MASK_NBITS);
> +	bitmap_and(state->advertising, state->advertising, mask,
> +		   __ETHTOOL_LINK_MODE_MASK_NBITS);
You can put this block into a common function it is also used the the 
xrx200  validate block.

>   	return;
> +
> +unsupported:
> +	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
> +	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
> +		phy_modes(state->interface), port);
>   }
>   
>   static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
> @@ -1614,7 +1678,7 @@ static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
>   	return ARRAY_SIZE(gswip_rmon_cnt);
>   }
>   
> -static const struct dsa_switch_ops gswip_switch_ops = {
> +static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
>   	.get_tag_protocol	= gswip_get_tag_protocol,
>   	.setup			= gswip_setup,
>   	.port_enable		= gswip_port_enable,
> @@ -1630,7 +1694,32 @@ static const struct dsa_switch_ops gswip_switch_ops = {
>   	.port_fdb_add		= gswip_port_fdb_add,
>   	.port_fdb_del		= gswip_port_fdb_del,
>   	.port_fdb_dump		= gswip_port_fdb_dump,
> -	.phylink_validate	= gswip_phylink_validate,
> +	.phylink_validate	= gswip_xrx200_phylink_validate,
> +	.phylink_mac_config	= gswip_phylink_mac_config,
> +	.phylink_mac_link_down	= gswip_phylink_mac_link_down,
> +	.phylink_mac_link_up	= gswip_phylink_mac_link_up,
> +	.get_strings		= gswip_get_strings,
> +	.get_ethtool_stats	= gswip_get_ethtool_stats,
> +	.get_sset_count		= gswip_get_sset_count,
> +};
> +
> +static const struct dsa_switch_ops gswip_xrx300_switch_ops = {
> +	.get_tag_protocol	= gswip_get_tag_protocol,
> +	.setup			= gswip_setup,
> +	.port_enable		= gswip_port_enable,
> +	.port_disable		= gswip_port_disable,
> +	.port_bridge_join	= gswip_port_bridge_join,
> +	.port_bridge_leave	= gswip_port_bridge_leave,
> +	.port_fast_age		= gswip_port_fast_age,
> +	.port_vlan_filtering	= gswip_port_vlan_filtering,
> +	.port_vlan_prepare	= gswip_port_vlan_prepare,
> +	.port_vlan_add		= gswip_port_vlan_add,
> +	.port_vlan_del		= gswip_port_vlan_del,
> +	.port_stp_state_set	= gswip_port_stp_state_set,
> +	.port_fdb_add		= gswip_port_fdb_add,
> +	.port_fdb_del		= gswip_port_fdb_del,
> +	.port_fdb_dump		= gswip_port_fdb_dump,
> +	.phylink_validate	= gswip_xrx300_phylink_validate,
>   	.phylink_mac_config	= gswip_phylink_mac_config,
>   	.phylink_mac_link_down	= gswip_phylink_mac_link_down,
>   	.phylink_mac_link_up	= gswip_phylink_mac_link_up,
> @@ -1892,7 +1981,7 @@ static int gswip_probe(struct platform_device *pdev)
>   	priv->ds->dev = dev;
>   	priv->ds->num_ports = priv->hw_info->max_ports;
>   	priv->ds->priv = priv;
> -	priv->ds->ops = &gswip_switch_ops;
> +	priv->ds->ops = priv->hw_info->ops;
>   	priv->dev = dev;
>   	version = gswip_switch_r(priv, GSWIP_VERSION);
>   
> @@ -1973,10 +2062,19 @@ static int gswip_remove(struct platform_device *pdev)
>   static const struct gswip_hw_info gswip_xrx200 = {
>   	.max_ports = 7,
>   	.cpu_port = 6,
> +	.ops = &gswip_xrx200_switch_ops,
> +};
> +
> +static const struct gswip_hw_info gswip_xrx300 = {
> +	.max_ports = 7,
> +	.cpu_port = 6,
> +	.ops = &gswip_xrx300_switch_ops,
>   };
>   
>   static const struct of_device_id gswip_of_match[] = {
>   	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },
> +	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },
> +	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },
>   	{},
>   };
>   MODULE_DEVICE_TABLE(of, gswip_of_match);
>
Andrew Lunn Dec. 4, 2020, 1:49 a.m. UTC | #2
>  static const struct of_device_id gswip_of_match[] = {

>  	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },

> +	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },

> +	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },

>  	{},


Is there an ID register which allows you to ask the silicon what it
is?

It would be good to verify the compatible string against the hardware,
if that is possible.

   Andrew
Hauke Mehrtens Dec. 4, 2020, 12:53 p.m. UTC | #3
On 12/4/20 2:49 AM, Andrew Lunn wrote:
>>   static const struct of_device_id gswip_of_match[] = {

>>   	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },

>> +	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },

>> +	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },

>>   	{},

> 

> Is there an ID register which allows you to ask the silicon what it

> is?


Yes there is, see GSWIP_VERSION.

> It would be good to verify the compatible string against the hardware,

> if that is possible.

> 

>     Andrew

>
diff mbox series

Patch

diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index 09701c17f3f6..540cf99ad7fe 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -222,6 +222,7 @@ 
 struct gswip_hw_info {
 	int max_ports;
 	int cpu_port;
+	struct dsa_switch_ops *ops;
 };
 
 struct xway_gphy_match_data {
@@ -1409,9 +1410,9 @@  static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
 	return 0;
 }
 
-static void gswip_phylink_validate(struct dsa_switch *ds, int port,
-				   unsigned long *supported,
-				   struct phylink_link_state *state)
+static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port,
+					  unsigned long *supported,
+					  struct phylink_link_state *state)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 
@@ -1471,7 +1472,70 @@  static void gswip_phylink_validate(struct dsa_switch *ds, int port,
 	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
 	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
 		phy_modes(state->interface), port);
+}
+
+static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port,
+					  unsigned long *supported,
+					  struct phylink_link_state *state)
+{
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+
+	switch (port) {
+	case 0:
+		if (!phy_interface_mode_is_rgmii(state->interface) &&
+		    state->interface != PHY_INTERFACE_MODE_MII &&
+		    state->interface != PHY_INTERFACE_MODE_REVMII &&
+		    state->interface != PHY_INTERFACE_MODE_RMII)
+			goto unsupported;
+		break;
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		if (state->interface != PHY_INTERFACE_MODE_INTERNAL)
+			goto unsupported;
+		break;
+	case 5:
+		if (!phy_interface_mode_is_rgmii(state->interface) &&
+		    state->interface != PHY_INTERFACE_MODE_INTERNAL)
+			goto unsupported;
+		break;
+	default:
+		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+		dev_err(ds->dev, "Unsupported port: %i\n", port);
+		return;
+	}
+
+	/* Allow all the expected bits */
+	phylink_set(mask, Autoneg);
+	phylink_set_port_modes(mask);
+	phylink_set(mask, Pause);
+	phylink_set(mask, Asym_Pause);
+
+	/* With the exclusion of MII and Reverse MII, we support Gigabit,
+	 * including Half duplex
+	 */
+	if (state->interface != PHY_INTERFACE_MODE_MII &&
+	    state->interface != PHY_INTERFACE_MODE_REVMII) {
+		phylink_set(mask, 1000baseT_Full);
+		phylink_set(mask, 1000baseT_Half);
+	}
+
+	phylink_set(mask, 10baseT_Half);
+	phylink_set(mask, 10baseT_Full);
+	phylink_set(mask, 100baseT_Half);
+	phylink_set(mask, 100baseT_Full);
+
+	bitmap_and(supported, supported, mask,
+		   __ETHTOOL_LINK_MODE_MASK_NBITS);
+	bitmap_and(state->advertising, state->advertising, mask,
+		   __ETHTOOL_LINK_MODE_MASK_NBITS);
 	return;
+
+unsupported:
+	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
+		phy_modes(state->interface), port);
 }
 
 static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
@@ -1614,7 +1678,7 @@  static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
 	return ARRAY_SIZE(gswip_rmon_cnt);
 }
 
-static const struct dsa_switch_ops gswip_switch_ops = {
+static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
 	.get_tag_protocol	= gswip_get_tag_protocol,
 	.setup			= gswip_setup,
 	.port_enable		= gswip_port_enable,
@@ -1630,7 +1694,32 @@  static const struct dsa_switch_ops gswip_switch_ops = {
 	.port_fdb_add		= gswip_port_fdb_add,
 	.port_fdb_del		= gswip_port_fdb_del,
 	.port_fdb_dump		= gswip_port_fdb_dump,
-	.phylink_validate	= gswip_phylink_validate,
+	.phylink_validate	= gswip_xrx200_phylink_validate,
+	.phylink_mac_config	= gswip_phylink_mac_config,
+	.phylink_mac_link_down	= gswip_phylink_mac_link_down,
+	.phylink_mac_link_up	= gswip_phylink_mac_link_up,
+	.get_strings		= gswip_get_strings,
+	.get_ethtool_stats	= gswip_get_ethtool_stats,
+	.get_sset_count		= gswip_get_sset_count,
+};
+
+static const struct dsa_switch_ops gswip_xrx300_switch_ops = {
+	.get_tag_protocol	= gswip_get_tag_protocol,
+	.setup			= gswip_setup,
+	.port_enable		= gswip_port_enable,
+	.port_disable		= gswip_port_disable,
+	.port_bridge_join	= gswip_port_bridge_join,
+	.port_bridge_leave	= gswip_port_bridge_leave,
+	.port_fast_age		= gswip_port_fast_age,
+	.port_vlan_filtering	= gswip_port_vlan_filtering,
+	.port_vlan_prepare	= gswip_port_vlan_prepare,
+	.port_vlan_add		= gswip_port_vlan_add,
+	.port_vlan_del		= gswip_port_vlan_del,
+	.port_stp_state_set	= gswip_port_stp_state_set,
+	.port_fdb_add		= gswip_port_fdb_add,
+	.port_fdb_del		= gswip_port_fdb_del,
+	.port_fdb_dump		= gswip_port_fdb_dump,
+	.phylink_validate	= gswip_xrx300_phylink_validate,
 	.phylink_mac_config	= gswip_phylink_mac_config,
 	.phylink_mac_link_down	= gswip_phylink_mac_link_down,
 	.phylink_mac_link_up	= gswip_phylink_mac_link_up,
@@ -1892,7 +1981,7 @@  static int gswip_probe(struct platform_device *pdev)
 	priv->ds->dev = dev;
 	priv->ds->num_ports = priv->hw_info->max_ports;
 	priv->ds->priv = priv;
-	priv->ds->ops = &gswip_switch_ops;
+	priv->ds->ops = priv->hw_info->ops;
 	priv->dev = dev;
 	version = gswip_switch_r(priv, GSWIP_VERSION);
 
@@ -1973,10 +2062,19 @@  static int gswip_remove(struct platform_device *pdev)
 static const struct gswip_hw_info gswip_xrx200 = {
 	.max_ports = 7,
 	.cpu_port = 6,
+	.ops = &gswip_xrx200_switch_ops,
+};
+
+static const struct gswip_hw_info gswip_xrx300 = {
+	.max_ports = 7,
+	.cpu_port = 6,
+	.ops = &gswip_xrx300_switch_ops,
 };
 
 static const struct of_device_id gswip_of_match[] = {
 	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },
+	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },
+	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, gswip_of_match);