diff options
author | Heiko Schocher <hs@denx.de> | 2010-01-20 09:04:28 +0100 |
---|---|---|
committer | Ben Warren <biggerbadderben@gmail.com> | 2010-01-31 22:37:12 -0800 |
commit | 582c55a0274f38e6e7e35b95e7ab81d3e912f700 (patch) | |
tree | 738a6e228401060be601b4fdd795e2de0b3d4bd3 /drivers/qe | |
parent | d7e354374c8eb0a5d8b8226b881c5ee276c77a60 (diff) |
83xx, uec: split enet_interface in two variables
There's no sensible reason to unite speed and interface type into
one variable. So split this variable enet_interface into two
vars: enet_interface_type, which hold the interface type and speed.
Also: add the possibility for switching between 10 and 100 MBit
interfaces on the fly, when running in FAST_ETH mode.
Signed-off-by: Heiko Schocher <hs@denx.de>
Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
Diffstat (limited to 'drivers/qe')
-rw-r--r-- | drivers/qe/uec.c | 122 | ||||
-rw-r--r-- | drivers/qe/uec.h | 34 | ||||
-rw-r--r-- | drivers/qe/uec_phy.c | 84 |
3 files changed, 131 insertions, 109 deletions
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index db95adaeef9..27dc5009c80 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -323,9 +323,10 @@ static int uec_set_mac_duplex(uec_private_t *uec, int duplex) return 0; } -static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode) +static int uec_set_mac_if_mode(uec_private_t *uec, + enet_interface_type_e if_mode, int speed) { - enet_interface_e enet_if_mode; + enet_interface_type_e enet_if_mode; uec_info_t *uec_info; uec_t *uec_regs; u32 upsmr; @@ -346,52 +347,68 @@ static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode) upsmr = in_be32(&uec->uccf->uf_regs->upsmr); upsmr &= ~(UPSMR_RPM | UPSMR_TBIM | UPSMR_R10M | UPSMR_RMM); - switch (enet_if_mode) { - case ENET_100_MII: - case ENET_10_MII: + switch (speed) { + case 10: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; + switch (enet_if_mode) { + case MII: + break; + case RGMII: + upsmr |= (UPSMR_RPM | UPSMR_R10M); + break; + case RMII: + upsmr |= (UPSMR_R10M | UPSMR_RMM); + break; + default: + return -EINVAL; + break; + } break; - case ENET_1000_GMII: - maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - break; - case ENET_1000_TBI: - maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - upsmr |= UPSMR_TBIM; - break; - case ENET_1000_RTBI: - maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - upsmr |= (UPSMR_RPM | UPSMR_TBIM); - break; - case ENET_1000_RGMII_RXID: - case ENET_1000_RGMII_ID: - case ENET_1000_RGMII: - maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - upsmr |= UPSMR_RPM; - break; - case ENET_100_RGMII: - maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; - upsmr |= UPSMR_RPM; - break; - case ENET_10_RGMII: - maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; - upsmr |= (UPSMR_RPM | UPSMR_R10M); - break; - case ENET_100_RMII: - maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; - upsmr |= UPSMR_RMM; - break; - case ENET_10_RMII: + case 100: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; - upsmr |= (UPSMR_R10M | UPSMR_RMM); + switch (enet_if_mode) { + case MII: + break; + case RGMII: + upsmr |= UPSMR_RPM; + break; + case RMII: + upsmr |= UPSMR_RMM; + break; + default: + return -EINVAL; + break; + } break; - case ENET_1000_SGMII: + case 1000: maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - upsmr |= UPSMR_SGMM; + switch (enet_if_mode) { + case GMII: + break; + case TBI: + upsmr |= UPSMR_TBIM; + break; + case RTBI: + upsmr |= (UPSMR_RPM | UPSMR_TBIM); + break; + case RGMII_RXID: + case RGMII_ID: + case RGMII: + upsmr |= UPSMR_RPM; + break; + case SGMII: + upsmr |= UPSMR_SGMM; + break; + default: + return -EINVAL; + break; + } break; default: return -EINVAL; break; } + out_be32(&uec_regs->maccfg2, maccfg2); out_be32(&uec->uccf->uf_regs->upsmr, upsmr); @@ -504,7 +521,7 @@ static void adjust_link(struct eth_device *dev) struct uec_mii_info *mii_info = uec->mii_info; extern void change_phy_interface_mode(struct eth_device *dev, - enet_interface_e mode); + enet_interface_type_e mode, int speed); uec_regs = uec->uec_regs; if (mii_info->link) { @@ -522,25 +539,19 @@ static void adjust_link(struct eth_device *dev) } if (mii_info->speed != uec->oldspeed) { + enet_interface_type_e mode = \ + uec->uec_info->enet_interface_type; if (uec->uec_info->uf_info.eth_type == GIGA_ETH) { switch (mii_info->speed) { case 1000: break; case 100: printf ("switching to rgmii 100\n"); - /* change phy to rgmii 100 */ - change_phy_interface_mode(dev, - ENET_100_RGMII); - /* change the MAC interface mode */ - uec_set_mac_if_mode(uec,ENET_100_RGMII); + mode = RGMII; break; case 10: printf ("switching to rgmii 10\n"); - /* change phy to rgmii 10 */ - change_phy_interface_mode(dev, - ENET_10_RGMII); - /* change the MAC interface mode */ - uec_set_mac_if_mode(uec,ENET_10_RGMII); + mode = RGMII; break; default: printf("%s: Ack,Speed(%d)is illegal\n", @@ -549,6 +560,11 @@ static void adjust_link(struct eth_device *dev) } } + /* change phy */ + change_phy_interface_mode(dev, mode, mii_info->speed); + /* change the MAC interface mode */ + uec_set_mac_if_mode(uec, mode, mii_info->speed); + printf("%s: Speed %dBT\n", dev->name, mii_info->speed); uec->oldspeed = mii_info->speed; } @@ -980,7 +996,6 @@ static int uec_startup(uec_private_t *uec) int num_threads_tx; int num_threads_rx; u32 utbipar; - enet_interface_e enet_interface; u32 length; u32 align; qe_bd_t *bd; @@ -1060,7 +1075,7 @@ static int uec_startup(uec_private_t *uec) out_be32(&uec_regs->maccfg2, MACCFG2_INIT_VALUE); /* Setup MAC interface mode */ - uec_set_mac_if_mode(uec, uec_info->enet_interface); + uec_set_mac_if_mode(uec, uec_info->enet_interface_type, uec_info->speed); /* Setup MII management base */ #ifndef CONFIG_eTSEC_MDIO_BUS @@ -1075,7 +1090,6 @@ static int uec_startup(uec_private_t *uec) /* Setup UTBIPAR */ utbipar = in_be32(&uec_regs->utbipar); utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK; - enet_interface = uec->uec_info->enet_interface; /* Initialize UTBIPAR address to CONFIG_UTBIPAR_INIT_TBIPA for ALL UEC. * This frees up the remaining SMI addresses for use. @@ -1084,7 +1098,8 @@ static int uec_startup(uec_private_t *uec) out_be32(&uec_regs->utbipar, utbipar); /* Configure the TBI for SGMII operation */ - if (uec->uec_info->enet_interface == ENET_1000_SGMII) { + if ((uec->uec_info->enet_interface_type == SGMII) && + (uec->uec_info->speed == 1000)) { uec_write_phy_reg(uec->dev, uec_regs->utbipar, ENET_TBI_MII_ANA, TBIANA_SETTINGS); @@ -1215,6 +1230,7 @@ static int uec_init(struct eth_device* dev, bd_t *bd) if (err || i <= 0) printf("warning: %s: timeout on PHY link\n", dev->name); + adjust_link(dev); uec->the_first_run = 1; } diff --git a/drivers/qe/uec.h b/drivers/qe/uec.h index febfbcef532..2a9e2dcd9c2 100644 --- a/drivers/qe/uec.h +++ b/drivers/qe/uec.h @@ -662,22 +662,18 @@ typedef enum uec_num_of_threads { /* UEC ethernet interface type */ -typedef enum enet_interface { - ENET_10_MII, - ENET_10_RMII, - ENET_10_RGMII, - ENET_100_MII, - ENET_100_RMII, - ENET_100_RGMII, - ENET_1000_GMII, - ENET_1000_RGMII, - ENET_1000_RGMII_ID, - ENET_1000_RGMII_RXID, - ENET_1000_RGMII_TXID, - ENET_1000_TBI, - ENET_1000_RTBI, - ENET_1000_SGMII -} enet_interface_e; +typedef enum enet_interface_type { + MII, + RMII, + RGMII, + GMII, + RGMII_ID, + RGMII_RXID, + RGMII_TXID, + TBI, + RTBI, + SGMII +} enet_interface_type_e; /* UEC initialization info struct */ @@ -696,7 +692,8 @@ typedef enum enet_interface { .tx_bd_ring_len = 16, \ .rx_bd_ring_len = 16, \ .phy_address = CONFIG_SYS_UEC##num##_PHY_ADDR, \ - .enet_interface = CONFIG_SYS_UEC##num##_INTERFACE_MODE, \ + .enet_interface_type = CONFIG_SYS_UEC##num##_INTERFACE_TYPE, \ + .speed = CONFIG_SYS_UEC##num##_INTERFACE_SPEED, \ } typedef struct uec_info { @@ -708,7 +705,8 @@ typedef struct uec_info { u16 rx_bd_ring_len; u16 tx_bd_ring_len; u8 phy_address; - enet_interface_e enet_interface; + enet_interface_type_e enet_interface_type; + int speed; } uec_info_t; /* UEC driver initialized info diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index 97151839428..c4214d9a0ae 100644 --- a/drivers/qe/uec_phy.c +++ b/drivers/qe/uec_phy.c @@ -401,7 +401,8 @@ static int bcm_init(struct uec_mii_info *mii_info) gbit_config_aneg(mii_info); - if (uec->uec_info->enet_interface == ENET_1000_RGMII_RXID) { + if ((uec->uec_info->enet_interface_type == RGMII_RXID) && + (uec->uec_info->speed == 1000)) { u16 val; int cnt = 50; @@ -429,20 +430,22 @@ static int marvell_init(struct uec_mii_info *mii_info) { struct eth_device *edev = mii_info->dev; uec_private_t *uec = edev->priv; - enum enet_interface iface = uec->uec_info->enet_interface; + enum enet_interface_type iface = uec->uec_info->enet_interface_type; + int speed = uec->uec_info->speed; - if (iface == ENET_1000_RGMII_ID || - iface == ENET_1000_RGMII_RXID || - iface == ENET_1000_RGMII_TXID) { + if ((speed == 1000) && + (iface == RGMII_ID || + iface == RGMII_RXID || + iface == RGMII_TXID)) { int temp; temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR); - if (iface == ENET_1000_RGMII_ID) { + if (iface == RGMII_ID) { temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY; - } else if (iface == ENET_1000_RGMII_RXID) { + } else if (iface == RGMII_RXID) { temp &= ~MII_M1111_TX_DELAY; temp |= MII_M1111_RX_DELAY; - } else if (iface == ENET_1000_RGMII_TXID) { + } else if (iface == RGMII_TXID) { temp &= ~MII_M1111_RX_DELAY; temp |= MII_M1111_TX_DELAY; } @@ -795,7 +798,9 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info) } void marvell_phy_interface_mode (struct eth_device *dev, - enet_interface_e mode) + enet_interface_type_e type, + int speed + ) { uec_private_t *uec = (uec_private_t *) dev->priv; struct uec_mii_info *mii_info; @@ -807,33 +812,35 @@ void marvell_phy_interface_mode (struct eth_device *dev, } mii_info = uec->mii_info; - if (mode == ENET_100_RGMII) { - phy_write (mii_info, 0x00, 0x9140); - phy_write (mii_info, 0x1d, 0x001f); - phy_write (mii_info, 0x1e, 0x200c); - phy_write (mii_info, 0x1d, 0x0005); - phy_write (mii_info, 0x1e, 0x0000); - phy_write (mii_info, 0x1e, 0x0100); - phy_write (mii_info, 0x09, 0x0e00); - phy_write (mii_info, 0x04, 0x01e1); - phy_write (mii_info, 0x00, 0x9140); - phy_write (mii_info, 0x00, 0x1000); - udelay (100000); - phy_write (mii_info, 0x00, 0x2900); - phy_write (mii_info, 0x14, 0x0cd2); - phy_write (mii_info, 0x00, 0xa100); - phy_write (mii_info, 0x09, 0x0000); - phy_write (mii_info, 0x1b, 0x800b); - phy_write (mii_info, 0x04, 0x05e1); - phy_write (mii_info, 0x00, 0xa100); - phy_write (mii_info, 0x00, 0x2100); - udelay (1000000); - } else if (mode == ENET_10_RGMII) { - phy_write (mii_info, 0x14, 0x8e40); - phy_write (mii_info, 0x1b, 0x800b); - phy_write (mii_info, 0x14, 0x0c82); - phy_write (mii_info, 0x00, 0x8100); - udelay (1000000); + if (type == RGMII) { + if (speed == 100) { + phy_write (mii_info, 0x00, 0x9140); + phy_write (mii_info, 0x1d, 0x001f); + phy_write (mii_info, 0x1e, 0x200c); + phy_write (mii_info, 0x1d, 0x0005); + phy_write (mii_info, 0x1e, 0x0000); + phy_write (mii_info, 0x1e, 0x0100); + phy_write (mii_info, 0x09, 0x0e00); + phy_write (mii_info, 0x04, 0x01e1); + phy_write (mii_info, 0x00, 0x9140); + phy_write (mii_info, 0x00, 0x1000); + udelay (100000); + phy_write (mii_info, 0x00, 0x2900); + phy_write (mii_info, 0x14, 0x0cd2); + phy_write (mii_info, 0x00, 0xa100); + phy_write (mii_info, 0x09, 0x0000); + phy_write (mii_info, 0x1b, 0x800b); + phy_write (mii_info, 0x04, 0x05e1); + phy_write (mii_info, 0x00, 0xa100); + phy_write (mii_info, 0x00, 0x2100); + udelay (1000000); + } else if (speed == 10) { + phy_write (mii_info, 0x14, 0x8e40); + phy_write (mii_info, 0x1b, 0x800b); + phy_write (mii_info, 0x14, 0x0c82); + phy_write (mii_info, 0x00, 0x8100); + udelay (1000000); + } } /* handle 88e1111 rev.B2 erratum 5.6 */ @@ -844,9 +851,10 @@ void marvell_phy_interface_mode (struct eth_device *dev, /* now the B2 will correctly report autoneg completion status */ } -void change_phy_interface_mode (struct eth_device *dev, enet_interface_e mode) +void change_phy_interface_mode (struct eth_device *dev, + enet_interface_type_e type, int speed) { #ifdef CONFIG_PHY_MODE_NEED_CHANGE - marvell_phy_interface_mode (dev, mode); + marvell_phy_interface_mode (dev, type, speed); #endif } |