mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	Added back some TCP/IP stack port layer files.
This commit is contained in:
		
							parent
							
								
									7cf721ccf7
								
							
						
					
					
						commit
						9c0c37ab9b
					
				@ -0,0 +1,721 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Handling of Ethernet PHY's
 | 
			
		||||
 * PHY's communicate with an EMAC either through
 | 
			
		||||
 * a Media-Independent Interface (MII), or a Reduced Media-Independent Interface (RMII).
 | 
			
		||||
 * The EMAC can poll for PHY ports on 32 different addresses. Each of the PHY ports
 | 
			
		||||
 * shall be treated independently.
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "semphr.h"
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS+TCP includes. */
 | 
			
		||||
#include "FreeRTOS_IP.h"
 | 
			
		||||
#include "FreeRTOS_Sockets.h"
 | 
			
		||||
 | 
			
		||||
#include "phyHandling.h"
 | 
			
		||||
 | 
			
		||||
#define phyMIN_PHY_ADDRESS		0
 | 
			
		||||
#define phyMAX_PHY_ADDRESS		31
 | 
			
		||||
 | 
			
		||||
#if defined( PHY_LS_HIGH_CHECK_TIME_MS ) || defined( PHY_LS_LOW_CHECK_TIME_MS )
 | 
			
		||||
	#warning please use the new defines with 'ipconfig' prefix
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef	ipconfigPHY_LS_HIGH_CHECK_TIME_MS
 | 
			
		||||
	/* Check if the LinkStatus in the PHY is still high after 15 seconds of not
 | 
			
		||||
	receiving packets. */
 | 
			
		||||
	#define ipconfigPHY_LS_HIGH_CHECK_TIME_MS	15000uL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef	ipconfigPHY_LS_LOW_CHECK_TIME_MS
 | 
			
		||||
	/* Check if the LinkStatus in the PHY is still low every second. */
 | 
			
		||||
	#define ipconfigPHY_LS_LOW_CHECK_TIME_MS	1000uL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* As the following 3 macro's are OK in most situations, and so they're not
 | 
			
		||||
included in 'FreeRTOSIPConfigDefaults.h'.
 | 
			
		||||
Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
 | 
			
		||||
#ifndef phyPHY_MAX_RESET_TIME_MS
 | 
			
		||||
	#define phyPHY_MAX_RESET_TIME_MS			1000uL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS
 | 
			
		||||
	#define phyPHY_MAX_NEGOTIATE_TIME_MS		3000uL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef phySHORT_DELAY_MS
 | 
			
		||||
	#define phySHORT_DELAY_MS					50uL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Naming and numbering of basic PHY registers. */
 | 
			
		||||
#define phyREG_00_BMCR				0x00u	/* Basic Mode Control Register. */
 | 
			
		||||
#define phyREG_01_BMSR				0x01u	/* Basic Mode Status Register. */
 | 
			
		||||
#define phyREG_02_PHYSID1			0x02u	/* PHYS ID 1 */
 | 
			
		||||
#define phyREG_03_PHYSID2			0x03u	/* PHYS ID 2 */
 | 
			
		||||
#define phyREG_04_ADVERTISE			0x04u	/* Advertisement control reg */
 | 
			
		||||
 | 
			
		||||
/* Naming and numbering of extended PHY registers. */
 | 
			
		||||
#define PHYREG_10_PHYSTS			0x10u	/* 16 PHY status register Offset */
 | 
			
		||||
#define	phyREG_19_PHYCR				0x19u	/* 25 RW PHY Control Register */
 | 
			
		||||
#define	phyREG_1F_PHYSPCS			0x1Fu	/* 31 RW PHY Special Control Status */
 | 
			
		||||
 | 
			
		||||
/* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */
 | 
			
		||||
#define phyBMCR_FULL_DUPLEX			0x0100u	/* Full duplex. */
 | 
			
		||||
#define phyBMCR_AN_RESTART			0x0200u	/* Auto negotiation restart. */
 | 
			
		||||
#define phyBMCR_ISOLATE				0x0400u /* 1 = Isolates 0 = Normal operation. */
 | 
			
		||||
#define phyBMCR_AN_ENABLE			0x1000u	/* Enable auto negotiation. */
 | 
			
		||||
#define phyBMCR_SPEED_100			0x2000u	/* Select 100Mbps. */
 | 
			
		||||
#define phyBMCR_RESET				0x8000u	/* Reset the PHY. */
 | 
			
		||||
 | 
			
		||||
/* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */
 | 
			
		||||
#define PHYCR_MDIX_EN				0x8000u	/* Enable Auto MDIX. */
 | 
			
		||||
#define PHYCR_MDIX_FORCE			0x4000u	/* Force MDIX crossed. */
 | 
			
		||||
 | 
			
		||||
#define phyBMSR_AN_COMPLETE			0x0020u	/* Auto-Negotiation process completed */
 | 
			
		||||
 | 
			
		||||
#define phyBMSR_LINK_STATUS			0x0004u
 | 
			
		||||
 | 
			
		||||
#define phyPHYSTS_LINK_STATUS		0x0001u	/* PHY Link mask */
 | 
			
		||||
#define phyPHYSTS_SPEED_STATUS		0x0002u	/* PHY Speed mask */
 | 
			
		||||
#define phyPHYSTS_DUPLEX_STATUS		0x0004u	/* PHY Duplex mask */
 | 
			
		||||
 | 
			
		||||
/* Bit fields for 'phyREG_1F_PHYSPCS
 | 
			
		||||
	001 = 10BASE-T half-duplex
 | 
			
		||||
	101 = 10BASE-T full-duplex
 | 
			
		||||
	010 = 100BASE-TX half-duplex
 | 
			
		||||
	110 = 100BASE-TX full-duplex
 | 
			
		||||
*/
 | 
			
		||||
#define phyPHYSPCS_SPEED_MASK		0x000Cu
 | 
			
		||||
#define phyPHYSPCS_SPEED_10			0x0004u
 | 
			
		||||
#define phyPHYSPCS_FULL_DUPLEX		0x0010u
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Description of all capabilities that can be advertised to
 | 
			
		||||
 * the peer (usually a switch or router).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define phyADVERTISE_CSMA			0x0001u	/* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
 | 
			
		||||
#define phyADVERTISE_10HALF			0x0020u	/* Try for 10mbps half-duplex. */
 | 
			
		||||
#define phyADVERTISE_10FULL			0x0040u	/* Try for 10mbps full-duplex. */
 | 
			
		||||
#define phyADVERTISE_100HALF		0x0080u	/* Try for 100mbps half-duplex. */
 | 
			
		||||
#define phyADVERTISE_100FULL		0x0100u	/* Try for 100mbps full-duplex. */
 | 
			
		||||
 | 
			
		||||
#define phyADVERTISE_ALL			( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \
 | 
			
		||||
									  phyADVERTISE_100HALF | phyADVERTISE_100FULL | \
 | 
			
		||||
									  phyADVERTISE_CSMA )
 | 
			
		||||
 | 
			
		||||
/* Send a reset command to a set of PHY-ports. */
 | 
			
		||||
static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );
 | 
			
		||||
 | 
			
		||||
static BaseType_t xHas_1F_PHYSPCS( uint32_t ulPhyID )
 | 
			
		||||
{
 | 
			
		||||
BaseType_t xResult;
 | 
			
		||||
 | 
			
		||||
	switch( ulPhyID )
 | 
			
		||||
	{
 | 
			
		||||
		case PHY_ID_LAN8720:
 | 
			
		||||
		case PHY_ID_LAN8742A:
 | 
			
		||||
		case PHY_ID_KSZ8041:
 | 
			
		||||
/*
 | 
			
		||||
		case PHY_ID_KSZ8051: // same ID as 8041
 | 
			
		||||
		case PHY_ID_KSZ8081: // same ID as 8041
 | 
			
		||||
*/
 | 
			
		||||
		case PHY_ID_KSZ8081MNXIA:
 | 
			
		||||
 | 
			
		||||
		case PHY_ID_KSZ8863:
 | 
			
		||||
		default:
 | 
			
		||||
			/* Most PHY's have a 1F_PHYSPCS */
 | 
			
		||||
			xResult = pdTRUE;
 | 
			
		||||
			break;
 | 
			
		||||
		case PHY_ID_DP83848I:
 | 
			
		||||
			xResult = pdFALSE;
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	return xResult;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static BaseType_t xHas_19_PHYCR( uint32_t ulPhyID )
 | 
			
		||||
{
 | 
			
		||||
BaseType_t xResult;
 | 
			
		||||
 | 
			
		||||
	switch( ulPhyID )
 | 
			
		||||
	{
 | 
			
		||||
		case PHY_ID_LAN8742A:
 | 
			
		||||
		case PHY_ID_DP83848I:
 | 
			
		||||
			xResult = pdTRUE;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			/* Most PHY's do not have a 19_PHYCR */
 | 
			
		||||
			xResult = pdFALSE;
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	return xResult;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Initialise the struct and assign a PHY-read and -write function. */
 | 
			
		||||
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite )
 | 
			
		||||
{
 | 
			
		||||
	memset( ( void * )pxPhyObject, '\0', sizeof( *pxPhyObject ) );
 | 
			
		||||
 | 
			
		||||
	pxPhyObject->fnPhyRead = fnPhyRead;
 | 
			
		||||
	pxPhyObject->fnPhyWrite = fnPhyWrite;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */
 | 
			
		||||
BaseType_t xPhyDiscover( EthernetPhy_t *pxPhyObject )
 | 
			
		||||
{
 | 
			
		||||
BaseType_t xPhyAddress;
 | 
			
		||||
 | 
			
		||||
	pxPhyObject->xPortCount = 0;
 | 
			
		||||
 | 
			
		||||
	for( xPhyAddress = phyMIN_PHY_ADDRESS; xPhyAddress <= phyMAX_PHY_ADDRESS; xPhyAddress++ )
 | 
			
		||||
	{
 | 
			
		||||
	uint32_t ulLowerID;
 | 
			
		||||
 | 
			
		||||
		pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );
 | 
			
		||||
		/* A valid PHY id can not be all zeros or all ones. */
 | 
			
		||||
		if( ( ulLowerID != ( uint16_t )~0u )  && ( ulLowerID != ( uint16_t )0u ) )
 | 
			
		||||
		{
 | 
			
		||||
		uint32_t ulUpperID;
 | 
			
		||||
		uint32_t ulPhyID;
 | 
			
		||||
 | 
			
		||||
			pxPhyObject->fnPhyRead( xPhyAddress, phyREG_02_PHYSID1, &ulUpperID );
 | 
			
		||||
			ulPhyID = ( ( ( uint32_t ) ulUpperID ) << 16 ) | ( ulLowerID & 0xFFF0 );
 | 
			
		||||
 | 
			
		||||
			pxPhyObject->ucPhyIndexes[ pxPhyObject->xPortCount ] = xPhyAddress;
 | 
			
		||||
			pxPhyObject->ulPhyIDs[ pxPhyObject->xPortCount ] = ulPhyID;
 | 
			
		||||
 | 
			
		||||
			pxPhyObject->xPortCount++;
 | 
			
		||||
 | 
			
		||||
			/* See if there is more storage space. */
 | 
			
		||||
			if( pxPhyObject->xPortCount == ipconfigPHY_MAX_PORTS )
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if( pxPhyObject->xPortCount > 0 )
 | 
			
		||||
	{
 | 
			
		||||
		FreeRTOS_printf( ( "PHY ID %lX\n", pxPhyObject->ulPhyIDs[ 0 ] ) );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pxPhyObject->xPortCount;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Send a reset command to a set of PHY-ports. */
 | 
			
		||||
static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulDoneMask, ulConfig;
 | 
			
		||||
TickType_t xRemainingTime;
 | 
			
		||||
TimeOut_t xTimer;
 | 
			
		||||
BaseType_t xPhyIndex;
 | 
			
		||||
 | 
			
		||||
	/* A bit-mask of PHY ports that are ready. */
 | 
			
		||||
	ulDoneMask = 0ul;
 | 
			
		||||
 | 
			
		||||
	/* Set the RESET bits high. */
 | 
			
		||||
	for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
 | 
			
		||||
	{
 | 
			
		||||
	BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
		/* Read Control register. */
 | 
			
		||||
		pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
 | 
			
		||||
		pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig | phyBMCR_RESET );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_RESET_TIME_MS );
 | 
			
		||||
	vTaskSetTimeOutState( &xTimer );
 | 
			
		||||
 | 
			
		||||
	/* The reset should last less than a second. */
 | 
			
		||||
	for( ;; )
 | 
			
		||||
	{
 | 
			
		||||
		for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
 | 
			
		||||
		{
 | 
			
		||||
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
			pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
 | 
			
		||||
			if( ( ulConfig & phyBMCR_RESET ) == 0 )
 | 
			
		||||
			{
 | 
			
		||||
				FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) );
 | 
			
		||||
				ulDoneMask |= ( 1ul << xPhyIndex );
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if( ulDoneMask == ulPhyMask )
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )
 | 
			
		||||
		{
 | 
			
		||||
			FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		/* Block for a while */
 | 
			
		||||
		vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Clear the reset bits. */
 | 
			
		||||
	for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
 | 
			
		||||
	{
 | 
			
		||||
		if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL )
 | 
			
		||||
		{
 | 
			
		||||
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
			/* The reset operation timed out, clear the bit manually. */
 | 
			
		||||
			pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
 | 
			
		||||
			pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
 | 
			
		||||
 | 
			
		||||
	return ulDoneMask;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
BaseType_t xPhyConfigure( EthernetPhy_t *pxPhyObject, const PhyProperties_t *pxPhyProperties )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulConfig, ulAdvertise;
 | 
			
		||||
BaseType_t xPhyIndex;
 | 
			
		||||
 | 
			
		||||
	if( pxPhyObject->xPortCount < 1 )
 | 
			
		||||
	{
 | 
			
		||||
		FreeRTOS_printf( ( "xPhyConfigure: No PHY's detected.\n" ) );
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The expected ID for the 'LAN8742A'  is 0x0007c130. */
 | 
			
		||||
	/* The expected ID for the 'LAN8720'   is 0x0007c0f0. */
 | 
			
		||||
	/* The expected ID for the 'DP83848I'  is 0x20005C90. */
 | 
			
		||||
 | 
			
		||||
    /* Set advertise register. */
 | 
			
		||||
	if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) && ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) )
 | 
			
		||||
	{
 | 
			
		||||
		ulAdvertise = phyADVERTISE_ALL;
 | 
			
		||||
		/* Reset auto-negotiation capability. */
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* Always select protocol 802.3u. */
 | 
			
		||||
		ulAdvertise = phyADVERTISE_CSMA;
 | 
			
		||||
 | 
			
		||||
		if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO )
 | 
			
		||||
		{
 | 
			
		||||
			if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL )
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_100FULL;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_10HALF | phyADVERTISE_100HALF;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO )
 | 
			
		||||
		{
 | 
			
		||||
			if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_10 )
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_10HALF;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_100FULL | phyADVERTISE_100HALF;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_100 )
 | 
			
		||||
		{
 | 
			
		||||
			if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL )
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_100FULL;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_100HALF;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL )
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_10FULL;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				ulAdvertise |= phyADVERTISE_10HALF;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Send a reset command to a set of PHY-ports. */
 | 
			
		||||
	xPhyReset( pxPhyObject, xPhyGetMask( pxPhyObject ) );
 | 
			
		||||
 | 
			
		||||
	for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
 | 
			
		||||
	{
 | 
			
		||||
	BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
	uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
		/* Write advertise register. */
 | 
			
		||||
		pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, ulAdvertise );
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
				AN_EN        AN1         AN0       Forced Mode
 | 
			
		||||
				  0           0           0        10BASE-T, Half-Duplex
 | 
			
		||||
				  0           0           1        10BASE-T, Full-Duplex
 | 
			
		||||
				  0           1           0        100BASE-TX, Half-Duplex
 | 
			
		||||
				  0           1           1        100BASE-TX, Full-Duplex
 | 
			
		||||
				AN_EN        AN1         AN0       Advertised Mode
 | 
			
		||||
				  1           0           0        10BASE-T, Half/Full-Duplex
 | 
			
		||||
				  1           0           1        100BASE-TX, Half/Full-Duplex
 | 
			
		||||
				  1           1           0        10BASE-T Half-Duplex
 | 
			
		||||
												   100BASE-TX, Half-Duplex
 | 
			
		||||
				  1           1           1        10BASE-T, Half/Full-Duplex
 | 
			
		||||
												   100BASE-TX, Half/Full-Duplex
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
		/* Read Control register. */
 | 
			
		||||
		pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
 | 
			
		||||
 | 
			
		||||
		ulConfig &= ~( phyBMCR_SPEED_100 | phyBMCR_FULL_DUPLEX );
 | 
			
		||||
 | 
			
		||||
		ulConfig |= phyBMCR_AN_ENABLE;
 | 
			
		||||
 | 
			
		||||
		if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_100 ) || ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) )
 | 
			
		||||
		{
 | 
			
		||||
			ulConfig |= phyBMCR_SPEED_100;
 | 
			
		||||
		}
 | 
			
		||||
		else if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_10 )
 | 
			
		||||
		{
 | 
			
		||||
			ulConfig &= ~phyBMCR_SPEED_100;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL ) || ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) )
 | 
			
		||||
		{
 | 
			
		||||
			ulConfig |= phyBMCR_FULL_DUPLEX;
 | 
			
		||||
		}
 | 
			
		||||
		else if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_HALF )
 | 
			
		||||
		{
 | 
			
		||||
			ulConfig &= ~phyBMCR_FULL_DUPLEX;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( xHas_19_PHYCR( ulPhyID ) )
 | 
			
		||||
		{
 | 
			
		||||
		uint32_t ulPhyControl;
 | 
			
		||||
			/* Read PHY Control register. */
 | 
			
		||||
			pxPhyObject->fnPhyRead( xPhyAddress, phyREG_19_PHYCR, &ulPhyControl );
 | 
			
		||||
 | 
			
		||||
			/* Clear bits which might get set: */
 | 
			
		||||
			ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE );
 | 
			
		||||
 | 
			
		||||
			if( pxPhyProperties->ucMDI_X == PHY_MDIX_AUTO )
 | 
			
		||||
			{
 | 
			
		||||
				ulPhyControl |= PHYCR_MDIX_EN;
 | 
			
		||||
			}
 | 
			
		||||
			else if( pxPhyProperties->ucMDI_X == PHY_MDIX_CROSSED )
 | 
			
		||||
			{
 | 
			
		||||
				/* Force direct link = Use crossed RJ45 cable. */
 | 
			
		||||
				ulPhyControl &= ~PHYCR_MDIX_FORCE;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				/* Force crossed link = Use direct RJ45 cable. */
 | 
			
		||||
				ulPhyControl |= PHYCR_MDIX_FORCE;
 | 
			
		||||
			}
 | 
			
		||||
			/* update PHY Control Register. */
 | 
			
		||||
			pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_19_PHYCR, ulPhyControl );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		FreeRTOS_printf( ( "+TCP: advertise: %04lX config %04lX\n", ulAdvertise, ulConfig ) );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Keep these values for later use. */
 | 
			
		||||
	pxPhyObject->ulBCRValue = ulConfig & ~phyBMCR_ISOLATE;
 | 
			
		||||
	pxPhyObject->ulACRValue = ulAdvertise;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* xPhyFixedValue(): this function is called in case auto-negotiation is disabled.
 | 
			
		||||
The caller has set the values in 'xPhyPreferences' (ucDuplex and ucSpeed).
 | 
			
		||||
The PHY register phyREG_00_BMCR will be set for every connected PHY that matches
 | 
			
		||||
with ulPhyMask. */
 | 
			
		||||
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
 | 
			
		||||
{
 | 
			
		||||
BaseType_t xPhyIndex;
 | 
			
		||||
uint32_t ulValue, ulBitMask = ( uint32_t )1u;
 | 
			
		||||
 | 
			
		||||
	ulValue = ( uint32_t )0u;
 | 
			
		||||
 | 
			
		||||
	if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL )
 | 
			
		||||
	{
 | 
			
		||||
		ulValue |= phyBMCR_FULL_DUPLEX;
 | 
			
		||||
	}
 | 
			
		||||
	if( pxPhyObject->xPhyPreferences.ucSpeed == PHY_SPEED_100 )
 | 
			
		||||
	{
 | 
			
		||||
		ulValue |= phyBMCR_SPEED_100;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
 | 
			
		||||
	{
 | 
			
		||||
		if( ( ulPhyMask & ulBitMask ) != 0lu )
 | 
			
		||||
		{
 | 
			
		||||
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
			/* Enable Auto-Negotiation. */
 | 
			
		||||
			pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulValue );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* xPhyStartAutoNegotiation() is the alternative xPhyFixedValue():
 | 
			
		||||
It sets the BMCR_AN_RESTART bit and waits for the auto-negotiation completion
 | 
			
		||||
( phyBMSR_AN_COMPLETE ). */
 | 
			
		||||
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
 | 
			
		||||
{
 | 
			
		||||
uint32_t xPhyIndex, ulDoneMask, ulBitMask;
 | 
			
		||||
uint32_t ulPHYLinkStatus, ulRegValue;
 | 
			
		||||
TickType_t xRemainingTime;
 | 
			
		||||
TimeOut_t xTimer;
 | 
			
		||||
 | 
			
		||||
	if( ulPhyMask == ( uint32_t )0u )
 | 
			
		||||
	{
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++ )
 | 
			
		||||
	{
 | 
			
		||||
		if( ( ulPhyMask & ( 1lu << xPhyIndex ) ) != 0lu )
 | 
			
		||||
		{
 | 
			
		||||
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
			/* Enable Auto-Negotiation. */
 | 
			
		||||
			pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, pxPhyObject->ulACRValue);
 | 
			
		||||
			pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue | phyBMCR_AN_RESTART );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_NEGOTIATE_TIME_MS );
 | 
			
		||||
	vTaskSetTimeOutState( &xTimer );
 | 
			
		||||
	ulDoneMask = 0;
 | 
			
		||||
	/* Wait until the auto-negotiation will be completed */
 | 
			
		||||
	for( ;; )
 | 
			
		||||
	{
 | 
			
		||||
		ulBitMask = ( uint32_t )1u;
 | 
			
		||||
		for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
 | 
			
		||||
		{
 | 
			
		||||
			if( ( ulPhyMask & ulBitMask ) != 0lu )
 | 
			
		||||
			{
 | 
			
		||||
				if( ( ulDoneMask & ulBitMask ) == 0lu )
 | 
			
		||||
				{
 | 
			
		||||
				BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
					pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue );
 | 
			
		||||
					if( ( ulRegValue & phyBMSR_AN_COMPLETE ) != 0 )
 | 
			
		||||
					{
 | 
			
		||||
						ulDoneMask |= ulBitMask;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if( ulPhyMask == ulDoneMask )
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )
 | 
			
		||||
		{
 | 
			
		||||
			FreeRTOS_printf( ( "xPhyStartAutoNegotiation: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( ulDoneMask != ( uint32_t)0u )
 | 
			
		||||
	{
 | 
			
		||||
		ulBitMask = ( uint32_t )1u;
 | 
			
		||||
		pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );
 | 
			
		||||
		for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
 | 
			
		||||
		{
 | 
			
		||||
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
		uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
			if( ( ulDoneMask & ulBitMask ) == ( uint32_t )0u )
 | 
			
		||||
			{
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Clear the 'phyBMCR_AN_RESTART'  bit. */
 | 
			
		||||
			pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue );
 | 
			
		||||
 | 
			
		||||
			pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue);
 | 
			
		||||
			if( ( ulRegValue & phyBMSR_LINK_STATUS ) != 0 )
 | 
			
		||||
			{
 | 
			
		||||
				ulPHYLinkStatus |= phyBMSR_LINK_STATUS;
 | 
			
		||||
				pxPhyObject->ulLinkStatusMask |= ulBitMask;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				ulPHYLinkStatus &= ~( phyBMSR_LINK_STATUS );
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if( ulPhyID == PHY_ID_KSZ8081MNXIA )
 | 
			
		||||
			{
 | 
			
		||||
			uint32_t ulControlStatus;
 | 
			
		||||
 | 
			
		||||
				pxPhyObject->fnPhyRead( xPhyAddress, 0x1E, &ulControlStatus);
 | 
			
		||||
				switch( ulControlStatus & 0x07 )
 | 
			
		||||
				{
 | 
			
		||||
				case 0x01:
 | 
			
		||||
				case 0x05:
 | 
			
		||||
//	[001] = 10BASE-T half-duplex
 | 
			
		||||
//	[101] = 10BASE-T full-duplex
 | 
			
		||||
					/* 10 Mbps. */
 | 
			
		||||
					ulRegValue |= phyPHYSTS_SPEED_STATUS;
 | 
			
		||||
					break;
 | 
			
		||||
				case 0x02:
 | 
			
		||||
				case 0x06:
 | 
			
		||||
//	[010] = 100BASE-TX half-duplex
 | 
			
		||||
//	[110] = 100BASE-TX full-duplex
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				switch( ulControlStatus & 0x07 )
 | 
			
		||||
				{
 | 
			
		||||
				case 0x05:
 | 
			
		||||
				case 0x06:
 | 
			
		||||
//	[101] = 10BASE-T full-duplex
 | 
			
		||||
//	[110] = 100BASE-TX full-duplex
 | 
			
		||||
					/* Full duplex. */
 | 
			
		||||
					ulRegValue |= phyPHYSTS_DUPLEX_STATUS;
 | 
			
		||||
					break;
 | 
			
		||||
				case 0x01:
 | 
			
		||||
				case 0x02:
 | 
			
		||||
//	[001] = 10BASE-T half-duplex
 | 
			
		||||
//	[010] = 100BASE-TX half-duplex
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if( xHas_1F_PHYSPCS( ulPhyID ) )
 | 
			
		||||
			{
 | 
			
		||||
			/* 31 RW PHY Special Control Status */
 | 
			
		||||
			uint32_t ulControlStatus;
 | 
			
		||||
 | 
			
		||||
				pxPhyObject->fnPhyRead( xPhyAddress, phyREG_1F_PHYSPCS, &ulControlStatus);
 | 
			
		||||
				ulRegValue = 0;
 | 
			
		||||
				if( ( ulControlStatus & phyPHYSPCS_FULL_DUPLEX ) != 0 )
 | 
			
		||||
				{
 | 
			
		||||
					ulRegValue |= phyPHYSTS_DUPLEX_STATUS;
 | 
			
		||||
				}
 | 
			
		||||
				if( ( ulControlStatus & phyPHYSPCS_SPEED_MASK ) == phyPHYSPCS_SPEED_10 )
 | 
			
		||||
				{
 | 
			
		||||
					ulRegValue |= phyPHYSTS_SPEED_STATUS;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				/* Read the result of the auto-negotiation. */
 | 
			
		||||
				pxPhyObject->fnPhyRead( xPhyAddress, PHYREG_10_PHYSTS, &ulRegValue);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			FreeRTOS_printf( ( "Autonego ready: %08lx: %s duplex %u mbit %s status\n",
 | 
			
		||||
				ulRegValue,
 | 
			
		||||
				( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",
 | 
			
		||||
				( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,
 | 
			
		||||
				( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) );
 | 
			
		||||
			if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t )0u )
 | 
			
		||||
			{
 | 
			
		||||
				pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_HALF;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if( ( ulRegValue & phyPHYSTS_SPEED_STATUS ) != 0 )
 | 
			
		||||
			{
 | 
			
		||||
				pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_10;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}	/* if( ulDoneMask != ( uint32_t)0u ) */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulStatus, ulBitMask = 1u;
 | 
			
		||||
BaseType_t xPhyIndex;
 | 
			
		||||
BaseType_t xNeedCheck = pdFALSE;
 | 
			
		||||
 | 
			
		||||
	if( xHadReception > 0 )
 | 
			
		||||
	{
 | 
			
		||||
		/* A packet was received. No need to check for the PHY status now,
 | 
			
		||||
		but set a timer to check it later on. */
 | 
			
		||||
		vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
 | 
			
		||||
		pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
 | 
			
		||||
		for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
 | 
			
		||||
		{
 | 
			
		||||
			if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0ul )
 | 
			
		||||
			{
 | 
			
		||||
				pxPhyObject->ulLinkStatusMask |= ulBitMask;
 | 
			
		||||
				FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
 | 
			
		||||
				xNeedCheck = pdTRUE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE )
 | 
			
		||||
	{
 | 
			
		||||
		/* Frequent checking the PHY Link Status can affect for the performance of Ethernet controller.
 | 
			
		||||
		As long as packets are received, no polling is needed.
 | 
			
		||||
		Otherwise, polling will be done when the 'xLinkStatusTimer' expires. */
 | 
			
		||||
		for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
 | 
			
		||||
		{
 | 
			
		||||
		BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
 | 
			
		||||
 | 
			
		||||
			if( pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulStatus ) == 0 )
 | 
			
		||||
			{
 | 
			
		||||
				if( !!( pxPhyObject->ulLinkStatusMask & ulBitMask ) != !!( ulStatus & phyBMSR_LINK_STATUS ) )
 | 
			
		||||
				{
 | 
			
		||||
					if( ( ulStatus & phyBMSR_LINK_STATUS ) != 0 )
 | 
			
		||||
					{
 | 
			
		||||
						pxPhyObject->ulLinkStatusMask |= ulBitMask;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						pxPhyObject->ulLinkStatusMask &= ~( ulBitMask );
 | 
			
		||||
					}
 | 
			
		||||
					FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
 | 
			
		||||
					xNeedCheck = pdTRUE;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
 | 
			
		||||
		if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
 | 
			
		||||
		{
 | 
			
		||||
			/* The link status is high, so don't poll the PHY too often. */
 | 
			
		||||
			pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			/* The link status is low, polling may be done more frequently. */
 | 
			
		||||
			pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return xNeedCheck;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The Ethernet header files for STM32F2, STM32F4 and STM32F7 have been merged to
 | 
			
		||||
 * a single module that works for both parts: "stm32fxx_hal_eth"
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "stm32fxx_hal_eth.h"
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The Ethernet header files for STM32F2, STM32F4 and STM32F7 have been merged to
 | 
			
		||||
 * a single module that works for both parts: "stm32fxx_hal_eth"
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "stm32fxx_hal_eth.h"
 | 
			
		||||
@ -0,0 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The Ethernet header files for STM32F2, STM32F4 and STM32F7 have been merged to
 | 
			
		||||
 * a single module that works for both parts: "stm32fxx_hal_eth"
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "stm32fxx_hal_eth.h"
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,132 @@
 | 
			
		||||
/*
 | 
			
		||||
 * uncached_memory.c
 | 
			
		||||
 *
 | 
			
		||||
 * This module will declare 1 MB of memory and switch off the caching for it.
 | 
			
		||||
 *
 | 
			
		||||
 * pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
 | 
			
		||||
 * rounded up to a multiple of 4 KB
 | 
			
		||||
 *
 | 
			
		||||
 * ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
 | 
			
		||||
 * within the range of the 1 MB non-cached memory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * After "_end", 1 MB of uncached memory will be allocated for DMA transfers.
 | 
			
		||||
 * Both the DMA descriptors as well as all EMAC TX-buffers will be allocated in
 | 
			
		||||
 * uncached memory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS+TCP includes. */
 | 
			
		||||
#include "FreeRTOS_IP.h"
 | 
			
		||||
#include "FreeRTOS_Sockets.h"
 | 
			
		||||
#include "FreeRTOS_IP_Private.h"
 | 
			
		||||
 | 
			
		||||
#include "Zynq/x_emacpsif.h"
 | 
			
		||||
#include "Zynq/x_topology.h"
 | 
			
		||||
#include "xstatus.h"
 | 
			
		||||
 | 
			
		||||
#include "xparameters.h"
 | 
			
		||||
#include "xparameters_ps.h"
 | 
			
		||||
#include "xil_exception.h"
 | 
			
		||||
#include "xil_mmu.h"
 | 
			
		||||
 | 
			
		||||
#include "uncached_memory.h"
 | 
			
		||||
 | 
			
		||||
#define UNCACHED_MEMORY_SIZE	0x100000ul
 | 
			
		||||
 | 
			
		||||
#define DDR_MEMORY_END	(XPAR_PS7_DDR_0_S_AXI_HIGHADDR+1)
 | 
			
		||||
 | 
			
		||||
static void vInitialiseUncachedMemory( void );
 | 
			
		||||
 | 
			
		||||
static uint8_t *pucHeadOfMemory;
 | 
			
		||||
static uint32_t ulMemorySize;
 | 
			
		||||
static uint8_t *pucStartOfMemory = NULL;
 | 
			
		||||
 | 
			
		||||
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
 | 
			
		||||
{
 | 
			
		||||
uint8_t ucReturn;
 | 
			
		||||
 | 
			
		||||
	if( ( pucStartOfMemory != NULL ) &&
 | 
			
		||||
		( pucBuffer >= pucStartOfMemory ) &&
 | 
			
		||||
		( pucBuffer < ( pucStartOfMemory + UNCACHED_MEMORY_SIZE ) ) )
 | 
			
		||||
	{
 | 
			
		||||
		ucReturn = pdFALSE;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		ucReturn = pdTRUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ucReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t *pucGetUncachedMemory( uint32_t ulSize )
 | 
			
		||||
{
 | 
			
		||||
uint8_t *pucReturn;
 | 
			
		||||
 | 
			
		||||
	if( pucStartOfMemory == NULL )
 | 
			
		||||
	{
 | 
			
		||||
		vInitialiseUncachedMemory( );
 | 
			
		||||
	}
 | 
			
		||||
	if( ( pucStartOfMemory == NULL ) || ( ulSize > ulMemorySize ) )
 | 
			
		||||
	{
 | 
			
		||||
		pucReturn = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	uint32_t ulSkipSize;
 | 
			
		||||
 | 
			
		||||
		pucReturn = pucHeadOfMemory;
 | 
			
		||||
		ulSkipSize = ( ulSize + 0x1000ul ) & ~0xffful;
 | 
			
		||||
		pucHeadOfMemory += ulSkipSize;
 | 
			
		||||
		ulMemorySize -= ulSkipSize;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pucReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern u8 _end;
 | 
			
		||||
 | 
			
		||||
static void vInitialiseUncachedMemory( )
 | 
			
		||||
{
 | 
			
		||||
	/* At the end of program's space... */
 | 
			
		||||
	pucStartOfMemory = (uint8_t *) &_end;
 | 
			
		||||
	/*
 | 
			
		||||
	 * Align the start address to 1 MB boundary.
 | 
			
		||||
	 */
 | 
			
		||||
	pucStartOfMemory = (uint8_t *)( ( ( uint32_t )pucStartOfMemory + UNCACHED_MEMORY_SIZE ) & ( ~( UNCACHED_MEMORY_SIZE - 1 ) ) );
 | 
			
		||||
 | 
			
		||||
	if( ( ( u32 )pucStartOfMemory ) + UNCACHED_MEMORY_SIZE > DDR_MEMORY_END )
 | 
			
		||||
	{
 | 
			
		||||
//		vLoggingPrintf("vInitialiseUncachedMemory: Can not allocate uncached memory\n" );
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/*
 | 
			
		||||
		 * Some objects want to be stored in uncached memory. Hence the 1 MB
 | 
			
		||||
		 * address range that starts after "_end" is made uncached
 | 
			
		||||
		 * by setting appropriate attributes in the translation table.
 | 
			
		||||
		 */
 | 
			
		||||
		/* FIXME claudio rossi. Modified to prevent data abort exception (misaligned access)
 | 
			
		||||
		 * when application is compiled with -O1 or more optimization flag.
 | 
			
		||||
		 */
 | 
			
		||||
/*		Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0xc02 ); // addr, attr */
 | 
			
		||||
		Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0x1c02 ); // addr, attr
 | 
			
		||||
 | 
			
		||||
		/* For experiments in the SDIO driver, make the remaining uncached memory public */
 | 
			
		||||
		pucHeadOfMemory = pucStartOfMemory;
 | 
			
		||||
		ulMemorySize = UNCACHED_MEMORY_SIZE;
 | 
			
		||||
		memset( pucStartOfMemory, '\0', UNCACHED_MEMORY_SIZE );
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * uncached_memory.h
 | 
			
		||||
 *
 | 
			
		||||
 * This module will declare 1 MB of memory and switch off the caching for it.
 | 
			
		||||
 *
 | 
			
		||||
 * pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
 | 
			
		||||
 * rounded up to a multiple of 4 KB
 | 
			
		||||
 *
 | 
			
		||||
 * ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
 | 
			
		||||
 * within the range of the 1 MB non-cached memory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UNCACHEMEMORY_H
 | 
			
		||||
 | 
			
		||||
#define UNCACHEMEMORY_H
 | 
			
		||||
 | 
			
		||||
uint8_t *pucGetUncachedMemory( uint32_t ulSize );
 | 
			
		||||
 | 
			
		||||
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer );
 | 
			
		||||
 | 
			
		||||
#endif /* UNCACHEMEMORY_H */
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Handling of Ethernet PHY's
 | 
			
		||||
 * PHY's communicate with an EMAC either through
 | 
			
		||||
 * a Media-Independent Interface (MII), or a Reduced Media-Independent Interface (RMII).
 | 
			
		||||
 * The EMAC can poll for PHY ports on 32 different addresses. Each of the PHY ports
 | 
			
		||||
 * shall be treated independently.
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PHYHANDLING_H
 | 
			
		||||
 | 
			
		||||
#define PHYHANDLING_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef ipconfigPHY_MAX_PORTS
 | 
			
		||||
	/* There can be at most 32 PHY ports, but in most cases there are 4 or less. */
 | 
			
		||||
	#define	ipconfigPHY_MAX_PORTS	4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* A generic user-provided function that reads from the PHY-port at 'xAddress'( 0-based ). A 16-bit value shall be stored in
 | 
			
		||||
  '*pulValue'. xRegister is the register number ( 0 .. 31 ). In fact all PHY registers are 16-bit.
 | 
			
		||||
  Return non-zero in case the action failed. */
 | 
			
		||||
typedef BaseType_t ( *xApplicationPhyReadHook_t )( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue );
 | 
			
		||||
 | 
			
		||||
/* A generic user-provided function that writes 'ulValue' to the
 | 
			
		||||
   PHY-port at 'xAddress' ( 0-based ). xRegister is the register number ( 0 .. 31 ).
 | 
			
		||||
   Return non-zero in case the action failed. */
 | 
			
		||||
typedef BaseType_t ( *xApplicationPhyWriteHook_t )( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue );
 | 
			
		||||
 | 
			
		||||
typedef struct xPhyProperties
 | 
			
		||||
{
 | 
			
		||||
	uint8_t ucSpeed;
 | 
			
		||||
	uint8_t ucMDI_X;		/* MDI-X : Medium Dependent Interface - Crossover */
 | 
			
		||||
	uint8_t ucDuplex;
 | 
			
		||||
	uint8_t ucSpare;
 | 
			
		||||
} PhyProperties_t;
 | 
			
		||||
 | 
			
		||||
typedef struct xEthernetPhy
 | 
			
		||||
{
 | 
			
		||||
	xApplicationPhyReadHook_t fnPhyRead;
 | 
			
		||||
	xApplicationPhyWriteHook_t fnPhyWrite;
 | 
			
		||||
	uint32_t ulPhyIDs[ ipconfigPHY_MAX_PORTS ];
 | 
			
		||||
	uint8_t ucPhyIndexes[ ipconfigPHY_MAX_PORTS ];
 | 
			
		||||
	TimeOut_t xLinkStatusTimer;
 | 
			
		||||
	TickType_t xLinkStatusRemaining;
 | 
			
		||||
	BaseType_t xPortCount;
 | 
			
		||||
	uint32_t ulBCRValue;
 | 
			
		||||
	uint32_t ulACRValue;
 | 
			
		||||
	uint32_t ulLinkStatusMask;
 | 
			
		||||
	PhyProperties_t xPhyPreferences;
 | 
			
		||||
	PhyProperties_t xPhyProperties;
 | 
			
		||||
} EthernetPhy_t;
 | 
			
		||||
 | 
			
		||||
/* Some defines used internally here to indicate preferences about speed, MDIX
 | 
			
		||||
(wired direct or crossed), and duplex (half or full). */
 | 
			
		||||
 | 
			
		||||
/* Values for PhyProperties_t::ucSpeed : */
 | 
			
		||||
#define	PHY_SPEED_10		1
 | 
			
		||||
#define	PHY_SPEED_100		2
 | 
			
		||||
#define	PHY_SPEED_AUTO		3
 | 
			
		||||
 | 
			
		||||
/* Values for PhyProperties_t::ucMDI_X : */
 | 
			
		||||
#define	PHY_MDIX_DIRECT		1
 | 
			
		||||
#define	PHY_MDIX_CROSSED	2
 | 
			
		||||
#define	PHY_MDIX_AUTO		3
 | 
			
		||||
 | 
			
		||||
/* Values for PhyProperties_t::ucDuplex : */
 | 
			
		||||
#define	PHY_DUPLEX_HALF		1
 | 
			
		||||
#define	PHY_DUPLEX_FULL		2
 | 
			
		||||
#define	PHY_DUPLEX_AUTO		3
 | 
			
		||||
 | 
			
		||||
/* ID's of supported PHY's : */
 | 
			
		||||
#define PHY_ID_LAN8742A		0x0007c130
 | 
			
		||||
#define PHY_ID_LAN8720		0x0007c0f0
 | 
			
		||||
 | 
			
		||||
#define PHY_ID_KSZ8041		0x000010A1
 | 
			
		||||
#define PHY_ID_KSZ8051		0x000010A1
 | 
			
		||||
#define PHY_ID_KSZ8081		0x000010A1
 | 
			
		||||
 | 
			
		||||
#define PHY_ID_KSZ8863		0x00221430
 | 
			
		||||
#define PHY_ID_KSZ8081MNXIA 0x00221560
 | 
			
		||||
 | 
			
		||||
#define PHY_ID_DP83848I		0x20005C90
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Initialise the struct and assign a PHY-read and -write function. */
 | 
			
		||||
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite );
 | 
			
		||||
 | 
			
		||||
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */
 | 
			
		||||
BaseType_t xPhyDiscover( EthernetPhy_t *pxPhyObject );
 | 
			
		||||
 | 
			
		||||
/* Send a reset command to the connected PHY ports and send configuration. */
 | 
			
		||||
BaseType_t xPhyConfigure( EthernetPhy_t *pxPhyObject, const PhyProperties_t *pxPhyProperties );
 | 
			
		||||
 | 
			
		||||
/* Give a command to start auto negotiation on a set of PHY port's. */
 | 
			
		||||
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );
 | 
			
		||||
 | 
			
		||||
/* Do not use auto negotiation but use predefined values from 'pxPhyObject->xPhyPreferences'. */
 | 
			
		||||
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );
 | 
			
		||||
 | 
			
		||||
/* Check the current Link Status.
 | 
			
		||||
'xHadReception' : make this true if a packet has been received since the
 | 
			
		||||
last call to this function. */
 | 
			
		||||
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception );
 | 
			
		||||
 | 
			
		||||
/* Get the bitmask of a given 'EthernetPhy_t'. */
 | 
			
		||||
#define xPhyGetMask( pxPhyObject ) \
 | 
			
		||||
	( ( ( ( uint32_t ) 1u ) << ( pxPhyObject )->xPortCount ) - 1u )
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -0,0 +1,610 @@
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * \file
 | 
			
		||||
 *
 | 
			
		||||
 * \brief KS8851SNL driver for SAM.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * \asf_license_start
 | 
			
		||||
 *
 | 
			
		||||
 * \page License
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
 *    and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * 3. The name of Atmel may not be used to endorse or promote products derived
 | 
			
		||||
 *    from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * 4. This software may only be redistributed and used in connection with an
 | 
			
		||||
 *    Atmel microcontroller product.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 | 
			
		||||
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 | 
			
		||||
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 | 
			
		||||
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
			
		||||
 * POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * \asf_license_stop
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
 | 
			
		||||
#include "spi_master.h"
 | 
			
		||||
#include "ksz8851snl.h"
 | 
			
		||||
#include "ksz8851snl_reg.h"
 | 
			
		||||
#include "delay.h"
 | 
			
		||||
#include "pio.h"
 | 
			
		||||
#include "pio_handler.h"
 | 
			
		||||
#include "pdc.h"
 | 
			
		||||
#include "conf_eth.h"
 | 
			
		||||
 | 
			
		||||
/* Clock polarity. */
 | 
			
		||||
#define SPI_CLK_POLARITY 0
 | 
			
		||||
 | 
			
		||||
/* Clock phase. */
 | 
			
		||||
#define SPI_CLK_PHASE 1
 | 
			
		||||
 | 
			
		||||
/* SPI PDC register base. */
 | 
			
		||||
Pdc *g_p_spi_pdc = 0;
 | 
			
		||||
 | 
			
		||||
int lUDPLoggingPrintf( const char *pcFormatString, ... );
 | 
			
		||||
 | 
			
		||||
/* Temporary buffer for PDC reception. */
 | 
			
		||||
uint8_t tmpbuf[1536] __attribute__ ((aligned (16)));
 | 
			
		||||
 | 
			
		||||
union {
 | 
			
		||||
	uint64_t ul[2];
 | 
			
		||||
	uint8_t uc[16];
 | 
			
		||||
} cmdBuf, respBuf;
 | 
			
		||||
 | 
			
		||||
void dbg_add_line( const char *pcFormat, ... );
 | 
			
		||||
 | 
			
		||||
static void spi_clear_ovres( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Read register content, set bitmask and write back to register.
 | 
			
		||||
 *
 | 
			
		||||
 * \param reg the register address to modify.
 | 
			
		||||
 * \param bits_to_set bitmask to apply.
 | 
			
		||||
 */
 | 
			
		||||
void ksz8851_reg_setbits(uint16_t reg, uint16_t bits_to_set)
 | 
			
		||||
{
 | 
			
		||||
   uint16_t	temp;
 | 
			
		||||
 | 
			
		||||
   temp = ksz8851_reg_read(reg);
 | 
			
		||||
   temp |= bits_to_set;
 | 
			
		||||
   ksz8851_reg_write(reg, temp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Read register content, clear bitmask and write back to register.
 | 
			
		||||
 *
 | 
			
		||||
 * \param reg the register address to modify.
 | 
			
		||||
 * \param bits_to_set bitmask to apply.
 | 
			
		||||
 */
 | 
			
		||||
void ksz8851_reg_clrbits(uint16_t reg, uint16_t bits_to_clr)
 | 
			
		||||
{
 | 
			
		||||
   uint16_t	temp;
 | 
			
		||||
 | 
			
		||||
   temp = ksz8851_reg_read(reg);
 | 
			
		||||
   temp &= ~(uint32_t) bits_to_clr;
 | 
			
		||||
   ksz8851_reg_write(reg, temp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Configure the INTN interrupt.
 | 
			
		||||
 */
 | 
			
		||||
void configure_intn(void (*p_handler) (uint32_t, uint32_t))
 | 
			
		||||
{
 | 
			
		||||
//	gpio_configure_pin(KSZ8851SNL_INTN_GPIO, PIO_INPUT);
 | 
			
		||||
//	pio_set_input(PIOA, PIO_PA11_IDX, PIO_PULLUP);
 | 
			
		||||
 | 
			
		||||
	/* Configure PIO clock. */
 | 
			
		||||
	pmc_enable_periph_clk(INTN_ID);
 | 
			
		||||
 | 
			
		||||
	/* Adjust PIO debounce filter parameters, uses 10 Hz filter. */
 | 
			
		||||
	pio_set_debounce_filter(INTN_PIO, INTN_PIN_MSK, 10);
 | 
			
		||||
 | 
			
		||||
	/* Initialize PIO interrupt handlers, see PIO definition in board.h. */
 | 
			
		||||
	pio_handler_set(INTN_PIO, INTN_ID, INTN_PIN_MSK,
 | 
			
		||||
		INTN_ATTR, p_handler);
 | 
			
		||||
 | 
			
		||||
	/* Enable NVIC interrupts. */
 | 
			
		||||
	NVIC_SetPriority(INTN_IRQn, INT_PRIORITY_PIO);
 | 
			
		||||
	NVIC_EnableIRQ((IRQn_Type)INTN_ID);
 | 
			
		||||
 | 
			
		||||
	/* Enable PIO interrupts. */
 | 
			
		||||
	pio_enable_interrupt(INTN_PIO, INTN_PIN_MSK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Read a register value.
 | 
			
		||||
 *
 | 
			
		||||
 * \param reg the register address to modify.
 | 
			
		||||
 *
 | 
			
		||||
 * \return the register value.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t ksz8851_reg_read(uint16_t reg)
 | 
			
		||||
{
 | 
			
		||||
pdc_packet_t g_pdc_spi_tx_packet;
 | 
			
		||||
pdc_packet_t g_pdc_spi_rx_packet;
 | 
			
		||||
uint16_t cmd = 0;
 | 
			
		||||
uint16_t res = 0;
 | 
			
		||||
int iTryCount = 3;
 | 
			
		||||
 | 
			
		||||
	while( iTryCount-- > 0 )
 | 
			
		||||
	{
 | 
			
		||||
	uint32_t ulStatus;
 | 
			
		||||
 | 
			
		||||
		spi_clear_ovres();
 | 
			
		||||
		/* Move register address to cmd bits 9-2, make 32-bit address. */
 | 
			
		||||
		cmd = (reg << 2) & REG_ADDR_MASK;
 | 
			
		||||
 | 
			
		||||
		/* Last 2 bits still under "don't care bits" handled with byte enable. */
 | 
			
		||||
		/* Select byte enable for command. */
 | 
			
		||||
		if (reg & 2) {
 | 
			
		||||
			/* Odd word address writes bytes 2 and 3 */
 | 
			
		||||
			cmd |= (0xc << 10);
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Even word address write bytes 0 and 1 */
 | 
			
		||||
			cmd |= (0x3 << 10);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Add command read code. */
 | 
			
		||||
		cmd |= CMD_READ;
 | 
			
		||||
		cmdBuf.uc[0] = cmd >> 8;
 | 
			
		||||
		cmdBuf.uc[1] = cmd & 0xff;
 | 
			
		||||
		cmdBuf.uc[2] = CONFIG_SPI_MASTER_DUMMY;
 | 
			
		||||
		cmdBuf.uc[3] = CONFIG_SPI_MASTER_DUMMY;
 | 
			
		||||
 | 
			
		||||
		/* Prepare PDC transfer. */
 | 
			
		||||
		g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
 | 
			
		||||
		g_pdc_spi_tx_packet.ul_size = 4;
 | 
			
		||||
		g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
 | 
			
		||||
		g_pdc_spi_rx_packet.ul_size = 4;
 | 
			
		||||
		pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
		pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
 | 
			
		||||
		pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
 | 
			
		||||
	gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
 | 
			
		||||
 | 
			
		||||
	spi_disable_interrupt( KSZ8851SNL_SPI, ~0ul );
 | 
			
		||||
		pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
 | 
			
		||||
		for( ;; )
 | 
			
		||||
		{
 | 
			
		||||
			ulStatus = spi_read_status( KSZ8851SNL_SPI );
 | 
			
		||||
			if( ( ulStatus & ( SPI_SR_OVRES | SPI_SR_ENDRX ) ) != 0 )
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
 | 
			
		||||
		if( ( ulStatus & SPI_SR_OVRES ) == 0 )
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
		lUDPLoggingPrintf( "ksz8851_reg_read: SPI_SR_OVRES\n" );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res = (tmpbuf[3] << 8) | tmpbuf[2];
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Write a register value.
 | 
			
		||||
 *
 | 
			
		||||
 * \param reg the register address to modify.
 | 
			
		||||
 * \param wrdata the new register value.
 | 
			
		||||
 */
 | 
			
		||||
void ksz8851_reg_write(uint16_t reg, uint16_t wrdata)
 | 
			
		||||
{
 | 
			
		||||
pdc_packet_t g_pdc_spi_tx_packet;
 | 
			
		||||
pdc_packet_t g_pdc_spi_rx_packet;
 | 
			
		||||
uint16_t cmd = 0;
 | 
			
		||||
int iTryCount = 3;
 | 
			
		||||
 | 
			
		||||
	while( iTryCount-- > 0 )
 | 
			
		||||
	{
 | 
			
		||||
	uint32_t ulStatus;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		spi_clear_ovres();
 | 
			
		||||
		/* Move register address to cmd bits 9-2, make 32-bit address. */
 | 
			
		||||
		cmd = (reg << 2) & REG_ADDR_MASK;
 | 
			
		||||
 | 
			
		||||
		/* Last 2 bits still under "don't care bits" handled with byte enable. */
 | 
			
		||||
		/* Select byte enable for command. */
 | 
			
		||||
		if (reg & 2) {
 | 
			
		||||
			/* Odd word address writes bytes 2 and 3 */
 | 
			
		||||
			cmd |= (0xc << 10);
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Even word address write bytes 0 and 1 */
 | 
			
		||||
			cmd |= (0x3 << 10);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Add command write code. */
 | 
			
		||||
		cmd |= CMD_WRITE;
 | 
			
		||||
		cmdBuf.uc[0] = cmd >> 8;
 | 
			
		||||
		cmdBuf.uc[1] = cmd & 0xff;
 | 
			
		||||
		cmdBuf.uc[2] = wrdata & 0xff;
 | 
			
		||||
		cmdBuf.uc[3] = wrdata >> 8;
 | 
			
		||||
 | 
			
		||||
		/* Prepare PDC transfer. */
 | 
			
		||||
		g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
 | 
			
		||||
		g_pdc_spi_tx_packet.ul_size = 4;
 | 
			
		||||
		g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
 | 
			
		||||
		g_pdc_spi_rx_packet.ul_size = 4;
 | 
			
		||||
		pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
		pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
 | 
			
		||||
		pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
 | 
			
		||||
		gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
 | 
			
		||||
 | 
			
		||||
		spi_disable_interrupt( KSZ8851SNL_SPI, ~0ul );
 | 
			
		||||
 | 
			
		||||
		pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
 | 
			
		||||
		for( ;; )
 | 
			
		||||
		{
 | 
			
		||||
			ulStatus = spi_read_status( KSZ8851SNL_SPI );
 | 
			
		||||
			if( ( ulStatus & ( SPI_SR_OVRES | SPI_SR_ENDRX ) ) != 0 )
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
 | 
			
		||||
		if( ( ulStatus & SPI_SR_OVRES ) == 0 )
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
		lUDPLoggingPrintf( "ksz8851_reg_write: SPI_SR_OVRES\n" );
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void spi_clear_ovres( void )
 | 
			
		||||
{
 | 
			
		||||
volatile uint32_t rc;
 | 
			
		||||
	rc = KSZ8851SNL_SPI->SPI_RDR;
 | 
			
		||||
 | 
			
		||||
	spi_read_status( KSZ8851SNL_SPI );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Read internal fifo buffer.
 | 
			
		||||
 *
 | 
			
		||||
 * \param buf the buffer to store the data from the fifo buffer.
 | 
			
		||||
 * \param len the amount of data to read.
 | 
			
		||||
 */
 | 
			
		||||
void ksz8851_fifo_read(uint8_t *buf, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	pdc_packet_t g_pdc_spi_tx_packet;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_rx_packet;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_tx_npacket;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_rx_npacket;
 | 
			
		||||
 | 
			
		||||
	memset( cmdBuf.uc, '\0', sizeof cmdBuf );
 | 
			
		||||
	cmdBuf.uc[0] = FIFO_READ;
 | 
			
		||||
	spi_clear_ovres();
 | 
			
		||||
 | 
			
		||||
	/* Prepare PDC transfer. */
 | 
			
		||||
	g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
 | 
			
		||||
	g_pdc_spi_tx_packet.ul_size = 9;
 | 
			
		||||
	g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
 | 
			
		||||
	g_pdc_spi_rx_packet.ul_size = 9;
 | 
			
		||||
 | 
			
		||||
	g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
 | 
			
		||||
	g_pdc_spi_tx_npacket.ul_size = len;
 | 
			
		||||
	g_pdc_spi_rx_npacket.ul_addr = (uint32_t) buf;
 | 
			
		||||
	g_pdc_spi_rx_npacket.ul_size = len;
 | 
			
		||||
	pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
	pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
 | 
			
		||||
	pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
 | 
			
		||||
 | 
			
		||||
spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_RXBUFF | SPI_IER_OVRES);
 | 
			
		||||
 | 
			
		||||
	pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Write internal fifo buffer.
 | 
			
		||||
 *
 | 
			
		||||
 * \param buf the buffer to send to the fifo buffer.
 | 
			
		||||
 * \param ulActualLength the total amount of data to write.
 | 
			
		||||
 * \param ulFIFOLength the size of the first pbuf to write from the pbuf chain.
 | 
			
		||||
 */
 | 
			
		||||
void ksz8851_fifo_write(uint8_t *buf, uint32_t ulActualLength, uint32_t ulFIFOLength)
 | 
			
		||||
{
 | 
			
		||||
	static uint8_t frameID = 0;
 | 
			
		||||
 | 
			
		||||
	pdc_packet_t g_pdc_spi_tx_packet;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_rx_packet;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_tx_npacket;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_rx_npacket;
 | 
			
		||||
 | 
			
		||||
	/* Prepare control word and byte count. */
 | 
			
		||||
	cmdBuf.uc[0] = FIFO_WRITE;
 | 
			
		||||
	cmdBuf.uc[1] = frameID++ & 0x3f;
 | 
			
		||||
	cmdBuf.uc[2] = 0;
 | 
			
		||||
	cmdBuf.uc[3] = ulActualLength & 0xff;
 | 
			
		||||
	cmdBuf.uc[4] = ulActualLength >> 8;
 | 
			
		||||
 | 
			
		||||
	spi_clear_ovres();
 | 
			
		||||
 | 
			
		||||
	/* Prepare PDC transfer. */
 | 
			
		||||
	g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
 | 
			
		||||
	g_pdc_spi_tx_packet.ul_size = 5;
 | 
			
		||||
 | 
			
		||||
	g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
 | 
			
		||||
	g_pdc_spi_rx_packet.ul_size = 5;
 | 
			
		||||
 | 
			
		||||
	g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
 | 
			
		||||
	g_pdc_spi_tx_npacket.ul_size = ulFIFOLength;
 | 
			
		||||
 | 
			
		||||
	g_pdc_spi_rx_npacket.ul_addr = (uint32_t) tmpbuf;
 | 
			
		||||
	g_pdc_spi_rx_npacket.ul_size = ulFIFOLength;
 | 
			
		||||
 | 
			
		||||
	pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
	pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
 | 
			
		||||
	#if( TX_USES_RECV == 1 )
 | 
			
		||||
		pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
 | 
			
		||||
		spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_ENDRX | SPI_IER_OVRES);
 | 
			
		||||
		pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
 | 
			
		||||
	#else
 | 
			
		||||
		spi_enable_interrupt(KSZ8851SNL_SPI, SPI_SR_TXBUFE | SPI_IER_OVRES);
 | 
			
		||||
		pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_TXTEN);
 | 
			
		||||
	#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Write dummy data to the internal fifo buffer.
 | 
			
		||||
 *
 | 
			
		||||
 * \param len the amount of dummy data to write.
 | 
			
		||||
 */
 | 
			
		||||
void ksz8851_fifo_dummy(uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	pdc_packet_t g_pdc_spi_tx_packet;
 | 
			
		||||
	pdc_packet_t g_pdc_spi_rx_packet;
 | 
			
		||||
 | 
			
		||||
	/* Prepare PDC transfer. */
 | 
			
		||||
	g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
 | 
			
		||||
	g_pdc_spi_tx_packet.ul_size = len;
 | 
			
		||||
	g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
 | 
			
		||||
	g_pdc_spi_rx_packet.ul_size = len;
 | 
			
		||||
	pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
 | 
			
		||||
	pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
 | 
			
		||||
	pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
 | 
			
		||||
	pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
 | 
			
		||||
 | 
			
		||||
	while (!(spi_read_status(KSZ8851SNL_SPI) & SPI_SR_ENDRX))
 | 
			
		||||
		;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ksz8851snl_set_registers(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Init step2-4: write QMU MAC address (low, middle then high). */
 | 
			
		||||
	ksz8851_reg_write(REG_MAC_ADDR_0, (ETHERNET_CONF_ETHADDR4 << 8) | ETHERNET_CONF_ETHADDR5);
 | 
			
		||||
	ksz8851_reg_write(REG_MAC_ADDR_2, (ETHERNET_CONF_ETHADDR2 << 8) | ETHERNET_CONF_ETHADDR3);
 | 
			
		||||
	ksz8851_reg_write(REG_MAC_ADDR_4, (ETHERNET_CONF_ETHADDR0 << 8) | ETHERNET_CONF_ETHADDR1);
 | 
			
		||||
 | 
			
		||||
	/* Init step5: enable QMU Transmit Frame Data Pointer Auto Increment. */
 | 
			
		||||
	ksz8851_reg_write(REG_TX_ADDR_PTR, ADDR_PTR_AUTO_INC);
 | 
			
		||||
 | 
			
		||||
	/* Init step6: configure QMU transmit control register. */
 | 
			
		||||
	ksz8851_reg_write(REG_TX_CTRL,
 | 
			
		||||
			TX_CTRL_ICMP_CHECKSUM |
 | 
			
		||||
			TX_CTRL_UDP_CHECKSUM |
 | 
			
		||||
			TX_CTRL_TCP_CHECKSUM |
 | 
			
		||||
			TX_CTRL_IP_CHECKSUM |
 | 
			
		||||
			TX_CTRL_FLOW_ENABLE |
 | 
			
		||||
			TX_CTRL_PAD_ENABLE |
 | 
			
		||||
			TX_CTRL_CRC_ENABLE
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
	/* Init step7: enable QMU Receive Frame Data Pointer Auto Increment. */
 | 
			
		||||
	ksz8851_reg_write(REG_RX_ADDR_PTR, ADDR_PTR_AUTO_INC);
 | 
			
		||||
 | 
			
		||||
	/* Init step8: configure QMU Receive Frame Threshold for one frame. */
 | 
			
		||||
	ksz8851_reg_write(REG_RX_FRAME_CNT_THRES, 1);
 | 
			
		||||
 | 
			
		||||
	/* Init step9: configure QMU receive control register1. */
 | 
			
		||||
	ksz8851_reg_write(REG_RX_CTRL1,
 | 
			
		||||
			RX_CTRL_UDP_CHECKSUM |
 | 
			
		||||
			RX_CTRL_TCP_CHECKSUM |
 | 
			
		||||
			RX_CTRL_IP_CHECKSUM |
 | 
			
		||||
			RX_CTRL_MAC_FILTER |
 | 
			
		||||
			RX_CTRL_FLOW_ENABLE |
 | 
			
		||||
			RX_CTRL_BROADCAST |
 | 
			
		||||
			RX_CTRL_ALL_MULTICAST|
 | 
			
		||||
			RX_CTRL_UNICAST);
 | 
			
		||||
//	ksz8851_reg_write(REG_RX_CTRL1,
 | 
			
		||||
//			RX_CTRL_UDP_CHECKSUM |
 | 
			
		||||
//			RX_CTRL_TCP_CHECKSUM |
 | 
			
		||||
//			RX_CTRL_IP_CHECKSUM |
 | 
			
		||||
//			RX_CTRL_FLOW_ENABLE |
 | 
			
		||||
//			RX_CTRL_PROMISCUOUS);
 | 
			
		||||
 | 
			
		||||
	ksz8851_reg_write(REG_RX_CTRL2,
 | 
			
		||||
			RX_CTRL_IPV6_UDP_NOCHECKSUM |
 | 
			
		||||
			RX_CTRL_UDP_LITE_CHECKSUM |
 | 
			
		||||
			RX_CTRL_ICMP_CHECKSUM |
 | 
			
		||||
			RX_CTRL_BURST_LEN_FRAME);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//#define   RXQ_TWOBYTE_OFFSET          (0x0200)    /* Enable adding 2-byte before frame header for IP aligned with DWORD */
 | 
			
		||||
#warning Remember to try the above option to get a 2-byte offset
 | 
			
		||||
 | 
			
		||||
	/* Init step11: configure QMU receive queue: trigger INT and auto-dequeue frame. */
 | 
			
		||||
	ksz8851_reg_write( REG_RXQ_CMD, RXQ_CMD_CNTL | RXQ_TWOBYTE_OFFSET );
 | 
			
		||||
 | 
			
		||||
	/* Init step12: adjust SPI data output delay. */
 | 
			
		||||
	ksz8851_reg_write(REG_BUS_CLOCK_CTRL, BUS_CLOCK_166 | BUS_CLOCK_DIVIDEDBY_1);
 | 
			
		||||
 | 
			
		||||
	/* Init step13: restart auto-negotiation. */
 | 
			
		||||
	ksz8851_reg_setbits(REG_PORT_CTRL, PORT_AUTO_NEG_RESTART);
 | 
			
		||||
 | 
			
		||||
	/* Init step13.1: force link in half duplex if auto-negotiation failed. */
 | 
			
		||||
	if ((ksz8851_reg_read(REG_PORT_CTRL) & PORT_AUTO_NEG_RESTART) != PORT_AUTO_NEG_RESTART)
 | 
			
		||||
	{
 | 
			
		||||
		ksz8851_reg_clrbits(REG_PORT_CTRL, PORT_FORCE_FULL_DUPLEX);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Init step14: clear interrupt status. */
 | 
			
		||||
	ksz8851_reg_write(REG_INT_STATUS, 0xFFFF);
 | 
			
		||||
 | 
			
		||||
	/* Init step15: set interrupt mask. */
 | 
			
		||||
	ksz8851_reg_write(REG_INT_MASK, INT_RX);
 | 
			
		||||
 | 
			
		||||
	/* Init step16: enable QMU Transmit. */
 | 
			
		||||
	ksz8851_reg_setbits(REG_TX_CTRL, TX_CTRL_ENABLE);
 | 
			
		||||
 | 
			
		||||
	/* Init step17: enable QMU Receive. */
 | 
			
		||||
	ksz8851_reg_setbits(REG_RX_CTRL1, RX_CTRL_ENABLE);
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 * \brief KSZ8851SNL initialization function.
 | 
			
		||||
 *
 | 
			
		||||
 * \return 0 on success, 1 on communication error.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ksz8851snl_init(void)
 | 
			
		||||
{
 | 
			
		||||
uint32_t count = 10;
 | 
			
		||||
uint16_t dev_id = 0;
 | 
			
		||||
uint8_t id_ok = 0;
 | 
			
		||||
 | 
			
		||||
	/* Configure the SPI peripheral. */
 | 
			
		||||
	spi_enable_clock(KSZ8851SNL_SPI);
 | 
			
		||||
	spi_disable(KSZ8851SNL_SPI);
 | 
			
		||||
	spi_reset(KSZ8851SNL_SPI);
 | 
			
		||||
	spi_set_master_mode(KSZ8851SNL_SPI);
 | 
			
		||||
	spi_disable_mode_fault_detect(KSZ8851SNL_SPI);
 | 
			
		||||
	spi_set_peripheral_chip_select_value(KSZ8851SNL_SPI, ~(uint32_t)(1UL << KSZ8851SNL_CS_PIN));
 | 
			
		||||
spi_set_fixed_peripheral_select(KSZ8851SNL_SPI);
 | 
			
		||||
//spi_disable_peripheral_select_decode(KSZ8851SNL_SPI);
 | 
			
		||||
 | 
			
		||||
	spi_set_clock_polarity(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, SPI_CLK_POLARITY);
 | 
			
		||||
	spi_set_clock_phase(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, SPI_CLK_PHASE);
 | 
			
		||||
	spi_set_bits_per_transfer(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN,
 | 
			
		||||
			SPI_CSR_BITS_8_BIT);
 | 
			
		||||
	spi_set_baudrate_div(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, (sysclk_get_cpu_hz() / KSZ8851SNL_CLOCK_SPEED));
 | 
			
		||||
//	spi_set_transfer_delay(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, CONFIG_SPI_MASTER_DELAY_BS,
 | 
			
		||||
//			CONFIG_SPI_MASTER_DELAY_BCT);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	spi_set_transfer_delay(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, 0, 0);
 | 
			
		||||
 | 
			
		||||
	spi_enable(KSZ8851SNL_SPI);
 | 
			
		||||
 | 
			
		||||
	/* Get pointer to UART PDC register base. */
 | 
			
		||||
	g_p_spi_pdc = spi_get_pdc_base(KSZ8851SNL_SPI);
 | 
			
		||||
	pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
 | 
			
		||||
 | 
			
		||||
	/* Control RSTN and CSN pin from the driver. */
 | 
			
		||||
	gpio_configure_pin(KSZ8851SNL_CSN_GPIO, KSZ8851SNL_CSN_FLAGS);
 | 
			
		||||
	gpio_set_pin_high(KSZ8851SNL_CSN_GPIO);
 | 
			
		||||
	gpio_configure_pin(KSZ8851SNL_RSTN_GPIO, KSZ8851SNL_RSTN_FLAGS);
 | 
			
		||||
 | 
			
		||||
	/* Reset the Micrel in a proper state. */
 | 
			
		||||
	while( count-- )
 | 
			
		||||
	{
 | 
			
		||||
		/* Perform hardware reset with respect to the reset timing from the datasheet. */
 | 
			
		||||
		gpio_set_pin_low(KSZ8851SNL_RSTN_GPIO);
 | 
			
		||||
		vTaskDelay(2);
 | 
			
		||||
		gpio_set_pin_high(KSZ8851SNL_RSTN_GPIO);
 | 
			
		||||
		vTaskDelay(2);
 | 
			
		||||
 | 
			
		||||
		/* Init step1: read chip ID. */
 | 
			
		||||
		dev_id = ksz8851_reg_read(REG_CHIP_ID);
 | 
			
		||||
		if( ( dev_id & 0xFFF0 ) == CHIP_ID_8851_16 )
 | 
			
		||||
		{
 | 
			
		||||
			id_ok = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if( id_ok != 0 )
 | 
			
		||||
	{
 | 
			
		||||
		ksz8851snl_set_registers();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return id_ok ? 1 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t ksz8851snl_reinit(void)
 | 
			
		||||
{
 | 
			
		||||
uint32_t count = 10;
 | 
			
		||||
uint16_t dev_id = 0;
 | 
			
		||||
uint8_t id_ok = 0;
 | 
			
		||||
	/* Reset the Micrel in a proper state. */
 | 
			
		||||
	while( count-- )
 | 
			
		||||
	{
 | 
			
		||||
		/* Perform hardware reset with respect to the reset timing from the datasheet. */
 | 
			
		||||
		gpio_set_pin_low(KSZ8851SNL_RSTN_GPIO);
 | 
			
		||||
		vTaskDelay(2);
 | 
			
		||||
		gpio_set_pin_high(KSZ8851SNL_RSTN_GPIO);
 | 
			
		||||
		vTaskDelay(2);
 | 
			
		||||
 | 
			
		||||
		/* Init step1: read chip ID. */
 | 
			
		||||
		dev_id = ksz8851_reg_read(REG_CHIP_ID);
 | 
			
		||||
		if( ( dev_id & 0xFFF0 ) == CHIP_ID_8851_16 )
 | 
			
		||||
		{
 | 
			
		||||
			id_ok = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if( id_ok != 0 )
 | 
			
		||||
	{
 | 
			
		||||
		ksz8851snl_set_registers();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return id_ok ? 1 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t ksz8851snl_reset_rx( void )
 | 
			
		||||
{
 | 
			
		||||
uint16_t usValue;
 | 
			
		||||
 | 
			
		||||
	usValue = ksz8851_reg_read(REG_RX_CTRL1);
 | 
			
		||||
 | 
			
		||||
	usValue &= ~( ( uint16_t ) RX_CTRL_ENABLE | RX_CTRL_FLUSH_QUEUE );
 | 
			
		||||
 | 
			
		||||
	ksz8851_reg_write( REG_RX_CTRL1, usValue ); vTaskDelay( 2 );
 | 
			
		||||
	ksz8851_reg_write( REG_RX_CTRL1, usValue | RX_CTRL_FLUSH_QUEUE ); vTaskDelay( 1 );
 | 
			
		||||
	ksz8851_reg_write( REG_RX_CTRL1, usValue ); vTaskDelay( 1 );
 | 
			
		||||
	ksz8851_reg_write( REG_RX_CTRL1, usValue | RX_CTRL_ENABLE ); vTaskDelay( 1 );
 | 
			
		||||
 | 
			
		||||
	return ( uint32_t )usValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t ksz8851snl_reset_tx( void )
 | 
			
		||||
{
 | 
			
		||||
uint16_t usValue;
 | 
			
		||||
 | 
			
		||||
	usValue = ksz8851_reg_read( REG_TX_CTRL );
 | 
			
		||||
 | 
			
		||||
	usValue &= ~( ( uint16_t ) TX_CTRL_ENABLE | TX_CTRL_FLUSH_QUEUE );
 | 
			
		||||
 | 
			
		||||
	ksz8851_reg_write( REG_TX_CTRL, usValue ); vTaskDelay( 2 );
 | 
			
		||||
	ksz8851_reg_write( REG_TX_CTRL, usValue | TX_CTRL_FLUSH_QUEUE ); vTaskDelay( 1 );
 | 
			
		||||
	ksz8851_reg_write( REG_TX_CTRL, usValue ); vTaskDelay( 1 );
 | 
			
		||||
	ksz8851_reg_write( REG_TX_CTRL, usValue | TX_CTRL_ENABLE ); vTaskDelay( 1 );
 | 
			
		||||
 | 
			
		||||
	return ( uint32_t )usValue;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * \file
 | 
			
		||||
 *
 | 
			
		||||
 * \brief KS8851SNL driver for SAM.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * \asf_license_start
 | 
			
		||||
 *
 | 
			
		||||
 * \page License
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
 *    and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * 3. The name of Atmel may not be used to endorse or promote products derived
 | 
			
		||||
 *    from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * 4. This software may only be redistributed and used in connection with an
 | 
			
		||||
 *    Atmel microcontroller product.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 | 
			
		||||
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 | 
			
		||||
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 | 
			
		||||
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
			
		||||
 * POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * \asf_license_stop
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef KSZ8851SNL_H_INCLUDED
 | 
			
		||||
#define KSZ8851SNL_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "gpio.h"
 | 
			
		||||
 | 
			
		||||
void configure_intn(void (*p_handler) (uint32_t, uint32_t));
 | 
			
		||||
void ksz8851_reg_setbits(uint16_t reg, uint16_t bits_to_set);
 | 
			
		||||
void ksz8851_reg_clrbits(uint16_t reg, uint16_t bits_to_clr);
 | 
			
		||||
void ksz8851_fifo_read(uint8_t *buf, uint32_t len);
 | 
			
		||||
void ksz8851_fifo_write(uint8_t *buf, uint32_t ulActualLength, uint32_t ulFIFOLength);
 | 
			
		||||
void ksz8851_fifo_dummy(uint32_t len);
 | 
			
		||||
void ksz8851_reg_write(uint16_t reg, uint16_t wrdata);
 | 
			
		||||
uint16_t ksz8851_reg_read(uint16_t reg);
 | 
			
		||||
uint32_t ksz8851snl_init(void);
 | 
			
		||||
uint32_t ksz8851snl_reinit(void);
 | 
			
		||||
 | 
			
		||||
uint32_t ksz8851snl_reset_rx( void );
 | 
			
		||||
uint32_t ksz8851snl_reset_tx( void );
 | 
			
		||||
 | 
			
		||||
#endif /* KSZ8851SNL_H_INCLUDED */
 | 
			
		||||
@ -0,0 +1,473 @@
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * \file
 | 
			
		||||
 *
 | 
			
		||||
 * \brief KS8851SNL registers definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * \asf_license_start
 | 
			
		||||
 *
 | 
			
		||||
 * \page License
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
 *    this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
 *    and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * 3. The name of Atmel may not be used to endorse or promote products derived
 | 
			
		||||
 *    from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * 4. This software may only be redistributed and used in connection with an
 | 
			
		||||
 *    Atmel microcontroller product.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 | 
			
		||||
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 | 
			
		||||
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 | 
			
		||||
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
			
		||||
 * POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * \asf_license_stop
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef KSZ8851SNL_REG_H_INCLUDED
 | 
			
		||||
#define KSZ8851SNL_REG_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#define REG_ADDR_MASK              (0x3F0)      /* Register address mask */
 | 
			
		||||
#define OPCODE_MASK                (3 << 14)
 | 
			
		||||
#define CMD_READ                   (0 << 14)
 | 
			
		||||
#define CMD_WRITE                  (1 << 14)
 | 
			
		||||
#define FIFO_READ                  (0x80)
 | 
			
		||||
#define FIFO_WRITE                 (0xC0)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MAC Registers
 | 
			
		||||
 * (Offset 0x00 - 0x25)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_BUS_ERROR_STATUS       (0x06)       /* BESR */
 | 
			
		||||
#define   BUS_ERROR_IBEC              (0x8000)
 | 
			
		||||
#define   BUS_ERROR_IBECV_MASK        (0x7800)    /* Default IPSec clock at 166Mhz */
 | 
			
		||||
 | 
			
		||||
#define REG_CHIP_CFG_STATUS        (0x08)       /* CCFG */
 | 
			
		||||
#define   LITTLE_ENDIAN_BUS_MODE      (0x0400)    /* Bus in little endian mode */
 | 
			
		||||
#define   EEPROM_PRESENCE             (0x0200)    /* External EEPROM is used */
 | 
			
		||||
#define   SPI_BUS_MODE                (0x0100)    /* In SPI bus mode */
 | 
			
		||||
#define   DATA_BUS_8BIT               (0x0080)    /* In 8-bit bus mode operation */
 | 
			
		||||
#define   DATA_BUS_16BIT              (0x0040)    /* In 16-bit bus mode operation */
 | 
			
		||||
#define   DATA_BUS_32BIT              (0x0020)    /* In 32-bit bus mode operation */
 | 
			
		||||
#define   MULTIPLEX_MODE              (0x0010)    /* Data and address bus are shared */
 | 
			
		||||
#define   CHIP_PACKAGE_128PIN         (0x0008)    /* 128-pin package */
 | 
			
		||||
#define   CHIP_PACKAGE_80PIN          (0x0004)    /* 80-pin package */
 | 
			
		||||
#define   CHIP_PACKAGE_48PIN          (0x0002)    /* 48-pin package */
 | 
			
		||||
#define   CHIP_PACKAGE_32PIN          (0x0001)    /* 32-pin package for SPI host interface only */
 | 
			
		||||
 | 
			
		||||
#define REG_MAC_ADDR_0             (0x10)       /* MARL */
 | 
			
		||||
#define REG_MAC_ADDR_1             (0x11)       /* MARL */
 | 
			
		||||
#define REG_MAC_ADDR_2             (0x12)       /* MARM */
 | 
			
		||||
#define REG_MAC_ADDR_3             (0x13)       /* MARM */
 | 
			
		||||
#define REG_MAC_ADDR_4             (0x14)       /* MARH */
 | 
			
		||||
#define REG_MAC_ADDR_5             (0x15)       /* MARH */
 | 
			
		||||
 | 
			
		||||
#define REG_BUS_CLOCK_CTRL         (0x20)       /* OBCR */
 | 
			
		||||
#define   BUS_CLOCK_166               (0x0004)    /* 166 MHz on-chip bus clock (defaul is 125MHz) */
 | 
			
		||||
#define   BUS_CLOCK_DIVIDEDBY_5       (0x0003)    /* Bus clock devided by 5 */
 | 
			
		||||
#define   BUS_CLOCK_DIVIDEDBY_3       (0x0002)    /* Bus clock devided by 3 */
 | 
			
		||||
#define   BUS_CLOCK_DIVIDEDBY_2       (0x0001)    /* Bus clock devided by 2 */
 | 
			
		||||
#define   BUS_CLOCK_DIVIDEDBY_1       (0x0000)    /* Bus clock devided by 1 */
 | 
			
		||||
#define   BUS_CLOCK_DIVIDED_MASK      (0x0003)    /* Bus clock devider mask */
 | 
			
		||||
 | 
			
		||||
#define   BUS_SPEED_166_MHZ           (0x0004)    /* Set bus speed to 166 MHz */
 | 
			
		||||
#define   BUS_SPEED_125_MHZ           (0x0000)    /* Set bus speed to 125 MHz */
 | 
			
		||||
#define   BUS_SPEED_83_MHZ            (0x0005)    /* Set bus speed to 83 MHz (166/2)*/
 | 
			
		||||
#define   BUS_SPEED_62_5_MHZ          (0x0001)    /* Set bus speed to 62.5 MHz (125/2) */
 | 
			
		||||
#define   BUS_SPEED_53_3_MHZ          (0x0006)    /* Set bus speed to 53.3 MHz (166/3) */
 | 
			
		||||
#define   BUS_SPEED_41_7_MHZ          (0x0002)    /* Set bus speed to 41.67 MHz (125/3) */
 | 
			
		||||
#define   BUS_SPEED_33_2_MHZ          (0x0007)    /* Set bus speed to 33.2 MHz (166/5) */
 | 
			
		||||
#define   BUS_SPEED_25_MHZ            (0x0003)    /* Set bus speed to 25 MHz (125/5) */
 | 
			
		||||
 | 
			
		||||
#define REG_EEPROM_CTRL            (0x22)       /* EEPCR */
 | 
			
		||||
#define   EEPROM_ACCESS_ENABLE        (0x0010)    /* Enable software to access EEPROM through bit 3 to bit 0 */
 | 
			
		||||
#define   EEPROM_DATA_IN              (0x0008)    /* Data receive from EEPROM (EEDI pin) */
 | 
			
		||||
#define   EEPROM_DATA_OUT             (0x0004)    /* Data transmit to EEPROM (EEDO pin) */
 | 
			
		||||
#define   EEPROM_SERIAL_CLOCK         (0x0002)    /* Serial clock (EESK pin) */
 | 
			
		||||
#define   EEPROM_CHIP_SELECT          (0x0001)    /* EEPROM chip select (EECS pin) */
 | 
			
		||||
 | 
			
		||||
#define REG_MEM_BIST_INFO          (0x24)       /* MBIR */
 | 
			
		||||
#define   TX_MEM_TEST_FINISHED        (0x1000)    /* TX memeory BIST test finish */
 | 
			
		||||
#define   TX_MEM_TEST_FAILED          (0x0800)    /* TX memory BIST test fail */
 | 
			
		||||
#define   TX_MEM_TEST_FAILED_COUNT    (0x0700)    /* TX memory BIST test fail count */
 | 
			
		||||
#define   RX_MEM_TEST_FINISHED        (0x0010)    /* RX memory BIST test finish */
 | 
			
		||||
#define   RX_MEM_TEST_FAILED          (0x0008)    /* RX memory BIST test fail */
 | 
			
		||||
#define   RX_MEM_TEST_FAILED_COUNT    (0x0003)    /* RX memory BIST test fail count */
 | 
			
		||||
 | 
			
		||||
#define REG_RESET_CTRL             (0x26)       /* GRR */
 | 
			
		||||
#define   QMU_SOFTWARE_RESET          (0x0002)    /* QMU soft reset (clear TxQ, RxQ) */
 | 
			
		||||
#define   GLOBAL_SOFTWARE_RESET       (0x0001)    /* Global soft reset (PHY, MAC, QMU) */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Wake On Lan Control Registers
 | 
			
		||||
 * (Offset 0x2A - 0x6B)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_WOL_CTRL               (0x2A)       /* WFCR */
 | 
			
		||||
#define   WOL_MAGIC_ENABLE            (0x0080)    /* Enable the magic packet pattern detection */
 | 
			
		||||
#define   WOL_FRAME3_ENABLE           (0x0008)    /* Enable the wake up frame 3 pattern detection */
 | 
			
		||||
#define   WOL_FRAME2_ENABLE           (0x0004)    /* Enable the wake up frame 2 pattern detection */
 | 
			
		||||
#define   WOL_FRAME1_ENABLE           (0x0002)    /* Enable the wake up frame 1 pattern detection */
 | 
			
		||||
#define   WOL_FRAME0_ENABLE           (0x0001)    /* Enable the wake up frame 0 pattern detection */
 | 
			
		||||
 | 
			
		||||
#define REG_WOL_FRAME0_CRC0        (0x30)       /* WF0CRC0 */
 | 
			
		||||
#define REG_WOL_FRAME0_CRC1        (0x32)       /* WF0CRC1 */
 | 
			
		||||
#define REG_WOL_FRAME0_BYTE_MASK0  (0x34)       /* WF0BM0 */
 | 
			
		||||
#define REG_WOL_FRAME0_BYTE_MASK1  (0x36)       /* WF0BM1 */
 | 
			
		||||
#define REG_WOL_FRAME0_BYTE_MASK2  (0x38)       /* WF0BM2 */
 | 
			
		||||
#define REG_WOL_FRAME0_BYTE_MASK3  (0x3A)       /* WF0BM3 */
 | 
			
		||||
 | 
			
		||||
#define REG_WOL_FRAME1_CRC0        (0x40)       /* WF1CRC0 */
 | 
			
		||||
#define REG_WOL_FRAME1_CRC1        (0x42)       /* WF1CRC1 */
 | 
			
		||||
#define REG_WOL_FRAME1_BYTE_MASK0  (0x44)       /* WF1BM0 */
 | 
			
		||||
#define REG_WOL_FRAME1_BYTE_MASK1  (0x46)       /* WF1BM1 */
 | 
			
		||||
#define REG_WOL_FRAME1_BYTE_MASK2  (0x48)       /* WF1BM2 */
 | 
			
		||||
#define REG_WOL_FRAME1_BYTE_MASK3  (0x4A)       /* WF1BM3 */
 | 
			
		||||
 | 
			
		||||
#define REG_WOL_FRAME2_CRC0        (0x50)       /* WF2CRC0 */
 | 
			
		||||
#define REG_WOL_FRAME2_CRC1        (0x52)       /* WF2CRC1 */
 | 
			
		||||
#define REG_WOL_FRAME2_BYTE_MASK0  (0x54)       /* WF2BM0 */
 | 
			
		||||
#define REG_WOL_FRAME2_BYTE_MASK1  (0x56)       /* WF2BM1 */
 | 
			
		||||
#define REG_WOL_FRAME2_BYTE_MASK2  (0x58)       /* WF2BM2 */
 | 
			
		||||
#define REG_WOL_FRAME2_BYTE_MASK3  (0x5A)       /* WF2BM3 */
 | 
			
		||||
 | 
			
		||||
#define REG_WOL_FRAME3_CRC0        (0x60)       /* WF3CRC0 */
 | 
			
		||||
#define REG_WOL_FRAME3_CRC1        (0x62)       /* WF3CRC1 */
 | 
			
		||||
#define REG_WOL_FRAME3_BYTE_MASK0  (0x64)       /* WF3BM0 */
 | 
			
		||||
#define REG_WOL_FRAME3_BYTE_MASK1  (0x66)       /* WF3BM1 */
 | 
			
		||||
#define REG_WOL_FRAME3_BYTE_MASK2  (0x68)       /* WF3BM2 */
 | 
			
		||||
#define REG_WOL_FRAME3_BYTE_MASK3  (0x6A)       /* WF3BM3 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Transmit/Receive Control Registers
 | 
			
		||||
 * (Offset 0x70 - 0x9F)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Transmit Frame Header */
 | 
			
		||||
#define REG_QDR_DUMMY              (0x00)       /* Dummy address to access QMU RxQ, TxQ */
 | 
			
		||||
#define   TX_CTRL_INTERRUPT_ON        (0x8000)    /* Transmit Interrupt on Completion */
 | 
			
		||||
 | 
			
		||||
#define REG_TX_CTRL                (0x70)       /* TXCR */
 | 
			
		||||
#define   TX_CTRL_ICMP_CHECKSUM       (0x0100)    /* Enable ICMP frame checksum generation */
 | 
			
		||||
#define   TX_CTRL_UDP_CHECKSUM        (0x0080)    /* Enable UDP frame checksum generation */
 | 
			
		||||
#define   TX_CTRL_TCP_CHECKSUM        (0x0040)    /* Enable TCP frame checksum generation */
 | 
			
		||||
#define   TX_CTRL_IP_CHECKSUM         (0x0020)    /* Enable IP frame checksum generation */
 | 
			
		||||
#define   TX_CTRL_FLUSH_QUEUE         (0x0010)    /* Clear transmit queue, reset tx frame pointer */
 | 
			
		||||
#define   TX_CTRL_FLOW_ENABLE         (0x0008)    /* Enable transmit flow control */
 | 
			
		||||
#define   TX_CTRL_PAD_ENABLE          (0x0004)    /* Eanble adding a padding to a packet shorter than 64 bytes */
 | 
			
		||||
#define   TX_CTRL_CRC_ENABLE          (0x0002)    /* Enable adding a CRC to the end of transmit frame */
 | 
			
		||||
#define   TX_CTRL_ENABLE              (0x0001)    /* Enable tranmsit */
 | 
			
		||||
 | 
			
		||||
#define REG_TX_STATUS              (0x72)       /* TXSR */
 | 
			
		||||
#define   TX_STAT_LATE_COL            (0x2000)    /* Tranmsit late collision occurs */
 | 
			
		||||
#define   TX_STAT_MAX_COL             (0x1000)    /* Tranmsit maximum collision is reached */
 | 
			
		||||
#define   TX_FRAME_ID_MASK            (0x003F)    /* Transmit frame ID mask */
 | 
			
		||||
#define   TX_STAT_ERRORS             ( TX_STAT_MAX_COL | TX_STAT_LATE_COL )
 | 
			
		||||
 | 
			
		||||
#define REG_RX_CTRL1               (0x74)       /* RXCR1 */
 | 
			
		||||
#define   RX_CTRL_FLUSH_QUEUE         (0x8000)    /* Clear receive queue, reset rx frame pointer */
 | 
			
		||||
#define   RX_CTRL_UDP_CHECKSUM        (0x4000)    /* Enable UDP frame checksum verification */
 | 
			
		||||
#define   RX_CTRL_TCP_CHECKSUM        (0x2000)    /* Enable TCP frame checksum verification */
 | 
			
		||||
#define   RX_CTRL_IP_CHECKSUM         (0x1000)    /* Enable IP frame checksum verification */
 | 
			
		||||
#define   RX_CTRL_MAC_FILTER          (0x0800)    /* Receive with address that pass MAC address filtering */
 | 
			
		||||
#define   RX_CTRL_FLOW_ENABLE         (0x0400)    /* Enable receive flow control */
 | 
			
		||||
#define   RX_CTRL_BAD_PACKET          (0x0200)    /* Eanble receive CRC error frames */
 | 
			
		||||
#define   RX_CTRL_MULTICAST           (0x0100)    /* Receive multicast frames that pass the CRC hash filtering */
 | 
			
		||||
#define   RX_CTRL_BROADCAST           (0x0080)    /* Receive all the broadcast frames */
 | 
			
		||||
#define   RX_CTRL_ALL_MULTICAST       (0x0040)    /* Receive all the multicast frames (including broadcast frames) */
 | 
			
		||||
#define   RX_CTRL_UNICAST             (0x0020)    /* Receive unicast frames that match the device MAC address */
 | 
			
		||||
#define   RX_CTRL_PROMISCUOUS         (0x0010)    /* Receive all incoming frames, regardless of frame's DA */
 | 
			
		||||
#define   RX_CTRL_STRIP_CRC           (0x0008)    /* Enable strip CRC on the received frames */
 | 
			
		||||
#define   RX_CTRL_INVERSE_FILTER      (0x0002)    /* Receive with address check in inverse filtering mode */
 | 
			
		||||
#define   RX_CTRL_ENABLE              (0x0001)    /* Enable receive */
 | 
			
		||||
 | 
			
		||||
/* Address filtering scheme mask */
 | 
			
		||||
#define RX_CTRL_FILTER_MASK    ( RX_CTRL_INVERSE_FILTER | RX_CTRL_PROMISCUOUS | RX_CTRL_MULTICAST | RX_CTRL_MAC_FILTER )
 | 
			
		||||
 | 
			
		||||
#define REG_RX_CTRL2               (0x76)       /* RXCR2 */
 | 
			
		||||
#define   RX_CTRL_IPV6_UDP_NOCHECKSUM (0x0010)    /* No checksum generation and verification if IPv6 UDP is fragment */
 | 
			
		||||
#define   RX_CTRL_IPV6_UDP_CHECKSUM   (0x0008)    /* Receive pass IPv6 UDP frame with UDP checksum is zero */
 | 
			
		||||
#define   RX_CTRL_UDP_LITE_CHECKSUM   (0x0004)    /* Enable UDP Lite frame checksum generation and verification */
 | 
			
		||||
#define   RX_CTRL_ICMP_CHECKSUM       (0x0002)    /* Enable ICMP frame checksum verification */
 | 
			
		||||
#define   RX_CTRL_BLOCK_MAC           (0x0001)    /* Receive drop frame if the SA is same as device MAC address */
 | 
			
		||||
#define   RX_CTRL_BURST_LEN_MASK      (0x00e0)    /* SRDBL SPI Receive Data Burst Length */
 | 
			
		||||
#define   RX_CTRL_BURST_LEN_4         (0x0000)
 | 
			
		||||
#define   RX_CTRL_BURST_LEN_8         (0x0020)
 | 
			
		||||
#define   RX_CTRL_BURST_LEN_16        (0x0040)
 | 
			
		||||
#define   RX_CTRL_BURST_LEN_32        (0x0060)
 | 
			
		||||
#define   RX_CTRL_BURST_LEN_FRAME     (0x0080)
 | 
			
		||||
 | 
			
		||||
#define REG_TX_MEM_INFO            (0x78)       /* TXMIR */
 | 
			
		||||
#define   TX_MEM_AVAILABLE_MASK       (0x1FFF)    /* The amount of memory available in TXQ */
 | 
			
		||||
 | 
			
		||||
#define REG_RX_FHR_STATUS          (0x7C)       /* RXFHSR */
 | 
			
		||||
#define   RX_VALID                    (0x8000)    /* Frame in the receive packet memory is valid */
 | 
			
		||||
#define   RX_ICMP_ERROR               (0x2000)    /* ICMP checksum field doesn't match */
 | 
			
		||||
#define   RX_IP_ERROR                 (0x1000)    /* IP checksum field doesn't match */
 | 
			
		||||
#define   RX_TCP_ERROR                (0x0800)    /* TCP checksum field doesn't match */
 | 
			
		||||
#define   RX_UDP_ERROR                (0x0400)    /* UDP checksum field doesn't match */
 | 
			
		||||
#define   RX_BROADCAST                (0x0080)    /* Received frame is a broadcast frame */
 | 
			
		||||
#define   RX_MULTICAST                (0x0040)    /* Received frame is a multicast frame */
 | 
			
		||||
#define   RX_UNICAST                  (0x0020)    /* Received frame is a unicast frame */
 | 
			
		||||
#define   RX_PHY_ERROR                (0x0010)    /* Received frame has runt error */
 | 
			
		||||
#define   RX_FRAME_ETHER              (0x0008)    /* Received frame is an Ethernet-type frame */
 | 
			
		||||
#define   RX_TOO_LONG                 (0x0004)    /* Received frame length exceeds max size 0f 2048 bytes */
 | 
			
		||||
#define   RX_RUNT_ERROR               (0x0002)    /* Received frame was demaged by a collision */
 | 
			
		||||
#define   RX_BAD_CRC                  (0x0001)    /* Received frame has a CRC error */
 | 
			
		||||
#define   RX_ERRORS                   ( RX_BAD_CRC | RX_TOO_LONG | RX_RUNT_ERROR | RX_PHY_ERROR | \
 | 
			
		||||
                                        RX_ICMP_ERROR | RX_IP_ERROR | RX_TCP_ERROR | RX_UDP_ERROR )
 | 
			
		||||
 | 
			
		||||
#define REG_RX_FHR_BYTE_CNT        (0x7E)       /* RXFHBCR */
 | 
			
		||||
#define   RX_BYTE_CNT_MASK            (0x0FFF)    /* Received frame byte size mask */
 | 
			
		||||
 | 
			
		||||
#define REG_TXQ_CMD                (0x80)       /* TXQCR */
 | 
			
		||||
#define   TXQ_AUTO_ENQUEUE            (0x0004)    /* Enable enqueue tx frames from tx buffer automatically */
 | 
			
		||||
#define   TXQ_MEM_AVAILABLE_INT       (0x0002)    /* Enable generate interrupt when tx memory is available */
 | 
			
		||||
#define   TXQ_ENQUEUE                 (0x0001)    /* Enable enqueue tx frames one frame at a time */
 | 
			
		||||
 | 
			
		||||
#define REG_RXQ_CMD                (0x82)       /* RXQCR */
 | 
			
		||||
#define   RXQ_STAT_TIME_INT           (0x1000)    /* RX interrupt is occured by timer duration */
 | 
			
		||||
#define   RXQ_STAT_BYTE_CNT_INT       (0x0800)    /* RX interrupt is occured by byte count threshold */
 | 
			
		||||
#define   RXQ_STAT_FRAME_CNT_INT      (0x0400)    /* RX interrupt is occured by frame count threshold */
 | 
			
		||||
#define   RXQ_TWOBYTE_OFFSET          (0x0200)    /* Enable adding 2-byte before frame header for IP aligned with DWORD */
 | 
			
		||||
#define   RXQ_TIME_INT                (0x0080)    /* Enable RX interrupt by timer duration */
 | 
			
		||||
#define   RXQ_BYTE_CNT_INT            (0x0040)    /* Enable RX interrupt by byte count threshold */
 | 
			
		||||
#define   RXQ_FRAME_CNT_INT           (0x0020)    /* Enable RX interrupt by frame count threshold */
 | 
			
		||||
#define   RXQ_AUTO_DEQUEUE            (0x0010)    /* Enable release rx frames from rx buffer automatically */
 | 
			
		||||
#define   RXQ_START                   (0x0008)    /* Start QMU transfer operation */
 | 
			
		||||
#define   RXQ_CMD_FREE_PACKET         (0x0001)    /* Manual dequeue (release the current frame from RxQ) */
 | 
			
		||||
 | 
			
		||||
#define   RXQ_CMD_CNTL                (RXQ_FRAME_CNT_INT|RXQ_AUTO_DEQUEUE)
 | 
			
		||||
 | 
			
		||||
#define REG_TX_ADDR_PTR            (0x84)       /* TXFDPR */
 | 
			
		||||
#define REG_RX_ADDR_PTR            (0x86)       /* RXFDPR */
 | 
			
		||||
#define   ADDR_PTR_AUTO_INC           (0x4000)    /* Enable Frame data pointer increments automatically */
 | 
			
		||||
#define   ADDR_PTR_MASK               (0x03ff)    /* Address pointer mask */
 | 
			
		||||
 | 
			
		||||
#define REG_RX_TIME_THRES          (0x8C)       /* RXDTTR */
 | 
			
		||||
#define   RX_TIME_THRESHOLD_MASK      (0xFFFF)    /* Set receive timer duration threshold */
 | 
			
		||||
 | 
			
		||||
#define REG_RX_BYTE_CNT_THRES      (0x8E)       /* RXDBCTR */
 | 
			
		||||
#define   RX_BYTE_THRESHOLD_MASK      (0xFFFF)    /* Set receive byte count threshold */
 | 
			
		||||
 | 
			
		||||
#define REG_INT_MASK               (0x90)       /* IER */
 | 
			
		||||
#define   INT_PHY                     (0x8000)    /* Enable link change interrupt */
 | 
			
		||||
#define   INT_TX                      (0x4000)    /* Enable transmit done interrupt */
 | 
			
		||||
#define   INT_RX                      (0x2000)    /* Enable receive interrupt */
 | 
			
		||||
#define   INT_RX_OVERRUN              (0x0800)    /* Enable receive overrun interrupt */
 | 
			
		||||
#define   INT_TX_STOPPED              (0x0200)    /* Enable transmit process stopped interrupt */
 | 
			
		||||
#define   INT_RX_STOPPED              (0x0100)    /* Enable receive process stopped interrupt */
 | 
			
		||||
#define   INT_TX_SPACE                (0x0040)    /* Enable transmit space available interrupt */
 | 
			
		||||
#define   INT_RX_WOL_FRAME            (0x0020)    /* Enable WOL on receive wake-up frame detect interrupt */
 | 
			
		||||
#define   INT_RX_WOL_MAGIC            (0x0010)    /* Enable WOL on receive magic packet detect interrupt */
 | 
			
		||||
#define   INT_RX_WOL_LINKUP           (0x0008)    /* Enable WOL on link up detect interrupt */
 | 
			
		||||
#define   INT_RX_WOL_ENERGY           (0x0004)    /* Enable WOL on energy detect interrupt */
 | 
			
		||||
#define   INT_RX_SPI_ERROR            (0x0002)    /* Enable receive SPI bus error interrupt */
 | 
			
		||||
#define   INT_RX_WOL_DELAY_ENERGY     (0x0001)    /* Enable WOL on delay energy detect interrupt */
 | 
			
		||||
#define   INT_MASK                    ( INT_RX | INT_TX | INT_PHY )
 | 
			
		||||
 | 
			
		||||
#define REG_INT_STATUS             (0x92)       /* ISR */
 | 
			
		||||
 | 
			
		||||
#define REG_RX_FRAME_CNT_THRES     (0x9C)       /* RXFCTFC */
 | 
			
		||||
#define   RX_FRAME_CNT_MASK           (0xFF00)    /* Received frame count mask */
 | 
			
		||||
#define   RX_FRAME_THRESHOLD_MASK     (0x00FF)    /* Set receive frame count threshold mask */
 | 
			
		||||
 | 
			
		||||
#define REG_TX_TOTAL_FRAME_SIZE    (0x9E)       /* TXNTFSR */
 | 
			
		||||
#define   TX_TOTAL_FRAME_SIZE_MASK    (0xFFFF)    /* Set next total tx frame size mask */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MAC Address Hash Table Control Registers
 | 
			
		||||
 * (Offset 0xA0 - 0xA7)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_MAC_HASH_0             (0xA0)       /* MAHTR0 */
 | 
			
		||||
#define REG_MAC_HASH_1             (0xA1)
 | 
			
		||||
 | 
			
		||||
#define REG_MAC_HASH_2             (0xA2)       /* MAHTR1 */
 | 
			
		||||
#define REG_MAC_HASH_3             (0xA3)
 | 
			
		||||
 | 
			
		||||
#define REG_MAC_HASH_4             (0xA4)       /* MAHTR2 */
 | 
			
		||||
#define REG_MAC_HASH_5             (0xA5)
 | 
			
		||||
 | 
			
		||||
#define REG_MAC_HASH_6             (0xA6)       /* MAHTR3 */
 | 
			
		||||
#define REG_MAC_HASH_7             (0xA7)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * QMU Receive Queue Watermark Control Registers
 | 
			
		||||
 * (Offset 0xB0 - 0xB5)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_RX_LOW_WATERMARK       (0xB0)       /* FCLWR */
 | 
			
		||||
#define   RX_LOW_WATERMARK_MASK       (0x0FFF)    /* Set QMU RxQ low watermark mask */
 | 
			
		||||
 | 
			
		||||
#define REG_RX_HIGH_WATERMARK      (0xB2)       /* FCHWR */
 | 
			
		||||
#define   RX_HIGH_WATERMARK_MASK      (0x0FFF)    /* Set QMU RxQ high watermark mask */
 | 
			
		||||
 | 
			
		||||
#define REG_RX_OVERRUN_WATERMARK   (0xB4)       /* FCOWR */
 | 
			
		||||
#define   RX_OVERRUN_WATERMARK_MASK   (0x0FFF)    /* Set QMU RxQ overrun watermark mask */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Global Control Registers
 | 
			
		||||
 * (Offset 0xC0 - 0xD3)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_CHIP_ID                (0xC0)       /* CIDER */
 | 
			
		||||
#define   CHIP_ID_MASK                (0xFFF0)     /* Family ID and chip ID mask */
 | 
			
		||||
#define   REVISION_MASK               (0x000E)     /* Chip revision mask */
 | 
			
		||||
#define   CHIP_ID_SHIFT               (4)
 | 
			
		||||
#define   REVISION_SHIFT              (1)
 | 
			
		||||
#define   CHIP_ID_8851_16             (0x8870)     /* KS8851-16/32MQL chip ID */
 | 
			
		||||
 | 
			
		||||
#define REG_LED_CTRL               (0xC6)       /* CGCR */
 | 
			
		||||
#define   LED_CTRL_SEL1               (0x8000)     /* Select LED3/LED2/LED1/LED0 indication */
 | 
			
		||||
#define   LED_CTRL_SEL0               (0x0200)     /* Select LED3/LED2/LED1/LED0 indication */
 | 
			
		||||
 | 
			
		||||
#define REG_IND_IACR               (0xC8)       /* IACR */
 | 
			
		||||
#define   TABLE_READ                  (0x1000)     /* Indirect read */
 | 
			
		||||
#define   TABLE_MIB                   (0x0C00)     /* Select MIB counter table */
 | 
			
		||||
#define   TABLE_ENTRY_MASK            (0x001F)     /* Set table entry to access */
 | 
			
		||||
 | 
			
		||||
#define REG_IND_DATA_LOW           (0xD0)       /* IADLR */
 | 
			
		||||
#define REG_IND_DATA_HIGH          (0xD2)       /* IADHR */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Power Management Control Registers
 | 
			
		||||
 * (Offset 0xD4 - 0xD7)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_POWER_CNTL             (0xD4)       /* PMECR */
 | 
			
		||||
#define   PME_DELAY_ENABLE            (0x4000)    /* Enable the PME output pin assertion delay */
 | 
			
		||||
#define   PME_ACTIVE_HIGHT            (0x1000)    /* PME output pin is active high */
 | 
			
		||||
#define   PME_FROM_WKFRAME            (0x0800)    /* PME asserted when wake-up frame is detected */
 | 
			
		||||
#define   PME_FROM_MAGIC              (0x0400)    /* PME asserted when magic packet is detected */
 | 
			
		||||
#define   PME_FROM_LINKUP             (0x0200)    /* PME asserted when link up is detected */
 | 
			
		||||
#define   PME_FROM_ENERGY             (0x0100)    /* PME asserted when energy is detected */
 | 
			
		||||
#define   PME_EVENT_MASK              (0x0F00)    /* PME asserted event mask */
 | 
			
		||||
#define   WAKEUP_AUTO_ENABLE          (0x0080)    /* Enable auto wake-up in energy mode */
 | 
			
		||||
#define   WAKEUP_NORMAL_AUTO_ENABLE   (0x0040)    /* Enable auto goto normal mode from energy detecion mode */
 | 
			
		||||
#define   WAKEUP_FROM_WKFRAME         (0x0020)    /* Wake-up from wake-up frame event detected */
 | 
			
		||||
#define   WAKEUP_FROM_MAGIC           (0x0010)    /* Wake-up from magic packet event detected */
 | 
			
		||||
#define   WAKEUP_FROM_LINKUP          (0x0008)    /* Wake-up from link up event detected */
 | 
			
		||||
#define   WAKEUP_FROM_ENERGY          (0x0004)    /* Wake-up from energy event detected */
 | 
			
		||||
#define   WAKEUP_EVENT_MASK           (0x003C)    /* Wake-up event mask */
 | 
			
		||||
#define   POWER_STATE_D1              (0x0003)    /* Power saving mode */
 | 
			
		||||
#define   POWER_STATE_D3              (0x0002)    /* Power down mode */
 | 
			
		||||
#define   POWER_STATE_D2              (0x0001)    /* Power detection mode */
 | 
			
		||||
#define   POWER_STATE_D0              (0x0000)    /* Normal operation mode (default) */
 | 
			
		||||
#define   POWER_STATE_MASK            (0x0003)    /* Power management mode mask */
 | 
			
		||||
 | 
			
		||||
#define REG_WAKEUP_TIME            (0xD6)       /* GSWUTR */
 | 
			
		||||
#define   WAKEUP_TIME                 (0xFF00)    /* Min time (sec) wake-uo after detected energy */
 | 
			
		||||
#define   GOSLEEP_TIME                (0x00FF)    /* Min time (sec) before goto sleep when in energy mode */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * PHY Control Registers
 | 
			
		||||
 * (Offset 0xD8 - 0xF9)
 | 
			
		||||
 */
 | 
			
		||||
#define REG_PHY_RESET              (0xD8)       /* PHYRR */
 | 
			
		||||
#define   PHY_RESET                   (0x0001)    /* Reset PHY */
 | 
			
		||||
 | 
			
		||||
#define REG_PHY_CNTL               (0xE4)       /* P1MBCR */
 | 
			
		||||
#define   PHY_SPEED_100MBIT           (0x2000)     /* Force PHY 100Mbps */
 | 
			
		||||
#define   PHY_AUTO_NEG_ENABLE         (0x1000)     /* Enable PHY auto-negotiation */
 | 
			
		||||
#define   PHY_POWER_DOWN              (0x0800)     /* Set PHY power-down */
 | 
			
		||||
#define   PHY_AUTO_NEG_RESTART        (0x0200)     /* Restart PHY auto-negotiation */
 | 
			
		||||
#define   PHY_FULL_DUPLEX             (0x0100)     /* Force PHY in full duplex mode */
 | 
			
		||||
#define   PHY_HP_MDIX                 (0x0020)     /* Set PHY in HP auto MDI-X mode */
 | 
			
		||||
#define   PHY_FORCE_MDIX              (0x0010)     /* Force MDI-X */
 | 
			
		||||
#define   PHY_AUTO_MDIX_DISABLE       (0x0008)     /* Disable auto MDI-X */
 | 
			
		||||
#define   PHY_TRANSMIT_DISABLE        (0x0002)     /* Disable PHY transmit */
 | 
			
		||||
#define   PHY_LED_DISABLE             (0x0001)     /* Disable PHY LED */
 | 
			
		||||
 | 
			
		||||
#define REG_PHY_STATUS             (0xE6)       /* P1MBSR */
 | 
			
		||||
#define   PHY_100BT4_CAPABLE          (0x8000)     /* 100 BASE-T4 capable */
 | 
			
		||||
#define   PHY_100BTX_FD_CAPABLE       (0x4000)     /* 100BASE-TX full duplex capable */
 | 
			
		||||
#define   PHY_100BTX_CAPABLE          (0x2000)     /* 100BASE-TX half duplex capable */
 | 
			
		||||
#define   PHY_10BT_FD_CAPABLE         (0x1000)     /* 10BASE-TX full duplex capable */
 | 
			
		||||
#define   PHY_10BT_CAPABLE            (0x0800)     /* 10BASE-TX half duplex capable */
 | 
			
		||||
#define   PHY_AUTO_NEG_ACKNOWLEDGE    (0x0020)     /* Auto-negotiation complete */
 | 
			
		||||
#define   PHY_AUTO_NEG_CAPABLE        (0x0008)     /* Auto-negotiation capable */
 | 
			
		||||
#define   PHY_LINK_UP                 (0x0004)     /* PHY link is up */
 | 
			
		||||
#define   PHY_EXTENDED_CAPABILITY     (0x0001)     /* PHY extended register capable */
 | 
			
		||||
 | 
			
		||||
#define REG_PHY_ID_LOW             (0xE8)       /* PHY1ILR */
 | 
			
		||||
#define REG_PHY_ID_HIGH            (0xEA)       /* PHY1IHR */
 | 
			
		||||
 | 
			
		||||
#define REG_PHY_AUTO_NEGOTIATION   (0xEC)       /* P1ANAR */
 | 
			
		||||
#define   PHY_AUTO_NEG_SYM_PAUSE      (0x0400)     /* Advertise pause capability */
 | 
			
		||||
#define   PHY_AUTO_NEG_100BTX_FD      (0x0100)     /* Advertise 100 full-duplex capability */
 | 
			
		||||
#define   PHY_AUTO_NEG_100BTX         (0x0080)     /* Advertise 100 half-duplex capability */
 | 
			
		||||
#define   PHY_AUTO_NEG_10BT_FD        (0x0040)     /* Advertise 10 full-duplex capability */
 | 
			
		||||
#define   PHY_AUTO_NEG_10BT           (0x0020)     /* Advertise 10 half-duplex capability */
 | 
			
		||||
#define   PHY_AUTO_NEG_SELECTOR       (0x001F)     /* Selector field mask */
 | 
			
		||||
#define   PHY_AUTO_NEG_802_3          (0x0001)     /* 802.3 */
 | 
			
		||||
 | 
			
		||||
#define REG_PHY_REMOTE_CAPABILITY  (0xEE)       /* P1ANLPR */
 | 
			
		||||
#define   PHY_REMOTE_SYM_PAUSE        (0x0400)     /* Link partner pause capability */
 | 
			
		||||
#define   PHY_REMOTE_100BTX_FD        (0x0100)     /* Link partner 100 full-duplex capability */
 | 
			
		||||
#define   PHY_REMOTE_100BTX           (0x0080)     /* Link partner 100 half-duplex capability */
 | 
			
		||||
#define   PHY_REMOTE_10BT_FD          (0x0040)     /* Link partner 10 full-duplex capability */
 | 
			
		||||
#define   PHY_REMOTE_10BT             (0x0020)     /* Link partner 10 half-duplex capability */
 | 
			
		||||
 | 
			
		||||
#define REG_PORT_LINK_MD           (0xF4)       /* P1SCLMD */
 | 
			
		||||
#define   PORT_CABLE_10M_SHORT        (0x8000)     /* Cable length is less than 10m short */
 | 
			
		||||
#define   PORT_CABLE_STAT_FAILED      (0x6000)     /* Cable diagnostic test fail */
 | 
			
		||||
#define   PORT_CABLE_STAT_SHORT       (0x4000)     /* Short condition detected in the cable */
 | 
			
		||||
#define   PORT_CABLE_STAT_OPEN        (0x2000)     /* Open condition detected in the cable */
 | 
			
		||||
#define   PORT_CABLE_STAT_NORMAL      (0x0000)     /* Normal condition */
 | 
			
		||||
#define   PORT_CABLE_DIAG_RESULT      (0x6000)     /* Cable diagnostic test result mask */
 | 
			
		||||
#define   PORT_START_CABLE_DIAG       (0x1000)     /* Enable cable diagnostic test */
 | 
			
		||||
#define   PORT_FORCE_LINK             (0x0800)     /* Enable force link pass */
 | 
			
		||||
#define   PORT_POWER_SAVING           (0x0400)     /* Disable power saving */
 | 
			
		||||
#define   PORT_REMOTE_LOOPBACK        (0x0200)     /* Enable remote loopback at PHY */
 | 
			
		||||
#define   PORT_CABLE_FAULT_COUNTER    (0x01FF)     /* Cable length distance to the fault */
 | 
			
		||||
 | 
			
		||||
#define REG_PORT_CTRL              (0xF6)       /* P1CR */
 | 
			
		||||
#define   PORT_LED_OFF                (0x8000)     /* Turn off all the port LEDs (LED3/LED2/LED1/LED0) */
 | 
			
		||||
#define   PORT_TX_DISABLE             (0x4000)     /* Disable port transmit */
 | 
			
		||||
#define   PORT_AUTO_NEG_RESTART       (0x2000)     /* Restart auto-negotiation */
 | 
			
		||||
#define   PORT_POWER_DOWN             (0x0800)     /* Set port power-down */
 | 
			
		||||
#define   PORT_AUTO_MDIX_DISABLE      (0x0400)     /* Disable auto MDI-X */
 | 
			
		||||
#define   PORT_FORCE_MDIX             (0x0200)     /* Force MDI-X */
 | 
			
		||||
#define   PORT_AUTO_NEG_ENABLE        (0x0080)     /* Enable auto-negotiation */
 | 
			
		||||
#define   PORT_FORCE_100_MBIT         (0x0040)     /* Force PHY 100Mbps */
 | 
			
		||||
#define   PORT_FORCE_FULL_DUPLEX      (0x0020)     /* Force PHY in full duplex mode */
 | 
			
		||||
#define   PORT_AUTO_NEG_SYM_PAUSE     (0x0010)     /* Advertise pause capability */
 | 
			
		||||
#define   PORT_AUTO_NEG_100BTX_FD     (0x0008)     /* Advertise 100 full-duplex capability */
 | 
			
		||||
#define   PORT_AUTO_NEG_100BTX        (0x0004)     /* Advertise 100 half-duplex capability */
 | 
			
		||||
#define   PORT_AUTO_NEG_10BT_FD       (0x0002)     /* Advertise 10 full-duplex capability */
 | 
			
		||||
#define   PORT_AUTO_NEG_10BT          (0x0001)     /* Advertise 10 half-duplex capability */
 | 
			
		||||
 | 
			
		||||
#define REG_PORT_STATUS            (0xF8)       /* P1SR */
 | 
			
		||||
#define   PORT_HP_MDIX                (0x8000)     /* Set PHY in HP auto MDI-X mode */
 | 
			
		||||
#define   PORT_REVERSED_POLARITY      (0x2000)     /* Polarity is reversed */
 | 
			
		||||
#define   PORT_RX_FLOW_CTRL           (0x1000)     /* Reeive flow control feature is active */
 | 
			
		||||
#define   PORT_TX_FLOW_CTRL           (0x0800)     /* Transmit flow control feature is active */
 | 
			
		||||
#define   PORT_STAT_SPEED_100MBIT     (0x0400)     /* Link is 100Mbps */
 | 
			
		||||
#define   PORT_STAT_FULL_DUPLEX       (0x0200)     /* Link is full duplex mode */
 | 
			
		||||
#define   PORT_MDIX_STATUS            (0x0080)     /* Is MDI */
 | 
			
		||||
#define   PORT_AUTO_NEG_COMPLETE      (0x0040)     /* Auto-negotiation complete */
 | 
			
		||||
#define   PORT_STATUS_LINK_GOOD       (0x0020)     /* PHY link is up */
 | 
			
		||||
#define   PORT_REMOTE_SYM_PAUSE       (0x0010)     /* Link partner pause capability */
 | 
			
		||||
#define   PORT_REMOTE_100BTX_FD       (0x0008)     /* Link partner 100 full-duplex capability */
 | 
			
		||||
#define   PORT_REMOTE_100BTX          (0x0004)     /* Link partner 100 half-duplex capability */
 | 
			
		||||
#define   PORT_REMOTE_10BT_FD         (0x0002)     /* Link partner 10 full-duplex capability */
 | 
			
		||||
#define   PORT_REMOTE_10BT            (0x0001)     /* Link partner 10 half-duplex capability */
 | 
			
		||||
 | 
			
		||||
#endif /* KSZ8851SNL_REG_H_INCLUDED */
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user