Commit b4748553 authored by Sascha Hauer's avatar Sascha Hauer Committed by David S. Miller

net: ethernet: mvneta: Fix Serdes configuration for SoCs without comphy

The MVNETA_SERDES_CFG register is only available on older SoCs like the
Armada XP. On newer SoCs like the Armada 38x the fields are moved to
comphy. This patch moves the writes to this register next to the comphy
initialization, so that depending on the SoC either comphy or
MVNETA_SERDES_CFG is configured.
With this we no longer write to the MVNETA_SERDES_CFG on SoCs where it
doesn't exist.
Suggested-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ef7232da
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
#define MVNETA_TX_IN_PRGRS BIT(1) #define MVNETA_TX_IN_PRGRS BIT(1)
#define MVNETA_TX_FIFO_EMPTY BIT(8) #define MVNETA_TX_FIFO_EMPTY BIT(8)
#define MVNETA_RX_MIN_FRAME_SIZE 0x247c #define MVNETA_RX_MIN_FRAME_SIZE 0x247c
/* Only exists on Armada XP and Armada 370 */
#define MVNETA_SERDES_CFG 0x24A0 #define MVNETA_SERDES_CFG 0x24A0
#define MVNETA_SGMII_SERDES_PROTO 0x0cc7 #define MVNETA_SGMII_SERDES_PROTO 0x0cc7
#define MVNETA_QSGMII_SERDES_PROTO 0x0667 #define MVNETA_QSGMII_SERDES_PROTO 0x0667
...@@ -3529,26 +3530,55 @@ static int mvneta_setup_txqs(struct mvneta_port *pp) ...@@ -3529,26 +3530,55 @@ static int mvneta_setup_txqs(struct mvneta_port *pp)
return 0; return 0;
} }
static int mvneta_comphy_init(struct mvneta_port *pp) static int mvneta_comphy_init(struct mvneta_port *pp, phy_interface_t interface)
{ {
int ret; int ret;
if (!pp->comphy) ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, interface);
return 0;
ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET,
pp->phy_interface);
if (ret) if (ret)
return ret; return ret;
return phy_power_on(pp->comphy); return phy_power_on(pp->comphy);
} }
static int mvneta_config_interface(struct mvneta_port *pp,
phy_interface_t interface)
{
int ret = 0;
if (pp->comphy) {
if (interface == PHY_INTERFACE_MODE_SGMII ||
interface == PHY_INTERFACE_MODE_1000BASEX ||
interface == PHY_INTERFACE_MODE_2500BASEX) {
ret = mvneta_comphy_init(pp, interface);
}
} else {
switch (interface) {
case PHY_INTERFACE_MODE_QSGMII:
mvreg_write(pp, MVNETA_SERDES_CFG,
MVNETA_QSGMII_SERDES_PROTO);
break;
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
mvreg_write(pp, MVNETA_SERDES_CFG,
MVNETA_SGMII_SERDES_PROTO);
break;
default:
return -EINVAL;
}
}
pp->phy_interface = interface;
return ret;
}
static void mvneta_start_dev(struct mvneta_port *pp) static void mvneta_start_dev(struct mvneta_port *pp)
{ {
int cpu; int cpu;
WARN_ON(mvneta_comphy_init(pp)); WARN_ON(mvneta_config_interface(pp, pp->phy_interface));
mvneta_max_rx_size_set(pp, pp->pkt_size); mvneta_max_rx_size_set(pp, pp->pkt_size);
mvneta_txq_max_tx_size_set(pp, pp->pkt_size); mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
...@@ -3926,14 +3956,10 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, ...@@ -3926,14 +3956,10 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
if (state->speed == SPEED_2500) if (state->speed == SPEED_2500)
new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE;
if (pp->comphy && pp->phy_interface != state->interface && if (pp->phy_interface != state->interface) {
(state->interface == PHY_INTERFACE_MODE_SGMII || if (pp->comphy)
state->interface == PHY_INTERFACE_MODE_1000BASEX || WARN_ON(phy_power_off(pp->comphy));
state->interface == PHY_INTERFACE_MODE_2500BASEX)) { WARN_ON(mvneta_config_interface(pp, state->interface));
pp->phy_interface = state->interface;
WARN_ON(phy_power_off(pp->comphy));
WARN_ON(mvneta_comphy_init(pp));
} }
if (new_ctrl0 != gmac_ctrl0) if (new_ctrl0 != gmac_ctrl0)
...@@ -4977,20 +5003,10 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp, ...@@ -4977,20 +5003,10 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
} }
/* Power up the port */ /* Power up the port */
static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
{ {
/* MAC Cause register should be cleared */ /* MAC Cause register should be cleared */
mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
else if (phy_mode == PHY_INTERFACE_MODE_SGMII ||
phy_interface_mode_is_8023z(phy_mode))
mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
else if (!phy_interface_mode_is_rgmii(phy_mode))
return -EINVAL;
return 0;
} }
/* Device initialization routine */ /* Device initialization routine */
...@@ -5176,11 +5192,7 @@ static int mvneta_probe(struct platform_device *pdev) ...@@ -5176,11 +5192,7 @@ static int mvneta_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
goto err_netdev; goto err_netdev;
err = mvneta_port_power_up(pp, phy_mode); mvneta_port_power_up(pp, phy_mode);
if (err < 0) {
dev_err(&pdev->dev, "can't power up port\n");
goto err_netdev;
}
/* Armada3700 network controller does not support per-cpu /* Armada3700 network controller does not support per-cpu
* operation, so only single NAPI should be initialized. * operation, so only single NAPI should be initialized.
...@@ -5334,11 +5346,7 @@ static int mvneta_resume(struct device *device) ...@@ -5334,11 +5346,7 @@ static int mvneta_resume(struct device *device)
} }
} }
mvneta_defaults_set(pp); mvneta_defaults_set(pp);
err = mvneta_port_power_up(pp, pp->phy_interface); mvneta_port_power_up(pp, pp->phy_interface);
if (err < 0) {
dev_err(device, "can't power up port\n");
return err;
}
netif_device_attach(dev); netif_device_attach(dev);
......
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