Commit 9612a8f9 authored by Russell King (Oracle)'s avatar Russell King (Oracle) Committed by David S. Miller

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: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 10728cd7
...@@ -1673,6 +1673,34 @@ qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_inde ...@@ -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); 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 static void
qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
const struct phylink_link_state *state) const struct phylink_link_state *state)
...@@ -1902,17 +1930,24 @@ qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, ...@@ -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); qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
} }
static int static struct qca8k_pcs *pcs_to_qca8k_pcs(struct phylink_pcs *pcs)
qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port,
struct phylink_link_state *state)
{ {
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; u32 reg;
int ret; int ret;
ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), &reg); ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), &reg);
if (ret < 0) if (ret < 0) {
return ret; state->link = false;
return;
}
state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP);
state->an_complete = state->link; state->an_complete = state->link;
...@@ -1935,13 +1970,39 @@ qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port, ...@@ -1935,13 +1970,39 @@ qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port,
break; break;
} }
state->pause = MLO_PAUSE_NONE;
if (reg & QCA8K_PORT_STATUS_RXFLOW) if (reg & QCA8K_PORT_STATUS_RXFLOW)
state->pause |= MLO_PAUSE_RX; state->pause |= MLO_PAUSE_RX;
if (reg & QCA8K_PORT_STATUS_TXFLOW) if (reg & QCA8K_PORT_STATUS_TXFLOW)
state->pause |= MLO_PAUSE_TX; 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 static void
...@@ -2806,6 +2867,9 @@ qca8k_setup(struct dsa_switch *ds) ...@@ -2806,6 +2867,9 @@ qca8k_setup(struct dsa_switch *ds)
if (ret) if (ret)
return 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 */ /* Make sure MAC06 is disabled */
ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL, ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN); QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
...@@ -2977,9 +3041,6 @@ qca8k_setup(struct dsa_switch *ds) ...@@ -2977,9 +3041,6 @@ qca8k_setup(struct dsa_switch *ds)
/* Flush the FDB table */ /* Flush the FDB table */
qca8k_fdb_flush(priv); 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 */ /* Set min a max ageing value supported */
ds->ageing_time_min = 7000; ds->ageing_time_min = 7000;
ds->ageing_time_max = 458745000; ds->ageing_time_max = 458745000;
...@@ -3018,7 +3079,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { ...@@ -3018,7 +3079,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
.port_vlan_add = qca8k_port_vlan_add, .port_vlan_add = qca8k_port_vlan_add,
.port_vlan_del = qca8k_port_vlan_del, .port_vlan_del = qca8k_port_vlan_del,
.phylink_get_caps = qca8k_phylink_get_caps, .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_config = qca8k_phylink_mac_config,
.phylink_mac_link_down = qca8k_phylink_mac_link_down, .phylink_mac_link_down = qca8k_phylink_mac_link_down,
.phylink_mac_link_up = qca8k_phylink_mac_link_up, .phylink_mac_link_up = qca8k_phylink_mac_link_up,
......
...@@ -376,6 +376,12 @@ struct qca8k_mdio_cache { ...@@ -376,6 +376,12 @@ struct qca8k_mdio_cache {
u16 hi; u16 hi;
}; };
struct qca8k_pcs {
struct phylink_pcs pcs;
struct qca8k_priv *priv;
int port;
};
struct qca8k_priv { struct qca8k_priv {
u8 switch_id; u8 switch_id;
u8 switch_revision; u8 switch_revision;
...@@ -397,6 +403,8 @@ struct qca8k_priv { ...@@ -397,6 +403,8 @@ struct qca8k_priv {
struct qca8k_mgmt_eth_data mgmt_eth_data; struct qca8k_mgmt_eth_data mgmt_eth_data;
struct qca8k_mib_eth_data mib_eth_data; struct qca8k_mib_eth_data mib_eth_data;
struct qca8k_mdio_cache mdio_cache; struct qca8k_mdio_cache mdio_cache;
struct qca8k_pcs pcs_port_0;
struct qca8k_pcs pcs_port_6;
}; };
struct qca8k_mib_desc { struct qca8k_mib_desc {
......
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