net: phy: dp83867: add workaround for incorrect RX_CTRL pin strap
authorMurali Karicheri <m-karicheri2@ti.com>
Thu, 28 Jun 2018 19:26:34 +0000 (14:26 -0500)
committerJoe Hershberger <joe.hershberger@ni.com>
Thu, 26 Jul 2018 19:08:21 +0000 (14:08 -0500)
The data manual for DP83867IR/CR, SNLS484E[1], revised march 2017,
advises that strapping RX_DV/RX_CTRL pin in mode 1 and 2 is not
supported (see note below Table 5 (4-Level Strap Pins)).

It further advises that if a board has this pin strapped in mode 1 and
mode 2, then bit[7] of Configuration Register 4 (address 0x0031) must
be cleared to 0. This is to ensure proper operation of PHY.

Since it is not possible to detect in software if RX_DV/RX_CTRL pin is
incorrectly strapped, add a device-tree property to advertise this and
allow corrective action in software.
[1] http://www.ti.com/lit/ds/snls484e/snls484e.pdf

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Reviewed-by: Hannes Schmelzer <oe5hpm@oevsv.at>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Tested-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
drivers/net/phy/ti.c

index 8f3ed8a..f1c9f7b 100644 (file)
@@ -24,6 +24,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define DP83867_CTRL           0x1f
 
 /* Extended Registers */
+#define DP83867_CFG4           0x0031
 #define DP83867_RGMIICTL       0x0032
 #define DP83867_RGMIIDCTL      0x0086
 #define DP83867_IO_MUX_CFG     0x0170
@@ -95,6 +96,7 @@ struct dp83867_private {
        int tx_id_delay;
        int fifo_depth;
        int io_impedance;
+       bool rxctrl_strap_quirk;
 };
 
 /**
@@ -183,6 +185,8 @@ static int dp83867_of_init(struct phy_device *phydev)
        else
                dp83867->io_impedance = -EINVAL;
 
+       if (fdtdec_get_bool(fdt, node, "ti,dp83867-rxctrl-strap-quirk"))
+               dp83867->rxctrl_strap_quirk = true;
        dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
                                 "ti,rx-internal-delay", -1);
 
@@ -232,6 +236,15 @@ static int dp83867_config(struct phy_device *phydev)
        phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
                  val | DP83867_SW_RESTART);
 
+       /* Mode 1 or 2 workaround */
+       if (dp83867->rxctrl_strap_quirk) {
+               val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
+                                           DP83867_DEVADDR, phydev->addr);
+               val &= ~BIT(7);
+               phy_write_mmd_indirect(phydev, DP83867_CFG4,
+                                      DP83867_DEVADDR, phydev->addr, val);
+       }
+
        if (phy_interface_is_rgmii(phydev)) {
                ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
                        (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |