Commit 9498da46 authored by Aaro Koskinen's avatar Aaro Koskinen Committed by Greg Kroah-Hartman

staging: octeon-ethernet: fix incorrect PHY mode

When connecting PHY, we set the mode to PHY_INTERFACE_MODE_GMII which is
not always correct. Specifically on boards where RGMII_RXID is needed
networking now longer works with at803x after commit 6d4cd041
("net: phy: at803x: disable delay only for RGMII mode").

Fix by passing the correct mode. Tested on EdgeRouter Lite
(RGMII_RXID, at803x PHY) and D-Link DSR-500N (RGMII, broadcom PHY).

Fixes: 6d4cd041 ("net: phy: at803x: disable delay only for RGMII mode")
Signed-off-by: default avatarAaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9b9c87cf
...@@ -163,7 +163,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev) ...@@ -163,7 +163,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
goto no_phy; goto no_phy;
phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
PHY_INTERFACE_MODE_GMII); priv->phy_mode);
of_node_put(phy_node); of_node_put(phy_node);
if (!phydev) if (!phydev)
......
...@@ -653,14 +653,37 @@ static struct device_node *cvm_oct_node_for_port(struct device_node *pip, ...@@ -653,14 +653,37 @@ static struct device_node *cvm_oct_node_for_port(struct device_node *pip,
return np; return np;
} }
static void cvm_set_rgmii_delay(struct device_node *np, int iface, int port) static void cvm_set_rgmii_delay(struct octeon_ethernet *priv, int iface,
int port)
{ {
struct device_node *np = priv->of_node;
u32 delay_value; u32 delay_value;
bool rx_delay;
bool tx_delay;
if (!of_property_read_u32(np, "rx-delay", &delay_value)) /* By default, both RX/TX delay is enabled in
* __cvmx_helper_rgmii_enable().
*/
rx_delay = true;
tx_delay = true;
if (!of_property_read_u32(np, "rx-delay", &delay_value)) {
cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value); cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value);
if (!of_property_read_u32(np, "tx-delay", &delay_value)) rx_delay = delay_value > 0;
}
if (!of_property_read_u32(np, "tx-delay", &delay_value)) {
cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value); cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value);
tx_delay = delay_value > 0;
}
if (!rx_delay && !tx_delay)
priv->phy_mode = PHY_INTERFACE_MODE_RGMII_ID;
else if (!rx_delay)
priv->phy_mode = PHY_INTERFACE_MODE_RGMII_RXID;
else if (!tx_delay)
priv->phy_mode = PHY_INTERFACE_MODE_RGMII_TXID;
else
priv->phy_mode = PHY_INTERFACE_MODE_RGMII;
} }
static int cvm_oct_probe(struct platform_device *pdev) static int cvm_oct_probe(struct platform_device *pdev)
...@@ -825,6 +848,7 @@ static int cvm_oct_probe(struct platform_device *pdev) ...@@ -825,6 +848,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
priv->port = port; priv->port = port;
priv->queue = cvmx_pko_get_base_queue(priv->port); priv->queue = cvmx_pko_get_base_queue(priv->port);
priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; priv->fau = fau - cvmx_pko_get_num_queues(port) * 4;
priv->phy_mode = PHY_INTERFACE_MODE_NA;
for (qos = 0; qos < 16; qos++) for (qos = 0; qos < 16; qos++)
skb_queue_head_init(&priv->tx_free_list[qos]); skb_queue_head_init(&priv->tx_free_list[qos]);
for (qos = 0; qos < cvmx_pko_get_num_queues(port); for (qos = 0; qos < cvmx_pko_get_num_queues(port);
...@@ -856,6 +880,7 @@ static int cvm_oct_probe(struct platform_device *pdev) ...@@ -856,6 +880,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
break; break;
case CVMX_HELPER_INTERFACE_MODE_SGMII: case CVMX_HELPER_INTERFACE_MODE_SGMII:
priv->phy_mode = PHY_INTERFACE_MODE_SGMII;
dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; dev->netdev_ops = &cvm_oct_sgmii_netdev_ops;
strcpy(dev->name, "eth%d"); strcpy(dev->name, "eth%d");
break; break;
...@@ -865,11 +890,16 @@ static int cvm_oct_probe(struct platform_device *pdev) ...@@ -865,11 +890,16 @@ static int cvm_oct_probe(struct platform_device *pdev)
strcpy(dev->name, "spi%d"); strcpy(dev->name, "spi%d");
break; break;
case CVMX_HELPER_INTERFACE_MODE_RGMII:
case CVMX_HELPER_INTERFACE_MODE_GMII: case CVMX_HELPER_INTERFACE_MODE_GMII:
priv->phy_mode = PHY_INTERFACE_MODE_GMII;
dev->netdev_ops = &cvm_oct_rgmii_netdev_ops;
strcpy(dev->name, "eth%d");
break;
case CVMX_HELPER_INTERFACE_MODE_RGMII:
dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; dev->netdev_ops = &cvm_oct_rgmii_netdev_ops;
strcpy(dev->name, "eth%d"); strcpy(dev->name, "eth%d");
cvm_set_rgmii_delay(priv->of_node, interface, cvm_set_rgmii_delay(priv, interface,
port_index); port_index);
break; break;
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#define OCTEON_ETHERNET_H #define OCTEON_ETHERNET_H
#include <linux/of.h> #include <linux/of.h>
#include <linux/phy.h>
#include <asm/octeon/cvmx-helper-board.h> #include <asm/octeon/cvmx-helper-board.h>
/** /**
...@@ -33,6 +33,8 @@ struct octeon_ethernet { ...@@ -33,6 +33,8 @@ struct octeon_ethernet {
* cvmx_helper_interface_mode_t * cvmx_helper_interface_mode_t
*/ */
int imode; int imode;
/* PHY mode */
phy_interface_t phy_mode;
/* List of outstanding tx buffers per queue */ /* List of outstanding tx buffers per queue */
struct sk_buff_head tx_free_list[16]; struct sk_buff_head tx_free_list[16];
unsigned int last_speed; unsigned int last_speed;
......
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