aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukasz Majewski2017-10-07 17:36:51 -0500
committerGreg Kroah-Hartman2017-11-08 03:08:35 -0600
commit64674bc8eeadb532cfc18e19a500294447d4bb2b (patch)
treeb88fd48d52692f0fecf41b404202a23b4181f4eb
parent227afd93a6ad921a89171422b60b91b9aa1d9af1 (diff)
downloadkernel-integration-tree-64674bc8eeadb532cfc18e19a500294447d4bb2b.tar.gz
kernel-integration-tree-64674bc8eeadb532cfc18e19a500294447d4bb2b.tar.xz
kernel-integration-tree-64674bc8eeadb532cfc18e19a500294447d4bb2b.zip
net: phy: dp83867: Recover from "port mirroring" N/A MODE4
[ Upstream commit ac6e058b75be71208e98a5808453aae9a17be480 ] The DP83867 when not properly bootstrapped - especially with LED_0 pin - can enter N/A MODE4 for "port mirroring" feature. To provide normal operation of the PHY, one needs not only to explicitly disable the port mirroring feature, but as well stop some IC internal testing (which disables RGMII communication). To do that the STRAP_STS1 (0x006E) register must be read and RESERVED bit 11 examined. When it is set, the another RESERVED bit (11) at PHYCR (0x0010) register must be clear to disable testing mode and enable RGMII communication. Thorough explanation of the problem can be found at following e2e thread: "DP83867IR: Problem with RESERVED bits in PHY Control Register (PHYCR) - Linux driver" https://e2e.ti.com/support/interface/ethernet/f/903/p/571313/2096954#2096954 Signed-off-by: Lukasz Majewski <lukma@denx.de> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/phy/dp83867.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 01cf094bee18..8f8496102926 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -33,6 +33,7 @@
33 33
34/* Extended Registers */ 34/* Extended Registers */
35#define DP83867_RGMIICTL 0x0032 35#define DP83867_RGMIICTL 0x0032
36#define DP83867_STRAP_STS1 0x006E
36#define DP83867_RGMIIDCTL 0x0086 37#define DP83867_RGMIIDCTL 0x0086
37 38
38#define DP83867_SW_RESET BIT(15) 39#define DP83867_SW_RESET BIT(15)
@@ -56,9 +57,13 @@
56#define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) 57#define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1)
57#define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) 58#define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0)
58 59
60/* STRAP_STS1 bits */
61#define DP83867_STRAP_STS1_RESERVED BIT(11)
62
59/* PHY CTRL bits */ 63/* PHY CTRL bits */
60#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 64#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
61#define DP83867_PHYCR_FIFO_DEPTH_MASK (3 << 14) 65#define DP83867_PHYCR_FIFO_DEPTH_MASK (3 << 14)
66#define DP83867_PHYCR_RESERVED_MASK BIT(11)
62 67
63/* RGMIIDCTL bits */ 68/* RGMIIDCTL bits */
64#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4 69#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
@@ -141,7 +146,7 @@ static int dp83867_of_init(struct phy_device *phydev)
141static int dp83867_config_init(struct phy_device *phydev) 146static int dp83867_config_init(struct phy_device *phydev)
142{ 147{
143 struct dp83867_private *dp83867; 148 struct dp83867_private *dp83867;
144 int ret, val; 149 int ret, val, bs;
145 u16 delay; 150 u16 delay;
146 151
147 if (!phydev->priv) { 152 if (!phydev->priv) {
@@ -164,6 +169,22 @@ static int dp83867_config_init(struct phy_device *phydev)
164 return val; 169 return val;
165 val &= ~DP83867_PHYCR_FIFO_DEPTH_MASK; 170 val &= ~DP83867_PHYCR_FIFO_DEPTH_MASK;
166 val |= (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT); 171 val |= (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT);
172
173 /* The code below checks if "port mirroring" N/A MODE4 has been
174 * enabled during power on bootstrap.
175 *
176 * Such N/A mode enabled by mistake can put PHY IC in some
177 * internal testing mode and disable RGMII transmission.
178 *
179 * In this particular case one needs to check STRAP_STS1
180 * register's bit 11 (marked as RESERVED).
181 */
182
183 bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1,
184 DP83867_DEVADDR);
185 if (bs & DP83867_STRAP_STS1_RESERVED)
186 val &= ~DP83867_PHYCR_RESERVED_MASK;
187
167 ret = phy_write(phydev, MII_DP83867_PHYCTRL, val); 188 ret = phy_write(phydev, MII_DP83867_PHYCTRL, val);
168 if (ret) 189 if (ret)
169 return ret; 190 return ret;