2022-07-25 00:31:20 +00:00
|
|
|
From fd993fd59d96d5e2d5972ec4ca1f9651025c987b Mon Sep 17 00:00:00 2001
|
|
|
|
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
|
|
|
Date: Mon, 11 Apr 2022 10:46:27 +0100
|
|
|
|
Subject: [PATCH 07/13] net: dsa: mt7530: partially convert to phylink_pcs
|
|
|
|
MIME-Version: 1.0
|
|
|
|
Content-Type: text/plain; charset=UTF-8
|
|
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
|
|
|
|
Partially convert the mt7530 driver to use phylink's PCS support. This
|
|
|
|
is a partial implementation as we don't move anything into the
|
|
|
|
pcs_config method yet - this driver supports SGMII or 1000BASE-X
|
|
|
|
without in-band.
|
|
|
|
|
|
|
|
Tested-by: Marek Behún <kabel@kernel.org>
|
|
|
|
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
|
|
|
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
|
|
---
|
|
|
|
drivers/net/dsa/mt7530.c | 144 +++++++++++++++++++++++----------------
|
|
|
|
drivers/net/dsa/mt7530.h | 21 +++---
|
|
|
|
2 files changed, 95 insertions(+), 70 deletions(-)
|
|
|
|
|
|
|
|
--- a/drivers/net/dsa/mt7530.c
|
|
|
|
+++ b/drivers/net/dsa/mt7530.c
|
|
|
|
@@ -24,6 +24,11 @@
|
|
|
|
|
|
|
|
#include "mt7530.h"
|
|
|
|
|
|
|
|
+static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs)
|
|
|
|
+{
|
|
|
|
+ return container_of(pcs, struct mt753x_pcs, pcs);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
/* String, offset, and register size in bytes if different from 4 bytes */
|
|
|
|
static const struct mt7530_mib_desc mt7530_mib[] = {
|
|
|
|
MIB_DESC(1, 0x00, "TxDrop"),
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2522,12 +2527,11 @@ static int mt7531_rgmii_setup(struct mt7
|
2022-07-25 00:31:20 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void
|
|
|
|
-mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port,
|
|
|
|
- unsigned int mode, phy_interface_t interface,
|
|
|
|
- int speed, int duplex)
|
|
|
|
+static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
|
|
|
|
+ phy_interface_t interface, int speed, int duplex)
|
|
|
|
{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
+ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
|
|
|
|
+ int port = pcs_to_mt753x_pcs(pcs)->port;
|
|
|
|
unsigned int val;
|
|
|
|
|
|
|
|
/* For adjusting speed and duplex of SGMII force mode. */
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2553,6 +2557,9 @@ mt7531_sgmii_link_up_force(struct dsa_sw
|
2022-07-25 00:31:20 +00:00
|
|
|
|
|
|
|
/* MT7531 SGMII 1G force mode can only work in full duplex mode,
|
|
|
|
* no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
|
|
|
|
+ *
|
|
|
|
+ * The speed check is unnecessary as the MAC capabilities apply
|
|
|
|
+ * this restriction. --rmk
|
|
|
|
*/
|
|
|
|
if ((speed == SPEED_10 || speed == SPEED_100) &&
|
|
|
|
duplex != DUPLEX_FULL)
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2628,9 +2635,10 @@ static int mt7531_sgmii_setup_mode_an(st
|
2022-07-25 00:31:20 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port)
|
|
|
|
+static void mt7531_pcs_an_restart(struct phylink_pcs *pcs)
|
|
|
|
{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
+ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
|
|
|
|
+ int port = pcs_to_mt753x_pcs(pcs)->port;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
/* Only restart AN when AN is enabled */
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2687,6 +2695,24 @@ mt753x_mac_config(struct dsa_switch *ds,
|
2022-07-25 00:31:20 +00:00
|
|
|
return priv->info->mac_port_config(ds, port, mode, state->interface);
|
|
|
|
}
|
|
|
|
|
|
|
|
+static struct phylink_pcs *
|
|
|
|
+mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
|
|
|
|
+ phy_interface_t interface)
|
|
|
|
+{
|
|
|
|
+ struct mt7530_priv *priv = ds->priv;
|
|
|
|
+
|
|
|
|
+ switch (interface) {
|
|
|
|
+ case PHY_INTERFACE_MODE_TRGMII:
|
|
|
|
+ case PHY_INTERFACE_MODE_SGMII:
|
|
|
|
+ case PHY_INTERFACE_MODE_1000BASEX:
|
|
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
|
|
+ return &priv->pcs[port].pcs;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
|
|
|
const struct phylink_link_state *state)
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2748,17 +2774,6 @@ unsupported:
|
2022-07-25 00:31:20 +00:00
|
|
|
mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void
|
|
|
|
-mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port)
|
|
|
|
-{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
-
|
|
|
|
- if (!priv->info->mac_pcs_an_restart)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- priv->info->mac_pcs_an_restart(ds, port);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
|
|
|
unsigned int mode,
|
|
|
|
phy_interface_t interface)
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2768,16 +2783,13 @@ static void mt753x_phylink_mac_link_down
|
2022-07-25 00:31:20 +00:00
|
|
|
mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port,
|
|
|
|
- unsigned int mode, phy_interface_t interface,
|
|
|
|
- int speed, int duplex)
|
|
|
|
+static void mt753x_phylink_pcs_link_up(struct phylink_pcs *pcs,
|
|
|
|
+ unsigned int mode,
|
|
|
|
+ phy_interface_t interface,
|
|
|
|
+ int speed, int duplex)
|
|
|
|
{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
-
|
|
|
|
- if (!priv->info->mac_pcs_link_up)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
|
|
|
|
+ if (pcs->ops->pcs_link_up)
|
|
|
|
+ pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2790,8 +2802,6 @@ static void mt753x_phylink_mac_link_up(s
|
2022-07-25 00:31:20 +00:00
|
|
|
struct mt7530_priv *priv = ds->priv;
|
|
|
|
u32 mcr;
|
|
|
|
|
|
|
|
- mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
|
|
|
|
-
|
|
|
|
mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
|
|
|
|
|
|
|
|
/* MT753x MAC works in 1G full duplex mode for all up-clocked
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2869,6 +2879,8 @@ mt7531_cpu_port_config(struct dsa_switch
|
2022-07-25 00:31:20 +00:00
|
|
|
return ret;
|
|
|
|
mt7530_write(priv, MT7530_PMCR_P(port),
|
|
|
|
PMCR_CPU_PORT_SETTING(priv->id));
|
|
|
|
+ mt753x_phylink_pcs_link_up(&priv->pcs[port].pcs, MLO_AN_FIXED,
|
|
|
|
+ interface, speed, DUPLEX_FULL);
|
|
|
|
mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
|
|
|
|
speed, DUPLEX_FULL, true, true);
|
|
|
|
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2908,16 +2920,13 @@ mt753x_phylink_validate(struct dsa_switc
|
2022-07-25 00:31:20 +00:00
|
|
|
linkmode_and(state->advertising, state->advertising, mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
|
|
|
- struct phylink_link_state *state)
|
|
|
|
+static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
|
|
|
|
+ struct phylink_link_state *state)
|
|
|
|
{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
+ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
|
|
|
|
+ int port = pcs_to_mt753x_pcs(pcs)->port;
|
|
|
|
u32 pmsr;
|
|
|
|
|
|
|
|
- if (port < 0 || port >= MT7530_NUM_PORTS)
|
|
|
|
- return -EINVAL;
|
|
|
|
-
|
|
|
|
pmsr = mt7530_read(priv, MT7530_PMSR_P(port));
|
|
|
|
|
|
|
|
state->link = (pmsr & PMSR_LINK);
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2944,8 +2953,6 @@ mt7530_phylink_mac_link_state(struct dsa
|
2022-07-25 00:31:20 +00:00
|
|
|
state->pause |= MLO_PAUSE_RX;
|
|
|
|
if (pmsr & PMSR_TX_FC)
|
|
|
|
state->pause |= MLO_PAUSE_TX;
|
|
|
|
-
|
|
|
|
- return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -2987,32 +2994,49 @@ mt7531_sgmii_pcs_get_state_an(struct mt7
|
2022-07-25 00:31:20 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
|
|
|
- struct phylink_link_state *state)
|
|
|
|
+static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
|
|
|
|
+ struct phylink_link_state *state)
|
|
|
|
{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
+ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
|
|
|
|
+ int port = pcs_to_mt753x_pcs(pcs)->port;
|
|
|
|
|
|
|
|
if (state->interface == PHY_INTERFACE_MODE_SGMII)
|
|
|
|
- return mt7531_sgmii_pcs_get_state_an(priv, port, state);
|
|
|
|
-
|
|
|
|
- return -EOPNOTSUPP;
|
|
|
|
+ mt7531_sgmii_pcs_get_state_an(priv, port, state);
|
|
|
|
+ else
|
|
|
|
+ state->link = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
|
|
|
- struct phylink_link_state *state)
|
|
|
|
+static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
|
|
|
+ phy_interface_t interface,
|
|
|
|
+ const unsigned long *advertising,
|
|
|
|
+ bool permit_pause_to_mac)
|
|
|
|
{
|
|
|
|
- struct mt7530_priv *priv = ds->priv;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
|
|
|
|
- return priv->info->mac_port_get_state(ds, port, state);
|
|
|
|
+static void mt7530_pcs_an_restart(struct phylink_pcs *pcs)
|
|
|
|
+{
|
|
|
|
}
|
|
|
|
|
|
|
|
+static const struct phylink_pcs_ops mt7530_pcs_ops = {
|
|
|
|
+ .pcs_get_state = mt7530_pcs_get_state,
|
|
|
|
+ .pcs_config = mt753x_pcs_config,
|
|
|
|
+ .pcs_an_restart = mt7530_pcs_an_restart,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct phylink_pcs_ops mt7531_pcs_ops = {
|
|
|
|
+ .pcs_get_state = mt7531_pcs_get_state,
|
|
|
|
+ .pcs_config = mt753x_pcs_config,
|
|
|
|
+ .pcs_an_restart = mt7531_pcs_an_restart,
|
|
|
|
+ .pcs_link_up = mt7531_pcs_link_up,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
static int
|
|
|
|
mt753x_setup(struct dsa_switch *ds)
|
|
|
|
{
|
|
|
|
struct mt7530_priv *priv = ds->priv;
|
|
|
|
int ret = priv->info->sw_setup(ds);
|
|
|
|
+ int i;
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -3025,6 +3049,13 @@ mt753x_setup(struct dsa_switch *ds)
|
2022-07-25 00:31:20 +00:00
|
|
|
if (ret && priv->irq)
|
|
|
|
mt7530_free_irq_common(priv);
|
|
|
|
|
|
|
|
+ /* Initialise the PCS devices */
|
|
|
|
+ for (i = 0; i < priv->ds->num_ports; i++) {
|
|
|
|
+ priv->pcs[i].pcs.ops = priv->info->pcs_ops;
|
|
|
|
+ priv->pcs[i].priv = priv;
|
|
|
|
+ priv->pcs[i].port = i;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -3086,9 +3117,8 @@ static const struct dsa_switch_ops mt753
|
2022-07-25 00:31:20 +00:00
|
|
|
.port_mirror_del = mt753x_port_mirror_del,
|
|
|
|
.phylink_get_caps = mt753x_phylink_get_caps,
|
|
|
|
.phylink_validate = mt753x_phylink_validate,
|
|
|
|
- .phylink_mac_link_state = mt753x_phylink_mac_link_state,
|
|
|
|
+ .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs,
|
|
|
|
.phylink_mac_config = mt753x_phylink_mac_config,
|
|
|
|
- .phylink_mac_an_restart = mt753x_phylink_mac_an_restart,
|
|
|
|
.phylink_mac_link_down = mt753x_phylink_mac_link_down,
|
|
|
|
.phylink_mac_link_up = mt753x_phylink_mac_link_up,
|
|
|
|
.get_mac_eee = mt753x_get_mac_eee,
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -3098,36 +3128,34 @@ static const struct dsa_switch_ops mt753
|
2022-07-25 00:31:20 +00:00
|
|
|
static const struct mt753x_info mt753x_table[] = {
|
|
|
|
[ID_MT7621] = {
|
|
|
|
.id = ID_MT7621,
|
|
|
|
+ .pcs_ops = &mt7530_pcs_ops,
|
|
|
|
.sw_setup = mt7530_setup,
|
|
|
|
.phy_read = mt7530_phy_read,
|
|
|
|
.phy_write = mt7530_phy_write,
|
|
|
|
.pad_setup = mt7530_pad_clk_setup,
|
|
|
|
.mac_port_get_caps = mt7530_mac_port_get_caps,
|
|
|
|
- .mac_port_get_state = mt7530_phylink_mac_link_state,
|
|
|
|
.mac_port_config = mt7530_mac_config,
|
|
|
|
},
|
|
|
|
[ID_MT7530] = {
|
|
|
|
.id = ID_MT7530,
|
|
|
|
+ .pcs_ops = &mt7530_pcs_ops,
|
|
|
|
.sw_setup = mt7530_setup,
|
|
|
|
.phy_read = mt7530_phy_read,
|
|
|
|
.phy_write = mt7530_phy_write,
|
|
|
|
.pad_setup = mt7530_pad_clk_setup,
|
|
|
|
.mac_port_get_caps = mt7530_mac_port_get_caps,
|
|
|
|
- .mac_port_get_state = mt7530_phylink_mac_link_state,
|
|
|
|
.mac_port_config = mt7530_mac_config,
|
|
|
|
},
|
|
|
|
[ID_MT7531] = {
|
|
|
|
.id = ID_MT7531,
|
|
|
|
+ .pcs_ops = &mt7531_pcs_ops,
|
|
|
|
.sw_setup = mt7531_setup,
|
|
|
|
.phy_read = mt7531_ind_phy_read,
|
|
|
|
.phy_write = mt7531_ind_phy_write,
|
|
|
|
.pad_setup = mt7531_pad_setup,
|
|
|
|
.cpu_port_config = mt7531_cpu_port_config,
|
|
|
|
.mac_port_get_caps = mt7531_mac_port_get_caps,
|
|
|
|
- .mac_port_get_state = mt7531_phylink_mac_link_state,
|
|
|
|
.mac_port_config = mt7531_mac_config,
|
|
|
|
- .mac_pcs_an_restart = mt7531_sgmii_restart_an,
|
|
|
|
- .mac_pcs_link_up = mt7531_sgmii_link_up_force,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-10-05 10:04:11 +00:00
|
|
|
@@ -3185,7 +3213,7 @@ mt7530_probe(struct mdio_device *mdiodev
|
2022-07-25 00:31:20 +00:00
|
|
|
if (!priv->info->sw_setup || !priv->info->pad_setup ||
|
|
|
|
!priv->info->phy_read || !priv->info->phy_write ||
|
|
|
|
!priv->info->mac_port_get_caps ||
|
|
|
|
- !priv->info->mac_port_get_state || !priv->info->mac_port_config)
|
|
|
|
+ !priv->info->mac_port_config)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
priv->id = priv->info->id;
|
|
|
|
--- a/drivers/net/dsa/mt7530.h
|
|
|
|
+++ b/drivers/net/dsa/mt7530.h
|
|
|
|
@@ -741,6 +741,12 @@ static const char *p5_intf_modes(unsigne
|
|
|
|
|
|
|
|
struct mt7530_priv;
|
|
|
|
|
|
|
|
+struct mt753x_pcs {
|
|
|
|
+ struct phylink_pcs pcs;
|
|
|
|
+ struct mt7530_priv *priv;
|
|
|
|
+ int port;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
/* struct mt753x_info - This is the main data structure for holding the specific
|
|
|
|
* part for each supported device
|
|
|
|
* @sw_setup: Holding the handler to a device initialization
|
|
|
|
@@ -752,18 +758,14 @@ struct mt7530_priv;
|
|
|
|
* port
|
|
|
|
* @mac_port_validate: Holding the way to set addition validate type for a
|
|
|
|
* certan MAC port
|
|
|
|
- * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain
|
|
|
|
- * MAC port
|
|
|
|
* @mac_port_config: Holding the way setting up the PHY attribute to a
|
|
|
|
* certain MAC port
|
|
|
|
- * @mac_pcs_an_restart Holding the way restarting PCS autonegotiation for a
|
|
|
|
- * certain MAC port
|
|
|
|
- * @mac_pcs_link_up: Holding the way setting up the PHY attribute to the pcs
|
|
|
|
- * of the certain MAC port
|
|
|
|
*/
|
|
|
|
struct mt753x_info {
|
|
|
|
enum mt753x_id id;
|
|
|
|
|
|
|
|
+ const struct phylink_pcs_ops *pcs_ops;
|
|
|
|
+
|
|
|
|
int (*sw_setup)(struct dsa_switch *ds);
|
|
|
|
int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
|
|
|
|
int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
|
|
|
|
@@ -774,15 +776,9 @@ struct mt753x_info {
|
|
|
|
void (*mac_port_validate)(struct dsa_switch *ds, int port,
|
|
|
|
phy_interface_t interface,
|
|
|
|
unsigned long *supported);
|
|
|
|
- int (*mac_port_get_state)(struct dsa_switch *ds, int port,
|
|
|
|
- struct phylink_link_state *state);
|
|
|
|
int (*mac_port_config)(struct dsa_switch *ds, int port,
|
|
|
|
unsigned int mode,
|
|
|
|
phy_interface_t interface);
|
|
|
|
- void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port);
|
|
|
|
- void (*mac_pcs_link_up)(struct dsa_switch *ds, int port,
|
|
|
|
- unsigned int mode, phy_interface_t interface,
|
|
|
|
- int speed, int duplex);
|
|
|
|
};
|
|
|
|
|
|
|
|
/* struct mt7530_priv - This is the main data structure for holding the state
|
|
|
|
@@ -824,6 +820,7 @@ struct mt7530_priv {
|
|
|
|
u8 mirror_tx;
|
|
|
|
|
|
|
|
struct mt7530_port ports[MT7530_NUM_PORTS];
|
|
|
|
+ struct mt753x_pcs pcs[MT7530_NUM_PORTS];
|
|
|
|
/* protect among processes for registers access*/
|
|
|
|
struct mutex reg_mutex;
|
|
|
|
int irq;
|