net: dsa: qca8k: convert to use phylink_pcs
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Thu, 17 Feb 2022 18:30:51 +0000 (18:30 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Feb 2022 11:28:33 +0000 (11:28 +0000)
Convert the qca8k driver to use the phylink_pcs support to talk to the
SGMII PCS.

Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/qca8k.c
drivers/net/dsa/qca8k.h

index ff572ab..4df7b55 100644 (file)
@@ -1673,6 +1673,34 @@ qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_inde
                        cpu_port_index == QCA8K_CPU_PORT0 ? 0 : 6);
 }
 
+static struct phylink_pcs *
+qca8k_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
+                            phy_interface_t interface)
+{
+       struct qca8k_priv *priv = ds->priv;
+       struct phylink_pcs *pcs = NULL;
+
+       switch (interface) {
+       case PHY_INTERFACE_MODE_SGMII:
+       case PHY_INTERFACE_MODE_1000BASEX:
+               switch (port) {
+               case 0:
+                       pcs = &priv->pcs_port_0.pcs;
+                       break;
+
+               case 6:
+                       pcs = &priv->pcs_port_6.pcs;
+                       break;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return pcs;
+}
+
 static void
 qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
                         const struct phylink_link_state *state)
@@ -1902,17 +1930,24 @@ qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
        qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
 }
 
-static int
-qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port,
-                            struct phylink_link_state *state)
+static struct qca8k_pcs *pcs_to_qca8k_pcs(struct phylink_pcs *pcs)
 {
-       struct qca8k_priv *priv = ds->priv;
+       return container_of(pcs, struct qca8k_pcs, pcs);
+}
+
+static void qca8k_pcs_get_state(struct phylink_pcs *pcs,
+                               struct phylink_link_state *state)
+{
+       struct qca8k_priv *priv = pcs_to_qca8k_pcs(pcs)->priv;
+       int port = pcs_to_qca8k_pcs(pcs)->port;
        u32 reg;
        int ret;
 
        ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), &reg);
-       if (ret < 0)
-               return ret;
+       if (ret < 0) {
+               state->link = false;
+               return;
+       }
 
        state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP);
        state->an_complete = state->link;
@@ -1935,13 +1970,39 @@ qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port,
                break;
        }
 
-       state->pause = MLO_PAUSE_NONE;
        if (reg & QCA8K_PORT_STATUS_RXFLOW)
                state->pause |= MLO_PAUSE_RX;
        if (reg & QCA8K_PORT_STATUS_TXFLOW)
                state->pause |= MLO_PAUSE_TX;
+}
 
-       return 1;
+static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+                           phy_interface_t interface,
+                           const unsigned long *advertising,
+                           bool permit_pause_to_mac)
+{
+       return 0;
+}
+
+static void qca8k_pcs_an_restart(struct phylink_pcs *pcs)
+{
+}
+
+static const struct phylink_pcs_ops qca8k_pcs_ops = {
+       .pcs_get_state = qca8k_pcs_get_state,
+       .pcs_config = qca8k_pcs_config,
+       .pcs_an_restart = qca8k_pcs_an_restart,
+};
+
+static void qca8k_setup_pcs(struct qca8k_priv *priv, struct qca8k_pcs *qpcs,
+                           int port)
+{
+       qpcs->pcs.ops = &qca8k_pcs_ops;
+
+       /* We don't have interrupts for link changes, so we need to poll */
+       qpcs->pcs.poll = true;
+       qpcs->priv = priv;
+       qpcs->port = port;
 }
 
 static void
@@ -2806,6 +2867,9 @@ qca8k_setup(struct dsa_switch *ds)
        if (ret)
                return ret;
 
+       qca8k_setup_pcs(priv, &priv->pcs_port_0, 0);
+       qca8k_setup_pcs(priv, &priv->pcs_port_6, 6);
+
        /* Make sure MAC06 is disabled */
        ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
                                QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
@@ -2977,9 +3041,6 @@ qca8k_setup(struct dsa_switch *ds)
        /* Flush the FDB table */
        qca8k_fdb_flush(priv);
 
-       /* We don't have interrupts for link changes, so we need to poll */
-       ds->pcs_poll = true;
-
        /* Set min a max ageing value supported */
        ds->ageing_time_min = 7000;
        ds->ageing_time_max = 458745000;
@@ -3018,7 +3079,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
        .port_vlan_add          = qca8k_port_vlan_add,
        .port_vlan_del          = qca8k_port_vlan_del,
        .phylink_get_caps       = qca8k_phylink_get_caps,
-       .phylink_mac_link_state = qca8k_phylink_mac_link_state,
+       .phylink_mac_select_pcs = qca8k_phylink_mac_select_pcs,
        .phylink_mac_config     = qca8k_phylink_mac_config,
        .phylink_mac_link_down  = qca8k_phylink_mac_link_down,
        .phylink_mac_link_up    = qca8k_phylink_mac_link_up,
index c3d3c22..f375627 100644 (file)
@@ -376,6 +376,12 @@ struct qca8k_mdio_cache {
        u16 hi;
 };
 
+struct qca8k_pcs {
+       struct phylink_pcs pcs;
+       struct qca8k_priv *priv;
+       int port;
+};
+
 struct qca8k_priv {
        u8 switch_id;
        u8 switch_revision;
@@ -397,6 +403,8 @@ struct qca8k_priv {
        struct qca8k_mgmt_eth_data mgmt_eth_data;
        struct qca8k_mib_eth_data mib_eth_data;
        struct qca8k_mdio_cache mdio_cache;
+       struct qca8k_pcs pcs_port_0;
+       struct qca8k_pcs pcs_port_6;
 };
 
 struct qca8k_mib_desc {