📄 ixdp2400.c
字号:
/*ixdp2400.c - npu, master/slave and flashmode identification routines*//*modification history--------------------01a,14jan03,scm add enum PciBarId here...rev, 1apr02, vgd - creation*/#include "vxWorks.h"#include "config.h"#include "ixdp2400.h"#include "ixdp2400Misc.h"#define QDR2/*global variables*/UINT32 strapOptionsVal = 0;UINT32 sramSize =0;UINT32 ixp2400XtalFreq;UINT32 sramChanSize[4]={0,0,0,0};static UINT32 _period;struct board_config *pBoardCfgData =(struct board_config *)IXP2400_SCRATCH_BASE;struct SPCfg spCfgCpld;/*externs*/extern UINT32 boardRev;/****************************************************************************** * int isNPUMaster(void) - identify whether the code is running on Master NPU or * slave NPU *This routine reads the STRAP OPTIONs register and if bit 2 is 1, then the npu *is master. It returns a value representative of whether or not running on the *master NPU * * RETURNS: TRUE if running on master FALSE if running on slave. */int isNPUMaster (void){ FAST int locKey; /* Lock Interrupts */ locKey = intLock(); /*Read STRAP_OPTIONS register*/ IXP2400_REG_READ(IXP2400_STRAP_OPTIONS,strapOptionsVal); /* UnLock Interrupts */ intUnlock (locKey); return ( (strapOptionsVal & CFG_PCI_BOOT_HOST) ? TRUE : FALSE); }/****************************************************************************** * int isNPUFlashEnabled(void) - identify the flash on the NPU where the code is running has flash or not. *This routine reads the STRAP OPTIONs register and returns a value representative *of whether the nPU's flash is enabled or not. The master NPU flash is always *enabled, while the slave NPU's flash could be either enabled or disabled * * RETURNS: TRUE if Flash enabled FALSE if Flash disabled. */int isNPUFlashEnabled (void){ FAST int locKey; /* Lock Interrupts */ locKey = intLock(); /*Read STRAP_OPTIONS register*/ IXP2400_REG_READ(IXP2400_STRAP_OPTIONS,strapOptionsVal); /* UnLock Interrupts */ intUnlock (locKey); return ( (strapOptionsVal & CFG_PROM_BOOT) ? TRUE : FALSE); }/******************************************************************************** *int getProductID (void) - return the product id *This function returns the major product type, minor product type, major revision, *and minor revision fields. *[31:21] RES Reserved *[20:16] MAJ_PROD_TYPE 0 = IXP2000 others will be assigned as needed *[15:8] MIN_PROD_TYPE 0 = IXP2800 with Crypto * 1 = IXP2800 * 2 = IXP2400 * *[7:4] MAJ_REV Current Revision. Starts at 0 *[3:0] MIN_REV Current Revision. Starts at 0 * *Return Value: IDData value */int getProductID (unsigned int mask){ int IDData; FAST int locKey; /* Lock Interrupts */ locKey = intLock(); /*Read the Product ID register */ IDData=((*(volatile unsigned int *)(IXP2400_PROD_ID))&mask); /* UnLock Interrupts */ intUnlock (locKey); return(IDData);}/****************************************************************************** * STATUS sysCFGDATAcopy(void ) - copies config data on I2C EEPROM attached to * master onto to SRAM on the master NPU. * *Return: OK if sucessful else ERROR */STATUS sysCFGDATAcopy(void){ int i; struct EEPROM_CONTENT temp; FAST int locKey; if(isNPUMaster()) { /* read config data and save it*/ i2c_seq_read(0xa2, 0x0, (unsigned char *)&temp, CONFIG_DATA_SIZE); if(temp.prom_fmt == '0') { locKey = intLock (); for(i = 0; i < CONFIG_DATA_SIZE; i += 4) { *((UINT32 *)((UINT32)&(pBoardCfgData->config_data) + i)) = *((UINT32 *)((UINT32)&temp + i)); } intUnlock (locKey); pBoardCfgData->config_valid = CONFIG_DATA_VALID; } } return OK;}/****************************************************************************** * STATUS ixdp2400SRAMInit(int channel, int skipCsr, int frmPci, int offset ) * Initializes SRAM with max size and the dynamically sizes it. * *Return: OK if sucessful else ERROR */STATUS ixdp2400SRAMInit(int channel, int skipCsr, int frmPci, int offset){ int i; int j; int qdrChSize = MIN_SRAM_SIZE; int qdrChanCsrBase; int qdrBase; volatile UINT32 *sramCmpLoc; volatile UINT32 *sramTstLoc; int sramDetected =0; UINT32 sramCsrVal, temp, addr; FAST int locKey;#ifndef INCLUDE_PCI qdrChanCsrBase = IXP2400_QDR_CH_CSR_BASE + (channel * 0x400000); qdrBase = IXP2400_SRAM_CH0_BASE + (channel * 0x10000000);#else /*calculate the csr base and qdr base*/ if(frmPci) { qdrChanCsrBase = pSlave->bar[CSR_BAR].address + SLAVE_QDR_CH_BASE + (channel * 0x400); qdrBase = pSlave->bar[SRAM_BAR].address + (channel * 0x10000000); } else { qdrChanCsrBase = IXP2400_QDR_CH_CSR_BASE + (channel * 0x400000); qdrBase = IXP2400_SRAM_CH0_BASE + (channel * 0x10000000); }#endif /* Init CSRs*/ if(!skipCsr) { locKey = intLock (); /*Program Slew rate tables for normal Rcomp operation*/ /* Rcomp registers are only 4 bytes distant. So, when this function * will be called by pci init it won't work properly due to pci bug. * Insert dummy read cycle in between write operations */ for(addr = 0x340; addr <= 0x3bc; addr+=4) { IXP2400_REG_WRITE((qdrChanCsrBase+addr),0xCCCC); #if A0_REV IXP2400_REG_READ((qdrChanCsrBase+addr),temp);#endif } /*Invert rcomp polarity*/ IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RCMP_SETUP_CONTROL_OFF), 0x00010060);#ifdef QDR1 /* Set 50 ohm ref resistor in real board/tester*/ IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RCOMP_OFF), 0xFFFF3); /*wait for 1 ms*/ delayUSec(1000); IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RX_DLL_OFF),0x48);#else /* Set 50 ohm ref resistor in real board/tester*/ IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RCOMP_OFF), 0x518C3); /*wait for 1 ms*/ delayUSec(1000); IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RX_DLL_OFF),0x52);#endif IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RX_DESKEW_OFF),0x12); /*Set SRAM CSR to use max size*/ IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_CH_CONTROL_OFF),MAX_SRAM_SIZE_CSR_VAL); /*wait for 3 ms*/ delayUSec(3000); IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_RD_PTR_OFF), 0x4); /*read RD_PTR back to ensure write is completed*/ IXP2400_REG_READ((qdrChanCsrBase+IXP2400_QDR_RD_PTR_OFF), temp); intUnlock (locKey); } if(!frmPci) { locKey = intLock (); for(j=1;j<=5;j++) { IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_CH_CONTROL_OFF),(PIPELINE|(j<<7))); /*wait for 3 ms*/ delayUSec(3000); /*Now probe for the right size*/ for(i = 0; i < SRAM_SIZE_LOOPS; i++) { sramCmpLoc = (UINT32 *)(qdrBase + qdrChSize); *sramCmpLoc = 0xAA55AA55; if(*sramCmpLoc != 0xAA55AA55) { break; } sramCmpLoc = (UINT32 *)(qdrBase + offset); sramTstLoc = (UINT32 *)(qdrBase + (qdrChSize/2) + offset); *sramCmpLoc = 0xA5A5A5A5; *sramTstLoc = 0x55AAAA55; if(*sramCmpLoc == *sramTstLoc) { break; } sramDetected = 1; qdrChSize *= 2; } } if(!sramDetected) { qdrChSize = 0; } sramChanSize[channel] = qdrChSize; /*save sram size*/ sramSize += qdrChSize; temp = 1024 * 1024; for(i = 0; i < 6; i++) { temp = temp * 2; if(temp == qdrChSize) break; } sramCsrVal = i << 7; sramCsrVal = sramCsrVal | PIPELINE; /* init channel 0*/ IXP2400_REG_WRITE((qdrChanCsrBase+IXP2400_QDR_CH_CONTROL_OFF), sramCsrVal); intUnlock (locKey); } if(!frmPci && qdrChSize ) { locKey = intLock (); /*Init whole SRAM with 0x0 so that the parity errors are not generated*/ memset((char *)(qdrBase+offset), 0, (qdrChSize-offset)); if(boardRev >= 3) { /*Parity is working only on board rev3 and above*/ *((UINT32*)(qdrChanCsrBase + IXP2400_QDR_CH_CONTROL_OFF)) |= PARITY_ENABLE; } intUnlock (locKey); } return OK;}void ixp2400Timer1Init(UINT32 period){ FAST int locKey; _period = period; locKey = intLock (); /* load the counter */ *((UINT32 *)IXP2400_TIMER1_LOAD) = period; /* start the timer */ *((UINT32 *)IXP2400_TIMER1_CONTROL) = (1 << 7); intUnlock (locKey);}/* Read the current value of the clock, returning the number of hardware * "ticks" that have occurred (i.e. how far away the current value is from * the start) */void ixp2400Timer1read(UINT32 *pvalue){ FAST int locKey; locKey = intLock (); /* read the current counter value */ *pvalue = *((UINT32 *)IXP2400_TIMER1_STATUS); intUnlock (locKey);}/* Delay for some usecs. */void delayUSec(UINT32 delay){ UINT32 now, last, diff, ticks, ticks_per_usec; ticks_per_usec = ixp2400XtalFreq / 1000000; ixp2400Timer1read(&last); diff = ticks = 0; while (delay > ticks) { ixp2400Timer1read(&now); if (now > last) diff += ((_period - now) + last); else diff += (last - now); last = now; if (diff >= ticks_per_usec) { ticks += (diff / ticks_per_usec); diff %= ticks_per_usec; } }}void getXtalFreq(void){ UINT32 cpld_rev; UINT32 board_rev; FAST int locKey; locKey = intLock (); cpld_rev = *((volatile UINT32*)(CPLD_REV)); intUnlock (locKey); board_rev = (cpld_rev & 0xF0) >> 4; if(board_rev < 4) { ixp2400XtalFreq = IXP2400_DEFAULT_CLK_RATE / 12; } else { int numerator, denominator; int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8}; numerator = ((*(volatile UINT32*)(SYS_CLK_M)) & 0xFF)*2; denominator = denom_array[((*(volatile UINT32*)(SYS_CLK_N)) & 0x7)]; ixp2400XtalFreq = (3125000 * numerator) / denominator; ixp2400XtalFreq = ixp2400XtalFreq/2; }}void ixdp2400SPCfgSave(struct SPCfg *slowPortCfg){ FAST int locKey; locKey = intLock (); IXP2400_REG_READ(IXP2400_SP_CCR, slowPortCfg->spCCR); IXP2400_REG_READ(IXP2400_SP_WTC2, slowPortCfg->spWTC2); IXP2400_REG_READ(IXP2400_SP_RTC2, slowPortCfg->spRTC2); IXP2400_REG_READ(IXP2400_SP_PCR, slowPortCfg->spPCR); IXP2400_REG_READ(IXP2400_SP_ADC, slowPortCfg->spADC); intUnlock (locKey);}void ixdp2400SPCfgRestore(struct SPCfg *slowPortCfg){ FAST int locKey; locKey = intLock (); IXP2400_REG_WRITE(IXP2400_SP_CCR, slowPortCfg->spCCR); IXP2400_REG_WRITE(IXP2400_SP_WTC2, slowPortCfg->spWTC2); IXP2400_REG_WRITE(IXP2400_SP_RTC2, slowPortCfg->spRTC2); IXP2400_REG_WRITE(IXP2400_SP_PCR, slowPortCfg->spPCR); IXP2400_REG_WRITE(IXP2400_SP_ADC, slowPortCfg->spADC); intUnlock (locKey);}#ifdef _DIAB_TOOL__asm void sync_dcache (){% lab loop_667;! "r0", "r1" mov r0, #0x70000000 add r1, r0, #0x8800loop_667: mcr p15, 0, r0, c7, c2, 5 add r0, r0, #32 teq r1, r0 bne loop_667 mcr p15, 0, r0, c7, c6, 0 mrc p15, 0, r1, c2, c0, 0 mov r1, r1 sub pc, pc, #4 mcr p15, 0, r0, c7, c10, 4 mrc p15, 0, r1, c2, c0, 0 mov r1, r1 sub pc, pc, #4 nop}#endifvoid dcacheSync(void){#ifdef _DIAB_TOOL sync_dcache ();#else /* The best way to evict a dirty line is by using the */ /* line allocate operation on non-existent memory. */ __asm ("mov r0, #0x70000000;" /* use upper 256M of SDRAM for cache flush region */ "add r1, r0, #0x8800;" /* 32KB cache + 2KB mini cache */ "667: " "mcr p15,0,r0,c7,c2,5;" /* allocate a line */ "add r0, r0, #32;" /* 32 bytes/line */ "teq r1, r0;" "bne 667b;" "mcr p15,0,r0,c7,c6,0;" /* invalidate data cache */ /* cpuwait */ "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ "mov r1,r1;" "sub pc,pc,#4;" "mcr p15,0,r0,c7,c10,4;" /* and drain the write buffer */ /* cpuwait */ "mrc p15,0,r1,c2,c0,0;" /* arbitrary read */ "mov r1,r1;" "sub pc,pc,#4;" "nop" : : : "r0","r1" /* Clobber list */ );#endif}void dcacheOn(void){ /* Enable data cahce and MMU by writing 1 to bits 0 and 2*/ __asm ("mrc p15,0,r1,c7,c10,4;" /* drain write buffer */ "mrc p15,0,r1,c1,c0,0;" "orr r1,r1,#0x0004;" "mcr p15,0,r1,c1,c0,0;" "mrc p15,0,r1,c2,c0,0;" /* arbitrary read*/ "mov r1,r1;" "sub pc,pc,#4;" "mcr p15,0,r1,c7,c6,0;" /* invalidate data cache*/ );}void dcacheOff(void){ __asm ("mrc p15,0,r1,c1,c0,0;" "bic r1,r1,#0x0004;" "mcr p15,0,r1,c1,c0,0;" "mrc p15,0,r1,c2,c0,0;" /* arbitrary read*/ "mov r1,r1;" "sub pc,pc,#4;" "mcr p15,0,r1,c7,c6,0;" /* invalidate data cache*/ "mrc p15,0,r1,c2,c0,0;" /* arbitrary read*/ "mov r1,r1;" "sub pc,pc,#4;" );}#ifdef _DIAB_TOOL__asm void flush_dcache(void){% lab loop_fd1;! "r0", "r1", "r2" ldr r0, =0x0 add r1, r0, #8192loop_fd1: ldr r2, [r0], #32 teqs r1, r0 bne loop_fd1 mcr p15, 0, r0, c7, c10, 4 mcr p15, 0, a1, c7, c6, 0 mov pc, lr}#endifvoid dcacheFlush(void){#ifdef _DIAB_TOOL flush_dcache();#else __asm ("ldr r0,=0x0;" "add r1,r0,#8192;" "1:;" "ldr r2,[r0],#32;" "teqs r1,r0;" "bne 01b;" "mcr p15,0,r0,c7,c10,4;" "mcr p15,0,a1,c7,c6,0;" "mov pc,lr;" );#endif}#ifdef _DIAB_TOOL__asm int cp15_val (void){! "r0" mrc p15, 0, r0, c1, c0, 0}#endifunsigned int getCP15(void){ unsigned int x = 0;#ifdef _DIAB_TOOL x = cp15_val();#else __asm ("mrc p15, 0, %0, c1, c0, 0;" : "=r"(x) :);#endif return x;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -