void mcf5223x_eth_init_ephy(char use_100_mbps, char negotiate){ uint16 reg0; while(!fec_mii_read(FEC_PHY0, PHY_REG_CR, ®0)) ; if (use_100_mbps) reg0 |= PHY_R0_DR; // 100 Mbps else reg0 &= ~PHY_R0_DR; // 10 Mbps reg0 &= ~PHY_R0_DPLX; // Half duplex reg0 &= ~PHY_R0_ANE; // Manual mode while(!fec_mii_write(FEC_PHY0, PHY_REG_CR, reg0)) ; if (negotiate) { while(!fec_mii_write(FEC_PHY0, PHY_REG_CR, (reg0|PHY_R0_RAN))) ; }}void mcf5223x_eth_init(char use_100_mbps){ uint16 mymwdata; // Temp variable for MII read/write data fec_mii_init(SYSTEM_CLOCK_MHZ); // Enable EPHY module with PHY clocks MCF_PHY_EPHYCTL0 &= ~(MCF_PHY_EPHYCTL0_EPHYEN); // Disable ePHY module MCF_PHY_EPHYCTL1 = MCF_PHY_EPHYCTL1_PHYADDR(FEC_PHY0); // Adress is 0 MCF_PHY_EPHYCTL0 &= ~(MCF_PHY_EPHYCTL0_DIS100 | MCF_PHY_EPHYCTL0_DIS10); MCF_PHY_EPHYCTL0 |= MCF_PHY_EPHYCTL0_ANDIS; // Disable HW auto-negotiate MCF_PHY_EPHYCTL0 |= MCF_PHY_EPHYCTL0_EPHYEN; // Enable ePHY module mcf5223x_eth_init_ephy(use_100_mbps, FALSE); // Enable PHY interrupts in Reg 16 (PHY Interrupt Control Register) mymwdata = PHY_R16_ACKIE | PHY_R16_PRIE | PHY_R16_LCIE | PHY_R16_ANIE; mymwdata = mymwdata | PHY_R16_PDFIE | PHY_R16_RFIE | PHY_R16_JABIE; while (!(fec_mii_write(FEC_PHY0, PHY_REG_IR, mymwdata))) ; // Set ePHY interrupt vector and control register mcf5xxx_set_handler(0x40+36, (ADDRESS)ephy_handler); MCF_INTC0_ICR36 = MCF_INTC_ICR_IL(2) | MCF_INTC_ICR_IP(7); MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_MASK36);}#define TRIES_100M 2typedef enum { DOWN_10 = 0, DOWN_100, UP_10, UP_100} eth_link_state;eth_link_state link_state = DOWN_100;char tries_100 = TRIES_100M, stable_state = FALSE, negotiate_10 = TRUE;int gotlink = FALSE;void mcf5223x_ephy_fsm(void){ uint16 reg1; eth_link_state state; char link_up; // Read link status while (!fec_mii_read(FEC_PHY0, PHY_REG_SR, ®1)) ; link_up = FALSE; if (reg1 & PHY_R1_LS) link_up = TRUE; state = link_state; switch (link_state) { case DOWN_10: if (link_up) { negotiate_10 = TRUE; if (tries_100) { printf("ephy: 10M OK, try 100M\n");#warning This does not work properly mcf5223x_eth_init(TRUE); // Re-init EPHY mcf5223x_eth_init_ephy(TRUE, TRUE); // 100M stable_state = FALSE; state = DOWN_100; } else { printf("ephy: 10M OK, link UP\n"); gotlink = TRUE; stable_state = TRUE; state = UP_10; } } else if (!stable_state) { if (negotiate_10) { printf("ephy: 10M negotiate\n"); mcf5223x_eth_init_ephy(FALSE, TRUE); // 10M, negotiate negotiate_10 = FALSE; } else { printf("ephy: 10M stable, link DOWN\n"); stable_state = TRUE; tries_100 = TRIES_100M; } } break; case UP_10: if (!link_up) { printf("ephy: 10M lost, link DOWN\n"); gotlink = FALSE; stable_state = FALSE; state = DOWN_10; } break; case DOWN_100: if (link_up) { printf("ephy: 100M OK, link UP\n"); gotlink = TRUE; stable_state = TRUE; state = UP_100; } else { tries_100--; if (tries_100) { mcf5223x_eth_init_ephy(TRUE, TRUE); // 100M, negotiate } else { printf("ephy: 100M failed, try 10M\n"); mcf5223x_eth_init(TRUE); // Re-init EPHY mcf5223x_eth_init_ephy(FALSE, TRUE); // 10M, negotiate state = DOWN_10; } } break; case UP_100: if (!link_up) { printf("ephy: 100M lost, try 10M, link DOWN\n"); mcf5223x_eth_init(TRUE); // Re-init EPHY gotlink = FALSE; stable_state = FALSE; state = DOWN_10; } break; default: asm("halt"); break; } link_state = state;}