diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 983c6b52d103..8039c4b99b71 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -19,19 +19,16 @@ #define PHY_ID_YT8531S 0x4f51e91a #define PHY_ID_YT8531 0x4f51e91b -/** - * YT8011 IO VOLTAGE LEVELS - * YT8011_RGMII_DVDDIO_3V3 -> VDDIO 3V3 - * YT8011_RGMII_DVDDIO_2V5 -> VDDIO 2V5 - * YT8011_RGMII_DVDDIO_1V8 -> VDDIO 1V8 - */ -#define YT8011_RGMII_DVDDIO_3V3 -/* #define YT8011_RGMII_DVDDIO_2V5 */ -/* #define YT8011_RGMII_DVDDIO_1V8 */ +enum { + YT8011_RGMII_DVDDIO_1V8 = 1, + YT8011_RGMII_DVDDIO_2V5, + YT8011_RGMII_DVDDIO_3V3 +}; struct yt8011_priv { u8 polling_mode; u8 chip_mode; + u8 vddio; }; #define YT8011_SPEED_MODE 0xc000 @@ -313,6 +310,55 @@ static int yt8011_config_aneg(struct phy_device *phydev) return 0; } +static int yt8011_config_vddio(struct phy_device *phydev) +{ + struct yt8011_priv *priv = phydev->priv; + + if (!(priv->chip_mode)) { /* rgmii config */ + switch (priv->vddio) { + case YT8011_RGMII_DVDDIO_2V5: + dev_info(&phydev->mdio.dev, "config PHY vddio 2v5\n"); + ytphy_write_ext(phydev, 0x9000, 0x8000); + ytphy_write_ext(phydev, 0x0062, 0x0000); + ytphy_write_ext(phydev, 0x9000, 0x0000); + ytphy_write_ext(phydev, 0x9031, 0xb200); + ytphy_write_ext(phydev, 0x9111, 0x5); + ytphy_write_ext(phydev, 0x9114, 0x3939); + ytphy_write_ext(phydev, 0x9112, 0xf); + ytphy_write_ext(phydev, 0x9110, 0x0); + ytphy_write_ext(phydev, 0x9113, 0x10); + ytphy_write_ext(phydev, 0x903d, 0x2); + break; + case YT8011_RGMII_DVDDIO_1V8: + dev_info(&phydev->mdio.dev, "config PHY for 1v8\n"); + ytphy_write_ext(phydev, 0x9000, 0x8000); + ytphy_write_ext(phydev, 0x0062, 0x0000); + ytphy_write_ext(phydev, 0x9000, 0x0000); + ytphy_write_ext(phydev, 0x9031, 0xb200); + ytphy_write_ext(phydev, 0x9116, 0x6); + ytphy_write_ext(phydev, 0x9119, 0x3939); + ytphy_write_ext(phydev, 0x9117, 0xf); + ytphy_write_ext(phydev, 0x9115, 0x0); + ytphy_write_ext(phydev, 0x9118, 0x20); + ytphy_write_ext(phydev, 0x903d, 0x3); + break; + case YT8011_RGMII_DVDDIO_3V3: + default: + dev_info(&phydev->mdio.dev, "config PHY for 3v3\n"); + ytphy_write_ext(phydev, 0x9000, 0x8000); + ytphy_write_ext(phydev, 0x0062, 0x0000); + ytphy_write_ext(phydev, 0x9000, 0x0000); + ytphy_write_ext(phydev, 0x9031, 0xb200); + ytphy_write_ext(phydev, 0x903b, 0x0040); + ytphy_write_ext(phydev, 0x903e, 0x3b3b); + ytphy_write_ext(phydev, 0x903c, 0xf); + ytphy_write_ext(phydev, 0x903d, 0x1000); + ytphy_write_ext(phydev, 0x9038, 0x0000); + break; + } + } + return 0; +} static int yt8011_aneg_done(struct phy_device *phydev) { int link_utp = 0; @@ -504,9 +550,31 @@ static int yt8512_led_init(struct phy_device *phydev) static int yt8011_config_init(struct phy_device *phydev) { struct yt8011_priv *priv = phydev->priv; + struct device_node *np = phydev->mdio.dev.of_node; + const char *vddio_conf; phydev->autoneg = AUTONEG_DISABLE; + if (!np) { + dev_err(&phydev->mdio.dev, "Device Tree node is missing\n"); + priv->vddio = YT8011_RGMII_DVDDIO_3V3; + } else { + if (of_property_read_string(np, "motorcomm,vddio", &vddio_conf)) { + dev_err(&phydev->mdio.dev, "Missing 'motorcomm,vddio' property in DTS, using 3v3 default\n"); + priv->vddio = YT8011_RGMII_DVDDIO_3V3; + } else { + if (!strcasecmp(vddio_conf, "1v8")) { + priv->vddio = YT8011_RGMII_DVDDIO_1V8; + } else if (!strcasecmp(vddio_conf, "2v5")) { + priv->vddio = YT8011_RGMII_DVDDIO_2V5; + } else if (!strcasecmp(vddio_conf, "3v3")) { + priv->vddio = YT8011_RGMII_DVDDIO_3V3; + } else { + dev_err(&phydev->mdio.dev, "Invalid 'motorcomm,vddio' value, using 3v3 default\n"); + priv->vddio = YT8011_RGMII_DVDDIO_3V3; + } + } + } /* UTP */ ytphy_write_ext(phydev, 0x9000, 0x0); @@ -520,53 +588,18 @@ static int yt8011_config_init(struct phy_device *phydev) ytphy_write_ext(phydev, 0x2015, 0x1012); ytphy_write_ext(phydev, 0x2005, 0x810); ytphy_write_ext(phydev, 0x2013, 0xff06); - ytphy_write_ext(phydev, 0x1000, 0x0028); - ytphy_write_ext(phydev, 0x1002, 0x3800); - ytphy_write_ext(phydev, 0x1090, 0x1012); - ytphy_write_ext(phydev, 0x1091, 0x1013); - ytphy_write_ext(phydev, 0x1100, 0x2020); - ytphy_write_mmd(phydev, 0x7, 0x1f42, 0x0016); + ytphy_write_ext(phydev, 0x1053, 0xf); + ytphy_write_ext(phydev, 0x105e, 0xa46c); ytphy_write_ext(phydev, 0x1088, 0x002b); - ytphy_write_ext(phydev, 0x1088, 0x022b); - ytphy_write_ext(phydev, 0x1088, 0x020b); + ytphy_write_ext(phydev, 0x1088, 0x002b); + ytphy_write_ext(phydev, 0x1088, 0xb); ytphy_write_ext(phydev, 0x3008, 0x143); ytphy_write_ext(phydev, 0x3009, 0x1918); - - if (!(priv->chip_mode)) { /* rgmii config */ -#if defined(YT8011_RGMII_DVDDIO_3V3) - ytphy_write_ext(phydev, 0x9000, 0x8000); - ytphy_write_ext(phydev, 0x0062, 0x0000); - ytphy_write_ext(phydev, 0x9000, 0x0000); - ytphy_write_ext(phydev, 0x9031, 0xb200); - ytphy_write_ext(phydev, 0x903b, 0x0040); - ytphy_write_ext(phydev, 0x903e, 0x3b3b); - ytphy_write_ext(phydev, 0x903c, 0xf); - ytphy_write_ext(phydev, 0x903d, 0x1000); - ytphy_write_ext(phydev, 0x9038, 0x0000); -#elif defined(YT8011_RGMII_DVDDIO_2V5) - ytphy_write_ext(phydev, 0x9000, 0x8000); - ytphy_write_ext(phydev, 0x0062, 0x0000); - ytphy_write_ext(phydev, 0x9000, 0x0000); - ytphy_write_ext(phydev, 0x9031, 0xb200); - ytphy_write_ext(phydev, 0x9111, 0x5); - ytphy_write_ext(phydev, 0x9114, 0x3939); - ytphy_write_ext(phydev, 0x9112, 0xf); - ytphy_write_ext(phydev, 0x9110, 0x0); - ytphy_write_ext(phydev, 0x9113, 0x10); - ytphy_write_ext(phydev, 0x903d, 0x2); -#elif defined(YT8011_RGMII_DVDDIO_1V8) - ytphy_write_ext(phydev, 0x9000, 0x8000); - ytphy_write_ext(phydev, 0x0062, 0x0000); - ytphy_write_ext(phydev, 0x9000, 0x0000); - ytphy_write_ext(phydev, 0x9031, 0xb200); - ytphy_write_ext(phydev, 0x9116, 0x6); - ytphy_write_ext(phydev, 0x9119, 0x3939); - ytphy_write_ext(phydev, 0x9117, 0xf); - ytphy_write_ext(phydev, 0x9115, 0x0); - ytphy_write_ext(phydev, 0x9118, 0x20); - ytphy_write_ext(phydev, 0x903d, 0x3); -#endif - } + ytphy_write_ext(phydev, 0x9095, 0x1a1a); + ytphy_write_ext(phydev, 0x9096, 0x1a10); + ytphy_write_ext(phydev, 0x9097, 0x101a); + ytphy_write_ext(phydev, 0x9098, 0x01ff); + yt8011_config_vddio(phydev); ytphy_soft_reset(phydev);