| /* | |
| * File: enet.c | |
| * Purpose: Driver for the ENET controller | |
| * | |
| * Notes: | |
| */ | |
| #include "common.h" | |
| #include "enet.h" | |
| #include "nbuf.h" | |
| #include "eth.h" | |
| /********************************************************************/ | |
| /* Initialize the MIB counters | |
| * | |
| * Parameters: | |
| * ch FEC channel | |
| */ | |
| void | |
| enet_mib_init(int ch) | |
| { | |
| //To do | |
| } | |
| /********************************************************************/ | |
| /* Display the MIB counters | |
| * | |
| * Parameters: | |
| * ch FEC channel | |
| */ | |
| void | |
| enet_mib_dump(int ch) | |
| { | |
| //To do | |
| } | |
| /********************************************************************/ | |
| /* | |
| * Set the duplex on the selected FEC controller | |
| * | |
| * Parameters: | |
| * ch FEC channel | |
| * duplex enet_MII_FULL_DUPLEX or enet_MII_HALF_DUPLEX | |
| */ | |
| void | |
| enet_duplex (int ch, ENET_DUPLEX duplex) | |
| { | |
| switch (duplex) | |
| { | |
| case MII_HDX: | |
| ENET_RCR/*(ch)*/ |= ENET_RCR_DRT_MASK; | |
| ENET_TCR/*(ch)*/ &= (uint32_t)~ENET_TCR_FDEN_MASK; | |
| break; | |
| case MII_FDX: | |
| default: | |
| ENET_RCR/*(ch)*/ &= ~ENET_RCR_DRT_MASK; | |
| ENET_TCR/*(ch)*/ |= ENET_TCR_FDEN_MASK; | |
| break; | |
| } | |
| } | |
| /********************************************************************/ | |
| /* | |
| * Generate the hash table settings for the given address | |
| * | |
| * Parameters: | |
| * addr 48-bit (6 byte) Address to generate the hash for | |
| * | |
| * Return Value: | |
| * The 6 most significant bits of the 32-bit CRC result | |
| */ | |
| uint8_t | |
| enet_hash_address(const uint8_t* addr) | |
| { | |
| uint32_t crc; | |
| uint8_t byte; | |
| int i, j; | |
| crc = 0xFFFFFFFF; | |
| for(i=0; i<6; ++i) | |
| { | |
| byte = addr[i]; | |
| for(j=0; j<8; ++j) | |
| { | |
| if((byte & 0x01)^(crc & 0x01)) | |
| { | |
| crc >>= 1; | |
| crc = crc ^ 0xEDB88320; | |
| } | |
| else | |
| crc >>= 1; | |
| byte >>= 1; | |
| } | |
| } | |
| return (uint8_t)(crc >> 26); | |
| } | |
| /********************************************************************/ | |
| /* | |
| * Set the Physical (Hardware) Address and the Individual Address | |
| * Hash in the selected FEC | |
| * | |
| * Parameters: | |
| * ch FEC channel | |
| * pa Physical (Hardware) Address for the selected FEC | |
| */ | |
| void | |
| enet_set_address (int ch, const uint8_t *pa) | |
| { | |
| uint8_t crc; | |
| /* | |
| * Set the Physical Address | |
| */ | |
| ENET_PALR/*(ch)*/ = (uint32_t)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]); | |
| ENET_PAUR/*(ch)*/ = (uint32_t)((pa[4]<<24) | (pa[5]<<16)); | |
| /* | |
| * Calculate and set the hash for given Physical Address | |
| * in the Individual Address Hash registers | |
| */ | |
| crc = enet_hash_address(pa); | |
| if(crc >= 32) | |
| ENET_IAUR/*(ch)*/ |= (uint32_t)(1 << (crc - 32)); | |
| else | |
| ENET_IALR/*(ch)*/ |= (uint32_t)(1 << crc); | |
| } | |
| /********************************************************************/ | |
| /* | |
| * Reset the selected FEC controller | |
| * | |
| * Parameters: | |
| * ch FEC channel | |
| */ | |
| void | |
| enet_reset (int ch) | |
| { | |
| int i; | |
| /* Set the Reset bit and clear the Enable bit */ | |
| ENET_ECR/*(ch)*/ = ENET_ECR_RESET_MASK; | |
| /* Wait at least 8 clock cycles */ | |
| for (i=0; i<10; ++i) | |
| asm( "NOP" ); | |
| } | |
| /********************************************************************/ | |
| /* | |
| * Initialize the selected FEC | |
| * | |
| * Parameters: | |
| * config: ENET parameters | |
| * | |
| * | |
| */ | |
| void | |
| enet_init (ENET_CONFIG *config) | |
| { | |
| /* Clear the Individual and Group Address Hash registers */ | |
| ENET_IALR/*(ch)*/ = 0; | |
| ENET_IAUR/*(ch)*/ = 0; | |
| ENET_GALR/*(ch)*/ = 0; | |
| ENET_GAUR/*(ch)*/ = 0; | |
| /* Set the Physical Address for the selected FEC */ | |
| enet_set_address(config->ch, config->mac); | |
| /* Mask all FEC interrupts */ | |
| ENET_EIMR/*(ch)*/ = 0;//FSL:ENET_EIMR_MASK_ALL_MASK; | |
| /* Clear all FEC interrupt events */ | |
| ENET_EIR/*(ch)*/ = 0xFFFFFFFF;//FSL:ENET_EIR_CLEAR_ALL_MASK; | |
| /* Initialize the Receive Control Register */ | |
| ENET_RCR/*(ch)*/ = 0 | |
| | ENET_RCR_MAX_FL(ETH_MAX_FRM) | |
| | ENET_RCR_MII_MODE_MASK /*always*/ | |
| | ENET_RCR_CRCFWD_MASK; /*no CRC pad required*/ | |
| if ( config->interface == mac_rmii ) | |
| { | |
| ENET_RCR/*(ch)*/ |= ENET_RCR_RMII_MODE_MASK; | |
| /*only set speed in RMII mode*/ | |
| if( config->speed == MII_10BASET ) | |
| { | |
| ENET_RCR/*(ch)*/ |= ENET_RCR_RMII_10T_MASK; | |
| } | |
| }/*no need to configure MAC MII interface*/ | |
| ENET_TCR/*(ch)*/ = 0; | |
| /* Set the duplex */ | |
| enet_duplex(config->ch, config->duplex); | |
| if (config->prom) | |
| { | |
| ENET_RCR/*(ch)*/ |= ENET_RCR_PROM_MASK; | |
| } | |
| #ifdef ENHANCED_BD | |
| ENET_ECR/*(ch)*/ = ENET_ECR_EN1588_MASK; | |
| #else | |
| ENET_ECR/*(ch)*/ = 0;//clear register | |
| #endif | |
| if(config->loopback == INTERNAL_LOOPBACK) | |
| { | |
| /*seems like RMII internal loopback works, even if it's not supported*/ | |
| ENET_RCR/*(0)*/ |= ENET_RCR_LOOP_MASK; | |
| } | |
| } | |
| /********************************************************************/ | |
| void | |
| enet_start (int ch) | |
| { | |
| // Enable FEC | |
| ENET_ECR/*(ch)*/ |= ENET_ECR_ETHEREN_MASK; | |
| } | |
| /********************************************************************/ | |
| int | |
| enet_wait_for_frame_receive(int ch, int timeout) | |
| { | |
| int i, return_val = 1; | |
| for (i=0; i < timeout; i++) | |
| { | |
| if (ENET_EIR/*(ch)*/ & ENET_EIR_RXF_MASK) | |
| { | |
| ENET_EIR/*(ch)*/ = ENET_EIR_RXF_MASK; | |
| break; | |
| } | |
| } | |
| if(i == timeout) | |
| { | |
| return_val = 0; | |
| } | |
| return return_val; | |
| } | |
| /********************************************************************/ | |