Commit 80ecb114 authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'net-dsa-mt7530-updates-for-phylink-changes'

Russell King says:

====================
net: dsa: mt7530: updates for phylink changes

This revised series is a partial conversion of the mt7530 DSA driver to
the modern phylink infrastructure. This driver has some exceptional
cases which prevent - at the moment - its full conversion (particularly
with the Autoneg bit) to using phylink_generic_validate().

Patch 1 fixes the incorrect test highlighted in the first RFC series.

Patch 2 fixes the incorrect assumption that RGMII is unable to support
1000BASE-X.

Patch 3 populates the supported_interfaces for each port

Patch 4 removes the interface checks that become unnecessary as a result
of patch 3.

Patch 5 removes use of phylink_helper_basex_speed() which is no longer
required by phylink.

Patch 6 becomes possible after patch 5, only indicating the ethtool
modes that can be supported with a particular interface mode - this
involves removing some modes and adding others as per phylink
documentation.

Patch 7 switches the driver to use phylink_get_linkmodes(), which moves
the driver as close as we can to phylink_generic_validate() due to the
Autoneg bit issue mentioned above.

Patch 8 converts the driver to the phylink pcs support, removing a bunch
of driver private indirected methods. We include TRGMII as a PCS even
though strictly TRGMII does not have a PCS. This is convenient to allow
the change in patch 9 to be made.

Patch 9 moves the special autoneg handling to the PCS validate method,
which means we can convert the MAC side to the generic validator.

Patch 10 marks the driver as non-legacy.

The series was posted on 23 February, and a ping sent on 3 March, but
no feedback has been received. The previous posting also received no
feedback on the actual patches either.

v2:
- fix build issue in patch 5
- add Marek's tested-by

 drivers/net/dsa/mt7530.c | 330 +++++++++++++++++++++--------------------------
 drivers/net/dsa/mt7530.h |  26 ++--
 2 files changed, 159 insertions(+), 197 deletions(-)
====================

Link: https://lore.kernel.org/r/YlP4vGKVrlIJUUHK@shell.armlinux.org.ukSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 1a915b23 7b972512
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
#include "mt7530.h" #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 */ /* String, offset, and register size in bytes if different from 4 bytes */
static const struct mt7530_mib_desc mt7530_mib[] = { static const struct mt7530_mib_desc mt7530_mib[] = {
MIB_DESC(1, 0x00, "TxDrop"), MIB_DESC(1, 0x00, "TxDrop"),
...@@ -2389,35 +2394,30 @@ mt7531_setup(struct dsa_switch *ds) ...@@ -2389,35 +2394,30 @@ mt7531_setup(struct dsa_switch *ds)
return 0; return 0;
} }
static bool static void mt7530_mac_port_get_caps(struct dsa_switch *ds, int port,
mt7530_phy_mode_supported(struct dsa_switch *ds, int port, struct phylink_config *config)
const struct phylink_link_state *state)
{ {
struct mt7530_priv *priv = ds->priv;
switch (port) { switch (port) {
case 0 ... 4: /* Internal phy */ case 0 ... 4: /* Internal phy */
if (state->interface != PHY_INTERFACE_MODE_GMII) __set_bit(PHY_INTERFACE_MODE_GMII,
return false; config->supported_interfaces);
break; break;
case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
if (!phy_interface_mode_is_rgmii(state->interface) && phy_interface_set_rgmii(config->supported_interfaces);
state->interface != PHY_INTERFACE_MODE_MII && __set_bit(PHY_INTERFACE_MODE_MII,
state->interface != PHY_INTERFACE_MODE_GMII) config->supported_interfaces);
return false; __set_bit(PHY_INTERFACE_MODE_GMII,
config->supported_interfaces);
break; break;
case 6: /* 1st cpu port */ case 6: /* 1st cpu port */
if (state->interface != PHY_INTERFACE_MODE_RGMII && __set_bit(PHY_INTERFACE_MODE_RGMII,
state->interface != PHY_INTERFACE_MODE_TRGMII) config->supported_interfaces);
return false; __set_bit(PHY_INTERFACE_MODE_TRGMII,
config->supported_interfaces);
break; break;
default:
dev_err(priv->dev, "%s: unsupported port: %i\n", __func__,
port);
return false;
} }
return true;
} }
static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port)
...@@ -2425,42 +2425,35 @@ static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) ...@@ -2425,42 +2425,35 @@ static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port)
return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII);
} }
static bool static void mt7531_mac_port_get_caps(struct dsa_switch *ds, int port,
mt7531_phy_mode_supported(struct dsa_switch *ds, int port, struct phylink_config *config)
const struct phylink_link_state *state)
{ {
struct mt7530_priv *priv = ds->priv; struct mt7530_priv *priv = ds->priv;
switch (port) { switch (port) {
case 0 ... 4: /* Internal phy */ case 0 ... 4: /* Internal phy */
if (state->interface != PHY_INTERFACE_MODE_GMII) __set_bit(PHY_INTERFACE_MODE_GMII,
return false; config->supported_interfaces);
break; break;
case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */
if (mt7531_is_rgmii_port(priv, port)) if (mt7531_is_rgmii_port(priv, port)) {
return phy_interface_mode_is_rgmii(state->interface); phy_interface_set_rgmii(config->supported_interfaces);
break;
}
fallthrough; fallthrough;
case 6: /* 1st cpu port supports sgmii/8023z only */ case 6: /* 1st cpu port supports sgmii/8023z only */
if (state->interface != PHY_INTERFACE_MODE_SGMII && __set_bit(PHY_INTERFACE_MODE_SGMII,
!phy_interface_mode_is_8023z(state->interface)) config->supported_interfaces);
return false; __set_bit(PHY_INTERFACE_MODE_1000BASEX,
config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_2500BASEX,
config->supported_interfaces);
config->mac_capabilities |= MAC_2500FD;
break; break;
default:
dev_err(priv->dev, "%s: unsupported port: %i\n", __func__,
port);
return false;
} }
return true;
}
static bool
mt753x_phy_mode_supported(struct dsa_switch *ds, int port,
const struct phylink_link_state *state)
{
struct mt7530_priv *priv = ds->priv;
return priv->info->phy_mode_supported(ds, port, state);
} }
static int static int
...@@ -2533,30 +2526,11 @@ static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, ...@@ -2533,30 +2526,11 @@ static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port,
return 0; return 0;
} }
static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
unsigned long *supported) phy_interface_t interface, int speed, int duplex)
{
/* Port5 supports ethier RGMII or SGMII.
* Port6 supports SGMII only.
*/
switch (port) {
case 5:
if (mt7531_is_rgmii_port(priv, port))
break;
fallthrough;
case 6:
phylink_set(supported, 1000baseX_Full);
phylink_set(supported, 2500baseX_Full);
phylink_set(supported, 2500baseT_Full);
}
}
static void
mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port,
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; unsigned int val;
/* For adjusting speed and duplex of SGMII force mode. */ /* For adjusting speed and duplex of SGMII force mode. */
...@@ -2582,6 +2556,9 @@ mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port, ...@@ -2582,6 +2556,9 @@ mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port,
/* MT7531 SGMII 1G force mode can only work in full duplex mode, /* MT7531 SGMII 1G force mode can only work in full duplex mode,
* no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. * 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) && if ((speed == SPEED_10 || speed == SPEED_100) &&
duplex != DUPLEX_FULL) duplex != DUPLEX_FULL)
...@@ -2657,9 +2634,10 @@ static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, ...@@ -2657,9 +2634,10 @@ static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port,
return 0; 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; u32 val;
/* Only restart AN when AN is enabled */ /* Only restart AN when AN is enabled */
...@@ -2716,6 +2694,24 @@ mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ...@@ -2716,6 +2694,24 @@ mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
return priv->info->mac_port_config(ds, port, mode, state->interface); 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 static void
mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
const struct phylink_link_state *state) const struct phylink_link_state *state)
...@@ -2723,9 +2719,6 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ...@@ -2723,9 +2719,6 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
struct mt7530_priv *priv = ds->priv; struct mt7530_priv *priv = ds->priv;
u32 mcr_cur, mcr_new; u32 mcr_cur, mcr_new;
if (!mt753x_phy_mode_supported(ds, port, state))
goto unsupported;
switch (port) { switch (port) {
case 0 ... 4: /* Internal phy */ case 0 ... 4: /* Internal phy */
if (state->interface != PHY_INTERFACE_MODE_GMII) if (state->interface != PHY_INTERFACE_MODE_GMII)
...@@ -2780,17 +2773,6 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ...@@ -2780,17 +2773,6 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); 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, static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
unsigned int mode, unsigned int mode,
phy_interface_t interface) phy_interface_t interface)
...@@ -2800,16 +2782,13 @@ static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, ...@@ -2800,16 +2782,13 @@ static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
} }
static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port, static void mt753x_phylink_pcs_link_up(struct phylink_pcs *pcs,
unsigned int mode, phy_interface_t interface, unsigned int mode,
int speed, int duplex) phy_interface_t interface,
int speed, int duplex)
{ {
struct mt7530_priv *priv = ds->priv; if (pcs->ops->pcs_link_up)
pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex);
if (!priv->info->mac_pcs_link_up)
return;
priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
} }
static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
...@@ -2822,8 +2801,6 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, ...@@ -2822,8 +2801,6 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
struct mt7530_priv *priv = ds->priv; struct mt7530_priv *priv = ds->priv;
u32 mcr; u32 mcr;
mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
/* MT753x MAC works in 1G full duplex mode for all up-clocked /* MT753x MAC works in 1G full duplex mode for all up-clocked
...@@ -2903,81 +2880,51 @@ mt7531_cpu_port_config(struct dsa_switch *ds, int port) ...@@ -2903,81 +2880,51 @@ mt7531_cpu_port_config(struct dsa_switch *ds, int port)
return ret; return ret;
mt7530_write(priv, MT7530_PMCR_P(port), mt7530_write(priv, MT7530_PMCR_P(port),
PMCR_CPU_PORT_SETTING(priv->id)); 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, mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
speed, DUPLEX_FULL, true, true); speed, DUPLEX_FULL, true, true);
return 0; return 0;
} }
static void static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
mt7530_mac_port_validate(struct dsa_switch *ds, int port, struct phylink_config *config)
unsigned long *supported)
{ {
if (port == 5)
phylink_set(supported, 1000baseX_Full);
}
static void mt7531_mac_port_validate(struct dsa_switch *ds, int port,
unsigned long *supported)
{
struct mt7530_priv *priv = ds->priv;
mt7531_sgmii_validate(priv, port, supported);
}
static void
mt753x_phylink_validate(struct dsa_switch *ds, int port,
unsigned long *supported,
struct phylink_link_state *state)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
struct mt7530_priv *priv = ds->priv; struct mt7530_priv *priv = ds->priv;
if (state->interface != PHY_INTERFACE_MODE_NA && /* This switch only supports full-duplex at 1Gbps */
!mt753x_phy_mode_supported(ds, port, state)) { config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
linkmode_zero(supported); MAC_10 | MAC_100 | MAC_1000FD;
return;
}
phylink_set_port_modes(mask);
if (state->interface != PHY_INTERFACE_MODE_TRGMII &&
!phy_interface_mode_is_8023z(state->interface)) {
phylink_set(mask, 10baseT_Half);
phylink_set(mask, 10baseT_Full);
phylink_set(mask, 100baseT_Half);
phylink_set(mask, 100baseT_Full);
phylink_set(mask, Autoneg);
}
/* This switch only supports 1G full-duplex. */
if (state->interface != PHY_INTERFACE_MODE_MII)
phylink_set(mask, 1000baseT_Full);
priv->info->mac_port_validate(ds, port, mask); /* This driver does not make use of the speed, duplex, pause or the
* advertisement in its mac_config, so it is safe to mark this driver
* as non-legacy.
*/
config->legacy_pre_march2020 = false;
phylink_set(mask, Pause); priv->info->mac_port_get_caps(ds, port, config);
phylink_set(mask, Asym_Pause); }
linkmode_and(supported, supported, mask); static int mt753x_pcs_validate(struct phylink_pcs *pcs,
linkmode_and(state->advertising, state->advertising, mask); unsigned long *supported,
const struct phylink_link_state *state)
{
/* Autonegotiation is not supported in TRGMII nor 802.3z modes */
if (state->interface == PHY_INTERFACE_MODE_TRGMII ||
phy_interface_mode_is_8023z(state->interface))
phylink_clear(supported, Autoneg);
/* We can only operate at 2500BaseX or 1000BaseX. If requested return 0;
* to advertise both, only report advertising at 2500BaseX.
*/
phylink_helper_basex_speed(state);
} }
static int static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port, struct phylink_link_state *state)
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; u32 pmsr;
if (port < 0 || port >= MT7530_NUM_PORTS)
return -EINVAL;
pmsr = mt7530_read(priv, MT7530_PMSR_P(port)); pmsr = mt7530_read(priv, MT7530_PMSR_P(port));
state->link = (pmsr & PMSR_LINK); state->link = (pmsr & PMSR_LINK);
...@@ -3004,8 +2951,6 @@ mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port, ...@@ -3004,8 +2951,6 @@ mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port,
state->pause |= MLO_PAUSE_RX; state->pause |= MLO_PAUSE_RX;
if (pmsr & PMSR_TX_FC) if (pmsr & PMSR_TX_FC)
state->pause |= MLO_PAUSE_TX; state->pause |= MLO_PAUSE_TX;
return 1;
} }
static int static int
...@@ -3047,32 +2992,51 @@ mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port, ...@@ -3047,32 +2992,51 @@ mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port,
return 0; return 0;
} }
static int static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port, struct phylink_link_state *state)
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) if (state->interface == PHY_INTERFACE_MODE_SGMII)
return mt7531_sgmii_pcs_get_state_an(priv, port, state); mt7531_sgmii_pcs_get_state_an(priv, port, state);
else
return -EOPNOTSUPP; state->link = false;
} }
static int static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, phy_interface_t interface,
struct phylink_link_state *state) 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_validate = mt753x_pcs_validate,
.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_validate = mt753x_pcs_validate,
.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 static int
mt753x_setup(struct dsa_switch *ds) mt753x_setup(struct dsa_switch *ds)
{ {
struct mt7530_priv *priv = ds->priv; struct mt7530_priv *priv = ds->priv;
int ret = priv->info->sw_setup(ds); int ret = priv->info->sw_setup(ds);
int i;
if (ret) if (ret)
return ret; return ret;
...@@ -3085,6 +3049,13 @@ mt753x_setup(struct dsa_switch *ds) ...@@ -3085,6 +3049,13 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq) if (ret && priv->irq)
mt7530_free_irq_common(priv); 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; return ret;
} }
...@@ -3144,10 +3115,9 @@ static const struct dsa_switch_ops mt7530_switch_ops = { ...@@ -3144,10 +3115,9 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
.port_vlan_del = mt7530_port_vlan_del, .port_vlan_del = mt7530_port_vlan_del,
.port_mirror_add = mt753x_port_mirror_add, .port_mirror_add = mt753x_port_mirror_add,
.port_mirror_del = mt753x_port_mirror_del, .port_mirror_del = mt753x_port_mirror_del,
.phylink_validate = mt753x_phylink_validate, .phylink_get_caps = mt753x_phylink_get_caps,
.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_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_down = mt753x_phylink_mac_link_down,
.phylink_mac_link_up = mt753x_phylink_mac_link_up, .phylink_mac_link_up = mt753x_phylink_mac_link_up,
.get_mac_eee = mt753x_get_mac_eee, .get_mac_eee = mt753x_get_mac_eee,
...@@ -3157,39 +3127,34 @@ static const struct dsa_switch_ops mt7530_switch_ops = { ...@@ -3157,39 +3127,34 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
static const struct mt753x_info mt753x_table[] = { static const struct mt753x_info mt753x_table[] = {
[ID_MT7621] = { [ID_MT7621] = {
.id = ID_MT7621, .id = ID_MT7621,
.pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7530_setup, .sw_setup = mt7530_setup,
.phy_read = mt7530_phy_read, .phy_read = mt7530_phy_read,
.phy_write = mt7530_phy_write, .phy_write = mt7530_phy_write,
.pad_setup = mt7530_pad_clk_setup, .pad_setup = mt7530_pad_clk_setup,
.phy_mode_supported = mt7530_phy_mode_supported, .mac_port_get_caps = mt7530_mac_port_get_caps,
.mac_port_validate = mt7530_mac_port_validate,
.mac_port_get_state = mt7530_phylink_mac_link_state,
.mac_port_config = mt7530_mac_config, .mac_port_config = mt7530_mac_config,
}, },
[ID_MT7530] = { [ID_MT7530] = {
.id = ID_MT7530, .id = ID_MT7530,
.pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7530_setup, .sw_setup = mt7530_setup,
.phy_read = mt7530_phy_read, .phy_read = mt7530_phy_read,
.phy_write = mt7530_phy_write, .phy_write = mt7530_phy_write,
.pad_setup = mt7530_pad_clk_setup, .pad_setup = mt7530_pad_clk_setup,
.phy_mode_supported = mt7530_phy_mode_supported, .mac_port_get_caps = mt7530_mac_port_get_caps,
.mac_port_validate = mt7530_mac_port_validate,
.mac_port_get_state = mt7530_phylink_mac_link_state,
.mac_port_config = mt7530_mac_config, .mac_port_config = mt7530_mac_config,
}, },
[ID_MT7531] = { [ID_MT7531] = {
.id = ID_MT7531, .id = ID_MT7531,
.pcs_ops = &mt7531_pcs_ops,
.sw_setup = mt7531_setup, .sw_setup = mt7531_setup,
.phy_read = mt7531_ind_phy_read, .phy_read = mt7531_ind_phy_read,
.phy_write = mt7531_ind_phy_write, .phy_write = mt7531_ind_phy_write,
.pad_setup = mt7531_pad_setup, .pad_setup = mt7531_pad_setup,
.cpu_port_config = mt7531_cpu_port_config, .cpu_port_config = mt7531_cpu_port_config,
.phy_mode_supported = mt7531_phy_mode_supported, .mac_port_get_caps = mt7531_mac_port_get_caps,
.mac_port_validate = mt7531_mac_port_validate,
.mac_port_get_state = mt7531_phylink_mac_link_state,
.mac_port_config = mt7531_mac_config, .mac_port_config = mt7531_mac_config,
.mac_pcs_an_restart = mt7531_sgmii_restart_an,
.mac_pcs_link_up = mt7531_sgmii_link_up_force,
}, },
}; };
...@@ -3246,9 +3211,8 @@ mt7530_probe(struct mdio_device *mdiodev) ...@@ -3246,9 +3211,8 @@ mt7530_probe(struct mdio_device *mdiodev)
*/ */
if (!priv->info->sw_setup || !priv->info->pad_setup || if (!priv->info->sw_setup || !priv->info->pad_setup ||
!priv->info->phy_read || !priv->info->phy_write || !priv->info->phy_read || !priv->info->phy_write ||
!priv->info->phy_mode_supported || !priv->info->mac_port_get_caps ||
!priv->info->mac_port_validate || !priv->info->mac_port_config)
!priv->info->mac_port_get_state || !priv->info->mac_port_config)
return -EINVAL; return -EINVAL;
priv->id = priv->info->id; priv->id = priv->info->id;
......
...@@ -741,6 +741,12 @@ static const char *p5_intf_modes(unsigned int p5_interface) ...@@ -741,6 +741,12 @@ static const char *p5_intf_modes(unsigned int p5_interface)
struct mt7530_priv; 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 /* struct mt753x_info - This is the main data structure for holding the specific
* part for each supported device * part for each supported device
* @sw_setup: Holding the handler to a device initialization * @sw_setup: Holding the handler to a device initialization
...@@ -752,36 +758,27 @@ struct mt7530_priv; ...@@ -752,36 +758,27 @@ struct mt7530_priv;
* port * port
* @mac_port_validate: Holding the way to set addition validate type for a * @mac_port_validate: Holding the way to set addition validate type for a
* certan MAC port * 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 * @mac_port_config: Holding the way setting up the PHY attribute to a
* certain MAC port * 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 { struct mt753x_info {
enum mt753x_id id; enum mt753x_id id;
const struct phylink_pcs_ops *pcs_ops;
int (*sw_setup)(struct dsa_switch *ds); int (*sw_setup)(struct dsa_switch *ds);
int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
int (*cpu_port_config)(struct dsa_switch *ds, int port); int (*cpu_port_config)(struct dsa_switch *ds, int port);
bool (*phy_mode_supported)(struct dsa_switch *ds, int port, void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
const struct phylink_link_state *state); struct phylink_config *config);
void (*mac_port_validate)(struct dsa_switch *ds, int port, void (*mac_port_validate)(struct dsa_switch *ds, int port,
phy_interface_t interface,
unsigned long *supported); 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, int (*mac_port_config)(struct dsa_switch *ds, int port,
unsigned int mode, unsigned int mode,
phy_interface_t interface); 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 /* struct mt7530_priv - This is the main data structure for holding the state
...@@ -823,6 +820,7 @@ struct mt7530_priv { ...@@ -823,6 +820,7 @@ struct mt7530_priv {
u8 mirror_tx; u8 mirror_tx;
struct mt7530_port ports[MT7530_NUM_PORTS]; struct mt7530_port ports[MT7530_NUM_PORTS];
struct mt753x_pcs pcs[MT7530_NUM_PORTS];
/* protect among processes for registers access*/ /* protect among processes for registers access*/
struct mutex reg_mutex; struct mutex reg_mutex;
int irq; int irq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment