📄 pxa-gspi.c
字号:
//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;
//GSPIMSG(1, (L"DMA IST routine\n"));
SetEvent(pDmaParam->dmaWaitObj);
result = TRUE;
/*
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)
{
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;
}
// Setup EINT11 (GPG3)
pHC->pGPIORegs->GPGCON &= ~(0x3 << 6); // Clear GPG3
pHC->pGPIORegs->GPGCON |= (0x2 << 6); // Set GPG3 to EINT11 for SPI interrupt
pHC->pGPIORegs->EXTINT1 &= ~(0x7 << 12); // Clear EINT11
pHC->pGPIORegs->EXTINT1 |= (0x2 << 12); // fallig edge triggered for EINT11
pHC->pGPIORegs ->GPGUP&=~(0x0008);
// pHC->pGPIORegs ->GPGUP|=0x0008;
// pHC->pGPIORegs->EINTMASK &= ~(0x1 << 11); // enable interrupt for EINT11
//pHC->DevIntrInfo.irq = IRQ_EINT8_23;
pHC->DevIntrInfo.irq = IRQ_EINT11;
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
/*
// 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;
DWORD inIoSpace=0; ///I/O Space
#if (USE_DMA == 1)
//PHYSICAL_ADDRESS DCSRAddr[] = { {DMA_DCSR(DMA_CH_READ), 0},
// {DMA_DCSR(DMA_CH_RW), 0}};
PHYSICAL_ADDRESS DCSRAddr[] = { {0x4B000054, 0},
{0x0, 0}};
#endif
pHC->pIntRegs->INTMSK&= ~(0x1<<18);//DMA1 service available
//DMA init
///Allocate the DMA buffers
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
Adapter.InterfaceType = Internal;
Adapter.BusNumber = 0;
///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)
/*
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[RWDMA_PARAM].pDMARegs = pHC->pDMARegs;
pHC->DMAParam[RWDMA_PARAM].channel = DMA_CH_RW;
if(!(pHC->DMAParam[RWDMA_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;
#endif
///==============================================================
/// 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_DMA1;
pHC->DMAIntrInfo[i].pIstFunc = (MYISTFUNC) dma_ist;
pHC->DMAIntrInfo[i].param = (LPVOID)&pHC->DMAParam[i];
pHC->DMAIntrInfo[i].IntrMask = (0x01 << 20);//need to check
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
return result;
errFuncRet:
return result;
}
///
/// ssp_init_hw: Initialize the H/W
/// Input:
/// pHC - Hard context
/// Output:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -