 
					
				
		
 
					
				
		
 
					
				
		
 
					
				
		
 
					
				
		
 
					
				
		
 
					
				
		
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;}