📄 pxa-gspi.c
字号:
///crlo: If the data length is NOT multiple of DWORD, add more
/// crlo: ref: SPU specification chap4
{
if (((nbyte %4) != 0) && ((reg ==0x0c)||(reg ==0x18)||(reg ==0x24) ))
{
///crlo: Because we are using 16-bit data accessing, if (nyte%4)!=0, it must be 2
/// => add one more WORD
//pHC->pSSPRegs->base.ssdr = 0;
temp=0;
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
pHC->pSSPRegs->SPTDAT0 = (UCHAR)(temp >> 8); // write 1st Byte
// RETAILMSG(1,(L"ssp_write_data_direct(): Reg 1st Byte=(0x%x)\n", (UCHAR)(temp >> 8)));
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
pHC->pSSPRegs->SPTDAT0 = (UCHAR)(temp & 0x00ff); // write 2nd Byte
// RETAILMSG(1,(L"ssp_write_data_direct(): Reg 1st Byte=(0x%x)\n", (UCHAR)(temp & 0x00ff)));
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
//udelay( 10);
GSPIMSG(1, (TEXT("Add one more WORD to fit 32-bit boundary\n"), accnbyte));
}
}
pHC->pGPIORegs->GPGDAT |= (0x1 << 2); //Set _SS signal to high (Slave Select)
LeaveCriticalSection(&pHC->SSPCrit);
funcLeave:
EXITFUNC(result);
return result;
}
static GSPI_STATUS setup_read_dma(PSSP_HARDWARE_CONTEXT pHC, int n)
{
GSPI_STATUS result = GSPI_SUCCESS;
DWORD dmaresult;
//DWORD TC;
MYDMAPARAM *pwtDmaParam = &pHC->DMAParam[RWDMA_PARAM];
// DMA mode, CLK enable, master mode, active high clock, format A, Tx Auto Garbage Data mode
pHC->pIntRegs->INTMSK&= ~(0x1<<18);//DMA1 service available
pHC->pSSPRegs->SPCON0 = (0x2<<5)|(1<<4)|(1<<3)|(0<<2)|(0<<1)|(1<<0);
pHC->pDMARegs->DISRC1= (unsigned)0x59000014;//SPI0 SPRDAT0 register(Physical Address)
pHC->pDMARegs->DISRCC1=(1<<1) | (1); //APB(SPI), fixed
//pHC->pDMARegs->DIDST1= (unsigned) (pHC->iodata);//Virtual address
pHC->pDMARegs->DIDST1= (unsigned) (pHC->phys_addr);//Phy address
pHC->pDMARegs->DIDSTC1=(0<<1) | (0);//AHB(Memory), inc
//Handshake Mode(31) , sync PCLK(30), TC intr(29), single TX(28), single service(27),
//request source SPI(26..24), H/W request(23), off-reload(22), data size:byte(21..20), transfer count
pHC->pDMARegs->DCON1=(1<<31) |(0<<30)|(1<<29)|(0<<28)|(0<<27)|(3<<24)|(1<<23)|(1<<22)|(0<<20)|(n);
#if (USE_DMAIRQ == 1)
ResetEvent(pwtDmaParam->dmaWaitObj);
#endif ///USE_DMAIRQ
pHC->pDMARegs->DMASKTRIG1=(0<<2)|(1<<1)|(0);//run, channel on, no s/w trigger
#if (USE_DMAIRQ == 1)
dmaresult = WaitForSingleObject(pwtDmaParam->dmaWaitObj, (MAX_WAITus/1000));
if (dmaresult == WAIT_TIMEOUT) {
GSPIMSG(1, (TEXT("WaitForSingleObject timeout (%d)\n"), n));
result = GSPI_TIMEOUT;
goto funcFinal;
}
pHC->pDMARegs->DMASKTRIG1=(0<<2)|(0<<1)|(0);//run, channel off, no s/w trigger
//pHC->pSSPRegs->SPCON0 = (0<<5)|(1<<4)|(1<<3)|(0<<2)|(0<<1)|(0<<0);
#endif
funcFinal:
return result;
}
static GSPI_STATUS ssp_read_data_direct(DWORD hDC, WORD* data, WORD reg, WORD nword, WORD dummy_clk)
{
GSPI_STATUS result = GSPI_SUCCESS;
PSSP_HARDWARE_CONTEXT pHC;
WORD nbyte = nword * 2;
//WORD temp,tt1,tt2;
WORD temp;
// int i,ii;
int i;
BYTE temp1;
PWORD dat = (PWORD)data;
PBYTE p;
#if (USE_DMA == 1)
int accnbyte; ///Accumulated length (0 - nbyte)
int fragnbyte; ///length of each fragment
BOOLEAN isfrag = FALSE;
#endif /// (USE_DMA == 1)
//GSPIMSG(1, (TEXT("nword=(%d)\n"), nword));
//GSPIMSG(1, (TEXT("nbyte=(%d)\n"), nbyte));
ENTERFUNC();
if (hDC == 0) {
result = GSPI_INVALIDARGS;
goto funcLeave;
}
pHC = (PSSP_HARDWARE_CONTEXT)hDC;
EnterCriticalSection(&pHC->SSPCrit);
pHC->pGPIORegs->GPGDAT &= ~(0x1 << 2); //Set _SS signal to low (Slave Select)
#if (USE_DMA == 1)
///DMA mode
{
///Write the register address
WORD *iodatPt = (WORD*)pHC->iodata;
// for(i=0;i<(1+dummy_clk);i++)
// *(iodatPt+i)=0;
//WORD *iodatPt = (WORD*)pHC->iorw;
*iodatPt = reg;
temp1=*(pHC->iodata);
*(pHC->iodata)=*(pHC->iodata+1);
*(pHC->iodata+1)=temp1;
result = setup_write_dma(pHC, (1+dummy_clk)*2);
//result = setup_read_dma(pHC, (1+dummy_clk)*2);
if (result != GSPI_SUCCESS) {
GSPIMSG(1, (TEXT("Fail to push reg+dummy_clk[%d]...\n"), dummy_clk));
}
}
///==============================================
accnbyte = 0;
while (1) {
fragnbyte = nbyte - accnbyte;
if (fragnbyte> PXA_SSP_IODATA_SIZE) {
fragnbyte = PXA_SSP_IODATA_SIZE;
isfrag = TRUE;
}
result = setup_read_dma(pHC, fragnbyte);
if (result != GSPI_SUCCESS) {
GSPIMSG(1, (TEXT("%s, Read data failed...\n"), TEXT(__FUNCTION__)));
break;
}
memcpy((PBYTE)dat, pHC->iodata, fragnbyte);
//memcpy(data, pHC->iodata, fragnbyte);
//0524
//for(i=0;i<fragnbyte;i++)
// GSPIMSG(1, (TEXT("%02X "), *(pHC->iodata+i)));
accnbyte += fragnbyte;
dat += (fragnbyte/2); ///type of data is WORD
if (accnbyte == nbyte) {
if (isfrag == TRUE) {
GSPIMSG(1, (TEXT("Cont. reading data. (now, exp)=(%d, %d), complete!\n"), accnbyte, nbyte));
}
break;
} else if (accnbyte > nbyte){
GSPIMSG(1, (TEXT("Invalid Rd Length, (exp, acc)=(%d, %d)\n"), nbyte, accnbyte));
} else {
if (isfrag == TRUE) {
GSPIMSG(1, (TEXT("Cont. reading data. (now, exp)=(%d, %d)\n"), accnbyte, nbyte));
}
}
}
// poll mode, CLK enable, master mode, active high clock, format A, normal mode
pHC->pSSPRegs->SPCON0 = (0<<5)|(1<<4)|(1<<3)|(0<<2)|(0<<1)|(0<<0);
pHC->pSSPRegs->SPPIN0= ((0<<2) |(1<<1) |(0<<0));
//read last byte
// while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
// pHC->pSSPRegs->SPTDAT0 = (UCHAR)(0xff);
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
temp=pHC->pSSPRegs->SPRDAT0;
// temp=temp<<8;
//GSPIMSG(1, (TEXT("Last Byte=%X\n"),temp));
//GSPIMSG(1, (TEXT("Before Swap....data0=%X data1=%X data2=%X data3=%X\r\n"),*(data),*(data+1),*(data+2),*(data+3)));
//GSPIMSG(1, (TEXT("Before Swap....\r\n")));
//for(i=0;i<nword;i++)
// GSPIMSG(1, (TEXT("%04X "), *(data+i)));
p = (PBYTE)data;
//p = data;
/*
for(i=0;i<nword*2-1;i++)
{
//need to check further
// *(data+i)=(*(data+i) << 8) | (*(data+i+1) >> 8);
*(p+i)=*(p+i+1);
}
*(p+nword*2-1)=temp;
*/
for(i=0;i<nword-1;i++)
{
//need to check further
// *(data+i)=(*(data+i) << 8) | (*(data+i+1) >> 8);
*(p+i*2)=*(p+(i+1)*2);
}
*(p+(nword-1)*2)=temp;
//*(p+(nword-1))=temp;
//GSPIMSG(1, (TEXT("After Swap....data0=%X data1=%X data2=%X data3=%X\r\n"),*(data),*(data+1),*(data+2),*(data+3)));
//GSPIMSG(1, (TEXT("After Swap....\r\n")));
//for(i=0;i<nword;i++)
//GSPIMSG(1, (TEXT("%04X "), *(data+i)));
/*
for(i=0;i<nword-1;i++)
{
//need to check further
// *(data+i)=(*(data+i) << 8) | (*(data+i+1) >> 8);
*(data+i)=(*(data+i) << 8) | (*(data+i+1) << 8);
}
*(data+nword-1)=(*(data+nword-1) & 0xff00) | temp;
GSPIMSG(1, (TEXT("data0=%X data1=%X\n"),*(data),*(data+1)));
*/
#else
///CPU mode
{
pHC->pSSPRegs->SPTDAT0 = (UCHAR)(reg >> 8); // write 1st Byte
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
pHC->pSSPRegs->SPTDAT0 = (UCHAR)(reg & 0x00ff); // write 2nd Byte
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
for (i=0 ; i<dummy_clk*2 ; i++)
//for (i=0;i<10;i++)
{
putcToSoc(pHC,0x00);
}
}
{
//PWORD dat = (PWORD)data;
WORD t1;
///================================
/// Write the dummy_write & fetch the data
///GSPIMSG(1, (TEXT("Reading datas(%d)WORD\n"), nword));
//for (i=0 ; i<nword+10 ; i++) {
for (i=0;i<nword;i++)
{
//Begin to read data
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
pHC->pSSPRegs->SPTDAT0 = (UCHAR)(0xff);
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
temp=pHC->pSSPRegs->SPRDAT0;
// RETAILMSG(1,(L"temp=(0x%X) ", temp));
udelay(10);
temp=temp<<8;
pHC->pSSPRegs->SPTDAT0 = (UCHAR)(0xff);
while((pHC->pSSPRegs->SPSTA0 & 0x1)==0); // wait while busy
t1=pHC->pSSPRegs->SPRDAT0;
temp=temp | t1;
// RETAILMSG(1,(L"t1=(0x%X) ", t1));
*dat=temp;
// RETAILMSG(1,(L"%02d READ Value=(0x%x)\r\n", i,*dat));
dat ++;
}
///GSPIMSG(1, (TEXT("Reading data done!\n")));
}
#endif
pHC->pGPIORegs->GPGDAT |= (0x1 << 2); //Set _SS signal to high (Slave Select)
goto funcFinal;
funcFinal:
LeaveCriticalSection(&pHC->SSPCrit);
funcLeave:
EXITFUNC(result);
return result;
}
///
/// ssp_read_register: Read the register from SSP interface
/// Input:
/// hDC - the context returned from SSP_Init
/// regaddr - register addreess
/// Output:
/// regdatPt - returned register value
/// Return:
/// 0 - success
/// -1 - failure
GSPI_STATUS ssp_read_register(DWORD hDC, WORD* regdatPt, WORD regaddr)
{
GSPI_STATUS result=0;
//BYTE *p,tb;
int i;
for (i=0 ; i<GSPI_MAX_REG_RETRY ; i++) {
result = ssp_read_data_direct(hDC, regdatPt, regaddr, 1, g_spi_dummy_clk_reg);
if (result == GSPI_SUCCESS) {
break;
}
}
if (i == GSPI_MAX_REG_RETRY) {
GSPIMSG(1, (L"%s, Read register(%xh) timeout \n", TEXT(__FUNCTION__), regaddr));
result = GSPI_TIMEOUT;
}
/*
p=(PBYTE)regdatPt;
tb=*(p+1);
*(p+1)=*p;
*p=tb;
*/
return result;
}
///
/// ssp_write_register: Write the register from SSP interface
/// Input:
/// hDC - the context returned from SSP_Init
/// regaddr - register addreess
/// regdat - register value to write
/// Output:
/// None
/// Return:
/// 0 - success
/// -1 - failure
// regval = 0x06;
// ssp_write_register((DWORD)pHC, 0x70, ®val);
GSPI_STATUS ssp_write_register(DWORD hDC, WORD regaddr, WORD* regdatPt)
{
GSPI_STATUS result=0;
int i;
for (i=0 ; i<GSPI_MAX_REG_RETRY ; i++) {
result = ssp_write_data_direct(hDC, regdatPt, regaddr, 1);
if (result == GSPI_SUCCESS) {
break;
}
}
if (i == GSPI_MAX_REG_RETRY) {
GSPIMSG(ERRMSG, (L"%s, Write register(%xh) timeout \n", TEXT(__FUNCTION__), regaddr));
result = GSPI_TIMEOUT;
}
return result;
}
///
/// ssp_read_data: Read the data from SSP interface
/// Input:
/// hDC - the context returned from SSP_Init
/// datPt - data buffer
/// size - size of the data buffer
/// Output:
/// none
/// Return:
/// 0 - success
/// -1 - failure
GSPI_STATUS ssp_read_data(DWORD hDC, WORD* datPt, WORD reg, WORD nword)
{
GSPI_STATUS result=0;
int i;
for (i=0 ; i<GSPI_MAX_REG_RETRY ; i++) {
result = ssp_read_data_direct(hDC, datPt, reg, nword, g_spi_dummy_clk_data);
if (result == GSPI_SUCCESS) {
break;
}
}
if (i == GSPI_MAX_REG_RETRY) {
GSPIMSG(1, (L"%s, Read data(%xh) timeout \n", TEXT(__FUNCTION__), nword));
result = GSPI_TIMEOUT;
}
return result;
}
///
/// ssp_write_data: Write the data from SSP interface
/// Input:
/// hDC - the context returned from SSP_Init
/// datPt - data buffer
/// size - size of the data buffer
/// Output:
/// datPt - returned data buffer
/// size - size of the returned data buffer
/// Return:
/// 0 - success
/// -1 - failure
GSPI_STATUS ssp_write_data(DWORD hDC, WORD* datPt, WORD reg, WORD nword)
{
///Note: reg(0x24) = DATA_PORT
GSPI_STATUS result=0;
int i;
for (i=0 ; i<GSPI_MAX_REG_RETRY ; i++) {
///result = ssp_write_data_direct(hDC, datPt, 0x24, size);
result = ssp_write_data_direct(hDC, datPt, reg, nword);
if (result == GSPI_SUCCESS) {
break;
}
}
if (i == GSPI_MAX_REG_RETRY) {
GSPIMSG(1, (L"%s, Read data(%xh) timeout \n", TEXT(__FUNCTION__), nword));
result = GSPI_TIMEOUT;
}
return result;
}
///===========================================
int pxa_read_intstate(DWORD hDC)
{
DWORD resval=0;
return resval;
}
///===========================================
static BOOLEAN dev_ist(PSSP_HARDWARE_CONTEXT pHC)
{
//return TRUE;
#if (USE_DEVIRQ == 0)
if (pHC->DriverShutdown == TRUE) {
return FALSE;
}
/// if (g_fmDnRdy == FALSE) {
///Firmware has not been downloaded. It's impossible to have an interrupt.
/// return FALSE;
/// }
/// If there is a pending intrrupt
//{
//WORD ucHostIntStatus;
///Note: HCR_HOST_INT_STATUS_REGISTER = 0x5c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -