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

📄 xscale_linux_2.4.c

📁 基于pxa270的linux下smsc9118的网卡驱动源码
💻 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

 * 06/14/2005 Bryan Whitehead, rev 4

 *    merged .h file into .c file

 * 11/07/2005 Phong Le, rev 5

 *    Update to version 1.21

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

 * 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.

 */



static const char date_code[] = "032306";



#ifndef USING_LINT

#include <asm/hardware.h>

#include <asm/arch/mainstone.h>

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

#endif //not USING_LINT



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 r5"

#define	PLATFORM_IRQ		(167)

#else

#define PLATFORM_NAME		"XScale with Linux 2.4 r5"

#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



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 0x01180000UL:

		case 0x01170000UL:

		case 0x01120000UL:

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

}



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 0x01180000UL:

			case 0x01170000UL:

			case 0x01120000UL:

			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 0x01160000UL:

			case 0x01150000UL:

			case 0x116A0000UL:

			case 0x115A0000UL:

				//115/116,16 bit,DMA

				flowControlParameters->MaxThroughput=0x96CF0UL;

				flowControlParameters->MaxPacketCount=0x198UL;

				flowControlParameters->PacketCost=0x00UL;

				flowControlParameters->BurstPeriod=0x73UL;

				flowControlParameters->IntDeas=0x31UL;

				break;

			default:break;//make lint happy

			}

		} else {

			switch(platformData->dwIdRev&0xFFFF0000) {

			case 0x01180000UL:

			case 0x01170000UL:

			case 0x01120000UL:

			case 0x118A0000UL:

			case 0x117A0000UL:

				//117/118,32 bit,DMA

				flowControlParameters->MaxThroughput=0x12D75AUL;

				flowControlParameters->MaxPacketCount=0x332UL;

				flowControlParameters->PacketCost=0xDBUL;

				flowControlParameters->BurstPeriod=0x15UL;

				flowControlParameters->IntDeas=0x0BUL;

				break;

			case 0x01160000UL:

			case 0x01150000UL:

			case 0x116A0000UL:

			case 0x115A0000UL:

				//115/116,32 bit,DMA

				flowControlParameters->MaxThroughput=0xF3EB6UL;

				flowControlParameters->MaxPacketCount=0x29BUL;

				flowControlParameters->PacketCost=0x00UL;

⌨️ 快捷键说明

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