⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xscale_linux.c

📁 SMSC NET controller 9218 driver software
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************

 *

 * Copyright (C) 2004-2005  SMSC

 *

 * This program is free software; you can redistribute it and/or

 * modify it under the terms of the GNU General Public License

 * as published by the Free Software Foundation; either version 2

 * of the License, or (at your option) any later version.

 *

 * This program is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 * GNU General Public License for more details.

 *

 * You should have received a copy of the GNU General Public License

 * along with this program; if not, write to the Free Software

 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 *

 ***************************************************************************

 * File: xscale.c

 ***************************************************************************

 * 04/11/2005 Bryan Whitehead, rev 2

 *    updated platform code to support version 1.14 platform changes

 * 04/15/2005 Bryan Whitehead, rev 3

 *    migrated to perforce

 *    merged .c and .h file

 * 10/24/2006 Nancy Lin, rev 4

 *    added flowControlParameters for Lan9211

 *    added LAN9211 to Full Speed Configuration

 * 01/31/2007 Nancy Lin, rev 5

 *    Removed Support for Lan9112

 * 04/05/2007 Nancy Lin, rev 6

 *    merged xscale_linux_2.4.c and xscale_linux_2.6.c to one file xscale_linux.c

 * 10/23/2007 Nancy Lin, rev 7

 *    Added Support for Lan9218A/9217A/9216A/9215A

 *    added flowControlParameters for Lan9218A/9217A/9216A/9215A

 * 01/07/2008 A. Hosseinipour, rev 8

 *    Added Support for Lan9210

 *    added flowControlParameters for Lan9210

 ***************************************************************************

 * NOTE: When making changes to platform specific code please remember to 

 *   update the revision number in the PLATFORM_NAME macro. This is a 

 *   platform specific version number and independent of the 

 *   common code version number. The PLATFORM_NAME macro should be found in

 *   your platforms ".h" file.

 */



#ifndef USING_LINT

#include <asm/hardware.h>

#include <asm/arch/mainstone.h>


#include <asm/arch/pxa-regs.h>

#endif //not USING_LINT


extern DWORD bus_timing;

typedef struct _PLATFORM_DATA {

	DWORD		dwIdRev;

	DWORD 		dwIrq;

	void 		*dev_id;

} PLATFORM_DATA, *PPLATFORM_DATA;



/* for register access */ 

typedef volatile unsigned char  Reg8;

typedef volatile unsigned short Reg16;

typedef volatile DWORD  Reg32;

typedef volatile unsigned char  * pReg8;

typedef volatile unsigned short * pReg16;

typedef volatile unsigned long *  pReg32;




#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))

#ifndef MST_EXP_BASE

#define MST_EXP_BASE (0xF5000000)

#endif

#ifndef MST_EXP_PHYS

#define MST_EXP_PHYS (PXA_CS5_PHYS)

#endif


//#ifndef MAINSTONE_nExBRD_IRQ


//#define MAINSTONE_nExBRD_IRQ MAINSTONE_IRQ(7)


//#endif


#endif



// Base address (Virtual Address)

#define LAN_CSBASE 			MST_EXP_BASE



#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))

#define LAN_IRQ				MAINSTONE_nExBRD_IRQ

#else

//#define LAN_IRQ				MAINSTONE_EXBRD_IRQ

#define LAN_IRQ				(167)

#endif



#define LAN_DMACH			(0UL)



// cache organization parameters

#define CACHE_SIZE_KB		32UL

#define CACHE_WAYS			32UL

#define CACHE_LINE_BYTES	32UL

#define CACHE_ALIGN_MASK		(~(CACHE_LINE_BYTES - 1UL))

#define CACHE_BYTES_PER_WAY		((CACHE_SIZE_KB * 1024UL) / CACHE_WAYS)



#define PLATFORM_CACHE_LINE_BYTES (CACHE_LINE_BYTES)



#define PLATFORM_IRQ_POL	(0UL)

#define PLATFORM_IRQ_TYPE	(0UL)

#define PLATFORM_DMA_THRESHOLD (200)



#define PLATFORM_RX_DMA		(1)

#define PLATFORM_TX_DMA		(2)





#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))


#define PLATFORM_NAME		"XScale with Linux 2.6 r8"

#define	PLATFORM_IRQ		(167)


#else


#define PLATFORM_NAME		"XScale with Linux 2.4 r8"

#define	PLATFORM_IRQ		(198)


#endif




#ifdef USING_LINT

void CleanCacheLine(DWORD addr);

void DrainWriteBuffers(void);

#else //not USING_LINT

static inline void CleanCacheLine(DWORD addr)

{

	addr = addr;		// let lint be happy :-)

	__asm("mov r0, %0" : : "r" (addr): "r0");

	__asm("mcr p15, 0, r0, c7, c10, 1");

	__asm("mcr p15, 0, r0, c7, c6, 1");

}



static inline void DrainWriteBuffers(void)

{

	__asm("mcr p15, 0, r0, c7, c10, 4");

}




inline void Platform_SetRegDW(


		DWORD dwLanBase,


		DWORD dwOffset,


		DWORD dwVal)


{


	(*(volatile DWORD *)(dwLanBase+dwOffset))=dwVal;


}





inline DWORD Platform_GetRegDW(


	DWORD dwLanBase,


	DWORD dwOffset)


{


	return (*(volatile DWORD *)(dwLanBase+dwOffset));


}




//See readme.txt for a description of how these 

//functions must be implemented

DWORD Platform_Initialize(

	PPLATFORM_DATA platformData,

	DWORD dwLanBase,

	DWORD dwBusWidth);

void Platform_CleanUp(

	PPLATFORM_DATA platformData);

BOOLEAN Platform_Is16BitMode(


	PPLATFORM_DATA platformData);


BOOLEAN Platform_RequestIRQ(


	PPLATFORM_DATA platformData,


	DWORD dwIrq,


	irqreturn_t (*pIsr)(int irq,void *dev_id,struct pt_regs *regs),


	void *dev_id);


DWORD Platform_CurrentIRQ(


	PPLATFORM_DATA platformData);


void Platform_FreeIRQ(


	PPLATFORM_DATA platformData);


BOOLEAN Platform_IsValidDmaChannel(DWORD dwDmaCh);


BOOLEAN Platform_DmaInitialize(


	PPLATFORM_DATA platformData,


	DWORD dwDmaCh);


BOOLEAN Platform_DmaDisable(


	PPLATFORM_DATA platformData,


	const DWORD dwDmaCh);


void Platform_CacheInvalidate(


	PPLATFORM_DATA platformData,


	const void * const pStartAddress,


	const DWORD dwLengthInBytes);


void Platform_CachePurge(


	PPLATFORM_DATA platformData,


	const void * const pStartAddress,


	const DWORD dwLengthInBytes);


DWORD Platform_RequestDmaChannel(


	PPLATFORM_DATA platformData);


void Platform_ReleaseDmaChannel(


	PPLATFORM_DATA platformData,


	DWORD dwDmaChannel);


BOOLEAN Platform_DmaStartXfer(


	PPLATFORM_DATA platformData,


	const DMA_XFER * const pDmaXfer);


DWORD Platform_DmaGetDwCnt(


	PPLATFORM_DATA platformData,


	const DWORD dwDmaCh);


void Platform_DmaComplete(


	PPLATFORM_DATA platformData,


	const DWORD dwDmaCh);


void Platform_GetFlowControlParameters(


	PPLATFORM_DATA platformData,


	PFLOW_CONTROL_PARAMETERS flowControlParameters,


	BOOLEAN useDma);


void Platform_WriteFifo(


	DWORD dwLanBase,


	DWORD *pdwBuf,


	DWORD dwDwordCount);


void Platform_ReadFifo(


	DWORD dwLanBase,


	DWORD *pdwBuf,


	DWORD dwDwordCount);





#endif //not USING_LINT

static const char date_code[] = "010708";



BOOLEAN Platform_IsValidDmaChannel(DWORD dwDmaCh)

{

	if(dwDmaCh<=16) {

		return TRUE;

	}

	return FALSE;

}



DWORD Platform_Initialize(

	PPLATFORM_DATA platformData,

	DWORD dwLanBase,DWORD dwBusWidth)

{

	DWORD mode=0;

	DWORD test=0;

	SMSC_TRACE("--> Platform_Initialize()");



	if(dwLanBase==0x0UL) {

		dwLanBase=LAN_CSBASE;

//		SMSC_TRACE("Using dwLanBase==0x%08lX",dwLanBase);

	}



	if(dwLanBase!=LAN_CSBASE) {

		SMSC_WARNING("PlatformInitialize: resetting dwLanBase from 0x%08lX to 0x%08X", dwLanBase, LAN_CSBASE);

		dwLanBase=LAN_CSBASE;

	}



#define BYTE_TEST_OFFSET	(0x64)

#define ID_REV_OFFSET		(0x50)

	switch(dwBusWidth) {

	case 16:

		mode=2;

		MSC2&=0x0000FFFFUL;

		MSC2|=0x8CD90000UL;

		test=(*(volatile unsigned long *)(dwLanBase+BYTE_TEST_OFFSET));

		if(test==0x87654321) {

			SMSC_TRACE(" 16 bit mode assigned and verified");

		} else {

			SMSC_WARNING(" failed to verify assigned 16 bit mode");

			dwLanBase=0;

		};break;

	case 32:

		mode=1;

		MSC2&=0x0000FFFFUL;

		MSC2|=0x8CD10000UL;

		test=(*(volatile unsigned long *)(dwLanBase+BYTE_TEST_OFFSET));

		if(test==0x87654321) {

			SMSC_TRACE(" 32 bit mode assigned and verified");

		} else {

			SMSC_WARNING(" failed to verify assigned 32 bit mode");

			dwLanBase=0;

		};break;

	default:

		mode=1;

		MSC2&=0x0000FFFFUL;

		MSC2|=0x8CD10000UL;

		{

			WORD dummy=0;

			test=(*(volatile unsigned long *)(dwLanBase+BYTE_TEST_OFFSET));

			dummy=(*(volatile unsigned short *)(dwLanBase+BYTE_TEST_OFFSET+2));

			if(test==0x87654321UL) {

				SMSC_TRACE(" 32 bit mode detected");

			} else {

				SMSC_TRACE(" 32 bit mode not detected, test=0x%08lX",test);

				MSC2|=0x00080000UL;

				test=(*(volatile unsigned long *)(dwLanBase+BYTE_TEST_OFFSET));

				if(test==0x87654321UL) {

					SMSC_TRACE(" 16 bit mode detected");

					mode=2;

				} else {

//					SMSC_WARNING(" test=0x%08lX",test);

					SMSC_WARNING(" neither 16 nor 32 bit mode detected.");

					dwLanBase=0;

				}

			}

			dummy=dummy;//make lint happy

		};break;

	}

	

	if(dwLanBase!=0) {

		DWORD idRev=(*(volatile unsigned long *)(dwLanBase+ID_REV_OFFSET));

		platformData->dwIdRev=idRev;

		switch(idRev&0xFFFF0000) {

		case 0x218A0000UL: 

		case 0x217A0000UL: 

		case 0x92110000UL:

		case 0x01180000UL:

		case 0x01170000UL:

		case 0x118A0000UL:

		case 0x117A0000UL:

			switch(mode) {

			case 1://32 bit mode

				MSC2 &= 0x0000FFFFUL;

				MSC2 |= 0x83710000UL;

				break;

			case 2://16 bit mode

				MSC2 &= 0x0000FFFFUL;

				MSC2 |= 0x83790000UL;

				break;

			default:break;//make lint happy

			};break;

		default:
			//This is used for the new unkonw chip before we formally add them in the driver
			if ((bus_timing==1)& ((idRev&0xFFFF0000) !=0x216A0000UL)
							   & ((idRev&0xFFFF0000) !=0x215A0000UL)
							   & ((idRev&0xFFFF0000) !=0x01160000UL)
							   & ((idRev&0xFFFF0000) !=0x01150000UL)
							   & ((idRev&0xFFFF0000) !=0x116A0000UL)
							   & ((idRev&0xFFFF0000) !=0x115A0000UL)
							   & ((idRev&0xFFFF0000) !=0x92100000UL)) {
				
				switch(mode) {

				case 1://32 bit mode

					MSC2 &= 0x0000FFFFUL;

					MSC2 |= 0x83710000UL;

					break;

				case 2://16 bit mode

					MSC2 &= 0x0000FFFFUL;

					MSC2 |= 0x83790000UL;

					break;

				default:break;//make lint happy

				}
				
			}
			break;//make lint happy

		}

	}



	SMSC_TRACE(" MSC2=0x%08X", MSC2);

	SMSC_TRACE("<-- Platform_Initialize()");

	return dwLanBase;

}



void Platform_CleanUp(

	PPLATFORM_DATA platformData)

{

}



BOOLEAN Platform_Is16BitMode(PPLATFORM_DATA platformData)

{

	SMSC_ASSERT(platformData!=NULL);



	if (MSC2 & 0x00080000)

		return TRUE;

	else

		return FALSE;

}


// We need to add FlowControlParameters for the new chips here

void Platform_GetFlowControlParameters(

	PPLATFORM_DATA platformData,

	PFLOW_CONTROL_PARAMETERS flowControlParameters,

	BOOLEAN useDma)

{

	memset(flowControlParameters,0,sizeof(FLOW_CONTROL_PARAMETERS));

	flowControlParameters->BurstPeriod=100;

	flowControlParameters->IntDeas=0;

	if(useDma) {

		if(Platform_Is16BitMode(platformData)) {

			switch(platformData->dwIdRev&0xFFFF0000) {
			

			case 0x92110000UL:

				#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
				//9211,16 bit,DMA

				flowControlParameters->MaxThroughput=0x11A8D0UL;

				flowControlParameters->MaxPacketCount=0x302UL;

				flowControlParameters->PacketCost=0x00UL;

				flowControlParameters->BurstPeriod=0x76UL;

				flowControlParameters->IntDeas=0x29UL;
				#else
				//9211,16 bit,DMA

				flowControlParameters->MaxThroughput=0x120C60UL;

				flowControlParameters->MaxPacketCount=0x310UL;

				flowControlParameters->PacketCost=0x00UL;

				flowControlParameters->BurstPeriod=0x6EUL;

				flowControlParameters->IntDeas=0x28UL;
				#endif

				break;

			case 0x218A0000UL:

			case 0x217A0000UL:

			case 0x01180000UL:

			case 0x01170000UL:

			case 0x118A0000UL:

			case 0x117A0000UL:


				//117/118,16 bit,DMA

				flowControlParameters->MaxThroughput=0x10C210UL;

				flowControlParameters->MaxPacketCount=0x2DCUL;

				flowControlParameters->PacketCost=0x82UL;

				flowControlParameters->BurstPeriod=0x75UL;

				flowControlParameters->IntDeas=0x1CUL;

				break;

			case 0x92100000UL:
				
				#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
				//9210,16 bit,DMA

				flowControlParameters->MaxThroughput=0x9BBF0UL;

				flowControlParameters->MaxPacketCount=0x1A8UL;

				flowControlParameters->PacketCost=0x00UL;

				flowControlParameters->BurstPeriod=0x55UL;

				flowControlParameters->IntDeas=0x1BUL;
				#else
				//9210,16 bit,DMA

				flowControlParameters->MaxThroughput=0x93AD4UL;

				flowControlParameters->MaxPacketCount=0x18FUL;

				flowControlParameters->PacketCost=0x00UL;

				flowControlParameters->BurstPeriod=0x72UL;

				flowControlParameters->IntDeas=0x3CUL;
				#endif

				break;


			case 0x216A0000UL:

			case 0x215A0000UL:
			
			case 0x01160000UL:

			case 0x01150000UL:

			case 0x116A0000UL:

			case 0x115A0000UL:

				//115/116,16 bit,DMA

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -