aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2017-01-31 16:54:54 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-01 14:20:20 -0500
commit62e13097c46c69dbd7544ab2cd585ccf48f360a4 (patch)
treed66ae203ddc68ae0ca919224e541992e29e1bd68
parent974c3f19acebaa40e391c69056ccf851e40a9c0c (diff)
net: phy: broadcom: rehook BCM54612E specific init
This extra BCM54612E code in PHY driver isn't really aneg specific. Even without it aneg works OK but the problem is no packets pass through PHY. Moreover putting this code inside config_aneg callback didn't allow resuming PHY correctly. When driver called phy_stop and phy_start it was putting PHY machine into RESUMING state. After that machine was switching into AN and NOLINK without ever calling phy_start_aneg. This prevented this extra setup from being called and PHY didn't work. This change has been verified to fix network on BCM47186B0 SoC device with BCM54612E. Signed-off-by: Rafał Miłecki <rafal@milecki.pl> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/broadcom.c67
1 files changed, 33 insertions, 34 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 794b9ec81ba5..9cd8b27d1292 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -46,6 +46,34 @@ static int bcm54210e_config_init(struct phy_device *phydev)
46 return 0; 46 return 0;
47} 47}
48 48
49static int bcm54612e_config_init(struct phy_device *phydev)
50{
51 /* Clear TX internal delay unless requested. */
52 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
53 (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
54 /* Disable TXD to GTXCLK clock delay (default set) */
55 /* Bit 9 is the only field in shadow register 00011 */
56 bcm_phy_write_shadow(phydev, 0x03, 0);
57 }
58
59 /* Clear RX internal delay unless requested. */
60 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
61 (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
62 u16 reg;
63
64 reg = bcm54xx_auxctl_read(phydev,
65 MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
66 /* Disable RXD to RXC delay (default set) */
67 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
68 /* Clear shadow selector field */
69 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
70 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
71 MII_BCM54XX_AUXCTL_MISC_WREN | reg);
72 }
73
74 return 0;
75}
76
49static int bcm54810_config(struct phy_device *phydev) 77static int bcm54810_config(struct phy_device *phydev)
50{ 78{
51 int rc, val; 79 int rc, val;
@@ -250,6 +278,10 @@ static int bcm54xx_config_init(struct phy_device *phydev)
250 err = bcm54210e_config_init(phydev); 278 err = bcm54210e_config_init(phydev);
251 if (err) 279 if (err)
252 return err; 280 return err;
281 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
282 err = bcm54612e_config_init(phydev);
283 if (err)
284 return err;
253 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) { 285 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
254 err = bcm54810_config(phydev); 286 err = bcm54810_config(phydev);
255 if (err) 287 if (err)
@@ -395,39 +427,6 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
395 return ret; 427 return ret;
396} 428}
397 429
398static int bcm54612e_config_aneg(struct phy_device *phydev)
399{
400 int ret;
401
402 /* First, auto-negotiate. */
403 ret = genphy_config_aneg(phydev);
404
405 /* Clear TX internal delay unless requested. */
406 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
407 (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
408 /* Disable TXD to GTXCLK clock delay (default set) */
409 /* Bit 9 is the only field in shadow register 00011 */
410 bcm_phy_write_shadow(phydev, 0x03, 0);
411 }
412
413 /* Clear RX internal delay unless requested. */
414 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
415 (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
416 u16 reg;
417
418 reg = bcm54xx_auxctl_read(phydev,
419 MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
420 /* Disable RXD to RXC delay (default set) */
421 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
422 /* Clear shadow selector field */
423 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
424 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
425 MII_BCM54XX_AUXCTL_MISC_WREN | reg);
426 }
427
428 return ret;
429}
430
431static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 430static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
432{ 431{
433 int val; 432 int val;
@@ -590,7 +589,7 @@ static struct phy_driver broadcom_drivers[] = {
590 .features = PHY_GBIT_FEATURES, 589 .features = PHY_GBIT_FEATURES,
591 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 590 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
592 .config_init = bcm54xx_config_init, 591 .config_init = bcm54xx_config_init,
593 .config_aneg = bcm54612e_config_aneg, 592 .config_aneg = genphy_config_aneg,
594 .read_status = genphy_read_status, 593 .read_status = genphy_read_status,
595 .ack_interrupt = bcm_phy_ack_intr, 594 .ack_interrupt = bcm_phy_ack_intr,
596 .config_intr = bcm_phy_config_intr, 595 .config_intr = bcm_phy_config_intr,