From: Aleksander Jan Bajkowski <a.bajkow...@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 <ol...@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 &&
+                   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);
-- 
2.20.1

Reply via email to