⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pxa-gspi.c

📁 非常好的marvall 8686驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -