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

📄 spi.c

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 C
📖 第 1 页 / 共 3 页
字号:
//-------------------------------------------------------------------------------------------------------------------------
// Copyright (c) Samsung Electronics Co., Ltd.  All rights reserved.
//-------------------------------------------------------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
// Module Name :    SPI.C
//
// Abstract     :   SPI Interface Routines for Samsung S3C6410 CPU
//
// Environment :    Samsung S3C6410 / WM6.0
//
// 2007/04/
//
//-------------------------------------------------------------------------------------------------------------------------

#include <windows.h>
//#include <types.h>	//
#include <nkintr.h>

//#include <ceddk.h>	//For DMA Buffer Alloc

#include <memory.h>
//#include <bsp_cfg.h>
#include <s3c6410.h>	// for 6410
#include <DrvLib.h>
#include "spi.h"

#include "oal_intr.h"

#include "s3c6410_dma_controller.h"

#define MASTER_CS_ENABLE		pSPIregs->SLAVE_SEL = 0
#define MASTER_CS_DISABLE		pSPIregs->SLAVE_SEL = 1

#define TRAIL_CNT(n)			(((n)&0x3FF)<<19)

#define SPI_POWER_ON		(1<<21)
#define SPI_SCLK_ON			(1<<20)
#define SPI_USBHOST_ON		(1<<22)

#define PCLOCK				(0)
#define USB_HOST_CLOCK		(1)
#define EPLL_CLOCK			(2)
#define SPI_CLOCK			EPLL_CLOCK

//#define TEST_MODE
//#define POLLING

// MSG
#define	SPI_MSG	0
#define	SPI_INIT	1

volatile S3C6410_SPI_REG 	*pRestoreSPIregs	=	NULL;

#define	WRITE_TIME_OUT_CONSTANT		5000
#define	WRITE_TIME_OUT_MULTIPLIER	1

#define	READ_TIME_OUT_CONSTANT		5000
#define	READ_TIME_OUT_MULTIPLIER		1

DWORD HW_Init(PSPI_PUBLIC_CONTEXT pPublicSpi);

DWORD ThreadForTx(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForRx(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForSpi(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForRxDmaDone(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForTxDmaDone(PSPI_PUBLIC_CONTEXT pPublicSpi);


static DMA_CH_CONTEXT	g_OutputDMA;
static DMA_CH_CONTEXT	g_InputDMA;


BOOL
DllEntry(
	HINSTANCE   hinstDll,
	DWORD   	dwReason,
	LPVOID  	lpReserved
	)
{
	if ( dwReason == DLL_PROCESS_ATTACH )
	{
		DEBUGMSG (1, (TEXT("[SPI] Process Attach\r\n")));
	}

	if ( dwReason == DLL_PROCESS_DETACH )
	{
		DEBUGMSG (1, (TEXT("[SPI] Process Detach\r\n")));
	}

	return(TRUE);
}

DWORD
HW_Init(
	PSPI_PUBLIC_CONTEXT pPublicSpi
	)
{

	BOOL bResult = TRUE;

	if ( !pPublicSpi )
	{
		return FALSE;
	}

	// GPIO Virtual alloc
	pPublicSpi->pGPIOregs = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);
	if (pPublicSpi->pGPIOregs == NULL)
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] For pGPIOregs: DrvLib_MapIoSpace failed!\r\n")));
		bResult = FALSE;
		goto CleanUp;
	}

	// HS-SPI Virtual alloc
	pPublicSpi->pSPIregs = (volatile S3C6410_SPI_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_SPI0, sizeof(S3C6410_SPI_REG), FALSE);
	if (pPublicSpi->pSPIregs == NULL)
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] For pSPIregs: DrvLib_MapIoSpace failed!\r\n")));
		bResult = FALSE;
		goto CleanUp;
	}

	// Syscon Virtual alloc
	pPublicSpi->pSYSCONregs = (volatile S3C6410_SYSCON_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_SYSCON, sizeof(S3C6410_SYSCON_REG), FALSE);
	if (pPublicSpi->pSYSCONregs == NULL)
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] For pSYSCONregs: DrvLib_MapIoSpace failed!\r\n")));
		bResult = FALSE;
		goto CleanUp;
	}

	// DMAC0 Virtual alloc
	pPublicSpi->pDMAC0regs = (volatile S3C6410_DMAC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_DMA0, sizeof(S3C6410_DMAC_REG), FALSE);
	if (pPublicSpi->pDMAC0regs == NULL)
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] For pDMAC0regs: DrvLib_MapIoSpace failed!\r\n")));
		bResult = FALSE;
		goto CleanUp;
	}

	// DMAC1 Virtual alloc
	pPublicSpi->pDMAC1regs = (volatile S3C6410_DMAC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_DMA1, sizeof(S3C6410_DMAC_REG), FALSE);
	if (pPublicSpi->pDMAC1regs == NULL)
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] For pDMAC1regs: DrvLib_MapIoSpace failed!\r\n")));
		bResult = FALSE;
		goto CleanUp;
	}

CleanUp:

	if (!bResult)
	{
		if (pPublicSpi->pGPIOregs)
		{
			DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pGPIOregs);
			pPublicSpi->pGPIOregs = NULL;
		}

		if (pPublicSpi->pSPIregs)
		{
			DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pSPIregs);
			pPublicSpi->pSPIregs = NULL;
		}

		if (pPublicSpi->pDMAC0regs)
		{
			DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pDMAC0regs);
			pPublicSpi->pDMAC0regs = NULL;
		}

		if (pPublicSpi->pDMAC1regs)
		{
			DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pDMAC1regs);
			pPublicSpi->pDMAC1regs = NULL;
		}

		if (pPublicSpi->pSYSCONregs)
		{
			DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pSYSCONregs);
			pPublicSpi->pSYSCONregs = NULL;
		}

		return FALSE;
	}

#if		(CPU_NAME == S3C6410)
	//Configure HS-SPI Port Drive Strength
	pPublicSpi->pGPIOregs->SPCON = pPublicSpi->pGPIOregs->SPCON & ~(0x3<<28) | (2<<28);
#endif
	//Set GPIO for MISO, MOSI, SPICLK, SS
	pPublicSpi->pGPIOregs->GPCPUD = pPublicSpi->pGPIOregs->GPCPUD & ~(0xFF<<0);
	pPublicSpi->pGPIOregs->GPCCON = pPublicSpi->pGPIOregs->GPCCON & ~(0xFFFF<<0) | (2<<0) | (2<<4) | (2<<8) |(2<<12);

	// Clock On
	pPublicSpi->pSYSCONregs->PCLK_GATE |= SPI_POWER_ON;
#if	(SPI_CLOCK == EPLL_CLOCK)
	pPublicSpi->pSYSCONregs->SCLK_GATE |= SPI_SCLK_ON;
#elif (SPI_CLOCK == USB_HOST_CLOCK)
	pPublicSpi->pSYSCONregs->SCLK_GATE |= SPI_USBHOST_ON;
#endif

	DMA_initialize_register_address((void *)pPublicSpi->pDMAC0regs, (void *)pPublicSpi->pDMAC1regs, (void *)pPublicSpi->pSYSCONregs);

	return TRUE;

}



PSPI_PUBLIC_CONTEXT SPI_Init(PVOID Context)
{
	LPTSTR          				ActivePath = (LPTSTR) Context; // HKLM\Drivers\Active\xx
	PSPI_PUBLIC_CONTEXT		pPublicSpi = NULL;
	BOOL            				bResult = TRUE;
	DWORD           			dwHwIntr=0;

	RETAILMSG(SPI_INIT,(TEXT("++[SPI] HSP_Init Function\r\n")));
	RETAILMSG(SPI_MSG,(TEXT("[SPI] Active Path : %s\n"), ActivePath));

	if ( !(pPublicSpi = (PSPI_PUBLIC_CONTEXT)LocalAlloc( LPTR, sizeof(SPI_PUBLIC_CONTEXT) )) )
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] Can't not allocate for SPI Context\n")));
		return NULL;
	}

	if ( !(pRestoreSPIregs = (PS3C6410_SPI_REG)LocalAlloc( LPTR, sizeof(S3C6410_SPI_REG) )) )
	{
		return NULL;
	}


	if(!HW_Init(pPublicSpi))
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] HW_Init is failed\n")));
		return NULL;
	}
	else
	{
		RETAILMSG(SPI_INIT,(TEXT("[SPI] HW_Init is completed\n")));
	}

	// Request DMA Channel
	// DMA context have Virtual IRQ Number of Allocated DMA Channel
	// You Should initialize DMA Interrupt Thread after "Request DMA Channel"
	DMA_request_channel(&g_OutputDMA, DMA_SPI0_TX);
	DMA_request_channel(&g_InputDMA, DMA_SPI0_RX);

	do
	{
		InitializeCriticalSection(&(pPublicSpi->CsRxAccess));
		InitializeCriticalSection(&(pPublicSpi->CsTxAccess));

		//Rx Thread
		pPublicSpi->hRxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

		pPublicSpi->hRxThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForRx, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwRxThreadId);
		if (pPublicSpi->hRxThread == NULL)
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Rx Thread creation error!!!\n")));
			bResult = FALSE;
			break;
		}

		pPublicSpi->hRxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		pPublicSpi->hRxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

		//Tx Thread
		pPublicSpi->hTxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

		pPublicSpi->hTxThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForTx, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwTxThreadId);
		if (pPublicSpi->hTxThread == NULL)
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Dma Thread creation error!!!\n")));
			bResult = FALSE;
			break;
		}

		pPublicSpi->hTxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		pPublicSpi->hTxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

		//Spi ISR
		pPublicSpi->dwSpiSysIntr = SYSINTR_NOP;
		dwHwIntr = IRQ_SPI0;		//HS-SPI

		pPublicSpi->hSpiEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

		if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwSpiSysIntr, sizeof(DWORD), NULL))
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] Failed to request the SPI sysintr.\n")));
			pPublicSpi->dwSpiSysIntr = SYSINTR_UNDEFINED;
			bResult = FALSE;
			break;
		}

		if (!InterruptInitialize(pPublicSpi->dwSpiSysIntr, pPublicSpi->hSpiEvent, NULL, 0))
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Interrupt Initialization failed!!!\n")));
			bResult = FALSE;
			break;
		}

		pPublicSpi->hSpiThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForSpi, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwSpiThreadId);
		if (pPublicSpi->hSpiThread == NULL)
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI ISR Thread creation error!!!\n")));
			bResult = FALSE;
			break;
		}

		//Tx DMA Done ISR
		pPublicSpi->dwTxDmaDoneSysIntr = SYSINTR_NOP;
		dwHwIntr = g_OutputDMA.dwIRQ;

		pPublicSpi->hTxDmaDoneDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		pPublicSpi->hTxDmaDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);


		if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwTxDmaDoneSysIntr, sizeof(DWORD), NULL))
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] Failed to request the SPI_DMA sysintr.\n")));
			pPublicSpi->dwTxDmaDoneSysIntr = SYSINTR_UNDEFINED;
			bResult = FALSE;
			break;
		}

		if (!InterruptInitialize(pPublicSpi->dwTxDmaDoneSysIntr, pPublicSpi->hTxDmaDoneEvent, NULL, 0))
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] DMA Interrupt Initialization failed!!!\n")));
			bResult = FALSE;
			break;
		}

		pPublicSpi->hTxDmaDoneThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForTxDmaDone, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwTxDmaDoneThreadId);
		if (pPublicSpi->hTxDmaDoneThread == NULL)
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Dma Thread creation error!!!\n")));
			bResult = FALSE;
			break;
		}

		//Rx DMA Done ISR
		pPublicSpi->dwRxDmaDoneSysIntr = SYSINTR_NOP;
		dwHwIntr = g_InputDMA.dwIRQ;

		pPublicSpi->hRxDmaDoneDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		pPublicSpi->hRxDmaDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);


		if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwRxDmaDoneSysIntr, sizeof(DWORD), NULL))
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] Failed to request the SPI_DMA sysintr.\n")));
			pPublicSpi->dwRxDmaDoneSysIntr = SYSINTR_UNDEFINED;
			bResult = FALSE;
			break;
		}

		if (!InterruptInitialize(pPublicSpi->dwRxDmaDoneSysIntr, pPublicSpi->hRxDmaDoneEvent, NULL, 0))
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] DMA Interrupt Initialization failed!!!\n")));
			bResult = FALSE;
			break;
		}

		pPublicSpi->hRxDmaDoneThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForRxDmaDone, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwRxDmaDoneThreadId);
		if (pPublicSpi->hRxDmaDoneThread == NULL)
		{
			RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Dma Thread creation error!!!\n")));
			bResult = FALSE;
			break;
		}

	} while (0);

	RETAILMSG(SPI_INIT,(TEXT("--[SPI] HSP_Init Function\r\n")));
	if(bResult)
	{
		return pPublicSpi;
	}
	else
	{
		return NULL;
	}
}

DWORD
SPI_Open(
   DWORD 		pContext,
   DWORD        AccessCode,
   DWORD        ShareMode)
{
	PSPI_PUBLIC_CONTEXT		pSpiPublic  = (PSPI_PUBLIC_CONTEXT) pContext;
	PSPI_PRIVATE_CONTEXT	pSpiPrivate = NULL;
	BOOL            		bResult 	= TRUE;

	if ( !(pSpiPrivate = (PSPI_PRIVATE_CONTEXT)LocalAlloc( LPTR, sizeof(SPI_PRIVATE_CONTEXT) )) )
	{
		RETAILMSG(SPI_MSG,(TEXT("[SPI] Can't not allocate for SPI Context\n")));
		return (DWORD)NULL;
	}

	do
	{
		pSpiPrivate->State				= STATE_INIT;

		pSpiPrivate->pSpiPublic			= pSpiPublic;

		pSpiPrivate->bUseRxDMA		= FALSE;
		pSpiPrivate->bUseRxIntr		= FALSE;
		pSpiPrivate->bUseTxDMA		= FALSE;
		pSpiPrivate->bUseTxIntr		= FALSE;

	} while(FALSE);

	if(bResult)
	{
		return (DWORD) pSpiPrivate;
	}
	else
	{
		return (DWORD) NULL;
	}
}

DWORD
SPI_Read(
	DWORD 	hOpenContext,
	LPVOID 	pBuffer,
	DWORD 	Count)
{
	PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)hOpenContext;
	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
//	DWORD dwReadSize;

	//param check
	if(pSpiPrivate->State != STATE_IDLE)
	{
		RETAILMSG(SPI_MSG,(TEXT("[SPI] READ ERROR : STATE IS NOT IDLE\n")));
		return 0;
	}
	RETAILMSG(SPI_MSG,(TEXT("[SPI] pBuffer : 0x%X, Count : %d\n"), pBuffer, Count));


	if(pSpiPrivate->bUseRxDMA)
	{
		PDMA_BUFFER pDmaBuffer = (PDMA_BUFFER) pBuffer;
		pSpiPrivate->pRxBuffer 		= pDmaBuffer->VirtualAddress;
		pSpiPrivate->pRxDMABuffer 	= pDmaBuffer->PhysicalAddress;
	}
	else
	{
		pSpiPrivate->pRxBuffer = (LPVOID)pBuffer;
	}

	pSpiPrivate->dwRxCount = Count;
	pSpiPublic->pSpiPrivate = pSpiPrivate;

	SetEvent(pSpiPublic->hRxEvent);

⌨️ 快捷键说明

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