diff options
Diffstat (limited to 'cpu/mpc8xx/fec.c')
-rw-r--r-- | cpu/mpc8xx/fec.c | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c index b7603da..6d1b178 100644 --- a/cpu/mpc8xx/fec.c +++ b/cpu/mpc8xx/fec.c @@ -60,22 +60,22 @@ static struct ether_fcc_info_s { int ether_index; int fecp_offset; - int bd_offset; int phy_addr; int actual_phy_addr; + int initialized; } ether_fcc_info[] = { #if defined(CONFIG_ETHER_ON_FEC1) { 0, offsetof(immap_t, im_cpm.cp_fec1), - CPM_FEC_BASE, #if defined(CONFIG_FEC1_PHY) CONFIG_FEC1_PHY, #else -1, /* discover */ #endif -1, + 0, }, #endif @@ -83,13 +83,13 @@ static struct ether_fcc_info_s { 1, offsetof(immap_t, im_cpm.cp_fec2), - CPM_FEC_BASE + 0x50, #if defined(CONFIG_FEC2_PHY) CONFIG_FEC2_PHY, #else -1, #endif -1, + 0, }, #endif }; @@ -383,6 +383,11 @@ static void fec_pin_init(int fecidx) */ fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1; +#if defined(CONFIG_NETTA) || defined(CONFIG_NETPHONE) + /* our PHYs are the limit at 2.5 MHz */ + fecp->fec_mii_speed <<= 1; +#endif + #if defined(CONFIG_DUET) && defined(WANT_MII) /* use MDC for MII */ immr->im_ioport.iop_pdpar |= 0x0080; @@ -695,6 +700,14 @@ static int fec_init (struct eth_device *dev, bd_t * bd) efis->actual_phy_addr = efis->phy_addr; } #if defined(CONFIG_MII) && defined(CONFIG_RMII) + + /* the MII interface is connected to FEC1 + so for the miiphy_xxx function to work we must + call mii_init since fec_halt messes the thing up */ + + if (efis->ether_index != 0) + mii_init(); + /* * adapt the RMII speed to the speed of the phy */ @@ -719,25 +732,43 @@ static int fec_init (struct eth_device *dev, bd_t * bd) /* And last, try to fill Rx Buffer Descriptors */ fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ + efis->initialized = 1; + return 1; } static void fec_halt(struct eth_device* dev) { -#if 0 - volatile immap_t *immr = (immap_t *)CFG_IMMR; - immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); -#endif -} + struct ether_fcc_info_s *efis = dev->priv; + volatile fec_t *fecp = (volatile fec_t *)(CFG_IMMR + efis->fecp_offset); + int i; -#if 0 -void restart(void) -{ - volatile immap_t *immr = (immap_t *)CFG_IMMR; - immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + /* avoid halt if initialized; mii gets stuck otherwise */ + if (!efis->initialized) + return; + + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) { + printf ("FEC_RESET_DELAY timeout\n"); + return; + } + + efis->initialized = 0; } -#endif #if defined(CFG_DISCOVER_PHY) || defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) @@ -781,14 +812,20 @@ mii_send(uint mii_cmd) { uint mii_reply; volatile fec_t *ep; + int cnt; ep = &(((immap_t *)CFG_IMMR)->im_cpm.cp_fec); ep->fec_mii_data = mii_cmd; /* command to phy */ /* wait for mii complete */ - while (!(ep->fec_ievent & FEC_ENET_MII)) - ; /* spin until done */ + cnt = 0; + while (!(ep->fec_ievent & FEC_ENET_MII)) { + if (++cnt > 1000) { + printf("mii_send STUCK!\n"); + break; + } + } mii_reply = ep->fec_mii_data; /* result from phy */ ep->fec_ievent = FEC_ENET_MII; /* clear MII complete */ #if 0 @@ -870,8 +907,6 @@ static int mii_discover_phy(struct eth_device *dev) #if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) && !defined(CONFIG_BITBANGMII) -static int mii_init_done = 0; - /**************************************************************************** * mii_init -- Initialize the MII for MII command without ethernet * This function is a subset of eth_init @@ -883,10 +918,6 @@ void mii_init (void) volatile fec_t *fecp = &(immr->im_cpm.cp_fec); int i, j; - if (mii_init_done != 0) { - return; - } - for (j = 0; j < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); j++) { /* Whack a reset. @@ -924,8 +955,6 @@ void mii_init (void) */ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; } - - mii_init_done = 1; } /***************************************************************************** |