Re: [PATCH] staging: octeon-ethernet: fix incorrect PHY mode

2019-03-26 Thread Aaro Koskinen
Hi,

On Tue, Mar 26, 2019 at 10:01:50AM +0100, Andrew Lunn wrote:
> Humm, that is unique, as far as i know. Every other MAC driver uses
> of_get_phy_mode() to get the value out of device tree. The proprietary
> delay values can then be used to fine tune the basic delay setting
> read from DT.

Problem is that OCTEON DTBs do not have phy-mode at the moment.
With the patch, I got the mode right also for board with SGMII
and non-upgradable firmware passed DTB.

A.


Re: [PATCH] staging: octeon-ethernet: fix incorrect PHY mode

2019-03-26 Thread Andrew Lunn
> -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;
> + bool rx_delay;
> + bool tx_delay;
>  
> - if (!of_property_read_u32(np, "rx-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", _value)) {
>   cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value);
> - if (!of_property_read_u32(np, "tx-delay", _value))
> + rx_delay = delay_value > 0;
> + }
> + if (!of_property_read_u32(np, "tx-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;

Humm, that is unique, as far as i know. Every other MAC driver uses
of_get_phy_mode() to get the value out of device tree. The proprietary
delay values can then be used to fine tune the basic delay setting
read from DT.

Andrew


[PATCH] staging: octeon-ethernet: fix incorrect PHY mode

2019-03-25 Thread Aaro Koskinen
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 6d4cd041f0af
("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: 6d4cd041f0af ("net: phy: at803x: disable delay only for RGMII mode")
Signed-off-by: Aaro Koskinen 
---
 drivers/staging/octeon/ethernet-mdio.c   |  2 +-
 drivers/staging/octeon/ethernet.c| 40 +---
 drivers/staging/octeon/octeon-ethernet.h |  4 ++-
 3 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/octeon/ethernet-mdio.c 
b/drivers/staging/octeon/ethernet-mdio.c
index d6248eecf123..2aee64fdaec5 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -163,7 +163,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
goto no_phy;
 
phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
-   PHY_INTERFACE_MODE_GMII);
+   priv->phy_mode);
of_node_put(phy_node);
 
if (!phydev)
diff --git a/drivers/staging/octeon/ethernet.c 
b/drivers/staging/octeon/ethernet.c
index ce61c5670ef6..986db76705cc 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -653,14 +653,37 @@ static struct device_node *cvm_oct_node_for_port(struct 
device_node *pip,
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;
+   bool rx_delay;
+   bool tx_delay;
 
-   if (!of_property_read_u32(np, "rx-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", _value)) {
cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value);
-   if (!of_property_read_u32(np, "tx-delay", _value))
+   rx_delay = delay_value > 0;
+   }
+   if (!of_property_read_u32(np, "tx-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)
@@ -825,6 +848,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
priv->port = port;
priv->queue = cvmx_pko_get_base_queue(priv->port);
priv->fau = fau - cvmx_pko_get_num_queues(port) * 4;
+   priv->phy_mode = PHY_INTERFACE_MODE_NA;
for (qos = 0; qos < 16; qos++)
skb_queue_head_init(>tx_free_list[qos]);
for (qos = 0; qos < cvmx_pko_get_num_queues(port);
@@ -856,6 +880,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
break;
 
case CVMX_HELPER_INTERFACE_MODE_SGMII:
+   priv->phy_mode = PHY_INTERFACE_MODE_SGMII;
dev->netdev_ops = _oct_sgmii_netdev_ops;
strcpy(dev->name, "eth%d");
break;
@@ -865,11 +890,16 @@ static int cvm_oct_probe(struct platform_device *pdev)
strcpy(dev->name, "spi%d");
break;
 
-   case CVMX_HELPER_INTERFACE_MODE_RGMII:
case CVMX_HELPER_INTERFACE_MODE_GMII:
+   priv->phy_mode = PHY_INTERFACE_MODE_GMII;
+   dev->netdev_ops = _oct_rgmii_netdev_ops;
+   strcpy(dev->name, "eth%d");
+   break;
+
+   case CVMX_HELPER_INTERFACE_MODE_RGMII:
dev->netdev_ops = _oct_rgmii_netdev_ops;
strcpy(dev->name, "eth%d");
-   cvm_set_rgmii_delay(priv->of_node, interface,
+   cvm_set_rgmii_delay(priv, interface,
port_index);
break;