[U-Boot] 83xx, uec: adjust enet_interface settings on the fly.

If using UCC as Ethernet Controller and type = FAST_ETH, it was not possible to switch between 10 and 100 MBit interfaces. This patch adds this for following interfaces:
10_MII 10_RMII 10_RGMII 100_MII 100_RMII 100_RGMII
Signed-off-by: Heiko Schocher hs@denx.de --- drivers/qe/uec.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index db95ada..9851cc4 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -65,6 +65,22 @@ static uec_info_t uec_info[] = {
#define MAXCONTROLLERS (8)
+static char *enet_interface_name[] = { + "10_MII", + "10_RMII", + "10_RGMII", + "100_MII", + "100_RMII", + "100_RGMII", + "1000_GMII", + "1000_RGMII", + "1000_RGMII_ID", + "1000_RGMII_RXID", + "1000_TBI", + "1000_RTBI", + "1000_SGMII" +}; + static struct eth_device *devlist[MAXCONTROLLERS];
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum); @@ -497,6 +513,60 @@ bus_fail: return err; }
+static void adjust_fast_enet_interface(int speed, struct eth_device *dev) +{ + uec_private_t *uec = (uec_private_t *)dev->priv; + uec_t *uec_regs; + int change = 0; + + extern void change_phy_interface_mode(struct eth_device *dev, + enet_interface_e mode); + uec_regs = uec->uec_regs; + + switch (speed) { + case 100: + switch (uec->uec_info->enet_interface) { + case ENET_10_MII: + case ENET_10_RMII: + case ENET_10_RGMII: + uec->uec_info->enet_interface += 3; + change = 1; + break; + default: + break; + } + break; + case 10: + switch (uec->uec_info->enet_interface) { + case ENET_100_MII: + case ENET_100_RMII: + case ENET_100_RGMII: + uec->uec_info->enet_interface -= 3; + change = 1; + break; + default: + break; + } + break; + default: + /* do nothing, not supported yet */ + printf("%s: speed: %d and mode: %d not supported yet.\n", + __func__, speed, uec->uec_info->enet_interface); + break; + } + if (change) { + printf ("switching to %s\n", + enet_interface_name[uec->uec_info->enet_interface]); + /* change phy */ + change_phy_interface_mode(dev, + uec->uec_info->enet_interface); + /* change the MAC interface mode */ + uec_set_mac_if_mode(uec, + uec->uec_info->enet_interface); + + } +} + static void adjust_link(struct eth_device *dev) { uec_private_t *uec = (uec_private_t *)dev->priv; @@ -547,6 +617,8 @@ static void adjust_link(struct eth_device *dev) dev->name, mii_info->speed); break; } + } else if (uec->uec_info->uf_info.eth_type == FAST_ETH) { + adjust_fast_enet_interface(mii_info->speed, dev); }
printf("%s: Speed %dBT\n", dev->name, mii_info->speed); @@ -1215,6 +1287,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; }

On Thu, 7 Jan 2010 09:01:32 +0100 Heiko Schocher hs@denx.de wrote:
static void adjust_link(struct eth_device *dev) { uec_private_t *uec = (uec_private_t *)dev->priv; @@ -547,6 +617,8 @@ static void adjust_link(struct eth_device *dev) dev->name, mii_info->speed); break; }
} else if (uec->uec_info->uf_info.eth_type == FAST_ETH) {
adjust_fast_enet_interface(mii_info->speed, dev); }
did you make any effort to refactor this into the existing eth_type == GIGA_ETH code? I'm not sure why that code became conditional in commit 24c3aca3f1358b113d3215adb5433b156e99f72b "mpc83xx: Add support for the MPC832XEMDS board" in the first place - Dave?
Kim

did you make any effort to refactor this into the existing eth_type == GIGA_ETH code? I'm not sure why that code became conditional in commit 24c3aca3f1358b113d3215adb5433b156e99f72b "mpc83xx: Add support for the MPC832XEMDS board" in the first place - Dave?
I don't remember why I added the eth_type==GIGA_ETH condition. If it is possible, please refactor it as Kim.
Thanks, Dave

Hello Liu,
Liu Dave-R63238 wrote:
did you make any effort to refactor this into the existing eth_type == GIGA_ETH code? I'm not sure why that code became conditional in commit 24c3aca3f1358b113d3215adb5433b156e99f72b "mpc83xx: Add support for the MPC832XEMDS board" in the first place - Dave?
I don't remember why I added the eth_type==GIGA_ETH condition. If it is possible, please refactor it as Kim.
Hmm.. while looking at this code, a question comes in mind: Did this code (eth_type==GIGA_ETH) work correctly?
I see there is a switching possible from 1000 to 100 or 10, but never back to 1000, because the 1000 case did nothing ...? Is this intentionally?
Also uec->uec_info->enet_interface is never updated, which should be done ... or?
If the above mentioned is no problem, following patch comes in my mind:
If using UCC as Ethernet Controller and type = FAST_ETH, it was not possible to switch between 10 and 100 MBit interfaces. This patch adds this for following interfaces:
10_MII 10_RMII 10_RGMII 100_MII 100_RMII 100_RGMII
Signed-off-by: Heiko Schocher hs@denx.de --- drivers/qe/uec.c | 104 ++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 78 insertions(+), 26 deletions(-)
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index db95ada..263df9c 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -65,6 +65,22 @@ static uec_info_t uec_info[] = {
#define MAXCONTROLLERS (8)
+static char *enet_interface_name[] = { + "10_MII", + "10_RMII", + "10_RGMII", + "100_MII", + "100_RMII", + "100_RGMII", + "1000_GMII", + "1000_RGMII", + "1000_RGMII_ID", + "1000_RGMII_RXID", + "1000_TBI", + "1000_RTBI", + "1000_SGMII" +}; + static struct eth_device *devlist[MAXCONTROLLERS];
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum); @@ -497,6 +513,66 @@ bus_fail: return err; }
+static void adjust_enet_interface_speed(int speed, struct eth_device *dev) +{ + uec_private_t *uec = (uec_private_t *)dev->priv; + uec_t *uec_regs; + int change = 0; + + extern void change_phy_interface_mode(struct eth_device *dev, + enet_interface_e mode); + uec_regs = uec->uec_regs; + + switch (speed) { + case 1000: + break; + case 100: + switch (uec->uec_info->enet_interface) { + case ENET_10_MII: + case ENET_10_RMII: + case ENET_10_RGMII: + uec->uec_info->enet_interface += 3; + change = 1; + break; + default: + uec->uec_info->enet_interface = ENET_100_RGMII; + change = 1; + break; + } + break; + case 10: + switch (uec->uec_info->enet_interface) { + case ENET_100_MII: + case ENET_100_RMII: + case ENET_100_RGMII: + uec->uec_info->enet_interface -= 3; + change = 1; + break; + default: + uec->uec_info->enet_interface = ENET_10_RGMII; + change = 1; + break; + } + break; + default: + /* do nothing, not supported yet */ + printf("%s: speed: %d and mode: %d not supported yet.\n", + __func__, speed, uec->uec_info->enet_interface); + break; + } + if (change) { + printf ("switching to %s\n", + enet_interface_name[uec->uec_info->enet_interface]); + /* change phy */ + change_phy_interface_mode(dev, + uec->uec_info->enet_interface); + /* change the MAC interface mode */ + uec_set_mac_if_mode(uec, + uec->uec_info->enet_interface); + + } +} + static void adjust_link(struct eth_device *dev) { uec_private_t *uec = (uec_private_t *)dev->priv; @@ -522,32 +598,7 @@ static void adjust_link(struct eth_device *dev) }
if (mii_info->speed != uec->oldspeed) { - 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); - 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); - break; - default: - printf("%s: Ack,Speed(%d)is illegal\n", - dev->name, mii_info->speed); - break; - } - } + adjust_enet_interface_speed(mii_info->speed, dev);
printf("%s: Speed %dBT\n", dev->name, mii_info->speed); uec->oldspeed = mii_info->speed; @@ -1215,6 +1266,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; }

I don't remember why I added the eth_type==GIGA_ETH condition. If it is possible, please refactor it as Kim.
Hmm.. while looking at this code, a question comes in mind: Did this code (eth_type==GIGA_ETH) work correctly?
Yes, It worked correctly. But later there are lots of change, I'm not sure if it is correct right now.
I see there is a switching possible from 1000 to 100 or 10, but never back to 1000, because the 1000 case did nothing ...? Is this intentionally?
The code was assuming the initial speed is 1000Mbps, so the 1000 case did nothing.
Also uec->uec_info->enet_interface is never updated, which should be done ... or?
IIRC, the enet_interface was designed for interface type according to board design. So it was placed on uec_info, it is never updated. eg: SGMII if board is SGMII connection RGMII if board is RGMII connection... RMII if board is RMII....
Thanks, Dave

Hello Liu,
Liu Dave-R63238 wrote:
I don't remember why I added the eth_type==GIGA_ETH condition. If it is possible, please refactor it as Kim.
Hmm.. while looking at this code, a question comes in mind: Did this code (eth_type==GIGA_ETH) work correctly?
Yes, It worked correctly. But later there are lots of change, I'm not sure if it is correct right now.
I see there is a switching possible from 1000 to 100 or 10, but never back to 1000, because the 1000 case did nothing ...? Is this intentionally?
The code was assuming the initial speed is 1000Mbps, so the 1000 case did nothing.
Hmm.. but what happend, if you connect a 100Mbps, and then back to the 1000Mpbs?
Also uec->uec_info->enet_interface is never updated, which should be done ... or?
IIRC, the enet_interface was designed for interface type according to board design. So it was placed on uec_info, it is never updated. eg: SGMII if board is SGMII connection RGMII if board is RGMII connection... RMII if board is RMII....
Ah, OK, thanks.
bye Heiko

On Thu, Jan 7, 2010 at 2:01 AM, Heiko Schocher hs@denx.de wrote:
If using UCC as Ethernet Controller and type = FAST_ETH, it was not possible to switch between 10 and 100 MBit interfaces. This patch adds this for following interfaces:
10_MII 10_RMII 10_RGMII 100_MII 100_RMII 100_RGMII
Signed-off-by: Heiko Schocher hs@denx.de
drivers/qe/uec.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index db95ada..9851cc4 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -65,6 +65,22 @@ static uec_info_t uec_info[] = {
#define MAXCONTROLLERS (8)
+static char *enet_interface_name[] = {
- "10_MII",
- "10_RMII",
- "10_RGMII",
- "100_MII",
- "100_RMII",
- "100_RGMII",
- "1000_GMII",
- "1000_RGMII",
- "1000_RGMII_ID",
- "1000_RGMII_RXID",
- "1000_TBI",
- "1000_RTBI",
- "1000_SGMII"
+};
static struct eth_device *devlist[MAXCONTROLLERS];
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum); @@ -497,6 +513,60 @@ bus_fail: return err; }
+static void adjust_fast_enet_interface(int speed, struct eth_device *dev) +{
- uec_private_t *uec = (uec_private_t *)dev->priv;
- uec_t *uec_regs;
- int change = 0;
- extern void change_phy_interface_mode(struct eth_device *dev,
- enet_interface_e mode);
- uec_regs = uec->uec_regs;
- switch (speed) {
- case 100:
- switch (uec->uec_info->enet_interface) {
- case ENET_10_MII:
- case ENET_10_RMII:
- case ENET_10_RGMII:
I know you aren't responsible for this design choice, but I'd love it if we stopped this sort of thing. There's no sensible reason to unite speed and interface type into one variable. They are, in fact, two nearly-independent variables. If they directly corresponded to some register value, it might make sense, but really they encourage a rigidity of thought about a concept which is much more fluid. The speed will vary based on the link partner. The interface is usually hardwired by the board designer, and at most, modifiable at boot time by DIP switches.
- uec->uec_info->enet_interface += 3;
And then we end up with something *highly* fragile like this. *3* has no meaning, except in the very specific context of the particular order in which the interfaces have been specified in this driver. All it takes is some architect deciding to add support for 10M SGMII, or 10M WHATEVERMII, and now everything breaks in a way that is not immediately apparent....
Andy

Hello Andy,
Andy Fleming wrote:
On Thu, Jan 7, 2010 at 2:01 AM, Heiko Schocher hs@denx.de wrote:
If using UCC as Ethernet Controller and type = FAST_ETH, it was not possible to switch between 10 and 100 MBit interfaces. This patch adds this for following interfaces:
10_MII 10_RMII 10_RGMII 100_MII 100_RMII 100_RGMII
Signed-off-by: Heiko Schocher hs@denx.de
drivers/qe/uec.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index db95ada..9851cc4 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -65,6 +65,22 @@ static uec_info_t uec_info[] = {
#define MAXCONTROLLERS (8)
+static char *enet_interface_name[] = {
"10_MII",
"10_RMII",
"10_RGMII",
"100_MII",
"100_RMII",
"100_RGMII",
"1000_GMII",
"1000_RGMII",
"1000_RGMII_ID",
"1000_RGMII_RXID",
"1000_TBI",
"1000_RTBI",
"1000_SGMII"
+};
static struct eth_device *devlist[MAXCONTROLLERS];
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum); @@ -497,6 +513,60 @@ bus_fail: return err; }
+static void adjust_fast_enet_interface(int speed, struct eth_device *dev) +{
uec_private_t *uec = (uec_private_t *)dev->priv;
uec_t *uec_regs;
int change = 0;
extern void change_phy_interface_mode(struct eth_device *dev,
enet_interface_e mode);
uec_regs = uec->uec_regs;
switch (speed) {
case 100:
switch (uec->uec_info->enet_interface) {
case ENET_10_MII:
case ENET_10_RMII:
case ENET_10_RGMII:
I know you aren't responsible for this design choice, but I'd love it if we stopped this sort of thing. There's no sensible reason to unite speed and interface type into one variable. They are, in fact, two nearly-independent variables. If they directly corresponded to some
Yes, you are right! That would be the right way ...
register value, it might make sense, but really they encourage a rigidity of thought about a concept which is much more fluid. The speed will vary based on the link partner. The interface is usually hardwired by the board designer, and at most, modifiable at boot time by DIP switches.
Yep, I try to prepare such a patch, which splits this variable in two (If others have no objections).
Thanks.
bye Heiko

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 --- board/freescale/mpc8360emds/mpc8360emds.c | 3 +- drivers/qe/uec.c | 122 ++++++++++++++++------------- drivers/qe/uec.h | 34 ++++---- drivers/qe/uec_phy.c | 84 +++++++++++--------- include/configs/MPC8323ERDB.h | 6 +- include/configs/MPC832XEMDS.h | 6 +- include/configs/MPC8360EMDS.h | 6 +- include/configs/MPC8360ERDK.h | 6 +- include/configs/MPC8568MDS.h | 6 +- include/configs/MPC8569MDS.h | 30 +++++--- include/configs/kmeter1.h | 3 +- 11 files changed, 175 insertions(+), 131 deletions(-)
diff --git a/board/freescale/mpc8360emds/mpc8360emds.c b/board/freescale/mpc8360emds/mpc8360emds.c index d4ba043..4f55732 100644 --- a/board/freescale/mpc8360emds/mpc8360emds.c +++ b/board/freescale/mpc8360emds/mpc8360emds.c @@ -159,7 +159,8 @@ int board_eth_init(bd_t *bd) int i;
for (i = 0; i < ARRAY_SIZE(uec_info); i++) - uec_info[i].enet_interface = ENET_1000_RGMII_RXID; + uec_info[i].enet_interface_type = RGMII_RXID; + uec_info[i].speed = 1000; } return uec_eth_init(bd, uec_info, ARRAY_SIZE(uec_info)); } diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index db95ada..881632d 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", @@ -548,6 +559,11 @@ static void adjust_link(struct eth_device *dev) break; } } + + /* 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 febfbce..2a9e2dc 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 9715183..c4214d9 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 } diff --git a/include/configs/MPC8323ERDB.h b/include/configs/MPC8323ERDB.h index 356586c..8e6f7ce 100644 --- a/include/configs/MPC8323ERDB.h +++ b/include/configs/MPC8323ERDB.h @@ -347,7 +347,8 @@ #define CONFIG_SYS_UEC1_TX_CLK QE_CLK10 #define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 4 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_100_MII +#define CONFIG_SYS_UEC1_INTERFACE_TYPE MII +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100 #endif
#define CONFIG_UEC_ETH2 /* ETH4 */ @@ -358,7 +359,8 @@ #define CONFIG_SYS_UEC2_TX_CLK QE_CLK3 #define CONFIG_SYS_UEC2_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 0 -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_100_MII +#define CONFIG_SYS_UEC2_INTERFACE_TYPE MII +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 100 #endif
/* diff --git a/include/configs/MPC832XEMDS.h b/include/configs/MPC832XEMDS.h index f17f9c7..1adac64 100644 --- a/include/configs/MPC832XEMDS.h +++ b/include/configs/MPC832XEMDS.h @@ -362,7 +362,8 @@ #define CONFIG_SYS_UEC1_TX_CLK QE_CLK10 #define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 3 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_100_MII +#define CONFIG_SYS_UEC1_INTERFACE_TYPE MII +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100 #endif
#define CONFIG_UEC_ETH2 /* ETH4 */ @@ -373,7 +374,8 @@ #define CONFIG_SYS_UEC2_TX_CLK QE_CLK8 #define CONFIG_SYS_UEC2_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 4 -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_100_MII +#define CONFIG_SYS_UEC2_INTERFACE_TYPE MII +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 100 #endif
/* diff --git a/include/configs/MPC8360EMDS.h b/include/configs/MPC8360EMDS.h index 8520155..6fa7287 100644 --- a/include/configs/MPC8360EMDS.h +++ b/include/configs/MPC8360EMDS.h @@ -400,7 +400,8 @@ #define CONFIG_SYS_UEC1_TX_CLK QE_CLK9 #define CONFIG_SYS_UEC1_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 0 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000 #endif
#define CONFIG_UEC_ETH2 /* GETH2 */ @@ -411,7 +412,8 @@ #define CONFIG_SYS_UEC2_TX_CLK QE_CLK4 #define CONFIG_SYS_UEC2_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 1 -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000 #endif
/* diff --git a/include/configs/MPC8360ERDK.h b/include/configs/MPC8360ERDK.h index 1d1f94f..c6f1409 100644 --- a/include/configs/MPC8360ERDK.h +++ b/include/configs/MPC8360ERDK.h @@ -318,7 +318,8 @@ #define CONFIG_SYS_UEC1_TX_CLK QE_CLK9 #define CONFIG_SYS_UEC1_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 2 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_1000_RGMII_RXID +#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_RXID +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000 #endif
#define CONFIG_UEC_ETH2 /* GETH2 */ @@ -329,7 +330,8 @@ #define CONFIG_SYS_UEC2_TX_CLK QE_CLK4 #define CONFIG_SYS_UEC2_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 4 -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_1000_RGMII_RXID +#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_RXID +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000 #endif
/* diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h index 128a7e1..6973538 100644 --- a/include/configs/MPC8568MDS.h +++ b/include/configs/MPC8568MDS.h @@ -333,7 +333,8 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC1_TX_CLK QE_CLK16 #define CONFIG_SYS_UEC1_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 7 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000 #endif
#define CONFIG_UEC_ETH2 /* GETH2 */ @@ -344,7 +345,8 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC2_TX_CLK QE_CLK16 #define CONFIG_SYS_UEC2_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 1 -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000 #endif #endif /* CONFIG_QE */
diff --git a/include/configs/MPC8569MDS.h b/include/configs/MPC8569MDS.h index 1e659e2..d80d897 100644 --- a/include/configs/MPC8569MDS.h +++ b/include/configs/MPC8569MDS.h @@ -317,12 +317,14 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC1_TX_CLK QE_CLK12 #define CONFIG_SYS_UEC1_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 7 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000 #elif defined(CONFIG_SYS_UCC_RMII_MODE) #define CONFIG_SYS_UEC1_TX_CLK QE_CLK16 /* CLK16 for RMII */ #define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 8 /* 0x8 for RMII */ -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_100_RMII +#define CONFIG_SYS_UEC1_INTERFACE_TYPE RMII +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100 #endif /* CONFIG_SYS_UCC_RGMII_MODE */ #endif /* CONFIG_UEC_ETH1 */
@@ -336,12 +338,14 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC2_TX_CLK QE_CLK17 #define CONFIG_SYS_UEC2_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 1 -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000 #elif defined(CONFIG_SYS_UCC_RMII_MODE) #define CONFIG_SYS_UEC2_TX_CLK QE_CLK16 /* CLK 16 for RMII */ #define CONFIG_SYS_UEC2_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC2_PHY_ADDR 0x9 /* 0x9 for RMII */ -#define CONFIG_SYS_UEC2_INTERFACE_MODE ENET_100_RMII +#define CONFIG_SYS_UEC2_INTERFACE_TYPE RMII +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 100 #endif /* CONFIG_SYS_UCC_RGMII_MODE */ #endif /* CONFIG_UEC_ETH2 */
@@ -355,12 +359,14 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC3_TX_CLK QE_CLK12 #define CONFIG_SYS_UEC3_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC3_PHY_ADDR 2 -#define CONFIG_SYS_UEC3_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC3_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC3_INTERFACE_SPEED 1000 #elif defined(CONFIG_SYS_UCC_RMII_MODE) #define CONFIG_SYS_UEC3_TX_CLK QE_CLK16 /* CLK_16 for RMII */ #define CONFIG_SYS_UEC3_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC3_PHY_ADDR 0xA /* 0xA for RMII */ -#define CONFIG_SYS_UEC3_INTERFACE_MODE ENET_100_RMII +#define CONFIG_SYS_UEC3_INTERFACE_TYPE RMII +#define CONFIG_SYS_UEC3_INTERFACE_SPEED 100 #endif /* CONFIG_SYS_UCC_RGMII_MODE */ #endif /* CONFIG_UEC_ETH3 */
@@ -374,12 +380,14 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC4_TX_CLK QE_CLK17 #define CONFIG_SYS_UEC4_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC4_PHY_ADDR 3 -#define CONFIG_SYS_UEC4_INTERFACE_MODE ENET_1000_RGMII_ID +#define CONFIG_SYS_UEC4_INTERFACE_TYPE RGMII_ID +#define CONFIG_SYS_UEC4_INTERFACE_SPEED 1000 #elif defined(CONFIG_SYS_UCC_RMII_MODE) #define CONFIG_SYS_UEC4_TX_CLK QE_CLK16 /* CLK16 for RMII */ #define CONFIG_SYS_UEC4_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC4_PHY_ADDR 0xB /* 0xB for RMII */ -#define CONFIG_SYS_UEC4_INTERFACE_MODE ENET_100_RMII +#define CONFIG_SYS_UEC4_INTERFACE_TYPE RMII +#define CONFIG_SYS_UEC4_INTERFACE_SPEED 100 #endif /* CONFIG_SYS_UCC_RGMII_MODE */ #endif /* CONFIG_UEC_ETH4 */
@@ -392,7 +400,8 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC6_TX_CLK QE_CLK_NONE #define CONFIG_SYS_UEC6_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC6_PHY_ADDR 4 -#define CONFIG_SYS_UEC6_INTERFACE_MODE ENET_1000_SGMII +#define CONFIG_SYS_UEC6_INTERFACE_TYPE SGMII +#define CONFIG_SYS_UEC6_INTERFACE_SPEED 1000 #endif /* CONFIG_UEC_ETH6 */
#undef CONFIG_UEC_ETH8 /* GETH8 */ @@ -404,7 +413,8 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_UEC8_TX_CLK QE_CLK_NONE #define CONFIG_SYS_UEC8_ETH_TYPE GIGA_ETH #define CONFIG_SYS_UEC8_PHY_ADDR 6 -#define CONFIG_SYS_UEC8_INTERFACE_MODE ENET_1000_SGMII +#define CONFIG_SYS_UEC8_INTERFACE_TYPE SGMII +#define CONFIG_SYS_UEC8_INTERFACE_SPEED 1000 #endif /* CONFIG_UEC_ETH8 */
#endif /* CONFIG_QE */ diff --git a/include/configs/kmeter1.h b/include/configs/kmeter1.h index 71658d8..e812eda 100644 --- a/include/configs/kmeter1.h +++ b/include/configs/kmeter1.h @@ -293,7 +293,8 @@ #define CONFIG_SYS_UEC1_TX_CLK QE_CLK17 #define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 0 -#define CONFIG_SYS_UEC1_INTERFACE_MODE ENET_100_RMII +#define CONFIG_SYS_UEC1_INTERFACE_TYPE RMII +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100 #endif
/*

Hi Heiko,
Heiko Schocher wrote:
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
board/freescale/mpc8360emds/mpc8360emds.c | 3 +- drivers/qe/uec.c | 122 ++++++++++++++++------------- drivers/qe/uec.h | 34 ++++---- drivers/qe/uec_phy.c | 84 +++++++++++--------- include/configs/MPC8323ERDB.h | 6 +- include/configs/MPC832XEMDS.h | 6 +- include/configs/MPC8360EMDS.h | 6 +- include/configs/MPC8360ERDK.h | 6 +- include/configs/MPC8568MDS.h | 6 +- include/configs/MPC8569MDS.h | 30 +++++--- include/configs/kmeter1.h | 3 +- 11 files changed, 175 insertions(+), 131 deletions(-)
Applied to net repo.
thanks, Ben
participants (5)
-
Andy Fleming
-
Ben Warren
-
Heiko Schocher
-
Kim Phillips
-
Liu Dave-R63238