📄 pxa-gspi.c
字号:
///Note: reg(0x24) = DATA_PORT
GSPI_STATUS result;
int i;
///crlo:critical ++
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)hDC;
//GSPIMSG(1, (L"wdat(%xh) \n", nword));
EnterCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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;
}
///crlo:critical ++
LeaveCriticalSection(&pHC->SSPCritFunc);
///crlo:critical --
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, DWORD dwSysIntr)
{
BOOLEAN result = TRUE;
if ((pHC->pGPIORegs->GEDR0 & (1 << SSP_INTR)) == 0) {
GSPIMSG(1, (TEXT("dev_ist(), not our interrupt")));
goto funcfinal;
}
///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);
InterruptDone(dwSysIntr);
}
//Doing the ISR service routine;
if (pHC->isrFunc != NULL) {
pHC->isrFunc(pHC->isrContext);
}
funcfinal:
return result;
}
static BOOLEAN dma_ist(LPVOID param, DWORD dwSysIntr)
{
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("dmaist(): 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;
InterruptDone(dwSysIntr);
}
///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;
}
///
/// intr_init: Initialize the Interrupt
/// Input:
/// pHC - Hard context
/// Output:
/// None
/// Return:
/// 0 - success
/// -1 - fail
static int intr_init(PSSP_HARDWARE_CONTEXT pHC)
{
int result = 0;
///DWORD threadID; // thread ID
ENTERFUNC();
if (pHC == NULL) {
result = -1;
goto funcFinal;
}
set_GPIO_mode(pHC->pGPIORegs, SSP_INTR|SSPIRQ_ATTR); ///INTR
set_GPIO_IRQ_edge(pHC->pGPIORegs, SSP_INTR, SIG_FALLING);
///Initialize the device interrupt info
pHC->DevIntrInfo.irq = IRQ_GPIOXX_2;
pHC->DevIntrInfo.pIstFunc = (MYISTFUNC) dev_ist;
pHC->DevIntrInfo.param = (LPVOID)pHC;
///Initialize the interrupt, IST
setupInterrupt(&pHC->DevIntrInfo);
///Load the ISR
//installISR(&pHC->DevIntrInfo);
funcFinal:
EXITFUNC(result);
return result;
}
///
/// dma_init: Initialize the DMA
/// Input:
/// pHC - Hard context
/// Output:
/// None
/// Return:
/// 0 - success
/// -1 - fail
///PERF_DMA ++
extern NDIS_HANDLE g_NdisAdapterHandle;
///PERF_DMA --
static int dma_init(PSSP_HARDWARE_CONTEXT pHC)
{
int result=0;
DMA_ADAPTER_OBJECT Adapter;
PHYSICAL_ADDRESS PA;
PHYSICAL_ADDRESS DCSRAddr[] = { {DMA_DCSR(DMA_CH_READ), 0},
{DMA_DCSR(DMA_CH_RW), 0}};
DWORD inIoSpace=0; ///I/O Space
BULVERDE_SSP_EXT_REG *phySSPBase = (BULVERDE_SSP_EXT_REG*)(SSPREG_PHY_BASE);
if (pHC == NULL) {
result = -1;
goto errFuncRet;
}
///Allocate the DMA buffers
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
Adapter.InterfaceType = Internal;
Adapter.BusNumber = 0;
///Allocate DMA Descriptor
pHC->read_desc = (DMADescriptorChannelType *) HalAllocateCommonBuffer(&Adapter, sizeof(DMADescriptorChannelType)*2, &PA, FALSE);
if (pHC->read_desc) {
pHC->read_desc_phys_addr = (DMADescriptorChannelType *) PA.LowPart;
}
pHC->write_desc = (DMADescriptorChannelType *) HalAllocateCommonBuffer(&Adapter, sizeof(DMADescriptorChannelType)*2, &PA, FALSE);
if (pHC->write_desc) {
pHC->write_desc_phys_addr = (DMADescriptorChannelType *) PA.LowPart;
}
pHC->rw_desc = (DMADescriptorChannelType *) HalAllocateCommonBuffer(&Adapter, sizeof(DMADescriptorChannelType)*2, &PA, FALSE);
if (pHC->rw_desc) {
pHC->rw_desc_phys_addr = (DMADescriptorChannelType *) PA.LowPart;
}
///Allocate I/O buffers
///PERF_DMA ++
pHC->iodata = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iodata) {
pHC->phys_addr = (PBYTE)PA.LowPart;
}
/*{
NDIS_STATUS ndisstatus;
ndisstatus = NdisMAllocateMapRegisters(g_NdisAdapterHandle, )
pHC->iodata = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iodata) {
pHC->phys_addr = (PBYTE)PA.LowPart;
}
}*/
///PERF_DMA --
pHC->iorw = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iorw) {
pHC->phys_addr_rw = (PBYTE)PA.LowPart;
}
///==============================================================
///Initialize the DMA channel parameters
pHC->DMAParam[RDDMA_PARAM].pDMARegs = pHC->pDMARegs;
pHC->DMAParam[RDDMA_PARAM].channel = DMA_CH_READ;
if(!(pHC->DMAParam[RDDMA_PARAM].dmaWaitObj = CreateEvent( NULL, FALSE, FALSE,NULL))) {
GSPIMSG(ERRMSG, (TEXT("Init rddmaWaitObj, CreateEvent FAILED")));
result = -1;
goto errFuncRet;
}
pHC->DMAParam[WTDMA_PARAM].pDMARegs = pHC->pDMARegs;
pHC->DMAParam[WTDMA_PARAM].channel = DMA_CH_RW;
if(!(pHC->DMAParam[WTDMA_PARAM].dmaWaitObj = CreateEvent( NULL, FALSE, FALSE,NULL))) {
GSPIMSG(ERRMSG, (TEXT("Init wtdmaWaitObj, CreateEvent FAILED")));
result = -1;
goto errFuncRet;
}
pHC->pDMARegs->drcmr[DMA_CHMAP_SSP_RX] = pHC->DMAParam[RDDMA_PARAM].channel | DRCMR_MAPVAL;
pHC->pDMARegs->drcmr[DMA_CHMAP_SSP_TX] = pHC->DMAParam[WTDMA_PARAM].channel | DRCMR_MAPVAL;
///==============================================================
/// Request the DMA IRQ
///
///Configure the DMA descriptor
{
union DMACmdReg CmdBuff;
volatile DMADescriptorChannelType* descPt;
// set CMD values with bit fields.
//
CmdBuff.DcmdReg.len = 0; // length of the memory buffer
CmdBuff.DcmdReg.width = 0x2; // binary 10 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x1; // binary 01
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 0; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 0; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 1; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 1; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 0; // 1 means increment the source address (since it's a peripheral)
descPt = pHC->read_desc;
descPt->ddadr = (UINT32)(pHC->read_desc_phys_addr + 1);
descPt->dsadr = (UINT32)(&(phySSPBase->base.ssdr));
descPt->dtadr = (UINT32) (pHC->phys_addr);
descPt->dcmd = CmdBuff.DcmdDword; // size and cmd values of the RcvA buffer
///====================================================================
// set CMD values with bit fields.
//
CmdBuff.DcmdReg.len = 0; // length of the memory buffer
CmdBuff.DcmdReg.width = 0x2; // binary 10 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x1; // binary 01
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 0; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 1; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 0; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 0; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 1; // 1 means increment the source address (since it's a peripheral)
descPt = pHC->write_desc;
///descPt->ddadr = (UINT32)(pHC->write_desc_phys_addr + sizeof(DMADescriptorChannelType));
descPt->ddadr = (UINT32)(pHC->write_desc_phys_addr + 1);
descPt->dsadr = (UINT32) (pHC->phys_addr);
///descPt->dtadr = (UINT32)(&(pHC->pSSPRegs->base.ssdr));
descPt->dtadr = (UINT32)(&(phySSPBase->base.ssdr));
descPt->dcmd = CmdBuff.DcmdDword; // size and cmd values of the RcvA buffer
///====================================================================
// set CMD values with bit fields.
//
CmdBuff.DcmdReg.len = 0; // length of the memory buffer
CmdBuff.DcmdReg.width = 0x2; // binary 10 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x1; // binary 01
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 0; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 1; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 0; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 0; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 1; // 1 means increment the source address (since it's a peripheral)
descPt = pHC->rw_desc;
descPt->ddadr = (UINT32)(pHC->rw_desc_phys_addr + 1);
descPt->dsadr = (UINT32) (pHC->phys_addr_rw);
descPt->dtadr = (UINT32)(&(phySSPBase->base.ssdr));
descPt->dcmd = CmdBuff.DcmdDword; // size and cmd values of the RcvA buffer
}
memset(pHC->iorw, 0xff, sizeof(PXA_SSP_IODATA_SIZE));
return result;
errFuncRet:
return result;
}
///
/// ssp_init_hw: Initialize the H/W
/// Input:
/// pHC - Hard context
/// Output:
/// None
/// Return:
/// None
void ssp_init_hw(PSSP_HARDWARE_CONTEXT pHC)
{
PHYSICAL_ADDRESS Bulverde_GPIO_Base = {BULVERDE_BASE_REG_PA_GPIO};
PHYSICAL_ADDRESS Bulverde_SSP_Base = {SSPREG_PHY_BASE};
PHYSICAL_ADDRESS Bulverde_CLKMGR_Base = {BULVERDE_BASE_REG_PA_CLKMGR};
PHYSICAL_ADDRESS Bulverde_DMA_Base = {BULVERDE_BASE_REG_PA_DMAC};
PHYSICAL_ADDRESS Bulverde_PA_OTS_Base = {BULVERDE_BASE_REG_PA_OST};
PHYSICAL_ADDRESS Bulverde_ICR_Base = {BULVERDE_BASE_REG_PA_INTC};
GSPIMSG(ERRMSG, (TEXT("===<NO DMA interrupt>===\n")));
pHC->pGPIORegs = (BULVERDE_GPIO_REG*)MmMapIoSpace(Bulverde_GPIO_Base, sizeof(BULVERDE_GPIO_REG), FALSE);
if (!pHC->pGPIORegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating GPIO register\n")));
goto funcFinal;
}
pHC->pSSPRegs = (BULVERDE_SSP_EXT_REG*)MmMapIoSpace(Bulverde_SSP_Base, sizeof(BULVERDE_SSP_EXT_REG), FALSE);
if (!pHC->pSSPRegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating SSP register\n")));
goto funcFinal;
}
pHC->pCLKRegs = (BULVERDE_CLKMGR_REG*)MmMapIoSpace(Bulverde_CLKMGR_Base, sizeof(BULVERDE_CLKMGR_REG), FALSE);
if (!pHC->pCLKRegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating CLK register\n")));
goto funcFinal;
}
pHC->pDMARegs = (BULVERDE_DMA_REG*)MmMapIoSpace(Bulverde_DMA_Base, sizeof(BULVERDE_DMA_REG), FALSE);
if (!pHC->pDMARegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating DMA register\n")));
goto funcFinal;
}
pHC->pOSTRegs = (BULVERDE_OST_REG*)MmMapIoSpace(Bulverde_PA_OTS_Base, sizeof(BULVERDE_OST_REG), FALSE);
if (!pHC->pOSTRegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating OST register\n")));
goto funcFinal;
}
///
///Configure the GPIO
///
set_GPIO_mode(pHC->pGPIORegs, SSP_SCLK|SSPSCLK_ATTR); ///SCLK
set_GPIO_mode(pHC->pGPIORegs, SSP_SFRM|SSPSFRM_ATTR); ///SFRM
set_GPIO_mode(pHC->pGPIORegs, SSP_TX|SSPTX_ATTR); ///TX
set_GPIO_mode(pHC->pGPIORegs, SSP_RX|SSPRX_ATTR); ///RX
set_GPIO_signal(pHC->pGPIORegs, SSP_SFRM, SIG_UP);
pHC->pSSPRegs->base.sscr0 = 0;
pHC->pSSPRegs->base.sscr1 = 0;
///udelay(pHC->pOSTRegs, 100);
NdisMSleep(10);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -