X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=drivers%2Fnet%2Fphy%2Fmarvell.c;h=46801c791903efcd36167d267a70be0b1ec978c8;hb=1415107e46460f988e19a5fc59e18f368e72ef19;hp=bd1cdc4f11d63ea56b13b77ea283d9aa61a680bd;hpb=9082eeac5de1335d663016668c9b89c290f5c79b;p=karo-tx-uboot.git diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index bd1cdc4f11..46801c7919 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -43,6 +43,24 @@ #define MIIM_88E1111_PHY_LED_DIRECT 0x4100 #define MIIM_88E1111_PHY_LED_COMBINE 0x411C +/* 88E1111 Extended PHY Specific Control Register */ +#define MIIM_88E1111_PHY_EXT_CR 0x14 +#define MIIM_88E1111_RX_DELAY 0x80 +#define MIIM_88E1111_TX_DELAY 0x2 + +/* 88E1111 Extended PHY Specific Status Register */ +#define MIIM_88E1111_PHY_EXT_SR 0x1b +#define MIIM_88E1111_HWCFG_MODE_MASK 0xf +#define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII 0xb +#define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII 0x3 +#define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK 0x4 +#define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI 0x9 +#define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO 0x8000 +#define MIIM_88E1111_HWCFG_FIBER_COPPER_RES 0x2000 + +#define MIIM_88E1111_COPPER 0 +#define MIIM_88E1111_FIBER 1 + /* 88E1118 PHY defines */ #define MIIM_88E1118_PHY_PAGE 22 #define MIIM_88E1118_PHY_LED_PAGE 3 @@ -162,19 +180,102 @@ static int m88e1011s_startup(struct phy_device *phydev) static int m88e1111s_config(struct phy_device *phydev) { int reg; + int timeout; 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)) { - reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x1b); - reg = (reg & 0xfff0) | 0xb; - phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, reg); - } else { - phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, 0x1f); + reg = phy_read(phydev, + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || + (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; + reg |= MIIM_88E1111_RX_DELAY; + } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { + reg &= ~MIIM_88E1111_RX_DELAY; + reg |= MIIM_88E1111_TX_DELAY; + } + + phy_write(phydev, + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); + + reg = phy_read(phydev, + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); + + reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); + + if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES) + reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII; + else + reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; + + phy_write(phydev, + MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); } - phy_write(phydev, MDIO_DEVAD_NONE, 0x14, 0x0cd2); + 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 (phydev->interface == PHY_INTERFACE_MODE_RTBI) { + reg = phy_read(phydev, + 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); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, + 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); + + /* soft reset */ + timeout = 1000; + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); + udelay(1000); + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + while ((reg & BMCR_RESET) && --timeout) { + udelay(1000); + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + } + if (!timeout) + printf("%s: phy soft reset timeout\n", __func__); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, + MIIM_88E1111_PHY_EXT_SR); + reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | + 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); + } + + /* soft reset */ + timeout = 1000; + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); + udelay(1000); + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + while ((reg & BMCR_RESET) && --timeout) { + udelay(1000); + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + } + if (!timeout) + printf("%s: phy soft reset timeout\n", __func__); genphy_config_aneg(phydev); @@ -324,6 +425,16 @@ static struct phy_driver M88E1118_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver M88E1118R_driver = { + .name = "Marvell 88E1118R", + .uid = 0x1410e40, + .mask = 0xffffff0, + .features = PHY_GBIT_FEATURES, + .config = &m88e1118_config, + .startup = &m88e1118_startup, + .shutdown = &genphy_shutdown, +}; + static struct phy_driver M88E1121R_driver = { .name = "Marvell 88E1121R", .uid = 0x1410cb0, @@ -354,14 +465,26 @@ static struct phy_driver M88E1149S_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver M88E1518_driver = { + .name = "Marvell 88E1518", + .uid = 0x1410dd1, + .mask = 0xffffff0, + .features = PHY_GBIT_FEATURES, + .config = &m88e1111s_config, + .startup = &m88e1011s_startup, + .shutdown = &genphy_shutdown, +}; + int phy_marvell_init(void) { phy_register(&M88E1149S_driver); phy_register(&M88E1145_driver); phy_register(&M88E1121R_driver); phy_register(&M88E1118_driver); + phy_register(&M88E1118R_driver); phy_register(&M88E1111S_driver); phy_register(&M88E1011S_driver); + phy_register(&M88E1518_driver); return 0; }