X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fnet%2Fphy%2Fmarvell.c;h=b7f300e40f2798c09bfa697d8edc860007fe4c17;hb=235c5b8315c6a9eb566fd3d99a098cc6db869fc5;hp=d24451be0a2d6fd56ff413e69cfc24877b79688b;hpb=ef5e821bd89aa059a20841e041221dadbf60aa7d;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index d24451b..b7f300e 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -8,10 +8,13 @@ */ #include #include +#include #include #define PHY_AUTONEGOTIATE_TIMEOUT 5000 +#define MII_MARVELL_PHY_PAGE 22 + /* 88E1011 PHY Status Register */ #define MIIM_88E1xxx_PHY_STATUS 0x11 #define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000 @@ -81,6 +84,26 @@ #define MIIM_88E1310_PHY_RGMII_CTRL 21 #define MIIM_88E1310_PHY_PAGE 22 +/* 88E151x PHY defines */ +/* Page 2 registers */ +#define MIIM_88E151x_PHY_MSCR 21 +#define MIIM_88E151x_RGMII_RX_DELAY BIT(5) +#define MIIM_88E151x_RGMII_TX_DELAY BIT(4) +#define MIIM_88E151x_RGMII_RXTX_DELAY (BIT(5) | BIT(4)) +/* Page 3 registers */ +#define MIIM_88E151x_LED_FUNC_CTRL 16 +#define MIIM_88E151x_LED_FLD_SZ 4 +#define MIIM_88E151x_LED0_OFFS (0 * MIIM_88E151x_LED_FLD_SZ) +#define MIIM_88E151x_LED1_OFFS (1 * MIIM_88E151x_LED_FLD_SZ) +#define MIIM_88E151x_LED0_ACT 3 +#define MIIM_88E151x_LED1_100_1000_LINK 6 +#define MIIM_88E151x_LED_TIMER_CTRL 18 +#define MIIM_88E151x_INT_EN_OFFS 7 +/* Page 18 registers */ +#define MIIM_88E151x_GENERAL_CTRL 20 +#define MIIM_88E151x_MODE_SGMII 1 +#define MIIM_88E151x_RESET_OFFS 15 + /* Marvell 88E1011S */ static int m88e1011s_config(struct phy_device *phydev) { @@ -162,10 +185,13 @@ static int m88e1xxx_parse_status(struct phy_device *phydev) static int m88e1011s_startup(struct phy_device *phydev) { - genphy_update_link(phydev); - m88e1xxx_parse_status(phydev); + int ret; - return 0; + ret = genphy_update_link(phydev); + if (ret) + return ret; + + return m88e1xxx_parse_status(phydev); } /* Marvell 88E1111S */ @@ -173,10 +199,7 @@ static int m88e1111s_config(struct phy_device *phydev) { int reg; - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { + if (phy_interface_is_rgmii(phydev)) { reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || @@ -279,13 +302,15 @@ void m88e1518_phy_writebits(struct phy_device *phydev, static int m88e1518_config(struct phy_device *phydev) { + u16 reg; + /* * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 * /88E1514 Rev A0, Errata Section 3.1 */ /* EEE initialization */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); @@ -294,43 +319,87 @@ static int m88e1518_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { /* Select page 18 */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 18); /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ - m88e1518_phy_writebits(phydev, 20, 0, 3, 1); + m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL, + 0, 3, MIIM_88E151x_MODE_SGMII); /* PHY reset is necessary after changing MODE[2:0] */ - m88e1518_phy_writebits(phydev, 20, 15, 1, 1); + m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL, + MIIM_88E151x_RESET_OFFS, 1, 1); /* Reset page selection */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0); udelay(100); } - return m88e1111s_config(phydev); + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + reg = phy_read(phydev, MDIO_DEVAD_NONE, + MIIM_88E1111_PHY_EXT_SR); + + reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); + reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; + reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; + + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_88E1111_PHY_EXT_SR, reg); + } + + if (phy_interface_is_rgmii(phydev)) { + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 2); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR); + reg &= ~MIIM_88E151x_RGMII_RXTX_DELAY; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + reg |= MIIM_88E151x_RGMII_RXTX_DELAY; + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + reg |= MIIM_88E151x_RGMII_RX_DELAY; + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + reg |= MIIM_88E151x_RGMII_TX_DELAY; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR, reg); + + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 0); + } + + /* soft reset */ + phy_reset(phydev); + + genphy_config_aneg(phydev); + genphy_restart_aneg(phydev); + + return 0; } /* Marvell 88E1510 */ static int m88e1510_config(struct phy_device *phydev) { /* Select page 3 */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 3); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, + MIIM_88E1118_PHY_LED_PAGE); /* Enable INTn output on LED[2] */ - m88e1518_phy_writebits(phydev, 18, 7, 1, 1); + m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_TIMER_CTRL, + MIIM_88E151x_INT_EN_OFFS, 1, 1); /* Configure LEDs */ - m88e1518_phy_writebits(phydev, 16, 0, 4, 3); /* LED[0]:0011 (ACT) */ - m88e1518_phy_writebits(phydev, 16, 4, 4, 6); /* LED[1]:0110 (LINK) */ + /* LED[0]:0011 (ACT) */ + m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL, + MIIM_88E151x_LED0_OFFS, MIIM_88E151x_LED_FLD_SZ, + MIIM_88E151x_LED0_ACT); + /* LED[1]:0110 (LINK 100/1000 Mbps) */ + m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL, + MIIM_88E151x_LED1_OFFS, MIIM_88E151x_LED_FLD_SZ, + MIIM_88E151x_LED1_100_1000_LINK); /* Reset page selection */ - phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0); return m88e1518_config(phydev); } @@ -349,22 +418,21 @@ static int m88e1118_config(struct phy_device *phydev) /* Change Page Number */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); - genphy_config_aneg(phydev); - - phy_reset(phydev); - - return 0; + return genphy_config_aneg(phydev); } static int m88e1118_startup(struct phy_device *phydev) { + int ret; + /* Change Page Number */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); - genphy_update_link(phydev); - m88e1xxx_parse_status(phydev); + ret = genphy_update_link(phydev); + if (ret) + return ret; - return 0; + return m88e1xxx_parse_status(phydev); } /* Marvell 88E1121R */ @@ -414,19 +482,25 @@ static int m88e1145_config(struct phy_device *phydev) genphy_config_aneg(phydev); - phy_reset(phydev); + /* soft reset */ + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + reg |= BMCR_RESET; + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg); return 0; } static int m88e1145_startup(struct phy_device *phydev) { - genphy_update_link(phydev); + int ret; + + ret = genphy_update_link(phydev); + if (ret) + return ret; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL, MIIM_88E1145_PHY_LED_DIRECT); - m88e1xxx_parse_status(phydev); - - return 0; + return m88e1xxx_parse_status(phydev); } /* Marvell 88E1149S */ @@ -471,8 +545,48 @@ static int m88e1310_config(struct phy_device *phydev) /* Ensure to return to page 0 */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); - genphy_config_aneg(phydev); - phy_reset(phydev); + return genphy_config_aneg(phydev); +} + +static int m88e1680_config(struct phy_device *phydev) +{ + /* + * As per Marvell Release Notes - Alaska V 88E1680 Rev A2 + * Errata Section 4.1 + */ + u16 reg; + int res; + + /* Matrix LED mode (not neede if single LED mode is used */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0004); + reg = phy_read(phydev, MDIO_DEVAD_NONE, 27); + reg |= (1 << 5); + phy_write(phydev, MDIO_DEVAD_NONE, 27, reg); + + /* QSGMII TX amplitude change */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00fd); + phy_write(phydev, MDIO_DEVAD_NONE, 8, 0x0b53); + phy_write(phydev, MDIO_DEVAD_NONE, 7, 0x200d); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); + + /* EEE initialization */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xb030); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x215c); + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00fc); + phy_write(phydev, MDIO_DEVAD_NONE, 24, 0x888c); + phy_write(phydev, MDIO_DEVAD_NONE, 25, 0x888c); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); + phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140); + + res = genphy_config_aneg(phydev); + if (res < 0) + return res; + + /* soft reset */ + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + reg |= BMCR_RESET; + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg); return 0; } @@ -550,17 +664,22 @@ static struct phy_driver M88E1149S_driver = { static struct phy_driver M88E1510_driver = { .name = "Marvell 88E1510", .uid = 0x1410dd0, - .mask = 0xffffff0, + .mask = 0xfffffff, .features = PHY_GBIT_FEATURES, .config = &m88e1510_config, .startup = &m88e1011s_startup, .shutdown = &genphy_shutdown, }; +/* + * This supports: + * 88E1518, uid 0x1410dd1 + * 88E1512, uid 0x1410dd4 + */ static struct phy_driver M88E1518_driver = { .name = "Marvell 88E1518", - .uid = 0x1410dd1, - .mask = 0xffffff0, + .uid = 0x1410dd0, + .mask = 0xffffffa, .features = PHY_GBIT_FEATURES, .config = &m88e1518_config, .startup = &m88e1011s_startup, @@ -577,6 +696,16 @@ static struct phy_driver M88E1310_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver M88E1680_driver = { + .name = "Marvell 88E1680", + .uid = 0x1410ed0, + .mask = 0xffffff0, + .features = PHY_GBIT_FEATURES, + .config = &m88e1680_config, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + int phy_marvell_init(void) { phy_register(&M88E1310_driver); @@ -589,6 +718,7 @@ int phy_marvell_init(void) phy_register(&M88E1011S_driver); phy_register(&M88E1510_driver); phy_register(&M88E1518_driver); + phy_register(&M88E1680_driver); return 0; }