📄 pxa-gspi.c
字号:
DWORD dwRegVal;
DWORD dwDataSize;
DWORD dwType;
// Get the DMA Information
dwDataSize = sizeof(DWORD);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_CHANNEL_TEXT,
NULL, &dwType, (LPBYTE)&dwRegVal, &dwDataSize ) &&
REG_DWORD == dwType )
{
if( dwRegVal > 31 )
{
pController->dwDmaChannel = 0xffffffff;
return FALSE;
}
pController->dwDmaChannel = dwRegVal;
// get the DMA IRQ
dwDataSize = sizeof(DWORD);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_IRQ_TEXT,
NULL, &dwType, (LPBYTE)&dwRegVal, &dwDataSize ) &&
REG_DWORD == dwType )
{
pController->dwDmaIRQ = dwRegVal;
}
else
{
pController->dwDmaIRQ = IRQ_DMAC;
}
// get the DMA buffer size
dwDataSize = sizeof(DWORD);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_BUFFER_SIZE_TEXT,
NULL, &dwType, (LPBYTE)&dwRegVal, &dwDataSize ) &&
REG_DWORD == dwType )
{
pController->dwDmaBufferSize = dwRegVal;
}
else
{
pController->dwDmaBufferSize = 0;
}
// get the DMA SysInt
dwDataSize = sizeof(DWORD);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_SYSINT_TEXT,
NULL, &dwType, (LPBYTE)&dwRegVal, &dwDataSize ) &&
REG_DWORD == dwType )
{
pController->dwDmaSysIntr = dwRegVal;
}
else
{
pController->dwDmaSysIntr = SYSINTR_UNDEFINED;
}
dwDataSize = sizeof(pController->wszDmaIsrDll);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_ISR_DLL_TEXT,
NULL, &dwType, (LPBYTE)pController->wszDmaIsrDll, &dwDataSize ) &&
REG_SZ == dwType )
{
}
else
{
pController->wszDmaIsrDll[0] = 0;
}
dwDataSize = sizeof(pController->wszDmaIsrHandler);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_ISR_HANDLER_TEXT,
NULL, &dwType, (LPBYTE)pController->wszDmaIsrHandler, &dwDataSize ) &&
REG_SZ == dwType )
{
}
else
{
pController->wszDmaIsrHandler[0] = 0;
}
dwDataSize = sizeof(DWORD);
if( ERROR_SUCCESS == RegQueryValueEx( hKeyDevice, CONTROLLER_DMA_IST_PRI_TEXT,
NULL, &dwType, (LPBYTE)&dwRegVal, &dwDataSize ) &&
REG_DWORD == dwType )
{
pController->DmaIstThreadPriority = dwRegVal;
}
else
{
pController->DmaIstThreadPriority = SDH_DMA_CONTROLLER_PRIORITY;
}
}
else
{
pController->dwDmaChannel = 0xffffffff;
pController->wszDmaIsrDll[0] = 0;
pController->wszDmaIsrHandler[0] = 0;
}
return;
}
#endif ///0
#if (USE_DEVIRQ == 0)
///crlo: A problem while using a polling mode:
///Description: there is a delay if no interrupt.
/// However, NdisMSleep has overhead that 1ns is still too big
///=> the performance of 1 tx thread in Chariot could be very bad
/// Note: If putting more threads, we may not see this problem
/// because there may always be interrupts
static ULONG dev_isrpoll_func(PSSP_HARDWARE_CONTEXT pHC)
{
DWORD dwStatus;
MYINTRINFO* pMyIntrInfo = &pHC->DevIntrInfo;
const DWORD EDGEREG = (0x00000001 << SSP_INTR);
DWORD intrval;
///Wait until we get the 1st edge detection.
while (((pHC->pGPIORegs->GEDR0 & EDGEREG) == 0) &&
(pMyIntrInfo->quitIST == FALSE)) {
dwStatus = WaitForSingleObject(pMyIntrInfo->hIntrEvent, 1);
}
while (pMyIntrInfo->quitIST == FALSE) {
/*if (pHC->pGPIORegs->GEDR0 & EDGEREG) {
pMyIntrInfo->pIstFunc(pMyIntrInfo->param);
}*/
intrval = pHC->pGPIORegs->GPLR0 & EDGEREG;
if (intrval == 0) {
pMyIntrInfo->pIstFunc(pMyIntrInfo->param);
} else {
/// intrval = pHC->pGPIORegs->GPLR0 & EDGEREG;
/// if (intrval != 0) {
///dwStatus = WaitForSingleObject(pMyIntrInfo->hIntrEvent, 1);
NdisMSleep(1);
}
}
SetEvent(pMyIntrInfo->waitobj);
return TRUE;
}
#endif ///USE_DEVIRQ
///
/// 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;
#if (USE_DEVIRQ == 1)
///Initialize the interrupt, IST
setupInterrupt(&pHC->DevIntrInfo);
///Load the ISR
//installISR(&pHC->DevIntrInfo);
#else
{
MYINTRINFO* pMyIntrInfo = &pHC->DevIntrInfo;
DWORD threadID;
if(!(pMyIntrInfo->hIntrEvent = CreateEvent( NULL, FALSE, FALSE, NULL))) {
GSPIMSG(ERRMSG, (TEXT("CreateEvent(DevIntrInfo.hIntrEvent) FAILED!\n")));
goto funcFinal;
}
pMyIntrInfo->hISTHandle = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
dev_isrpoll_func,
pHC,
0,
&threadID);
if (pMyIntrInfo->hISTHandle == NULL) {
GSPIMSG(ERRMSG, (TEXT("hSSPInterThread Create FAILED!\n")));
goto funcFinal;
}
CeSetThreadPriority(pMyIntrInfo->hISTHandle, DEFAULT_IST_PRIORITY);
}
#endif ///USE_DEVIRQ
funcFinal:
EXITFUNC(result);
return result;
}
///
/// dma_init: Initialize the DMA
/// Input:
/// pHC - Hard context
/// Output:
/// None
/// Return:
/// 0 - success
/// -1 - fail
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
///DWORD threadID; // thread ID
#if (USE_DMA == 1)
BULVERDE_SSP_EXT_REG *phySSPBase = (BULVERDE_SSP_EXT_REG*)(SSPREG_PHY_BASE);
#endif ///USE_DMA
if (pHC == NULL) {
result = -1;
goto errFuncRet;
}
///Allocate the DMA buffers
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
Adapter.InterfaceType = Internal;
Adapter.BusNumber = 0;
#if (USE_DMA == 1)
///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;
}
#endif ///(USE_DMA == 1)
///Allocate I/O buffers
pHC->iodata = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iodata) {
pHC->phys_addr = (PBYTE)PA.LowPart;
}
pHC->iorw = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iorw) {
pHC->phys_addr_rw = (PBYTE)PA.LowPart;
}
///#if (USE_DMA == 1)
///Get the DMA channel
/*{
DWORD dwTmpChannel;
///Request the DMA Channels => none
pHC->chan = pHC->chanrw = 0xffffffff;
if (XllpDmacAllocChannel((P_XLLP_DMAC_T) pHC->pDMARegs,
pHC->chan, ///requested channel number
(P_XLLP_DMAC_CHANNEL_T)&dwTmpChannel, ///output channel number
XLLP_DMAC_CHANNEL_PRIORITY_MEDIUM,
XLLP_DMAC_SSP_RX) != XLLP_STATUS_SUCCESS) {
GSPIMSG(1, (TEXT("Error obtaining DMA Rx Channel value!\n")));
pHC->dwDmaSysIntr = SYSINTR_UNDEFINED;
goto funcFinal;
}
pHC->chan = dwTmpChannel;
if (XllpDmacAllocChannel((P_XLLP_DMAC_T) pHC->pDMARegs,
pHC->chanrw, ///requested channel number
(P_XLLP_DMAC_CHANNEL_T)&dwTmpChannel, ///output channel number
XLLP_DMAC_CHANNEL_PRIORITY_MEDIUM,
XLLP_DMAC_SSP_RX) != XLLP_STATUS_SUCCESS) {
GSPIMSG(1, (TEXT("Error obtaining DMA Rx Channel value!\n")));
pHC->dwDmaSysIntr = SYSINTR_UNDEFINED;
goto funcFinal;
}
pHC->chanrw = dwTmpChannel;
}*/
///==============================================================
///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
#if (USE_DMA == 1) && (USE_DMAIRQ == 1)
pHC->hBusAcceHND = CreateBusAccessHandle( pg_szActiveKey );
{
int i;
for (i=0 ; i<MAXDMA_PARAM ; i++) {
pHC->DMAIntrInfo[i].irq = IRQ_DMAC;
pHC->DMAIntrInfo[i].pIstFunc = (MYISTFUNC) dma_ist;
pHC->DMAIntrInfo[i].param = (LPVOID)&pHC->DMAParam[i];
pHC->DMAIntrInfo[i].IntrMask = 0x04;
if (!BusTransBusAddrToStatic(pHC->hBusAcceHND, Internal, 0, DCSRAddr[i], sizeof(DWORD), &inIoSpace, &pHC->DMAIntrInfo[i].IntrRgPhysAddr)) {
GSPIMSG(ERRMSG, (TEXT("installISR: Failed TransBusAddrToStatic - (read)\r\n")));
}
///RETAILMSG(1, (TEXT("installISR: PhysAddr: %xh\r\n"), pHC->DMAIntrInfo[i].IntrRgPhysAddr));
///Initialize the interrupt, IST
setupInterrupt(&pHC->DMAIntrInfo[i]);
///Load the ISR
installISR(&pHC->DMAIntrInfo[i]);
}
}
#endif ///USE_DMAIRQ
///#endif ///USE_DMA
#if (USE_DMA == 1)
///
///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
}
#endif ///(USE_DMA == 1)
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};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -