📄 pxa-gspi.c
字号:
} else if (accnbyte > nbyte) {
GSPIMSG(ERRMSG|PERF_MSG, (TEXT("Invalid fragment, (exp, acc)=(%d, %d).\n"), nbyte, accnbyte));
break;
}
}
///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;
udelay(pHC->pOSTRegs, 10);
GSPIMSG(1, (TEXT("Add one more WORD to fit 32-bit boundary\n"), accnbyte));
}
}
set_GPIO_signal(pHC->pGPIORegs, SSP_SFRM,SIG_UP);
///crlo:no2udelay ++
///udelay(pHC->pOSTRegs, 2);
///crlo:no2udelay --
LeaveCriticalSection(&pHC->SSPCrit);
funcLeave:
EXITFUNC(result);
return result;
}
static GSPI_STATUS setup_read_dma(PSSP_HARDWARE_CONTEXT pHC, int n)
{
volatile DMADescriptorChannelType *rddesc = pHC->read_desc;
volatile DMADescriptorChannelType *wtdesc = pHC->rw_desc;
MYDMAPARAM *pwtDmaParam = &pHC->DMAParam[WTDMA_PARAM];
MYDMAPARAM *prdDmaParam = &pHC->DMAParam[RDDMA_PARAM];
GSPI_STATUS result = GSPI_SUCCESS;
rddesc->ddadr |= DDADR_STOP;
rddesc->dcmd &= ~(DCMD_LENGTH);
rddesc->dcmd |= n;
if (n > PXA_SSP_IODATA_SIZE) {
GSPIMSG(ERRMSG, (TEXT("Requested length is too large (limit, req) = (%d, %xh)\n"), PXA_SSP_IODATA_SIZE, n));
result = GSPI_INVALIDARGS;
goto funcFinal;
}
wtdesc->ddadr |= DDADR_STOP;
wtdesc->dcmd &= ~(DCMD_LENGTH);
///CRLo: Not enabling the IRQ for the dummy-write. We only care about the read in here
/// wtdesc->dcmd |= DCMD_ENDIRQEN | n;
///ResetEvent(pwtDmaParam->dmaWaitObj);
wtdesc->dcmd |= n;
pHC->pDMARegs->ddg[pwtDmaParam->channel].ddadr = (UINT32) pHC->rw_desc_phys_addr;
pHC->pDMARegs->ddg[prdDmaParam->channel].ddadr = (UINT32) pHC->read_desc_phys_addr;
pHC->pDMARegs->dcsr[pwtDmaParam->channel] |= DCSR_RUN; // set the RUN bit
pHC->pDMARegs->dcsr[prdDmaParam->channel] |= DCSR_RUN; // set the RUN bit
///Wait here until it's done
///crlo:dmawait ++
{
int i;
volatile DWORD dcsr;
for (i=0 ; i<MAX_WAITus ; i++) {
dcsr = pHC->pDMARegs->dcsr[prdDmaParam->channel];
if (dcsr & DCSR_STOPSTATE) {
break;
}
udelay(pHC->pOSTRegs, 1);
}
if (i == MAX_WAITus) {
/// GSPIMSG(ERRMSG, (TEXT("Rd-DMA timeout (%d), lp: %d\n"), n, i));
}
if (n > 6) {
///We are reading the data, not registers
udelay(pHC->pOSTRegs, 5); ///Trial value
}
}
///crlo:dmawait --
/*
///crlo-2k60704: Old implementation
///Wait here until it's done
{
int lp;
volatile DWORD dcsr;
for (lp=0 ; lp<MAX_WAITus ; lp++) {
///dcsr = pHC->pDMARegs->dcsr[DMA_CH_READ];
dcsr = pHC->pDMARegs->dcsr[prdDmaParam->channel];
///if (dcsr & (DCSR_EORINT|DCSR_STOPSTATE)) {
if (dcsr & (DCSR_STOPSTATE)) {
///if ((n % 4) == 0) {
/// GSPIMSG(1, (TEXT("rd(%d), (lp, dcsr)= (%d, %xh)\n"), n, lp, dcsr));
///}
break;
}
udelay(pHC->pOSTRegs, 1);
///NdisMSleep(1);
///for (a=0 ; a<10 ; a++) ;
}
if (lp == MAX_WAITus) {
GSPIMSG(ERRMSG, (TEXT("Rd-DMA(%d), (lp, dcsr) = (%d, %xh)\n"), n, lp, dcsr));
result = GSPI_TIMEOUT;
///} else {
/// GSPIMSG(1, (TEXT("Rd-DMA ok, dcsr= %xh\n"), dcsr));
}
///Add one more delay at the end. Otherwise, the firmware download will failed.
/// (Don't know why)
udelay(pHC->pOSTRegs, 50); ///trial value (50us);
///NdisMSleep(1);
}
*/
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;
int accnbyte; ///Accumulated length (0 - nbyte)
int fragnbyte; ///length of each fragment
BOOLEAN isfrag = FALSE;
///GSPIMSG(1, (TEXT("r(%d)\n"), nbyte));
ENTERFUNC();
if (hDC == 0) {
result = GSPI_INVALIDARGS;
goto funcLeave;
}
pHC = (PSSP_HARDWARE_CONTEXT)hDC;
EnterCriticalSection(&pHC->SSPCrit);
///Reset the RX FIFO
pHC->pSSPRegs->base.sscr0 &= ~SSCR0_SSE;
pHC->pSSPRegs->base.sscr0 |= SSCR0_SSE;
///2 more bytes for register address
/// [Address][dummy_clk][data...]
///n = 2 + dummy_clk*2 + n*2;
set_GPIO_signal(pHC->pGPIORegs, SSP_SFRM,SIG_DOWN);
///================================
///DMA mode
///crlo:onerddma ++
{
BOOLEAN needAddr = TRUE;
///Write the register address
///WORD *iodatPt = (WORD*)pHC->iodata;
WORD *iodatPt = (WORD*)pHC->iorw;
*iodatPt = reg;
///result = setup_write_dma(pHC, (1+dummy_clk)*2);
///result = setup_read_dma(pHC, (1+dummy_clk)*2);
///==============================================
accnbyte = 0;
while (1) {
fragnbyte = nbyte - accnbyte;
if (fragnbyte> PXA_SSP_IODATA_SIZE) {
GSPIMSG(RX_FRAG, (TEXT("Fragment Rx Data (now, exp)=(%d, %d)\n"), (nbyte - accnbyte), nbyte));
if (needAddr == TRUE) {
/// We need an extra space for the address & dummy_clk
fragnbyte = PXA_SSP_IODATA_SIZE - (1+dummy_clk)*2;
} else {
///The address & dummy_clk has been sent in the 1st segment
fragnbyte = PXA_SSP_IODATA_SIZE;
}
isfrag = TRUE;
}
if (needAddr == TRUE) {
*iodatPt = reg;
result = setup_read_dma(pHC, (1+dummy_clk)*2 + fragnbyte);
if (result != GSPI_SUCCESS) {
GSPIMSG(ERRMSG, (TEXT("%s, Read data failed...\n"), TEXT(__FUNCTION__)));
break;
}
memcpy(data, &pHC->iodata[(1+dummy_clk)*2], fragnbyte);
needAddr = FALSE;
} else {
result = setup_read_dma(pHC, fragnbyte);
if (result != GSPI_SUCCESS) {
GSPIMSG(ERRMSG, (TEXT("%s, Read data failed...\n"), TEXT(__FUNCTION__)));
break;
}
memcpy(data, pHC->iodata, fragnbyte);
}
accnbyte += fragnbyte;
data += (fragnbyte/2); ///type of data is WORD
if (accnbyte == nbyte) {
if (isfrag == TRUE) {
GSPIMSG(RX_FRAG, (TEXT("Cont. reading data. (now, exp)=(%d, %d), complete!\n"), accnbyte, nbyte));
}
break;
} else if (accnbyte > nbyte){
GSPIMSG(ERRMSG, (TEXT("Invalid Rd Length, (exp, acc)=(%d, %d)\n"), nbyte, accnbyte));
} else {
if (isfrag == TRUE) {
GSPIMSG(RX_FRAG, (TEXT("Cont. reading data. (now, exp)=(%d, %d)\n"), accnbyte, nbyte));
}
}
}
}
/// Old Implementation
/*
{
///Write the register address
///WORD *iodatPt = (WORD*)pHC->iodata;
WORD *iodatPt = (WORD*)pHC->iorw;
*iodatPt = reg;
///result = setup_write_dma(pHC, (1+dummy_clk)*2);
result = setup_read_dma(pHC, (1+dummy_clk)*2);
if (result != GSPI_SUCCESS) {
GSPIMSG(ERRMSG, (TEXT("Fail to push reg+dummy_clk[%d]...\n"), dummy_clk));
}
}
///==============================================
accnbyte = 0;
while (1) {
fragnbyte = nbyte - accnbyte;
if (fragnbyte> PXA_SSP_IODATA_SIZE) {
GSPIMSG(TX_FRAG|PERF_MSG, (TEXT("Fragment Rx Data (now, exp)=(%d, %d)\n"), (nbyte - accnbyte), nbyte));
fragnbyte = PXA_SSP_IODATA_SIZE;
isfrag = TRUE;
}
result = setup_read_dma(pHC, fragnbyte);
if (result != GSPI_SUCCESS) {
GSPIMSG(ERRMSG, (TEXT("%s, Read data failed...\n"), TEXT(__FUNCTION__)));
break;
}
///} while ((!(pHC->pDMARegs->dcsr[pHC->DMAParam[RDDMA_PARAM].channel] & DCSR_REQPEND) || retry) && --timeout);
memcpy(data, pHC->iodata, fragnbyte);
accnbyte += fragnbyte;
data += (fragnbyte/2); ///type of data is WORD
if (accnbyte == nbyte) {
if (isfrag == TRUE) {
GSPIMSG(RX_FRAG|PERF_MSG, (TEXT("Cont. reading data. (now, exp)=(%d, %d), complete!\n"), accnbyte, nbyte));
}
break;
} else if (accnbyte > nbyte){
GSPIMSG(ERRMSG, (TEXT("Invalid Rd Length, (exp, acc)=(%d, %d)\n"), nbyte, accnbyte));
} else {
if (isfrag == TRUE) {
GSPIMSG(RX_FRAG, (TEXT("Cont. reading data. (now, exp)=(%d, %d)\n"), accnbyte, nbyte));
}
}
}
*/
///crlo:onerddma --
set_GPIO_signal(pHC->pGPIORegs, SSP_SFRM,SIG_UP);
///crlo:no2udelay ++
///udelay(pHC->pOSTRegs, 2);
///crlo:no2udelay --
///Comment it out temporally to make compiler happy
///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;
int i;
///crlo:critical ++
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)hDC;
EnterCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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(ERRMSG, (L"%s, Read register(%xh) timeout \n", TEXT(__FUNCTION__), regaddr));
result = GSPI_TIMEOUT;
}
///crlo:critical ++
LeaveCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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
GSPI_STATUS ssp_write_register(DWORD hDC, WORD regaddr, WORD* regdatPt)
{
GSPI_STATUS result;
int i;
///crlo:critical ++
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)hDC;
EnterCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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;
}
///crlo:critical ++
LeaveCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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;
int i;
///crlo:critical ++
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)hDC;
///GSPIMSG(1, (L"rdat(%d) \n", nword));
EnterCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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(ERRMSG, (L"%s, Read data(%xh) timeout \n", TEXT(__FUNCTION__), nword));
result = GSPI_TIMEOUT;
}
///crlo:critical ++
LeaveCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -