
T1040rdb has 2 VSC8514 quad PHYs attached to 8 ports from a layer 2 switch. The PHYs Serdes Auto-negotiation must be enabled in order to have link between internal PHYs and external PHYs.
Signed-off-by: Codrin Ciubotariu codrin.ciubotariu@freescale.com Cc: York Sun yorksun@freescale.com --- board/freescale/t104xrdb/eth.c | 115 +++++++++++++++++++++++++++++++++++++++++ include/configs/T1040RDB.h | 2 + 2 files changed, 117 insertions(+)
diff --git a/board/freescale/t104xrdb/eth.c b/board/freescale/t104xrdb/eth.c index 0188fd4..93b758d 100644 --- a/board/freescale/t104xrdb/eth.c +++ b/board/freescale/t104xrdb/eth.c @@ -14,12 +14,101 @@
#include "../common/fman.h"
+#define PHY_ID_VSC8514 0x00070670 + +#define PHY_ID_REG1 0x02 +#define PHY_ID_REG2 0x03 + +#define PHY_EXT_PAGE_ACCESS_EXTENDED3 0x3 +#define PHY_EXT_PAGE_ACCESS_GENERAL 0x10 +#define MIIM_VSC8514_MAC_SERDES_CON 0x10 +#define MIIM_VSC8514_MAC_SERDES_ANEG 0x80 + +/* Vitesse VSC8514 control register */ +#define MIIM_VSC8514_GENERAL18 0x12 +#define MIIM_VSC8514_GENERAL19 0x13 +#define MIIM_VSC8514_GENERAL23 0x17 + +/* Vitesse VSC8514 general purpose register 18 */ +#define MIIM_VSC8514_18G_QSGMII 0x80e0 +#define MIIM_VSC8514_18G_CMDSTAT 0x8000 + +#ifdef CONFIG_T1040RDB +static int vsc8514_config(struct mii_dev *bus, int phy_addr, + phy_interface_t interface) +{ + int i; + u32 val; + int timeout = 1000000; + + /* this is a quad PHY, so we must initialize 4 PHYs + * starting with phy_addr */ + for (i = phy_addr; i < phy_addr + 4; i++) { + /* configure register to access 19G */ + bus->write(bus, i, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_GENERAL); + + val = bus->read(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL19); + if (interface == PHY_INTERFACE_MODE_QSGMII) { + /* set bit 15:14 to '01' for QSGMII mode */ + val = (val & 0x3fff) | (1 << 14); + bus->write(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL19, val); + /* Enable 4 ports MAC QSGMII */ + bus->write(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL18, + MIIM_VSC8514_18G_QSGMII); + } + + val = bus->read(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL18); + /* When bit 15 is cleared the command has completed */ + while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--) + val = bus->read(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL18); + + if (0 == timeout) { + printf("PHY 8514 config failed\n"); + return -1; + } + + bus->write(bus, i, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); + + /* configure register to access 23 */ + val = bus->read(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL23); + /* set bits 10:8 to '000' */ + val = (val & 0xf8ff); + bus->write(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_GENERAL23, val); + + /* Enable Serdes Auto-negotiation */ + bus->write(bus, i, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_EXTENDED3); + val = bus->read(bus, i, MDIO_DEVAD_NONE, + MIIM_VSC8514_MAC_SERDES_CON); + val = val | MIIM_VSC8514_MAC_SERDES_ANEG; + bus->write(bus, i, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, + val); + bus->write(bus, i, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); + } + + return 0; +} +#endif + int board_eth_init(bd_t *bis) { #ifdef CONFIG_FMAN_ENET struct memac_mdio_info memac_mdio_info; unsigned int i; int phy_addr = 0; +#ifdef CONFIG_T1040RDB + struct mii_dev *bus; + u32 val; +#endif + printf("Initializing Fman\n");
memac_mdio_info.regs = @@ -66,6 +155,32 @@ int board_eth_init(bd_t *bis) }
cpu_eth_init(bis); + +#ifdef CONFIG_T1040RDB + bus = miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME); + + /* if there are VSC8514 quad PHYs over QSGMII, configure them + * these are l2switch PHYs and they are not associated + * with ethernet interfaces*/ + val = 0xFFFF & bus->read(bus, CONFIG_SYS_FM1_QSGMII11_PHY_ADDR, + MDIO_DEVAD_NONE, PHY_ID_REG1); + val <<= 16; + val += 0xFFFF & bus->read(bus, CONFIG_SYS_FM1_QSGMII11_PHY_ADDR, + MDIO_DEVAD_NONE, PHY_ID_REG2); + if (val == PHY_ID_VSC8514) + vsc8514_config(bus, CONFIG_SYS_FM1_QSGMII11_PHY_ADDR, + PHY_INTERFACE_MODE_QSGMII); + + val = 0xFFFF & bus->read(bus, CONFIG_SYS_FM1_QSGMII21_PHY_ADDR, + MDIO_DEVAD_NONE, PHY_ID_REG1); + val <<= 16; + val += 0xFFFF & bus->read(bus, CONFIG_SYS_FM1_QSGMII21_PHY_ADDR, + MDIO_DEVAD_NONE, PHY_ID_REG2); + if (val == PHY_ID_VSC8514) + vsc8514_config(bus, CONFIG_SYS_FM1_QSGMII21_PHY_ADDR, + PHY_INTERFACE_MODE_QSGMII); +#endif + #endif
return pci_eth_init(bis); diff --git a/include/configs/T1040RDB.h b/include/configs/T1040RDB.h index 395845b..af9d073 100644 --- a/include/configs/T1040RDB.h +++ b/include/configs/T1040RDB.h @@ -544,6 +544,8 @@ #endif
#ifdef CONFIG_FMAN_ENET +#define CONFIG_SYS_FM1_QSGMII11_PHY_ADDR 0x04 +#define CONFIG_SYS_FM1_QSGMII21_PHY_ADDR 0x08 #define CONFIG_SYS_SGMII1_PHY_ADDR 0x03 #define CONFIG_SYS_RGMII1_PHY_ADDR 0x01 #define CONFIG_SYS_RGMII2_PHY_ADDR 0x02