X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fphy%2Fbroadcom.c;h=e4afa90dca02e7c6c620f9dfbeaa56c16322ec83;hb=e1541b1d7fb94ed9ac2bfe4c324afd91d77aee11;hp=4b2808eff00f27320ea60fc15c7ac089f6b50faa;hpb=1b564cecc358ccd08691c879fca95c2075fcb702;p=oweals%2Fu-boot.git diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 4b2808eff0..e4afa90dca 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -30,6 +30,29 @@ #define MIIM_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */ #define MIIM_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */ +#define MIIM_BCM_AUXCNTL_SHDWSEL_MISC 0x0007 +#define MIIM_BCM_AUXCNTL_ACTL_SMDSP_EN 0x0800 + +#define MIIM_BCM_CHANNEL_WIDTH 0x2000 + +static void bcm_phy_write_misc(struct phy_device *phydev, + u16 reg, u16 chl, u16 value) +{ + int reg_val; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL, + MIIM_BCM_AUXCNTL_SHDWSEL_MISC); + + reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL); + reg_val |= MIIM_BCM_AUXCNTL_ACTL_SMDSP_EN; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL, reg_val); + + reg_val = (chl * MIIM_BCM_CHANNEL_WIDTH) | reg; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL, reg_val); + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA, value); +} + /* Broadcom BCM5461S */ static int bcm5461_config(struct phy_device *phydev) { @@ -84,11 +107,14 @@ static int bcm54xx_parse_status(struct phy_device *phydev) static int bcm54xx_startup(struct phy_device *phydev) { + int ret; + /* Read the Status (2x to make sure link is right) */ - genphy_update_link(phydev); - bcm54xx_parse_status(phydev); + ret = genphy_update_link(phydev); + if (ret) + return ret; - return 0; + return bcm54xx_parse_status(phydev); } /* Broadcom BCM5482S */ @@ -139,18 +165,60 @@ static int bcm5482_config(struct phy_device *phydev) static int bcm_cygnus_startup(struct phy_device *phydev) { + int ret; + /* Read the Status (2x to make sure link is right) */ - genphy_update_link(phydev); - genphy_parse_link(phydev); + ret = genphy_update_link(phydev); + if (ret) + return ret; - return 0; + return genphy_parse_link(phydev); +} + +static void bcm_cygnus_afe(struct phy_device *phydev) +{ + /* ensures smdspclk is enabled */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL, 0x0c30); + + /* AFE_VDAC_ICTRL_0 bit 7:4 Iq=1100 for 1g 10bt, normal modes */ + bcm_phy_write_misc(phydev, 0x39, 0x01, 0xA7C8); + + /* AFE_HPF_TRIM_OTHERS bit11=1, short cascode for all modes*/ + bcm_phy_write_misc(phydev, 0x3A, 0x00, 0x0803); + + /* AFE_TX_CONFIG_1 bit 7:4 Iq=1100 for test modes */ + bcm_phy_write_misc(phydev, 0x3A, 0x01, 0xA740); + + /* AFE TEMPSEN_OTHERS rcal_HT, rcal_LT 10000 */ + bcm_phy_write_misc(phydev, 0x3A, 0x03, 0x8400); + + /* AFE_FUTURE_RSV bit 2:0 rccal <2:0>=100 */ + bcm_phy_write_misc(phydev, 0x3B, 0x00, 0x0004); + + /* Adjust bias current trim to overcome digital offSet */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x02); + + /* make rcal=100, since rdb default is 000 */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x17, 0x00B1); + phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x0010); + + /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x17, 0x00B0); + phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x0010); + + /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x17, 0x00B0); + phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x0000); } static int bcm_cygnus_config(struct phy_device *phydev) { genphy_config_aneg(phydev); - phy_reset(phydev); + /* AFE settings for PHY stability */ + bcm_cygnus_afe(phydev); + /* Forcing aneg after applying the AFE settings */ + genphy_restart_aneg(phydev); return 0; } @@ -239,17 +307,21 @@ static u32 bcm5482_parse_serdes_sr(struct phy_device *phydev) */ static int bcm5482_startup(struct phy_device *phydev) { + int ret; + if (bcm5482_is_serdes(phydev)) { bcm5482_parse_serdes_sr(phydev); phydev->port = PORT_FIBRE; - } else { - /* Wait for auto-negotiation to complete or fail */ - genphy_update_link(phydev); - /* Parse BCM54xx copper aux status register */ - bcm54xx_parse_status(phydev); + return 0; } - return 0; + /* Wait for auto-negotiation to complete or fail */ + ret = genphy_update_link(phydev); + if (ret) + return ret; + + /* Parse BCM54xx copper aux status register */ + return bcm54xx_parse_status(phydev); } static struct phy_driver BCM5461S_driver = {