diff options
author | Sylvain Rochet <sylvain.rochet@finsecur.com> | 2015-02-13 15:35:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-14 23:30:55 -0500 |
commit | 2b0ba96cea6066d2543066fa524120b384f3bd6b (patch) | |
tree | b6f8ac9fb6c223c763e82887f19d02110aae6872 /drivers/net/phy | |
parent | 3b4711757d7903ab6fa88a9e7ab8901b8227da60 (diff) |
net: phy: micrel: disable NAND-tree for KSZ8021, KSZ8031, KSZ8051, KSZ8081
NAND-tree is used to check wiring between MAC and PHY using NAND gates
on the PHY side, hence the name.
NAND-tree initial status is latched at reset by probing the IRQ pin.
However some devices are sharing the PHY IRQ pin with other peripherals
such as Atmel SAMA5D[34]x-EK boards when using the optional TM7000
display module, therefore they are switching the PHY in NAND-tree test
mode depending on the current IRQ line status at reset.
This patch ensure PHY is not in NAND-tree test mode for all Micrel PHYs
using IRQ line as a NAND-tree toggle mode at reset.
Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/micrel.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3ad8ca76196d..1190fd8f0088 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
@@ -32,6 +32,7 @@ | |||
32 | /* Operation Mode Strap Override */ | 32 | /* Operation Mode Strap Override */ |
33 | #define MII_KSZPHY_OMSO 0x16 | 33 | #define MII_KSZPHY_OMSO 0x16 |
34 | #define KSZPHY_OMSO_B_CAST_OFF BIT(9) | 34 | #define KSZPHY_OMSO_B_CAST_OFF BIT(9) |
35 | #define KSZPHY_OMSO_NAND_TREE_ON BIT(5) | ||
35 | #define KSZPHY_OMSO_RMII_OVERRIDE BIT(1) | 36 | #define KSZPHY_OMSO_RMII_OVERRIDE BIT(1) |
36 | #define KSZPHY_OMSO_MII_OVERRIDE BIT(0) | 37 | #define KSZPHY_OMSO_MII_OVERRIDE BIT(0) |
37 | 38 | ||
@@ -76,6 +77,7 @@ struct kszphy_type { | |||
76 | u32 led_mode_reg; | 77 | u32 led_mode_reg; |
77 | u16 interrupt_level_mask; | 78 | u16 interrupt_level_mask; |
78 | bool has_broadcast_disable; | 79 | bool has_broadcast_disable; |
80 | bool has_nand_tree_disable; | ||
79 | bool has_rmii_ref_clk_sel; | 81 | bool has_rmii_ref_clk_sel; |
80 | }; | 82 | }; |
81 | 83 | ||
@@ -89,6 +91,7 @@ struct kszphy_priv { | |||
89 | static const struct kszphy_type ksz8021_type = { | 91 | static const struct kszphy_type ksz8021_type = { |
90 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 92 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
91 | .has_broadcast_disable = true, | 93 | .has_broadcast_disable = true, |
94 | .has_nand_tree_disable = true, | ||
92 | .has_rmii_ref_clk_sel = true, | 95 | .has_rmii_ref_clk_sel = true, |
93 | }; | 96 | }; |
94 | 97 | ||
@@ -98,11 +101,13 @@ static const struct kszphy_type ksz8041_type = { | |||
98 | 101 | ||
99 | static const struct kszphy_type ksz8051_type = { | 102 | static const struct kszphy_type ksz8051_type = { |
100 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 103 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
104 | .has_nand_tree_disable = true, | ||
101 | }; | 105 | }; |
102 | 106 | ||
103 | static const struct kszphy_type ksz8081_type = { | 107 | static const struct kszphy_type ksz8081_type = { |
104 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 108 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
105 | .has_broadcast_disable = true, | 109 | .has_broadcast_disable = true, |
110 | .has_nand_tree_disable = true, | ||
106 | .has_rmii_ref_clk_sel = true, | 111 | .has_rmii_ref_clk_sel = true, |
107 | }; | 112 | }; |
108 | 113 | ||
@@ -231,6 +236,26 @@ out: | |||
231 | return ret; | 236 | return ret; |
232 | } | 237 | } |
233 | 238 | ||
239 | static int kszphy_nand_tree_disable(struct phy_device *phydev) | ||
240 | { | ||
241 | int ret; | ||
242 | |||
243 | ret = phy_read(phydev, MII_KSZPHY_OMSO); | ||
244 | if (ret < 0) | ||
245 | goto out; | ||
246 | |||
247 | if (!(ret & KSZPHY_OMSO_NAND_TREE_ON)) | ||
248 | return 0; | ||
249 | |||
250 | ret = phy_write(phydev, MII_KSZPHY_OMSO, | ||
251 | ret & ~KSZPHY_OMSO_NAND_TREE_ON); | ||
252 | out: | ||
253 | if (ret) | ||
254 | dev_err(&phydev->dev, "failed to disable NAND tree mode\n"); | ||
255 | |||
256 | return ret; | ||
257 | } | ||
258 | |||
234 | static int kszphy_config_init(struct phy_device *phydev) | 259 | static int kszphy_config_init(struct phy_device *phydev) |
235 | { | 260 | { |
236 | struct kszphy_priv *priv = phydev->priv; | 261 | struct kszphy_priv *priv = phydev->priv; |
@@ -245,6 +270,9 @@ static int kszphy_config_init(struct phy_device *phydev) | |||
245 | if (type->has_broadcast_disable) | 270 | if (type->has_broadcast_disable) |
246 | kszphy_broadcast_disable(phydev); | 271 | kszphy_broadcast_disable(phydev); |
247 | 272 | ||
273 | if (type->has_nand_tree_disable) | ||
274 | kszphy_nand_tree_disable(phydev); | ||
275 | |||
248 | if (priv->rmii_ref_clk_sel) { | 276 | if (priv->rmii_ref_clk_sel) { |
249 | ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); | 277 | ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); |
250 | if (ret) { | 278 | if (ret) { |