Commit 7e14a2dc authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: felix: use resolved link config in mac_link_up()

Phylink now requires that parameters established through
auto-negotiation be written into the MAC at the time of the
mac_link_up() callback. In the case of felix, that means taking the port
out of reset, setting the correct timers for PAUSE frames, and
enabling/disabling TX flow control.

This patch also splits the inband and noinband configuration of the
vsc9959 PCS (currently found in a function called "init") into 2
different functions, which have a nomenclature closer to phylink:
"config", for inband setup, and "link_up", for noinband (forced) setup.

This is necessary as a preparation step for giving up control of the PCS
to phylink, which will be done in further patch series.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b4c23545
...@@ -233,6 +233,32 @@ static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port, ...@@ -233,6 +233,32 @@ static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port,
static void felix_phylink_mac_config(struct dsa_switch *ds, int port, static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
unsigned int link_an_mode, unsigned int link_an_mode,
const struct phylink_link_state *state) const struct phylink_link_state *state)
{
struct ocelot *ocelot = ds->priv;
struct felix *felix = ocelot_to_felix(ocelot);
if (felix->info->pcs_config)
felix->info->pcs_config(ocelot, port, link_an_mode, state);
}
static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
unsigned int link_an_mode,
phy_interface_t interface)
{
struct ocelot *ocelot = ds->priv;
struct ocelot_port *ocelot_port = ocelot->ports[port];
ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
QSYS_SWITCH_PORT_MODE, port);
}
static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
unsigned int link_an_mode,
phy_interface_t interface,
struct phy_device *phydev,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{ {
struct ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
...@@ -250,7 +276,7 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port, ...@@ -250,7 +276,7 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
DEV_CLOCK_CFG_LINK_SPEED(OCELOT_SPEED_1000), DEV_CLOCK_CFG_LINK_SPEED(OCELOT_SPEED_1000),
DEV_CLOCK_CFG); DEV_CLOCK_CFG);
switch (state->speed) { switch (speed) {
case SPEED_10: case SPEED_10:
mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(3); mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(3);
break; break;
...@@ -261,12 +287,9 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port, ...@@ -261,12 +287,9 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
case SPEED_2500: case SPEED_2500:
mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(1); mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(1);
break; break;
case SPEED_UNKNOWN:
mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(0);
break;
default: default:
dev_err(ocelot->dev, "Unsupported speed on port %d: %d\n", dev_err(ocelot->dev, "Unsupported speed on port %d: %d\n",
port, state->speed); port, speed);
return; return;
} }
...@@ -275,7 +298,7 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port, ...@@ -275,7 +298,7 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
*/ */
mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA; mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA;
if (state->pause & MLO_PAUSE_TX) if (tx_pause)
mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA | mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA |
SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) | SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) | SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
...@@ -288,37 +311,9 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port, ...@@ -288,37 +311,9 @@ static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port); ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
if (felix->info->pcs_init) /* Undo the effects of felix_phylink_mac_link_down:
felix->info->pcs_init(ocelot, port, link_an_mode, state); * enable MAC module
*/
if (felix->info->port_sched_speed_set)
felix->info->port_sched_speed_set(ocelot, port,
state->speed);
}
static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
unsigned int link_an_mode,
phy_interface_t interface)
{
struct ocelot *ocelot = ds->priv;
struct ocelot_port *ocelot_port = ocelot->ports[port];
ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
QSYS_SWITCH_PORT_MODE, port);
}
static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
unsigned int link_an_mode,
phy_interface_t interface,
struct phy_device *phydev,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
struct ocelot *ocelot = ds->priv;
struct ocelot_port *ocelot_port = ocelot->ports[port];
/* Enable MAC module */
ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG); DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
...@@ -335,6 +330,13 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, ...@@ -335,6 +330,13 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
QSYS_SWITCH_PORT_MODE_PORT_ENA, QSYS_SWITCH_PORT_MODE_PORT_ENA,
QSYS_SWITCH_PORT_MODE, port); QSYS_SWITCH_PORT_MODE, port);
if (felix->info->pcs_link_up)
felix->info->pcs_link_up(ocelot, port, link_an_mode, interface,
speed, duplex);
if (felix->info->port_sched_speed_set)
felix->info->port_sched_speed_set(ocelot, port, speed);
} }
static void felix_port_qos_map_init(struct ocelot *ocelot, int port) static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
......
...@@ -28,9 +28,13 @@ struct felix_info { ...@@ -28,9 +28,13 @@ struct felix_info {
int imdio_pci_bar; int imdio_pci_bar;
int (*mdio_bus_alloc)(struct ocelot *ocelot); int (*mdio_bus_alloc)(struct ocelot *ocelot);
void (*mdio_bus_free)(struct ocelot *ocelot); void (*mdio_bus_free)(struct ocelot *ocelot);
void (*pcs_init)(struct ocelot *ocelot, int port, void (*pcs_config)(struct ocelot *ocelot, int port,
unsigned int link_an_mode, unsigned int link_an_mode,
const struct phylink_link_state *state); const struct phylink_link_state *state);
void (*pcs_link_up)(struct ocelot *ocelot, int port,
unsigned int link_an_mode,
phy_interface_t interface,
int speed, int duplex);
void (*pcs_link_state)(struct ocelot *ocelot, int port, void (*pcs_link_state)(struct ocelot *ocelot, int port,
struct phylink_link_state *state); struct phylink_link_state *state);
int (*prevalidate_phy_mode)(struct ocelot *ocelot, int port, int (*prevalidate_phy_mode)(struct ocelot *ocelot, int port,
......
This diff is collapsed.
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