From 908050e88f781e7c904887e713d2254389dcd844 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 23 Nov 2021 15:34:14 +0000 Subject: net: dsa: qca8k: convert to use phylink_pcs Convert the qca8k driver to use the phylink_pcs support to talk to the SGMII PCS. Signed-off-by: Russell King (Oracle) --- drivers/net/dsa/qca8k.c | 85 ++++++++++++++++++++++++++++++++++++++++++------- drivers/net/dsa/qca8k.h | 8 +++++ 2 files changed, 81 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index 597c15e7bd65..fea4fc0e0549 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1173,6 +1173,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) @@ -1402,17 +1430,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), ®); - 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; @@ -1435,13 +1470,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 @@ -1966,6 +2027,9 @@ qca8k_setup(struct dsa_switch *ds) mutex_init(&priv->reg_mutex); + qca8k_setup_pcs(priv, &priv->pcs_port_0, 0); + qca8k_setup_pcs(priv, &priv->pcs_port_6, 6); + /* Start by setting up the register mapping */ priv->regmap = devm_regmap_init(ds->dev, NULL, priv, &qca8k_regmap_config); @@ -2157,9 +2221,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; @@ -2393,7 +2454,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, diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h index ab4a417b25a9..88d61b2d6ea7 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -336,6 +336,12 @@ struct qca8k_ports_config { u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ }; +struct qca8k_pcs { + struct phylink_pcs pcs; + struct qca8k_priv *priv; + int port; +}; + struct qca8k_priv { u8 switch_id; u8 switch_revision; @@ -353,6 +359,8 @@ struct qca8k_priv { struct dsa_switch_ops ops; struct gpio_desc *reset_gpio; unsigned int port_mtu[QCA8K_NUM_PORTS]; + struct qca8k_pcs pcs_port_0; + struct qca8k_pcs pcs_port_6; }; struct qca8k_mib_desc { -- cgit