X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fphy%2Fmarvell.c;h=efbbd31ff71ba1df73a07b2be1469d58768316ca;hb=1d63ec3fa40e4899ad1d74d5ed3c926acfda54f2;hp=c3058a40b2241bde2abf4a11c42f0a365dab4593;hpb=c52d428dccbd793e991ce0bcc45c6ca8d33aabf7;p=oweals%2Fu-boot.git diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index c3058a40b2..efbbd31ff7 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1,18 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Marvell PHY drivers * - * SPDX-License-Identifier: GPL-2.0+ - * * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ -#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 @@ -82,6 +82,51 @@ #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 + +static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr, + int devaddr, int regnum) +{ + int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE); + int val; + + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, devaddr); + val = phy_read(phydev, MDIO_DEVAD_NONE, regnum); + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, oldpage); + + return val; +} + +static int m88e1xxx_phy_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) +{ + int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE); + + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, devaddr); + phy_write(phydev, MDIO_DEVAD_NONE, regnum, val); + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, oldpage); + + return 0; +} + /* Marvell 88E1011S */ static int m88e1011s_config(struct phy_device *phydev) { @@ -112,7 +157,7 @@ static int m88e1xxx_parse_status(struct phy_device *phydev) mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS); if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) && - !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { + !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { int i = 0; puts("Waiting for PHY realtime link"); @@ -128,10 +173,10 @@ static int m88e1xxx_parse_status(struct phy_device *phydev) putc('.'); udelay(1000); mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, - MIIM_88E1xxx_PHY_STATUS); + MIIM_88E1xxx_PHY_STATUS); } puts(" done\n"); - udelay(500000); /* another 500 ms (results in faster booting) */ + mdelay(500); /* another 500 ms (results in faster booting) */ } else { if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) phydev->link = 1; @@ -177,14 +222,11 @@ 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); + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { + (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { reg &= ~MIIM_88E1111_TX_DELAY; @@ -195,10 +237,10 @@ static int m88e1111s_config(struct phy_device *phydev) } phy_write(phydev, - MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); reg = phy_read(phydev, - MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); @@ -208,47 +250,47 @@ static int m88e1111s_config(struct phy_device *phydev) reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; phy_write(phydev, - MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { reg = phy_read(phydev, - MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); + 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); + MIIM_88E1111_PHY_EXT_SR, reg); } if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { reg = phy_read(phydev, - MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); phy_write(phydev, - MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); reg = phy_read(phydev, MDIO_DEVAD_NONE, - MIIM_88E1111_PHY_EXT_SR); + MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | MIIM_88E1111_HWCFG_FIBER_COPPER_RES); reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; phy_write(phydev, MDIO_DEVAD_NONE, - MIIM_88E1111_PHY_EXT_SR, reg); + MIIM_88E1111_PHY_EXT_SR, reg); /* soft reset */ phy_reset(phydev); reg = phy_read(phydev, MDIO_DEVAD_NONE, - MIIM_88E1111_PHY_EXT_SR); + MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | - MIIM_88E1111_HWCFG_FIBER_COPPER_RES); + MIIM_88E1111_HWCFG_FIBER_COPPER_RES); reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; phy_write(phydev, MDIO_DEVAD_NONE, - MIIM_88E1111_PHY_EXT_SR, reg); + MIIM_88E1111_PHY_EXT_SR, reg); } /* soft reset */ @@ -264,7 +306,7 @@ static int m88e1111s_config(struct phy_device *phydev) * m88e1518_phy_writebits - write bits to a register */ void m88e1518_phy_writebits(struct phy_device *phydev, - u8 reg_num, u16 offset, u16 len, u16 data) + u8 reg_num, u16 offset, u16 len, u16 data) { u16 reg, mask; @@ -283,13 +325,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); @@ -298,43 +342,88 @@ 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 || + 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); } @@ -381,10 +470,10 @@ static int m88e1121_config(struct phy_device *phydev) /* Switch the page to access the led register */ pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, - MIIM_88E1121_PHY_LED_PAGE); + MIIM_88E1121_PHY_LED_PAGE); /* Configure leds */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL, - MIIM_88E1121_PHY_LED_DEF); + MIIM_88E1121_PHY_LED_DEF); /* Restore the page pointer */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg); @@ -407,7 +496,7 @@ static int m88e1145_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR, - MIIM_88E1xxx_PHY_MDI_X_AUTO); + MIIM_88E1xxx_PHY_MDI_X_AUTO); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) @@ -417,7 +506,10 @@ 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; } @@ -431,7 +523,7 @@ static int m88e1145_startup(struct phy_device *phydev) return ret; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL, - MIIM_88E1145_PHY_LED_DIRECT); + MIIM_88E1145_PHY_LED_DIRECT); return m88e1xxx_parse_status(phydev); } @@ -596,21 +688,30 @@ 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, + .readext = &m88e1xxx_phy_extread, + .writeext = &m88e1xxx_phy_extwrite, }; +/* + * 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, .shutdown = &genphy_shutdown, + .readext = &m88e1xxx_phy_extread, + .writeext = &m88e1xxx_phy_extwrite, }; static struct phy_driver M88E1310_driver = {