b7326c3df4955086de89beed700d502e98a78438
[librecmc/librecmc.git] /
1 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
2 Date: Tue, 31 Jan 2017 22:54:54 +0100
3 Subject: [PATCH] net: phy: broadcom: rehook BCM54612E specific init
4 MIME-Version: 1.0
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
7
8 This extra BCM54612E code in PHY driver isn't really aneg specific. Even
9 without it aneg works OK but the problem is no packets pass through PHY.
10
11 Moreover putting this code inside config_aneg callback didn't allow
12 resuming PHY correctly. When driver called phy_stop and phy_start it was
13 putting PHY machine into RESUMING state. After that machine was
14 switching into AN and NOLINK without ever calling phy_start_aneg. This
15 prevented this extra setup from being called and PHY didn't work.
16
17 This change has been verified to fix network on BCM47186B0 SoC device
18 with BCM54612E.
19
20 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
21 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
22 Signed-off-by: David S. Miller <davem@davemloft.net>
23 ---
24
25 --- a/drivers/net/phy/broadcom.c
26 +++ b/drivers/net/phy/broadcom.c
27 @@ -46,6 +46,34 @@ static int bcm54210e_config_init(struct
28         return 0;
29  }
30  
31 +static int bcm54612e_config_init(struct phy_device *phydev)
32 +{
33 +       /* Clear TX internal delay unless requested. */
34 +       if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
35 +           (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
36 +               /* Disable TXD to GTXCLK clock delay (default set) */
37 +               /* Bit 9 is the only field in shadow register 00011 */
38 +               bcm_phy_write_shadow(phydev, 0x03, 0);
39 +       }
40 +
41 +       /* Clear RX internal delay unless requested. */
42 +       if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
43 +           (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
44 +               u16 reg;
45 +
46 +               reg = bcm54xx_auxctl_read(phydev,
47 +                                         MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
48 +               /* Disable RXD to RXC delay (default set) */
49 +               reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
50 +               /* Clear shadow selector field */
51 +               reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
52 +               bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
53 +                                    MII_BCM54XX_AUXCTL_MISC_WREN | reg);
54 +       }
55 +
56 +       return 0;
57 +}
58 +
59  static int bcm54810_config(struct phy_device *phydev)
60  {
61         int rc, val;
62 @@ -250,6 +278,10 @@ static int bcm54xx_config_init(struct ph
63                 err = bcm54210e_config_init(phydev);
64                 if (err)
65                         return err;
66 +       } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
67 +               err = bcm54612e_config_init(phydev);
68 +               if (err)
69 +                       return err;
70         } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
71                 err = bcm54810_config(phydev);
72                 if (err)
73 @@ -395,39 +427,6 @@ static int bcm5481_config_aneg(struct ph
74         return ret;
75  }
76  
77 -static int bcm54612e_config_aneg(struct phy_device *phydev)
78 -{
79 -       int ret;
80 -
81 -       /* First, auto-negotiate. */
82 -       ret = genphy_config_aneg(phydev);
83 -
84 -       /* Clear TX internal delay unless requested. */
85 -       if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
86 -           (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
87 -               /* Disable TXD to GTXCLK clock delay (default set) */
88 -               /* Bit 9 is the only field in shadow register 00011 */
89 -               bcm_phy_write_shadow(phydev, 0x03, 0);
90 -       }
91 -
92 -       /* Clear RX internal delay unless requested. */
93 -       if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
94 -           (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
95 -               u16 reg;
96 -
97 -               reg = bcm54xx_auxctl_read(phydev,
98 -                                         MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
99 -               /* Disable RXD to RXC delay (default set) */
100 -               reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
101 -               /* Clear shadow selector field */
102 -               reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
103 -               bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
104 -                                    MII_BCM54XX_AUXCTL_MISC_WREN | reg);
105 -       }
106 -
107 -       return ret;
108 -}
109 -
110  static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
111  {
112         int val;
113 @@ -594,7 +593,7 @@ static struct phy_driver broadcom_driver
114                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
115         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
116         .config_init    = bcm54xx_config_init,
117 -       .config_aneg    = bcm54612e_config_aneg,
118 +       .config_aneg    = genphy_config_aneg,
119         .read_status    = genphy_read_status,
120         .ack_interrupt  = bcm_phy_ack_intr,
121         .config_intr    = bcm_phy_config_intr,