📄 pxa-gspi.c
字号:
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
#if (USE_DMAIRQ == 1)
dmaresult = WaitForSingleObject(prdDmaParam->dmaWaitObj, (MAX_WAITus/1000));
if (dmaresult == WAIT_TIMEOUT) {
GSPIMSG(ERRMSG, (TEXT("Rd-DMA timeout (%d)\n"), n));
result = GSPI_TIMEOUT;
goto funcFinal;
}
#else ///USE_DMAIRQ
///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);
}
#endif ///USE_DMAIRQ
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;
#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("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);
///================================
#if (USE_DMA == 1)
///DMA mode
{
///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) {
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, (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));
}
}
}
#else
///CPU mode
{
int i;
WORD tmpval;
///Write the register address
///GSPIMSG(1, (TEXT("Writing reg-addreess\n")));
pHC->pSSPRegs->base.ssdr = reg;
udelay(pHC->pOSTRegs, 1);
tmpval = pHC->pSSPRegs->base.ssdr;
udelay(pHC->pOSTRegs, 1);
///================================
///Write Dummy clock
///GSPIMSG(1, (TEXT("Dummy-clk(%d)\n"), dummy_clk));
for (i=0 ; i<dummy_clk ; i++) {
pHC->pSSPRegs->base.ssdr = 0; ///dummy_write
udelay(pHC->pOSTRegs, 1);
tmpval = pHC->pSSPRegs->base.ssdr;
udelay(pHC->pOSTRegs, 1);
}
} ///================================
{
PWORD dat = (PWORD)data;
///================================
/// Write the dummy_write & fetch the data
///GSPIMSG(1, (TEXT("Reading datas(%d)WORD\n"), nword));
for (i=0 ; i<nword ; i++) {
pHC->pSSPRegs->base.ssdr = 0; ///dummy_write
udelay(pHC->pOSTRegs, 1);
*dat = pHC->pSSPRegs->base.ssdr;
udelay(pHC->pOSTRegs, 1);
dat ++;
}
///GSPIMSG(1, (TEXT("Reading data done!\n")));
}
#endif ///USE_DMA
set_GPIO_signal(pHC->pGPIORegs, SSP_SFRM,SIG_UP);
udelay(pHC->pOSTRegs, 2);
///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;
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;
}
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;
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;
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(ERRMSG, (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;
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(ERRMSG, (L"%s, Read data(%xh) timeout \n", TEXT(__FUNCTION__), nword));
result = GSPI_TIMEOUT;
}
return result;
}
///===========================================
int pxa_read_intstate(DWORD hDC)
{
PSSP_HARDWARE_CONTEXT pHC;
DWORD gplr, gedr;
DWORD resval;
if (hDC == 0) {
resval = 0;
goto funcfinal;
}
pHC = (PSSP_HARDWARE_CONTEXT) hDC;
gedr = pHC->pGPIORegs->GEDR0;
gplr = pHC->pGPIORegs->GPLR0;
GSPIMSG(1, (L"(GPLR0, GEDR): (%08xh, %08xh) \n", gplr, gedr));
resval = (gplr >> SSP_INTR)&1;
funcfinal:
return resval;
}
///===========================================
static BOOLEAN dev_ist(PSSP_HARDWARE_CONTEXT pHC)
{
#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
ssp_read_register((DWORD)pHC, 0x5c, &ucHostIntStatus);
if (ucHostIntStatus == 0x00) {
return FALSE;
}
}*/
#endif ///USE_DEVIRQ
/*{
DWORD gedr = pHC->pGPIORegs->GEDR0;
if ((gedr & (1 << SSP_INTR)) == 0) {
GSPIMSG(1, (TEXT("GEDR: %x"), gedr));
}
}*/
////crlo:BSP patch ++
///#if (USE_DEVIRQ == 1)
///A patch for the MAINSTONE BSP
///We use GPIO_22 as our interrupt source. We need to clear the GEDR (GPIO Edge Detect Status Register)
/// manually. Otherwise, the BSP will think the interrupt has not been served & come to IST continually
{
pHC->pGPIORegs->GEDR0 = (1 << SSP_INTR);
}
///#endif ///USE_DEVIRQ
////crlo:BSP patch --
//Doing the ISR service routine;
if (pHC->isrFunc != NULL) {
pHC->isrFunc(pHC->isrContext);
}
return TRUE;
}
static BOOLEAN dma_ist(LPVOID param)
{
BOOLEAN result = FALSE;
MYDMAPARAM *pDmaParam = (MYDMAPARAM *)param;
volatile DWORD dcsr;
///GSPIMSG(1, (TEXT("Enter %s"), TEXT(__FUNCTION__)));
dcsr = pDmaParam->pDMARegs->dcsr[pDmaParam->channel];
///GSPIMSG(1, (TEXT("ch:%d dcsr= %xh"), pDmaParam->channel, dcsr));
//dcsr &= ~DCSR_STOPIRQEN;
//dcsr |= DCSR_ENDINTR;
///pDmaParam->pDMARegs->dcsr[pDmaParam->channel] = dcsr;
GSPIMSG(DMA_MSG, (TEXT("Write dcsr= %xh"), dcsr));
///if ((dcsr & DCSR_RUN) && (dcsr & DCSR_STOPSTATE)) {
if (dcsr & (DCSR_BUSERR|DCSR_ENDINTR)) {
dcsr &= ~DCSR_STOPIRQEN;
dcsr |= DCSR_ENDINTR;
pDmaParam->pDMARegs->dcsr[pDmaParam->channel] = dcsr;
dcsr = pDmaParam->pDMARegs->dcsr[pDmaParam->channel];
GSPIMSG(DMA_MSG, (TEXT("=>after clr: ch:%d dcsr= %xh"), pDmaParam->channel, dcsr));
SetEvent(pDmaParam->dmaWaitObj);
result = TRUE;
}
///Bus Error
if (dcsr & DCSR_BUSERR) {
///dcsr |= DCSR_BUSERR;
GSPIMSG(ERRMSG, (TEXT("%s => DMA Bus Error"), TEXT(__FUNCTION__)));
goto funcFinal;
}
///Data transfer completed
if (dcsr & DCSR_ENDINTR) {
GSPIMSG(PROGFLOW, (TEXT("%s => DMA Complete"), TEXT(__FUNCTION__)));
goto funcFinal;
}
funcFinal:
return result;
}
#if 0
#define CONTROLLER_DMA_ISR_DLL_TEXT _T("DMAIsrDll")
#define CONTROLLER_DMA_ISR_HANDLER_TEXT _T("DMAIsrHandler")
#define CONTROLLER_DMA_IRQ_TEXT _T("DMAIRQ")
#define CONTROLLER_DMA_SYSINT_TEXT _T("DMASysIntr")
#define CONTROLLER_DMA_CHANNEL_TEXT _T("DMAChannel")
#define CONTROLLER_DMA_IST_PRI_TEXT _T("DMAISTPriority")
#define CONTROLLER_DMA_BUFFER_SIZE_TEXT _T("DMABufferSize")
void LoadRegistrySettings(HKEY hKeyDevice, PSSP_HARDWARE_CONTEXT pController)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -