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

📄 cspsocspi.c

📁 WINCE 架构下SPI驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent)
			CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent);
		if((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent)
			CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent);

		InterruptDisable(g_oalSysInfo.spiInfo[1].dwSysIntr);
		break;
	default:
		RETAILMSG (1, (TEXT("+SPI StopDispatchThread+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
		return FALSE;
	}

	return TRUE;
}
#endif //SPI_INTR
//////////////////////////////////////////////////////////////////////////


BOOL   SpiSocInit(PVOID pSpiHandle)
{
	BOOL bRet = TRUE;
	PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;	

	//check inited or not
	switch (pDevHdl->uiHwPort)
	{
	case SEPARATE_SPI0:	

	       if (!v_pDriverGlobals->misc.spiDev[0].bSpiInited)
	       {
			if(NULL == pDevHdl->v_hSpiMutex)
			{
				RETAILMSG(DEBUGPRINT, (TEXT("CreateMutex SPI0_MUTEX_NAME\r\n")));
				pDevHdl->v_hSpiMutex=CreateMutex(NULL,FALSE,SPI0_MUTEX_NAME);
			}
			
			// Reset SPI0 interface - bit17
			WRITE_BITFIELD(struct ResetSWRBits, &(v_pRstRegs->resetswrReg), spi0, 1);  //PR2X0A_RST.h -- confirmed -- riverlj 06/03/06
			usWait (1);
			WRITE_BITFIELD(struct ResetSWRBits, &(v_pRstRegs->resetswrReg), spi0, 0);  //PR2X0A_RST.h -- confirmed -- riverlj 06/03/06
			usWait (1);

			// SPI pin mux;
			PadEnableSpi0();
			
			pDevHdl->pSpiSocRegs = (PVOID)&g_spi0_soc_regs;	
			((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs = (volatile struct SpiReg *)v_pSpi0Regs;

			v_pDriverGlobals->misc.spiDev[0].bSpiInited = TRUE;
		}
		else
		{
			RETAILMSG(1, (TEXT("Spi Init Error Port(0) has been initialized\r\n")));
			return FALSE;
		}
		break;
	case SEPARATE_SPI1:	
		if (!v_pDriverGlobals->misc.spiDev[1].bSpiInited)
		{
			if(NULL == pDevHdl->v_hSpiMutex)
			{
				RETAILMSG(DEBUGPRINT, (TEXT("CreateMutex SPI1_MUTEX_NAME\r\n")));
				pDevHdl->v_hSpiMutex=CreateMutex(NULL,FALSE,SPI1_MUTEX_NAME);
			}
			
			// Reset SPI0 interface - bit17
			WRITE_BITFIELD(struct ResetSWRBits, &(v_pRstRegs->resetswrReg), spi1, 1);  //PR2X0A_RST.h -- confirmed -- riverlj 06/03/06
			usWait (1);
			WRITE_BITFIELD(struct ResetSWRBits, &(v_pRstRegs->resetswrReg), spi1, 0);  //PR2X0A_RST.h -- confirmed -- riverlj 06/03/06
			usWait (1);
			WRITE_BITFIELD (struct RSCPinMuxBits, &(v_pRscRegs->rscPinMux), spi1, 1);// spi1 enable, muxed, xh add

			// SPI pin mux;
			PadEnableSpi1();

			pDevHdl->pSpiSocRegs = (PVOID)&g_spi1_soc_regs;	
			((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs = (volatile struct SpiReg *)v_pSpi1Regs;

			v_pDriverGlobals->misc.spiDev[1].bSpiInited = TRUE;
		}
		else
		{
			RETAILMSG(1, (TEXT("Spi Init Error Port(0) has been initialized\r\n")));
			return FALSE;
		}
		break;
	default:
		RETAILMSG (1, (TEXT("+Spi SocInit+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
		return FALSE;
	}
	
	//add by riverlj for DMA -- 06/04/26
	pDevHdl->dwSizeR = DMA_LENGTH; //32k byte mem for dma read
	pDevHdl->dwVirtAddrR = (DWORD) AllocPhysMem ( pDevHdl->dwSizeR,
		PAGE_READWRITE | PAGE_NOCACHE,
		0xffff, //64k Byte Alignment
		0,
		&(pDevHdl->dwPhyAddrR) );
	if (NULL == (LPVOID)pDevHdl->dwVirtAddrR )
	{
		RETAILMSG(1, (TEXT("+Spi SocInit+ failed! dwVirtAddrR is NULL.\r\n")));
		return FALSE;
	}

	pDevHdl->dwSizeW = DMA_LENGTH; //32k byte mem for dma write
	pDevHdl->dwVirtAddrW = (DWORD) AllocPhysMem ( pDevHdl->dwSizeW,
		PAGE_READWRITE | PAGE_NOCACHE,
		0xffff, //64k Byte Alignment
		0,
		&(pDevHdl->dwPhyAddrW) );
	if (NULL == (LPVOID)pDevHdl->dwVirtAddrW )
	{
		RETAILMSG(1, (TEXT("+Spi SocInit+ failed! dwVirtAddrW is NULL.\r\n")));
		return FALSE;
	}
	//endof

#if SPI_INTR
	if (v_pDriverGlobals->misc.spiDev[0].bSpiInited || v_pDriverGlobals->misc.spiDev[1].bSpiInited) 
	{
		if(!KernelIoControl(IOCTL_HAL_GET_OALSYSINFO, 
			NULL,
			0,
			&g_oalSysInfo,
			sizeof(OALSYSINFO),
			NULL))
		{
			RETAILMSG(1, (TEXT("+Spi SocInit+ GET OALSYSINFO ERROR!\r\n")));
			return FALSE;
		}

		// init interrupt part, must be only single time
		if (!StartDispatchThread(pDevHdl))
		{
			// Failed on InterruptInitialize or CreateThread.
			RETAILMSG(1, (TEXT("+Spi SocInit+ fail to StartDispatchThread!\r\n")));
			SetLastError(ERROR_OPEN_FAILED);

			return FALSE;
		}
	}
#endif	//SPI_INTR
       pDevHdl->bSpiOpen = FALSE;
	return bRet;	
}

BOOL   SpiSocOpen(PVOID pSpiHandle)
{
	PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
	BOOL bRet = TRUE;

	SYSTEMCLOCKINFO systemClocks;
	DWORD dwSysIoClock;
	INT SPI_CLK_DIVISOR;
	INT txfifo_ctrl,rxfifo_ctrl;
	INT tmp;

	//DumpSPIDevInfo(pDevHdl);
	RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocOpen Port(%d)\r\n"), pDevHdl->uiHwPort));
	if(!SPI_GRABMUTEX(pDevHdl))
	{
		RETAILMSG (1, (TEXT("+SpiSocOpen+ GRABMUTEX failed!\r\n") ));
		return FALSE;
	}

	switch (pDevHdl->uiHwPort)
	{
	case SEPARATE_SPI0:		    
		if(!v_pDriverGlobals->misc.spiDev[0].bSpiOpened)
		{
			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), io, 1);
			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi0, 1);  
			v_pDriverGlobals->misc.spiDev[0].bSpiOpened = TRUE;
		}
		else
		{
			RETAILMSG (1, (TEXT(" Port(0) has been opened\r\n")));
			SPI_RELEASEMUTEX(pDevHdl);
			return FALSE;
		}
		break;
	case SEPARATE_SPI1:
		if(!v_pDriverGlobals->misc.spiDev[1].bSpiOpened)
		{
			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), io, 1);
			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi1, 1);
			v_pDriverGlobals->misc.spiDev[1].bSpiOpened = TRUE;
		}
		else
		{
			RETAILMSG (1, (TEXT(" Port(1) has been opened\r\n")));
			SPI_RELEASEMUTEX(pDevHdl);
			return FALSE;
		}

		break;
	default:
		RETAILMSG (1, (TEXT("+SpiSocOpen+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
		bRet = FALSE;
		break;
	}

	if (pDevHdl->SpiDevInfo.IoMod != SPI_INFO_IO_MODE)
	{
		WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), dma, 1);
	}	

	//*************Config SPI according SpiDevInfo *****************//
	//step 1: calculate clock divisor
	//SPI_CLK_DIVISOR = pDevHdl->SpiDevInfo.ClkDiv;	//TODO: calc div base freq?
	//get io clk
	if (!KernelIoControl(IOCTL_HAL_GET_SYS_CLOCK_INFO,
		NULL,
		0,
		&systemClocks,
		sizeof(SYSTEMCLOCKINFO),
		NULL))
	{
		RETAILMSG(1,(L"+Spi SocOpen+ failed! Cannot get system clock info.\r\n"));
		SPI_CLK_DIVISOR = 150;	//Set Default Value
	}
	else
	{	
		dwSysIoClock = systemClocks.dwIoClock;
		//RETAILMSG(1,(TEXT("system clk=%d\r\n"),dwSysIoClock));
		
		SPI_CLK_DIVISOR = dwSysIoClock/(pDevHdl->SpiDevInfo.dwSPIFreq*2)-1;	//Set the working freq 
		if (0 == SPI_CLK_DIVISOR)
		{
			SPI_CLK_DIVISOR = 0x01;	
		}	
	}
	
	//RETAILMSG(DEBUGPRINT,(TEXT("SPI_CLK_DIVISOR=0x%x\r\n"),SPI_CLK_DIVISOR));
	//step 2: config SPI Control register (SPI_CTRL)
	if (SPI_INFO_ONLY_COMMAND_DATA == pDevHdl->SpiDevInfo.HaveCmdInFrm) 
	{
		tmp = SPI_CLK_DIVISOR 			//iWorkingFreqKhz --> SPI_CLK_DIVISOR
			| pDevHdl->SpiDevInfo.SlaveMod
			| (0x1 << 17)
			| pDevHdl->SpiDevInfo.CsIoOutHigh
			| pDevHdl->SpiDevInfo.CsIoCtlMod
			| pDevHdl->SpiDevInfo.ClkIdleStatHigh
			| pDevHdl->SpiDevInfo.CsIdleStatHigh
			| pDevHdl->SpiDevInfo.TransModeMsb
			| pDevHdl->SpiDevInfo.DrvRsingEdge
			| pDevHdl->SpiDevInfo.CsHold2Clk
			| pDevHdl->SpiDevInfo.Clk3SampleFilterGlitch
			| pDevHdl->SpiDevInfo.DataFmt
			| pDevHdl->SpiDevInfo.CmdByteNum
			| pDevHdl->SpiDevInfo.AutoClearTXEn
			| pDevHdl->SpiDevInfo.MulDataMod;
	}
	else
	{
		tmp = SPI_CLK_DIVISOR 			//iWorkingFreqKhz --> SPI_CLK_DIVISOR
			| pDevHdl->SpiDevInfo.SlaveMod
			| pDevHdl->SpiDevInfo.HaveCmdInFrm
			| pDevHdl->SpiDevInfo.CsIoOutHigh
			| pDevHdl->SpiDevInfo.CsIoCtlMod
			| pDevHdl->SpiDevInfo.ClkIdleStatHigh
			| pDevHdl->SpiDevInfo.CsIdleStatHigh
			| pDevHdl->SpiDevInfo.TransModeMsb
			| pDevHdl->SpiDevInfo.DrvRsingEdge
			| pDevHdl->SpiDevInfo.CsHold2Clk
			| pDevHdl->SpiDevInfo.Clk3SampleFilterGlitch
			| pDevHdl->SpiDevInfo.DataFmt
			| pDevHdl->SpiDevInfo.CmdByteNum
			| pDevHdl->SpiDevInfo.AutoClearTXEn
			| pDevHdl->SpiDevInfo.MulDataMod;
	}


	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl), tmp);

	//step 3: io or dma mode
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxmode), pDevHdl->SpiDevInfo.IoMod);
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxmode), pDevHdl->SpiDevInfo.IoMod);  

	// Initialize FIFO level check registers
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxfifolevel), (0x06 | (0x04 << 10) | (0x02 << 20)) );
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifolevel), (0x02 | (0x04 << 10) | (0x06 << 20)) );

	// Set FIFO threshold and FIFO WIDTH
       //for IO mode with cmd -- fifo_ctrl -- TODO CHECK
	//if ((SPI_INFO_IO_MODE == pDevHdl->SpiDevInfo.IoMod) && (SPI_INFO_HAVE_COMMAND_DATA == pDevHdl->SpiDevInfo.HaveCmdInFrm))
	if (SPI_INFO_IO_MODE == pDevHdl->SpiDevInfo.IoMod)
	{
		txfifo_ctrl = (0x08 << 2) | 0x2;
		rxfifo_ctrl = (0x18 << 2) | 0x2;
	}
	else
	{
		switch (pDevHdl->SpiDevInfo.DataFmt)
		{
		case SPI_INFO_TRAN_DATA_FORMAT_8BIT:	
			txfifo_ctrl = (0x08 << 2) & 0x7c;
			rxfifo_ctrl = (0x18 << 2) & 0x7c;
			break;
		case SPI_INFO_TRAN_DATA_FORMAT_12BIT:
		case SPI_INFO_TRAN_DATA_FORMAT_16BIT:	
			txfifo_ctrl = (0x08 << 2) | 0x1;
			rxfifo_ctrl = (0x18 << 2) | 0x1;
			break;
		case SPI_INFO_TRAN_DATA_FORMAT_32BIT:	
			txfifo_ctrl = (0x08 << 2) | 0x2;
			rxfifo_ctrl = (0x18 << 2) | 0x2;
			break;
		default:
			RETAILMSG (1,(TEXT("+Spi SocOpen+ Data Frame Error\r\n")));
			bRet = FALSE;
			break;
		}
	}

	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxfifoctrl), txfifo_ctrl);
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoctrl), rxfifo_ctrl);
	//********************* end of config ****************************//

	// FIFO Reset
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxfifoop), SPI_FIFO_RESET);
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoop), SPI_FIFO_RESET);
	// FIFO start
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxfifoop), SPI_FIFO_START);
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoop), SPI_FIFO_START);

	// Disable inturrpts
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten), 0);
	// Clear All Interrupt Status
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus), SPI_INT_MASK_ALL);

	WRITE_BITFIELD(struct pendingBits, &v_pIntRegs->riscmask, spi0, 1);
	WRITE_BITFIELD(struct pendingBits, &v_pIntRegs->riscmask, spi1, 1);

	switch (pDevHdl->uiHwPort)
	{
	case SEPARATE_SPI0:
		if ( pDevHdl->SpiDevInfo.IoMod != SPI_INFO_IO_MODE )
		{
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn12, 0);
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intStatus, chn12, 1);
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn13, 0);
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intStatus, chn13, 1);
			v_pDriverGlobals->sharedrc.dmaStatus &= ~0x3000;
		}

		break;
	case SEPARATE_SPI1:
		if ( pDevHdl->SpiDevInfo.IoMod != SPI_INFO_IO_MODE )
		{
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn14, 0);
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intStatus, chn14, 1);
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn15, 0);
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intStatus, chn15, 1);
			v_pDriverGlobals->sharedrc.dmaStatus &= ~0xc000;
		}

		break;
	default:
		RETAILMSG (1,(TEXT("+Spi SocOpen+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
		bRet = FALSE;
		break;
	}
       pDevHdl->bSpiOpen = TRUE;
	SPI_RELEASEMUTEX(pDevHdl);
	RETAILMSG (DEBUGPRINT, (TEXT("-Spi SocOpen Port(%d)\r\n"), pDevHdl->uiHwPort));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -