📄 xscale_linux_2.4.c
字号:
/***************************************************************************
*
* 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 + -