//-------------------------------------------------------------------------------------------------------------------------
// 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 S5PV210 CPU
//
// Environment : Samsung S5PV210 / WincCE6.0
//
// 2010/02/10 asdf Added Full duplex mode (Ver 1.01)
// Define SPI_FULL_DUPLEX in sources file to use full duplex
// 2009/07/10 asdf Modified for supporting multi-channel
//
//-------------------------------------------------------------------------------------------------------------------------
/*****************************************************************************
* Includes
*****************************************************************************/
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <memory.h>
#include <types.h>
#include <ddkreg.h>
#include <bsp.h>
#include <oal_intr.h>
#include <drvmsg.h>
#include <dma_controller.h>
#include <spi_reg.h>
#include "spi_priv.h"
#include <pmplatform.h>
#ifdef SPI_COMM_STREAM_IF
//#include <serpriv.h>
#endif
/*****************************************************************************
* Definitions
*****************************************************************************/
//#define SLAVE_READY 0
//#define TEST_MODE
// MSG
#define SPI_MSG SPI_USR1
#define SPI_INIT SPI_INFO
#define SPI_DEBUG SPI_DBG
#define VERSION_INFO "SPI"
#define DateInformation "1.03"
#define SPI_CLOCK MPLL_CLOCK //EPLL_CLOCK//MPLL_CLOCK
#define CLKSEL (0x1 << 9) //SCLK
/*****************************************************************************
* Functions
*****************************************************************************/
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);
#ifdef SPI_EX_GPIO_CALLBACK
extern BOOL HSPCALLBACK_SetSlaveReady(PSPI_PRIVATE_CONTEXT pSpiPrivate); // SLAVE SIDE
extern BOOL HSPCALLBACK_ClrSlaveReady(PSPI_PRIVATE_CONTEXT pSpiPrivate);
extern BOOL HSPCALLBACK_GetSlaveReady(PSPI_PRIVATE_CONTEXT pSpiPrivate);
extern BOOL HSPCALLBACK_Init(PSPI_PRIVATE_CONTEXT pSpiPrivate);
extern BOOL HSPCALLBACK_Deinit(PSPI_PRIVATE_CONTEXT pSpiPrivate);
#endif
#ifdef SPI_FULL_DUPLEX
BOOL SPI_FullDuplex(PSPI_PRIVATE_CONTEXT pSpiPrivate, PBYTE pRxBuf, PBYTE pTxBuf, DWORD dwCount);
#endif
void SPI_SFR_DUMP(PSPI_PUBLIC_CONTEXT pPublicSpi)
{
#if 0
volatile SPI_REG *pSPIregs = pPublicSpi->pSPIregs;
DBGMSG(SPI_INFO,(TEXT("**** SPI SFR CH%d*****\r\n"), pPublicSpi->chnum));
DBGMSG(SPI_INFO,(TEXT(" CH_CFG : 0x%x \r\n"), pSPIregs->CH_CFG));
DBGMSG(SPI_INFO,(TEXT(" CLK_CFG : 0x%x \r\n"), pSPIregs->CLK_CFG));
DBGMSG(SPI_INFO,(TEXT(" MODE_CFG : 0x%x \r\n"), pSPIregs->MODE_CFG));
DBGMSG(SPI_INFO,(TEXT(" SPI_INT_EN : 0x%x \r\n"), pSPIregs->SPI_INT_EN));
DBGMSG(SPI_INFO,(TEXT(" STATUS : 0x%x \r\n"), pSPIregs->SPI_STATUS));
DBGMSG(SPI_INFO,(TEXT(" FB CLK DELAY : 0x%x \r\n"), pSPIregs->FB_CLK_SEL));
#endif
}
BOOL
DllEntry(
HINSTANCE hinstDll,
DWORD dwReason,
LPVOID lpReserved
)
{
if ( dwReason == DLL_PROCESS_ATTACH )
{
DBGMSG (SPI_DEBUG, (TEXT("[SPI] Process Attach\r\n")));
}
if ( dwReason == DLL_PROCESS_DETACH )
{
DBGMSG (SPI_DEBUG, (TEXT("[SPI] Process Detach\r\n")));
}
return(TRUE);
}
DWORD
HW_Init(
PSPI_PUBLIC_CONTEXT pPublicSpi
)
{
BOOL bResult = TRUE;
PHYSICAL_ADDRESS ioPhysicalBase = {0, 0};
if ( !pPublicSpi )
{
bResult = FALSE;
goto CleanUp;
}
// GPIO Virtual alloc
ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
pPublicSpi->pGPIOregs = (PGPIO_REG)MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG), FALSE);
if (pPublicSpi->pGPIOregs == NULL)
{
ERRMSG((TEXT("[SPI] For pGPIOregs: MmMapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// Syscon Virtual alloc
ioPhysicalBase.LowPart = BASE_REG_PA_CMU_CLK;
pPublicSpi->pSYSCONregs = (PCMU_CLK_REG)MmMapIoSpace(ioPhysicalBase, sizeof(CMU_CLK_REG), FALSE);
if (pPublicSpi->pSYSCONregs == NULL)
{
ERRMSG((TEXT("[SPI] For pSYSCONregs: MmMapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// MDMAC Virtual alloc
ioPhysicalBase.LowPart = BASE_REG_PA_MDMA;
pPublicSpi->pDMACregs = (PDMAC_REG)MmMapIoSpace(ioPhysicalBase, sizeof(DMAC_REG), FALSE);
if (pPublicSpi->pDMACregs == NULL)
{
ERRMSG((TEXT("[SPI] For pDMACregs: MmMapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// DMAC0 Virtual alloc
ioPhysicalBase.LowPart = BASE_REG_PA_PDMA0;
pPublicSpi->pDMAC0regs = (PDMAC_REG)MmMapIoSpace(ioPhysicalBase, sizeof(DMAC_REG), FALSE);
if (pPublicSpi->pDMAC0regs == NULL)
{
ERRMSG((TEXT("[SPI] For pDMAC0regs: MmMapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// DMAC1 Virtual alloc
ioPhysicalBase.LowPart = BASE_REG_PA_PDMA1;
pPublicSpi->pDMAC1regs = (PDMAC_REG)MmMapIoSpace(ioPhysicalBase, sizeof(DMAC_REG), FALSE);
if (pPublicSpi->pDMAC1regs == NULL)
{
ERRMSG((TEXT("[SPI] For pDMAC1regs: MmMapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// HS-SPI Virtual alloc
ioPhysicalBase.LowPart = BASE_REG_PA_SPI0+(pPublicSpi->chnum * BASE_REG_SPI_OFFSET);
pPublicSpi->pSPIregs = (PSPI_REG)MmMapIoSpace(ioPhysicalBase, sizeof(SPI_REG), FALSE);
if (pPublicSpi->pSPIregs == NULL)
{
ERRMSG((TEXT("[SPI] For pSPIregs: MmMapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
if(pPublicSpi->chnum==SPI0)
{
DBGMSG(SPI_INFO,(TEXT("[SPI] CH0 HW_init\r\n")));
//Configure SPI Port Drive Strength
pPublicSpi->pGPIOregs->GPB.GP_DRV_SR = (pPublicSpi->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<0)) | (0x55<<0);
//Set GPIO for MISO, MOSI, SPICLK, SS
Set_PinFunction(pPublicSpi->pGPIOregs, SPI0_CLK);
Set_PinFunction(pPublicSpi->pGPIOregs, SPI0_nSS);
Set_PinFunction(pPublicSpi->pGPIOregs, SPI0_MISO);
Set_PinFunction(pPublicSpi->pGPIOregs, SPI0_MOSI);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI0_CLK, sgip_PULL_DISABLE);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI0_nSS, sgip_PULL_DISABLE);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI0_MISO, sgip_PULL_DISABLE);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI0_MOSI, sgip_PULL_DISABLE);
DBGMSG(SPI_INFO,(TEXT("++[SPI] SPI_GPIO GPB_DRV_SR =%x, GPB_PUD = %x, GPB_CON = %x\r\n")
, pPublicSpi->pGPIOregs->GPB.GP_DRV_SR
, pPublicSpi->pGPIOregs->GPB.GP_PUD
, pPublicSpi->pGPIOregs->GPB.GP_CON));
// Clock On
#if (SPI_CLOCK == EPLL_CLOCK)
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 & ~(0xF << 0)) | (0x7 << 0);
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 | (1 << 16));
pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 0));
#elif (SPI_CLOCK == MPLL_CLOCK)
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 & ~(0xF << 0)) | (0x6 << 0);
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 | (1 << 16));
pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 0)) | (7 << 0);
#endif
pPublicSpi->pSYSCONregs->CLK_GATE.CLK_GATE_IP3 = (pPublicSpi->pSYSCONregs->CLK_GATE.CLK_GATE_IP3 & ~(0x1 << 12)) | (0x1 << 12);
}
else if(pPublicSpi->chnum==SPI1)
{
DBGMSG(SPI_INFO,(TEXT("[SPI] CH1 HW_init\r\n")));
//Configure SPI Port Drive Strength
pPublicSpi->pGPIOregs->GPB.GP_DRV_SR = (pPublicSpi->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<8)) | (0xFF<<8);
//Set GPIO for MISO, MOSI, SPICLK, SS
Set_PinFunction(pPublicSpi->pGPIOregs, SPI1_CLK);
Set_PinFunction(pPublicSpi->pGPIOregs, SPI1_nSS);
Set_PinFunction(pPublicSpi->pGPIOregs, SPI1_MISO);
Set_PinFunction(pPublicSpi->pGPIOregs, SPI1_MOSI);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI1_CLK, sgip_PULL_DISABLE);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI1_nSS, sgip_PULL_DISABLE);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI1_MISO, sgip_PULL_DISABLE);
Set_PinPullUD(pPublicSpi->pGPIOregs, SPI1_MOSI, sgip_PULL_DISABLE);
DBGMSG(SPI_INFO,(TEXT("++[SPI] SPI_GPIO GPB_DRV_SR =%x, GPB_PUD = %x, GPB_CON = %x\r\n")
, pPublicSpi->pGPIOregs->GPB.GP_DRV_SR
, pPublicSpi->pGPIOregs->GPB.GP_PUD
, pPublicSpi->pGPIOregs->GPB.GP_CON));
// Clock On
#if (SPI_CLOCK == EPLL_CLOCK)
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 & ~(0xF << 4)) | (0x7 << 4);
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 | (1 << 17));
//pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 4));
pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 4))| (2 << 4);//asdf
#elif (SPI_CLOCK == MPLL_CLOCK)
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 & ~(0xF << 4)) | (0x6 << 4);
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 | (1 << 17));
//pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 4)) | (12 << 4);
pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 4)) | (19 << 4);//asdf test
#endif
pPublicSpi->pSYSCONregs->CLK_GATE.CLK_GATE_IP3 = (pPublicSpi->pSYSCONregs->CLK_GATE.CLK_GATE_IP3 & ~(0x1 << 13)) | (0x1 << 13);
}
else if(pPublicSpi->chnum==SPI2)
{
DBGMSG(SPI_INFO,(TEXT("[SPI] CH2 HW_init\r\n")));
//Configure SPI Port Drive Strength
pPublicSpi->pGPIOregs->GPG2.GP_DRV_SR = (pPublicSpi->pGPIOregs->GPG2.GP_DRV_SR & ~(0xFF<<0)) | (0x55<<0);
//Set GPIO for MISO, MOSI, SPICLK, SS
pPublicSpi->pGPIOregs->GPG2.GP_PUD= (pPublicSpi->pGPIOregs->GPG2.GP_PUD & ~(0xFF<<0));
pPublicSpi->pGPIOregs->GPG2.GP_CON = (pPublicSpi->pGPIOregs->GPG2.GP_CON & ~(0xFFFF<<0)) | (0x3333<<0);
// Clock On
#if (SPI_CLOCK == EPLL_CLOCK)
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 & ~(0xF << 8)) | (0x7 << 8);
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 | (1 << 18));
pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF<<8));
#elif (SPI_CLOCK == MPLL_CLOCK)
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC5 & ~(0xF << 8)) | (0x6 << 8);
pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 = (pPublicSpi->pSYSCONregs->CLK_SRC.CLK_SRC_MASK0 | (1 << 18));
pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 = (pPublicSpi->pSYSCONregs->CLK_DIV.CLK_DIV5 & ~(0xF << 8)) | (13 << 8);
#endif
pPublicSpi->pSYSCONregs->CLK_GATE.CLK_GATE_IP3 = (pPublicSpi->pSYSCONregs->CLK_GATE.CLK_GATE_IP3 & ~(0x1 << 14)) | (0x1 << 14);
}
else
{
ERRMSG((TEXT("[SPI] Invalid channel \r\n")));
}
DMA_initialize_register_address((void *)pPublicSpi->pDMAC0regs,
(void *)pPublicSpi->pDMAC1regs,
(void *)pPublicSpi->pDMACregs,
(void *)pPublicSpi->pSYSCONregs);
CleanUp:
if (!bResult)
{
if (pPublicSpi != NULL)
{
if (pPublicSpi->pGPIOregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pGPIOregs, sizeof(GPIO_REG));
pPublicSpi->pGPIOregs = NULL;
}
if (pPublicSpi->pSPIregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pSPIregs, sizeof(SPI_REG));
pPublicSpi->pSPIregs = NULL;
}
if (pPublicSpi->pDMACregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pDMACregs, sizeof(DMAC_REG));
pPublicSpi->pDMACregs = NULL;
}
if (pPublicSpi->pDMAC0regs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pDMAC0regs, sizeof(DMAC_REG));
pPublicSpi->pDMAC0regs = NULL;
}
if (pPublicSpi->pDMAC1regs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pDMAC1regs, sizeof(DMAC_REG));
pPublicSpi->pDMAC1regs = NULL;
}
if (pPublicSpi->pSYSCONregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pSYSCONregs, sizeof(CMU_CLK_REG));
pPublicSpi->pSYSCONregs = NULL;
}
}
bResult = FALSE;
}
return bResult;
}
BOOL InitializeDMABuffer(PSPI_PUBLIC_CONTEXT pPublicSpi)
{
BOOL bResult = TRUE;
DMA_ADAPTER_OBJECT Adapter1, Adapter2;
DBGMSG(SPI_FUNC,(TEXT("+[SPI] InitializeBuffer\n")));
if ( !pPublicSpi )
{
bResult = FALSE;
goto CleanUp;
}
memset(&Adapter1, 0, sizeof(DMA_ADAPTER_OBJECT));
Adapter1.InterfaceType = Internal;
Adapter1.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
memset(&Adapter2, 0, sizeof(DMA_ADAPTER_OBJECT));
Adapter2.InterfaceType = Internal;
Adapter2.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
// Allocate a block of virtual memory (physically contiguous) for the DMA buffers.
//
pPublicSpi->SPIDMAInfo.pVirtDmaDstBufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter1, SPI_DMA_BUF_SIZE, &pPublicSpi->SPIDMAInfo.PhysDmaDstBufferAddr, FALSE);
DBGMSG(FALSE, (TEXT("[SPIDD] InitializeBuffer() - pVirtDmaDstBufferAddr %x\r\n"),pPublicSpi->SPIDMAInfo.pVirtDmaDstBufferAddr));
if (pPublicSpi->SPIDMAInfo.pVirtDmaDstBufferAddr == NULL)
{
ERRMSG( (TEXT("[SPI] InitializeBuffer() - Failed to allocate DMA buffer for SPI.\r\n")));
HalFreeCommonBuffer(0, 0, pPublicSpi->SPIDMAInfo.PhysDmaDstBufferAddr, pPublicSpi->SPIDMAInfo.pVirtDmaDstBufferAddr, FALSE);
bResult = FALSE;
goto CleanUp;
}
pPublicSpi->SPIDMAInfo.pVirtDmaSrcBufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter2, SPI_DMA_BUF_SIZE, &pPublicSpi->SPIDMAInfo.PhysDmaSrcBufferAddr, FALSE);
DBGMSG(FALSE, (TEXT("[SPIDD] InitializeBuffer() - pVirtDmaSrcBufferAddr %x\r\n"),pPublicSpi->SPIDMAInfo.pVirtDmaSrcBufferAddr));
if (pPublicSpi->SPIDMAInfo.pVirtDmaSrcBufferAddr == NULL)
{
ERRMSG( (TEXT("[SPI] InitializeBuffer() - Failed to allocate DMA buffer for SPI.\r\n")));
HalFreeCommonBuffer(0, 0, pPublicSpi->SPIDMAInfo.PhysDmaSrcBufferAddr, pPublicSpi->SPIDMAInfo.pVirtDmaSrcBufferAddr, FALSE);
bResult = FALSE;
goto CleanUp;
}
//DMA Address
pPublicSpi->SPIDMAInfo.DmaDstAddress = (UINT)(pPublicSpi->SPIDMAInfo.PhysDmaDstBufferAddr.LowPart);
pPublicSpi->SPIDMAInfo.DmaSrcAddress = (UINT)(pPublicSpi->SPIDMAInfo.PhysDmaSrcBufferAddr.LowPart);
DBGMSG(SPI_INFO, (TEXT("[SPI] pVirtDmaSrcBufferAddr 0x%x DmaSrcAddress 0x%x \r\n"),pPublicSpi->SPIDMAInfo.pVirtDmaSrcBufferAddr, pPublicSpi->SPIDMAInfo.DmaSrcAddress));
DBGMSG(SPI_INFO, (TEXT("[SPI] pVirtDmaDstBufferAddr 0x%x DmaDstAddress 0x%x \r\n"),pPublicSpi->SPIDMAInfo.pVirtDmaDstBufferAddr, pPublicSpi->SPIDMAInfo.DmaDstAddress));
DBGMSG(SPI_FUNC,(TEXT("-[SPI] InitializeBuffer\n")));
CleanUp:
return bResult;
}
PSPI_PUBLIC_CONTEXT SPI_Init(PVOID Context)
{
PSPI_PUBLIC_CONTEXT pPublicSpi = NULL;
LPTSTR ActivePath = (LPTSTR) Context;
BOOL bResult = TRUE;
DWORD dwHwIntr=0;
HKEY hKey = NULL;
DDKISRINFO isri;
DWORD dwDataSize=4;
DBGMSG(SPI_INFO,(TEXT("*************************************************\r\n")));
DBGMSG(SPI_INFO,(TEXT("* %a_%a : %s\r\n"),VERSION_INFO,DateInformation, ActivePath));
DBGMSG(SPI_INFO,(TEXT("*************************************************\r\n")));
DBGMSG(SPI_FUNC,(TEXT("[SPI] ++HSP_Init \r\n")));
if ( !(pPublicSpi = (PSPI_PUBLIC_CONTEXT)LocalAlloc( LPTR, sizeof(SPI_PUBLIC_CONTEXT) )) )
{
ERRMSG((TEXT("[SPI] Can't not allocate for SPI Context\n")));
bResult = FALSE;
goto CleanUp;
}
pPublicSpi->hSpiEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pPublicSpi->dwSpiSysIntr = SYSINTR_NOP;
hKey = OpenDeviceKey((LPCTSTR)Context);
if (hKey == NULL )
{
ERRMSG((TEXT("[SPI] Failed to open device key\r\n")));
bResult = FALSE;
goto CleanUp;
}
// Read ISR information
isri.cbSize = sizeof(isri);
if (DDKReg_GetIsrInfo(hKey, &isri) != ERROR_SUCCESS)
{
ERRMSG((TEXT("[SPI] Error getting ISR information\r\n")));
bResult = FALSE;
goto CleanUp;
}
DBGMSG(SPI_INFO,(TEXT("[SPI] IRQ(%d)\r\n"), isri.dwIrq));
if (isri.dwSysintr == SYSINTR_NOP)
{
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &(isri.dwIrq), sizeof(DWORD), &pPublicSpi->dwSpiSysIntr, sizeof(DWORD), NULL))
{
ERRMSG((TEXT("[SPI] Error KernelIoControl\r\n")));
bResult = FALSE;
goto CleanUp;
}
}
// Get Device Index.
if(RegQueryValueEx(hKey, PC_REG_SPI_DEVICE_INDEX, NULL, NULL,(LPBYTE)(&pPublicSpi->chnum),&dwDataSize)!=ERROR_SUCCESS)
{
ERRMSG((TEXT("[SPI] Error RegQueryValueEx\r\n")));
pPublicSpi->chnum=0;
bResult = FALSE;
goto CleanUp;
}
DBGMSG(SPI_DEBUG,(TEXT("[SPI] chnum=%d\r\n"), pPublicSpi->chnum));
if (!InterruptInitialize(pPublicSpi->dwSpiSysIntr, pPublicSpi->hSpiEvent, NULL, 0))
{
ERRMSG((TEXT("[SPI] SPI Interrupt Initialization failed!!!\n")));
bResult = FALSE;
goto CleanUp;
}
if(!HW_Init(pPublicSpi))
{
ERRMSG((TEXT("[SPI] HW_Init is failed\n")));
bResult = FALSE;
goto CleanUp;
}
if(!InitializeDMABuffer(pPublicSpi))
{
ERRMSG((TEXT("[SPI] InitializeBuffer is failed\n")));
bResult = FALSE;
goto CleanUp;
}
if(pPublicSpi->chnum==SPI0)
{
DBGMSG(SPI_INFO,(TEXT("[SPI] CH0 DMA \n")));
pPublicSpi->dw_spi_dma_tx_ch = DMAsrc_SPI_0_TX;
pPublicSpi->dw_spi_dma_rx_ch = DMAsrc_SPI_0_RX;
}
else if(pPublicSpi->chnum==SPI1)
{
DBGMSG(SPI_INFO,(TEXT("[SPI] CH1 DMA \n")));
pPublicSpi->dw_spi_dma_tx_ch = DMAsrc_SPI_1_TX;
pPublicSpi->dw_spi_dma_rx_ch = DMAsrc_SPI_1_RX;
}
else if(pPublicSpi->chnum==SPI2)
{
DBGMSG(SPI_INFO,(TEXT("[SPI] CH2 DMA \n")));
pPublicSpi->dw_spi_dma_tx_ch = DMAsrc_SPI_2_TX;
pPublicSpi->dw_spi_dma_rx_ch = DMAsrc_SPI_2_RX;
}
else
{
ERRMSG((TEXT("[SPI] Invalid channel \n")));
}
if( DMA_request_channel(&pPublicSpi->SPIDMAInfo.g_OutputDMA, pPublicSpi->dw_spi_dma_tx_ch) != TRUE )
{
ERRMSG((TEXT("[SPI] DMA SPI TX channel request is failed\n")));
bResult = FALSE;
goto CleanUp;
}
if( DMA_request_channel(&pPublicSpi->SPIDMAInfo.g_InputDMA, pPublicSpi->dw_spi_dma_rx_ch) != TRUE )
{
ERRMSG((TEXT("[SPI] DMA SPI RX channel request is failed\n")));
bResult = FALSE;
goto CleanUp;
}
do
{
InitializeCriticalSection(&(pPublicSpi->CsRxAccess));
InitializeCriticalSection(&(pPublicSpi->CsTxAccess));
//Rx Thread
pPublicSpi->hRxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pPublicSpi->hRxEvent == NULL)
{
ERRMSG((TEXT("[SPI] SPI Rx Event creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hRxThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForRx, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwRxThreadId);
if (pPublicSpi->hRxThread == NULL)
{
ERRMSG((TEXT("[SPI] SPI Rx Thread creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hRxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pPublicSpi->hRxDoneEvent == NULL)
{
ERRMSG( (TEXT("[SPI] SPI Rx Done Event creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hRxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pPublicSpi->hRxIntrDoneEvent == NULL)
{
ERRMSG( (TEXT("[SPI] SPI Rx Interrupt Event creation error!!!\n")));
bResult = FALSE;
break;
}
//Tx Thread
pPublicSpi->hTxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pPublicSpi->hTxEvent == NULL)
{
ERRMSG((TEXT("[SPI] SPI Tx Event creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hTxThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForTx, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwTxThreadId);
if (pPublicSpi->hTxThread == NULL)
{
ERRMSG((TEXT("[SPI] SPI Tx Thread creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hTxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pPublicSpi->hTxDoneEvent == NULL)
{
ERRMSG( (TEXT("[SPI] SPI Tx Done Event creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hTxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pPublicSpi->hTxIntrDoneEvent == NULL)
{
ERRMSG( (TEXT("[SPI] SPI Tx Interrupt Event creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hSpiThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForSpi, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwSpiThreadId);
if (pPublicSpi->hSpiThread == NULL)
{
ERRMSG((TEXT("[SPI] SPI ISR Thread creation error!!!\n")));
bResult = FALSE;
break;
}
//Tx DMA Done ISR
pPublicSpi->dwTxDmaDoneSysIntr = SYSINTR_NOP;
dwHwIntr = pPublicSpi->SPIDMAInfo.g_OutputDMA.dwIRQ;
pPublicSpi->hTxDmaDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwTxDmaDoneSysIntr, sizeof(DWORD), NULL))
{
ERRMSG((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))
{
ERRMSG((TEXT("[SPI] DMA Interrupt Initialization failed!!!\n")));
bResult = FALSE;
break;
}
//Rx DMA Done ISR
pPublicSpi->dwRxDmaDoneSysIntr = SYSINTR_NOP;
dwHwIntr = pPublicSpi->SPIDMAInfo.g_InputDMA.dwIRQ;
pPublicSpi->hRxDmaDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwRxDmaDoneSysIntr, sizeof(DWORD), NULL))
{
ERRMSG((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))
{
ERRMSG((TEXT("[SPI] DMA Interrupt Initialization failed!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->m_hPowerCon = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if(pPublicSpi->m_hPowerCon == INVALID_HANDLE_VALUE)
{
ERRMSG((L"[SPI:ERR] Initialize() : CreateFile() m_hPowerCon Open is failed\n\r"));
bResult = FALSE;
break;
}
DMA_initialize_channel(&pPublicSpi->SPIDMAInfo.g_OutputDMA, TRUE);
DMA_initialize_channel(&pPublicSpi->SPIDMAInfo.g_InputDMA, TRUE);
} while (0);
CleanUp:
DBGMSG(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 = NULL;
PSPI_PRIVATE_CONTEXT pSpiPrivate = NULL;
BOOL bResult = TRUE;
DBGMSG(SPI_FUNC,(TEXT("++[SPI] SPI_Open CH\r\n")));
if(pContext != 0)
{
pSpiPublic = (PSPI_PUBLIC_CONTEXT) pContext;
}
else
{
bResult = FALSE;
goto CleanUp;
}
if ( !(pSpiPrivate = (PSPI_PRIVATE_CONTEXT)LocalAlloc( LPTR, sizeof(SPI_PRIVATE_CONTEXT) )) )
{
ERRMSG((TEXT("[SPI] Can't not allocate for SPI Context\n")));
bResult = FALSE;
goto CleanUp;
}
pSpiPrivate->State = STATE_INIT;
pSpiPrivate->pSpiPublic = pSpiPublic;
// Display driver use GPB4,5,6,7(SPI1) as output mode
// To test SPI1, reconfiguration
// Apply this at Display driver
/*if(pSpiPublic->chnum==SPI1)
{
Set_PinFunction(pSpiPublic->pGPIOregs, SPI1_CLK);
Set_PinFunction(pSpiPublic->pGPIOregs, SPI1_nSS);
Set_PinFunction(pSpiPublic->pGPIOregs, SPI1_MISO);
Set_PinFunction(pSpiPublic->pGPIOregs, SPI1_MOSI);
Set_PinPullUD(pSpiPublic->pGPIOregs, SPI1_CLK, sgip_PULL_DISABLE);
Set_PinPullUD(pSpiPublic->pGPIOregs, SPI1_nSS, sgip_PULL_DISABLE);
Set_PinPullUD(pSpiPublic->pGPIOregs, SPI1_MISO, sgip_PULL_DISABLE);
Set_PinPullUD(pSpiPublic->pGPIOregs, SPI1_MOSI, sgip_PULL_DISABLE);
}*/
DBGMSG(SPI_INFO,(TEXT("[SPI_CH%d] GPB_CON = %x\r\n"),pSpiPublic->chnum ,pSpiPublic->pGPIOregs->GPB.GP_CON));
pSpiPrivate->bUseRxDMA = FALSE;
pSpiPrivate->bUseRxIntr = FALSE;
pSpiPrivate->bUseTxDMA = FALSE;
pSpiPrivate->bUseTxIntr = FALSE;
pSpiPrivate->spi_tx_data_addr = BASE_REG_PA_SPI0+(pSpiPublic->chnum*BASE_REG_SPI_OFFSET)+0x18;
pSpiPrivate->spi_rx_data_addr = BASE_REG_PA_SPI0+(pSpiPublic->chnum*BASE_REG_SPI_OFFSET)+0x1C;
CleanUp:
DBGMSG(SPI_FUNC,(TEXT("--[SPI] SPI_Open\r\n")));
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;
BOOL bResult = TRUE;
ULONG BytesRead = 0;
UINT i;
DBGMSG(SPI_FUNC,(TEXT("++[SPI] SPI_Read \r\n")));
DBGMSG(SPI_INFO,(TEXT("++[SPI] SPI_GPIO GPB_DRV_SR =%x, GPB_PUD = %x, GPB_CON = %x\r\n")
, pSpiPublic->pGPIOregs->GPB.GP_DRV_SR
, pSpiPublic->pGPIOregs->GPB.GP_PUD
, pSpiPublic->pGPIOregs->GPB.GP_CON));
DBGMSG(SPI_INFO,(TEXT("++[SPI] SPI_GPIO GPG2_DRV_SR =%x, GPG2_PUD = %x, GPG2_CON = %x\r\n")
, pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR
, pSpiPublic->pGPIOregs->GPG2.GP_PUD
, pSpiPublic->pGPIOregs->GPG2.GP_CON));
if((PSPI_PRIVATE_CONTEXT)hOpenContext == NULL)
{
bResult = FALSE;
goto CleanUp;
}
//param check
if(pSpiPrivate->State != STATE_IDLE)
{
ERRMSG((TEXT("[SPI] READ ERROR : STATE IS NOT IDLE\n")));
bResult = FALSE;
goto CleanUp;
}
DBGMSG(SPI_INFO,(TEXT("[SPI] pRxBuffer : 0x%X, Count : %d\n"), pBuffer, Count));
if(SPI_DEBUG)
{
memset(pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr, 0, SPI_DMA_BUF_SIZE);
for (i = 0; i < Count; i++)
{
DBGMSG(SPI_USR2,(TEXT("%d "),pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr[i]));
}
}
if(pSpiPrivate->bUseRxDMA)
{
pSpiPrivate->pRxBuffer = pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr;
pSpiPrivate->pRxDMABuffer = (LPVOID)pSpiPublic->SPIDMAInfo.DmaDstAddress;
}
else
{
pSpiPrivate->pRxBuffer = pBuffer;
}
pSpiPrivate->dwRxCount = Count;
pSpiPublic->pSpiPrivate = pSpiPrivate;
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_SLAVE_MODE && pSpiPrivate->ClrSlaveReady)
{
pSpiPrivate->ClrSlaveReady(pSpiPrivate);
}
#endif
SetEvent(pSpiPublic->hRxEvent);
//Thread call
WaitForSingleObject(pSpiPublic->hRxDoneEvent, INFINITE);
pSpiPrivate->State = STATE_IDLE;
if(pSpiPrivate->bUseRxDMA)
{
memcpy(pBuffer, pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr,Count);
}
else if(SPI_DEBUG)
{
memcpy(pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr, pBuffer,Count);
}
CleanUp:
BytesRead = Count - pSpiPrivate->dwRxCount;
DBGMSG(SPI_MSG,(TEXT("[SPI] SPI_Read : Return Value : %d\n\n"), BytesRead));
if(SPI_DEBUG)
{
for (i = 0; i < Count; i++)
{
DBGMSG(SPI_USR4,(TEXT("%d "),pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr[i]));
}
}
DBGMSG(SPI_FUNC,(TEXT("--[SPI] SPI_Read\r\n")));
if(bResult)
{
return BytesRead;
}
else
{
return -1;
}
}
DWORD
SPI_Write(
DWORD hOpenContext,
LPVOID pBuffer,
DWORD Count)
{
PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)hOpenContext;
PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
BOOL bResult = TRUE;
ULONG BytesWritten = 0;
UINT i;
DBGMSG(SPI_FUNC,(TEXT("++[SPI] SPI_Write chnum = %d\r\n"),pSpiPublic->chnum));
DBGMSG(SPI_INFO,(TEXT("++[SPI] SPI_GPIO GP_DRV_SR =%x, GP_PUD = %x, GP_CON = %x\r\n")
, pSpiPublic->pGPIOregs->GPB.GP_DRV_SR
, pSpiPublic->pGPIOregs->GPB.GP_PUD
, pSpiPublic->pGPIOregs->GPB.GP_CON));
if((PSPI_PRIVATE_CONTEXT)hOpenContext == NULL)
{
bResult = FALSE;
goto CleanUp;
}
//param check
if(pSpiPrivate->State != STATE_IDLE)
{
ERRMSG((TEXT("[SPI] WRITE ERROR : STATE IS NOT IDLE\n")));
bResult = FALSE;
goto CleanUp;
}
DBGMSG(SPI_MSG,(TEXT("[SPI] pBuffer : 0x%X, Count : %d\n"), pBuffer, Count));
if(pSpiPrivate->bUseTxDMA)
{
memcpy(pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr,pBuffer, Count);
pSpiPrivate->pTxBuffer = pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr;
pSpiPrivate->pTxDMABuffer = (LPVOID)pSpiPublic->SPIDMAInfo.DmaSrcAddress;
}
else if(SPI_DEBUG)
{
memcpy(pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr,pBuffer, Count);
pSpiPrivate->pTxBuffer = (LPVOID)pBuffer;
}
if(SPI_DEBUG)
{
for (i = 0; i < Count; i++)
{
DBGMSG(SPI_USR1,(TEXT("%d "),pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr[i]));
}
}
pSpiPrivate->dwTxCount = Count;
pSpiPublic->pSpiPrivate = pSpiPrivate;
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_MASTER_MODE && pSpiPrivate->GetSlaveReady)
{
while(!(pSpiPrivate->GetSlaveReady(pSpiPrivate)))
{
Sleep(1); //Do nothing
}
}
#endif
SetEvent(pSpiPublic->hTxEvent);
//Thread call
WaitForSingleObject(pSpiPublic->hTxDoneEvent, INFINITE);
pSpiPrivate->State = STATE_IDLE;
CleanUp:
BytesWritten = Count - pSpiPrivate->dwTxCount;
DBGMSG(SPI_INFO,(TEXT("[SPI] SPI_Write : Return Value : %d\n"), BytesWritten));
if(SPI_DEBUG)
{
for (i = 0; i < Count; i++)
{
DBGMSG(SPI_USR3,(TEXT("%d "),pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr[i]));
}
}
DBGMSG(SPI_FUNC,(TEXT("--[SPI] SPI_Write\r\n")));
if(bResult)
{
return BytesWritten;
}
else
{
return -1;
}
}
BOOL
SPI_IOControl(
DWORD dwInst,
DWORD dwIoControlCode,
PBYTE lpInBuf,
DWORD nInBufSize,
PBYTE lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesRetruned)
{
PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)dwInst;
PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
volatile SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
volatile SPI_REG *pRxSPIregs = &pSpiPrivate->RxSPIregs;
volatile SPI_REG *pTxSPIregs = &pSpiPrivate->TxSPIregs;
PSPI_SET_CONFIG pSetConfig;
BOOL bResult = TRUE;
#ifdef BSP_USEDVFS
DWORD Profile;
DWORD dwBytes;
#endif
#ifdef SPI_FULL_DUPLEX
DWORD dwCount=0;
#endif
if((PSPI_PRIVATE_CONTEXT)dwInst == NULL)
{
bResult = FALSE;
goto CleanUp;
}
switch(dwIoControlCode)
{
case SPI_IOCTL_SET_CONFIG:
DBGMSG(SPI_INFO,(TEXT("[SPI] SPI STATE : SPI_IOCTL_SET_CONFIG\n")));
if( nInBufSize != sizeof(SPI_SET_CONFIG) )
{
bResult = FALSE;
break;
}
pSetConfig = (PSPI_SET_CONFIG) lpInBuf;
pSpiPrivate->dwTimeOutVal = pSetConfig->dwTimeOutVal;
pSpiPrivate->dwMode = pSetConfig->dwMode;
pSpiPrivate->dwPrescaler = pSetConfig->dwPrescaler;
pSpiPrivate->bUseRxDMA = pSetConfig->bUseRxDMA;
pSpiPrivate->bUseRxIntr = pSetConfig->bUseRxIntr;
pSpiPrivate->bUseTxDMA = pSetConfig->bUseTxDMA;
pSpiPrivate->bUseTxIntr = pSetConfig->bUseTxIntr;
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->dwTimeOutVal = %d \n"),pSpiPublic->chnum, pSetConfig->dwTimeOutVal));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->dwMode = %d \n"),pSpiPublic->chnum, pSetConfig->dwMode));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->dwPrescaler = %d (%d) \n"),pSpiPublic->chnum, pSetConfig->dwPrescaler, pSpiPrivate->dwPrescaler ));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->bUseRxDMA = %d \n"),pSpiPublic->chnum, pSetConfig->bUseRxDMA));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->bUseRxIntr = %d \n"),pSpiPublic->chnum, pSetConfig->bUseRxIntr));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->bUseTxDMA = %d \n"),pSpiPublic->chnum, pSetConfig->bUseTxDMA));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->bUseTxIntr = %d \n"),pSpiPublic->chnum, pSetConfig->bUseTxIntr));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pSetConfig->Format = %d \n"),pSpiPublic->chnum, pSetConfig->Format));
if (pSetConfig->Format == SPI_FORMAT_0)
{
pRxSPIregs->CH_CFG = CPOL_RISING|CPHA_FORMAT_A;
}
else if (pSetConfig->Format == SPI_FORMAT_1)
{
pRxSPIregs->CH_CFG = CPOL_RISING | CPHA_FORMAT_B;
}
else if (pSetConfig->Format == SPI_FORMAT_2)
{
pRxSPIregs->CH_CFG = CPOL_FALLING | CPHA_FORMAT_A;
}
else if (pSetConfig->Format == SPI_FORMAT_3)
{
pRxSPIregs->CH_CFG = CPOL_FALLING | CPHA_FORMAT_B;
}
else
{
ERRMSG((TEXT("[SPI] This SPI_FORMAT is not supported\n")));
}
//Slave TX output time control
pRxSPIregs->CH_CFG &= ~(HIGH_SPEED_MASK);
if (pSpiPrivate->dwPrescaler == 0)
{
pRxSPIregs->CH_CFG |= (HIGH_SPEED_EN);
}
pRxSPIregs->FB_CLK_SEL = pSetConfig->dwFBClkSel;
pRxSPIregs->CLK_CFG = CLKSEL|(pSpiPrivate->dwPrescaler);
pRxSPIregs->MODE_CFG = MODE_DEFAULT;
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pRxSPIregs->CH_CFG = %d \n"), pSpiPublic->chnum, pRxSPIregs->CH_CFG));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pRxSPIregs->FB_CLK_SEL = %d \n"), pSpiPublic->chnum, pRxSPIregs->FB_CLK_SEL));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pRxSPIregs->CLK_CFG = %d \n"), pSpiPublic->chnum, pRxSPIregs->CLK_CFG));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pRxSPIregs->MODE_CFG = %d \n"), pSpiPublic->chnum, pRxSPIregs->MODE_CFG));
pTxSPIregs->CH_CFG &= ~(HIGH_SPEED_MASK);
pTxSPIregs->CH_CFG = pRxSPIregs->CH_CFG;
pTxSPIregs->FB_CLK_SEL = pSetConfig->dwFBClkSel;
pTxSPIregs->CLK_CFG = pRxSPIregs->CLK_CFG;
pTxSPIregs->MODE_CFG = pRxSPIregs->MODE_CFG;
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pTxSPIregs->CH_CFG = %d \n"), pSpiPublic->chnum, pTxSPIregs->CH_CFG));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pTxSPIregs->FB_CLK_SEL = %d \n"), pSpiPublic->chnum, pTxSPIregs->FB_CLK_SEL));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pTxSPIregs->CLK_CFG = %d \n"), pSpiPublic->chnum, pTxSPIregs->CLK_CFG));
DBGMSG(SPI_USR2,(TEXT("[SPI%d] pTxSPIregs->MODE_CFG = %d \n"), pSpiPublic->chnum, pTxSPIregs->MODE_CFG));
//SPI_SFR_DUMP(pSpiPublic);
if (pSetConfig->dwLineStrength == 0)
{
DBGMSG(SPI_USR2,(TEXT("[SPI%d] DRV Strength 1x \n"), pSpiPublic->chnum));
if (pSpiPublic->chnum == SPI0)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<0)) | (0x0<<0);
}
else if (pSpiPublic->chnum == SPI1)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<8)) | (0x0<<8);
}
else if (pSpiPublic->chnum == SPI2)
{
pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR & ~(0xFF<<0)) | (0x0<<0);
}
else
{
ERRMSG((TEXT("[SPI%d] It's not supported MODE\n"), pSpiPublic->chnum));
}
}
else if (pSetConfig->dwLineStrength == 1)
{
DBGMSG(SPI_USR2,(TEXT("[SPI%d] DRV Strength 2x \n"), pSpiPublic->chnum));
if (pSpiPublic->chnum == SPI0)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<0)) | (0xAA<<0);
}
else if (pSpiPublic->chnum == SPI1)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<8)) | (0xAA<<8);
}
else if (pSpiPublic->chnum == SPI2)
{
pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR & ~(0xFF<<0)) | (0xAA<<0);
}
else
{
ERRMSG((TEXT("[SPI%d] It's not supported MODE\n"), pSpiPublic->chnum));
}
}
else if (pSetConfig->dwLineStrength == 2)
{
DBGMSG(SPI_USR2,(TEXT("[SPI%d] DRV Strength 3x \n"), pSpiPublic->chnum));
if (pSpiPublic->chnum == SPI0)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<0)) | (0x55<<0);
}
else if (pSpiPublic->chnum == SPI1)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<8)) | (0x55<<8);
}
else if (pSpiPublic->chnum == SPI2)
{
pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR & ~(0xFF<<0)) | (0x55<<0);
}
else
{
ERRMSG((TEXT("[SPI%d] It's not supported MODE\n"), pSpiPublic->chnum));
}
}
else if (pSetConfig->dwLineStrength == 3)
{
DBGMSG(SPI_USR2,(TEXT("[SPI%d] DRV Strength 4x \n"), pSpiPublic->chnum));
if (pSpiPublic->chnum == SPI0)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<0)) | (0xFF<<0);
}
else if (pSpiPublic->chnum == SPI1)
{
pSpiPublic->pGPIOregs->GPB.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPB.GP_DRV_SR & ~(0xFF<<8)) | (0xFF<<8);
}
else if (pSpiPublic->chnum == SPI2)
{
pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR = (pSpiPublic->pGPIOregs->GPG2.GP_DRV_SR & ~(0xFF<<0)) | (0xFF<<0);
}
else
{
ERRMSG((TEXT("[SPI%d] LineStrength for this channel not supported \n"), pSpiPublic->chnum));
}
}
else
{
ERRMSG((TEXT("[SPI%d] This LineStrength value is not supported\n"), pSpiPublic->chnum));
}
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pRxSPIregs->CH_CFG |= SPI_MASTER;
pRxSPIregs->CLK_CFG |= ENCLK_ENABLE;
pTxSPIregs->CH_CFG |= SPI_MASTER;
pTxSPIregs->CLK_CFG |= ENCLK_ENABLE;
}
else if(pSpiPrivate->dwMode == SPI_SLAVE_MODE)
{
pRxSPIregs->CH_CFG |= SPI_SLAVE;
pRxSPIregs->CLK_CFG |= ENCLK_DISABLE;
pTxSPIregs->CH_CFG |= SPI_SLAVE;
pTxSPIregs->CLK_CFG |= ENCLK_DISABLE;
}
else
{
ERRMSG((TEXT("[SPI%d] It's not supported MODE\n"), pSpiPublic->chnum));
pSpiPrivate->State = STATE_ERROR;
}
#ifdef BSP_USEDVFS
if(!pSpiPublic->m_bDVFSFixed)
{
Profile = HIGH_PERF;
if(!DeviceIoControl(pSpiPublic->m_hPowerCon, IOCTL_DVFS_SET_PROFILE, &Profile, sizeof(DWORD), NULL, 0, &dwBytes, NULL))
{
ERRMSG((L"[WAV] ERROR : It's failed to fix DVFS into HIGH_PERF\r\n"));
}
else
pSpiPublic->m_bDVFSFixed = TRUE;
}
#endif
#ifdef SPI_EX_GPIO_CALLBACK
HSPCALLBACK_Init(pSpiPrivate);
#endif
break;
case SPI_IOCTL_START:
DBGMSG(SPI_INFO,(TEXT("[SPI%d] SPI STATE : SPI_IOCTL_START\n"), pSpiPublic->chnum));
if(pSpiPrivate->State == STATE_ERROR)
{
ERRMSG((TEXT("[SPI%d] SPI_IOCTL_START ERROR\n"), pSpiPublic->chnum));
bResult = FALSE;
break;
}
pSpiPrivate->State = STATE_IDLE;
break;
case SPI_IOCTL_STOP:
DBGMSG(SPI_INFO,(TEXT("[SPI%d] SPI STATE : SPI_IOCTL_STOP\n"), pSpiPublic->chnum));
#ifdef BSP_USEDVFS
if(pSpiPublic->m_bDVFSFixed)
{
Profile = HIGH_PERF;
if(!DeviceIoControl(pSpiPublic->m_hPowerCon, IOCTL_DVFS_CLEAR_PROFILE, &Profile, sizeof(DWORD), NULL, 0, &dwBytes, NULL))
{
ERRMSG((L"[WAV] ERROR : It's failed to clear fixed DVFS value\r\n"));
}
else
pSpiPublic->m_bDVFSFixed = FALSE;
}
#endif
break;
#ifdef SPI_EX_GPIO_CALLBACK
case SPI_IOCTL_SET_CALLBACK:
DBGMSG(SPI_INFO,(TEXT("[SPI%d] SPI STATE : SPI_IOCTL_SET_CALLBACK\n"), pSpiPublic->chnum));
HSPCALLBACK_Init(pSpiPrivate);
break;
case SPI_IOCTL_CLR_CALLBACK:
DBGMSG(SPI_INFO,(TEXT("[SPI%d] SPI STATE : SPI_IOCTL_CLR_CALLBACK\n"), pSpiPublic->chnum));
HSPCALLBACK_Deinit(pSpiPrivate);
break;
case SPI_IOCTL_IS_SLAVE_READY:
DBGMSG(SPI_INFO,(TEXT("[SPI%d] SPI STATE : SPI_IOCTL_IS_SLAVE_READY\n"), pSpiPublic->chnum));
*(BOOL *)lpOutBuf = pSpiPrivate->GetSlaveReady(pSpiPrivate);
break;
#endif
#ifdef SPI_COMM_STREAM_IF
case SPI_IOCTL_SERIAL_GET_WAIT_MASK:
DBGMSG (SPI_INFO,(TEXT("[SPI%d] IOCTL_SERIAL_GET_WAIT_MASK\r\n"), pSpiPublic->chnum));
if ( (nOutBufSize < sizeof(DWORD)) || (NULL == lpOutBuf) ||(NULL == lpBytesRetruned) )
{
SetLastError (ERROR_INVALID_PARAMETER);
bResult = FALSE;
ERRMSG((TEXT("[SPI%d] SPI_IOCTL_SERIAL_GET_WAIT_MASK: Invalid parameter\r\n"), pSpiPublic->chnum));
break;
}
// Set The Wait Mask
*(DWORD *)lpOutBuf = pSpiPrivate->dwEventMask;
// Return the size
*lpBytesRetruned = sizeof(DWORD);
break;
case SPI_IOCTL_SERIAL_SET_WAIT_MASK:
DBGMSG (SPI_INFO,(TEXT("[SPI%d] SPI_IOCTL_SERIAL_SET_WAIT_MASK\r\n"), pSpiPublic->chnum));
if ( (nInBufSize < sizeof(DWORD)) || (NULL == lpInBuf) )
{
SetLastError (ERROR_INVALID_PARAMETER);
bResult = FALSE;
ERRMSG((TEXT("[SPI%d] SPI_IOCTL_SERIAL_SET_WAIT_MASK: Invalid parameter\r\n"), pSpiPublic->chnum));
break;
}
else
{
DWORD dwFlagEventMask = 0;
dwFlagEventMask = *(DWORD *)lpInBuf;
pSpiPrivate->dwEventMask = dwFlagEventMask;
SetEvent(pSpiPrivate->hCommEvent);
}
break;
case SPI_IOCTL_SERIAL_WAIT_ON_MASK:
DBGMSG (SPI_INFO,(TEXT("[SPI%d] SPI_IOCTL_SERIAL_WAIT_ON_MASK\r\n"), pSpiPublic->chnum));
if ( (nOutBufSize < sizeof(DWORD)) || (NULL == lpOutBuf) ||(NULL == lpBytesRetruned) )
{
SetLastError (ERROR_INVALID_PARAMETER);
bResult = FALSE;
ERRMSG((TEXT("[SPI%d] SPI_IOCTL_SERIAL_WAIT_ON_MASK: Invalid parameter\r\n"), pSpiPublic->chnum));
break;
}
if(pSpiPrivate->dwEventMask==0)
{
return (FALSE);
}
WaitForSingleObject(pSpiPrivate->hCommEvent, (ULONG)-1);
*(DWORD *)lpOutBuf = pSpiPrivate->dwEventMask;
*lpBytesRetruned = sizeof(DWORD);
bResult=TRUE;
break;
#endif //SPI_COMM_STREAM_IF
#ifdef SPI_FULL_DUPLEX
case SPI_IOCTL_FULL_DUPLEX:
DBGMSG (SPI_INFO,(TEXT("[SPI%d] SPI_IOCTL_FULL_DUPLEX\r\n"), pSpiPublic->chnum));
if ( (nInBufSize < sizeof(DWORD)) || (NULL == lpInBuf) )
{
SetLastError (ERROR_INVALID_PARAMETER);
bResult = FALSE;
ERRMSG((TEXT("[SPI%d] SPI_IOCTL_FULL_DUPLEX: Invalid parameter\r\n"), pSpiPublic->chnum));
break;
}
else
{
dwCount=(nInBufSize>nOutBufSize)? (nInBufSize):(nOutBufSize);
*lpBytesRetruned = dwCount;
if(!SPI_FullDuplex(pSpiPrivate, lpInBuf, lpOutBuf, dwCount))
bResult = FALSE;
}
break;
#endif
default:
pSpiPrivate->Error = UNDEFINED_ERROR;
goto CleanUp;
}
CleanUp:
return bResult;
}
DWORD ThreadForTx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwTxCount;
PBYTE pTxBuffer;
DWORD dwOldPerm;
PBYTE pTestBuffer;
DWORD dwTestCount;
ULONG TimeOut;
ULONG TotalTimeOut;
ULONG WaitReturn;
INT TimeOutCount;
do
{
WaitForSingleObject(pSpiPublic->hTxEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
if(pSpiPrivate->dwTxCount != 0)
{
dwTestCount = dwTxCount = pSpiPrivate->dwTxCount;
}
dwOldPerm = SetProcPermissions((DWORD)-1);
pTestBuffer = pTxBuffer = (PBYTE) MapPtrToProcess(pSpiPrivate->pTxBuffer, (HANDLE) GetCurrentProcessId());
DBGMSG(SPI_USR2,(TEXT("[SPI] pTxBuffer : 0x%X, dwTxCount : %d \r\n"), pTxBuffer, dwTxCount));
//Reset
pSPIregs->CH_CFG |= SW_RST;
while(!(pSPIregs->CH_CFG & SW_RST));
DBGMSG(SPI_USR2,(TEXT("[SPI] HS SPI reset\n")));
pSPIregs->CH_CFG &= ~SW_RST;
if(pSpiPrivate->bUseTxIntr)
// INT + TX
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : USE INT \r\n")));
pSpiPrivate->State = STATE_TXINTR;
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->TxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG|(GetTxTriggerLevel(pSpiPublic->chnum) <<5);
DBGMSG(SPI_USR2,(TEXT("[SPI] pSPIregs->FB_CLK_SEL = %d \n"),pSPIregs->FB_CLK_SEL));
pSPIregs->SPI_INT_EN = TX_FIFORDY;
pSPIregs->PENDING_CLR_REG = TX_UNDERRUN_CLR|TX_OVERRUN_CLR|RX_UNDERRUN_CLR|RX_OVERRUN_CLR|TRAILING_CLR;
pSPIregs->CH_CFG |= TX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
}
//Timeout value setting
TotalTimeOut = WRITE_TIME_OUT_CONSTANT + (WRITE_TIME_OUT_MULTIPLIER/1000)*dwTxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hTxIntrDoneEvent, TimeOut);
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
ERRMSG ((TEXT("Write timeout!!!\r\n")));
goto LEAVEWRITE;
}
TimeOutCount = 1000;
while((((pSPIregs ->SPI_STATUS>>6) & 0x1ff) && !(pSPIregs ->SPI_STATUS & TX_DONE))
|| (TimeOutCount>0))
{
TimeOutCount--;
}
}
else if(pSpiPrivate->bUseTxDMA)
// DMA + TX
{
DWORD dwDmaLen = dwTxCount & 0xFFFFF;
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : USE DMA (TxCount : %d) \r\n"),dwDmaLen));
pSpiPrivate->State = STATE_TXDMA;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->TxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG;
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->TxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG;
}
if(dwDmaLen > 0)
{
pSPIregs->MODE_CFG |= TX_DMA_ON|DMA_SINGLE;
pSPIregs->CH_CFG |= TX_CH_ON;
{
DBGMSG(SPI_USR2,(TEXT("[SPI] pSpiPrivate->pTxDMABuffer : 0x%X \r\n"), pSpiPrivate->pTxDMABuffer));
DMA_set_channel_source(&pSpiPublic->SPIDMAInfo.g_OutputDMA, (UINT)pSpiPrivate->pTxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
DMA_set_channel_destination(&pSpiPublic->SPIDMAInfo.g_OutputDMA, pSpiPrivate->spi_tx_data_addr, BYTE_UNIT, BURST_1, FIXED);
DMA_set_channel_transfer_size(&pSpiPublic->SPIDMAInfo.g_OutputDMA, dwDmaLen);
DMA_initialize_LLI(&pSpiPublic->SPIDMAInfo.g_OutputDMA, 1);
DMA_set_LLI_entry(&pSpiPublic->SPIDMAInfo.g_OutputDMA, 0, LLI_FIRST_ENTRY, (UINT)pSpiPrivate->pTxDMABuffer,
pSpiPrivate->spi_tx_data_addr, dwDmaLen);
}
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
}
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_MASTER_MODE && pSpiPrivate->GetSlaveReady)
{
while(!(pSpiPrivate->GetSlaveReady(pSpiPrivate)))
{
Sleep(1) ; //Do nothing
}
}
#endif
//SPI_SFR_DUMP(pSpiPublic);
DMA_channel_start(&pSpiPublic->SPIDMAInfo.g_OutputDMA);
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_SLAVE_MODE && pSpiPrivate->SetSlaveReady)
{
// while((pSPIregs->SPI_STATUS & (0x1FF >> 6)) < (GetFifoSize(pSpiPublic->chnum)))
{
; //Do nothing
}
pSpiPrivate->SetSlaveReady(pSpiPrivate);
}
#endif
//Timeout value setting
TotalTimeOut = WRITE_TIME_OUT_CONSTANT + (WRITE_TIME_OUT_MULTIPLIER/1000)*dwTxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hTxDmaDoneEvent, TimeOut);
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_SLAVE_MODE && pSpiPrivate->ClrSlaveReady)
{
pSpiPrivate->ClrSlaveReady(pSpiPrivate);
}
#endif
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
DBGMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
// Stop output DMA
DMA_channel_stop(&pSpiPublic->SPIDMAInfo.g_OutputDMA);
goto LEAVEWRITE;
}
DMA_clear_interrupt_pending(&pSpiPublic->SPIDMAInfo.g_OutputDMA);
DMA_set_interrupt_mask(&pSpiPublic->SPIDMAInfo.g_OutputDMA);
InterruptDone(pSpiPublic->dwTxDmaDoneSysIntr);
DMA_clear_interrupt_mask(&pSpiPublic->SPIDMAInfo.g_OutputDMA);
pSpiPrivate->dwTxCount -= dwDmaLen;
pSpiPrivate->pTxBuffer = (((PUINT) pSpiPrivate->pTxBuffer) + dwDmaLen);
}
TimeOutCount = 1000;
while((((pSPIregs ->SPI_STATUS>>6) & 0x1ff) && !(pSPIregs ->SPI_STATUS & TX_DONE))
|| (TimeOutCount>0))
{
TimeOutCount--;
}
}
else
// POLLING + TX
{
ULONG Count;
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : USE Polling (TxCount : %d) \r\n"), dwTxCount));
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG;
pSPIregs->CH_CFG |= TX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
}
TotalTimeOut = WRITE_TIME_OUT_CONSTANT*100*50 + (WRITE_TIME_OUT_MULTIPLIER)*dwTxCount;
Count = 0;
do
{
while(((pSPIregs ->SPI_STATUS>>6) & 0x1ff)== GetFifoSize(pSpiPublic->chnum)) //FIFO_FULL
{
Count++;
if(TotalTimeOut == Count)
{
// Timeout
ERRMSG ((TEXT("Write timeout!!!\r\n")));
goto LEAVEWRITE;
}
}
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer);
TimeOutCount = 1000;
while((((pSPIregs ->SPI_STATUS>>6) & 0x1ff) && !(pSPIregs ->SPI_STATUS & TX_DONE))
|| (TimeOutCount>0))
{
TimeOutCount--;
}
}
LEAVEWRITE:
#ifdef TEST_MODE
do
{
DBGMSG(SPI_USR2,(TEXT("[SPI] WRITE BYTE : %02X(dwTxCount : %d)\n"), *pTestBuffer, dwTestCount));
} while( (--dwTestCount > 0) && ++pTestBuffer);
#endif
DBGMSG(FALSE,(TEXT("[SPI] TX_CH_OFF \n")));
pSPIregs->CH_CFG &= ~TX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
MASTER_CS_DISABLE;
}
UnMapPtr(pTxBuffer);
SetProcPermissions(dwOldPerm);
SetEvent(pSpiPublic->hTxDoneEvent);
} while(TRUE);
return 0;
}
DWORD ThreadForRx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwRxCount;
PBYTE pRxBuffer;
DWORD dwOldPerm;
PBYTE pTestBuffer;
DWORD dwTestCount;
ULONG TimeOut;
ULONG TotalTimeOut;
ULONG WaitReturn;
do
{
WaitForSingleObject(pSpiPublic->hRxEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
if(pSpiPrivate->dwRxCount != 0)
{
dwTestCount = dwRxCount = pSpiPrivate->dwRxCount;
}
dwOldPerm = SetProcPermissions((DWORD)-1);
pTestBuffer = pRxBuffer = (PBYTE) MapPtrToProcess(pSpiPrivate->pRxBuffer, (HANDLE) GetCurrentProcessId());
DBGMSG(SPI_USR2,(TEXT("[SPI] pRxBuffer : 0x%X, dwRxCount : %d \r\n"), pRxBuffer, dwRxCount));
//Reset
pSPIregs->CH_CFG |= SW_RST;
while(!(pSPIregs->CH_CFG & SW_RST));
DBGMSG(SPI_USR2,(TEXT("[SPI] HS SPI reset\n")));
pSPIregs->CH_CFG &= ~SW_RST;
if(pSpiPrivate->bUseRxIntr)
//INT Mode + RX
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : USE INT \r\n")));
pSpiPrivate->State = STATE_RXINTR;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->RxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11);
pSPIregs->PACKET_CNT_REG = PACKET_CNT_EN | (pSpiPrivate->dwRxCount) ;
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->RxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11);
pSPIregs->PACKET_CNT_REG = PACKET_CNT_EN | (pSpiPrivate->dwRxCount) ;
}
DBGMSG(SPI_USR2,(TEXT("[SPI] pSPIregs->FB_CLK_SEL = %d \n"),pSPIregs->FB_CLK_SEL));
pSPIregs->SPI_INT_EN = RX_FIFORDY;
pSPIregs->PENDING_CLR_REG = TX_UNDERRUN_CLR|TX_OVERRUN_CLR|RX_UNDERRUN_CLR|RX_OVERRUN_CLR|TRAILING_CLR;
pSPIregs->CH_CFG |= RX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
}
//Timeout value setting
TotalTimeOut = READ_TIME_OUT_CONSTANT + (READ_TIME_OUT_MULTIPLIER/1000)*dwRxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hRxIntrDoneEvent, TimeOut);
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
ERRMSG ((TEXT("Read timeout!!!\r\n")));
goto LEAVEREAD;
}
}
else if(pSpiPrivate->bUseRxDMA)
//DMA Mode + Rx
{
DWORD dwDmaLen = (pSpiPrivate->dwRxCount & 0xFFFFF);
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : USE DMA \r\n")));
pSpiPrivate->State = STATE_RXDMA;
//Reset
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->RxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
pSPIregs->PACKET_CNT_REG = PACKET_CNT_EN | (pSpiPrivate->dwRxCount);
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->FB_CLK_SEL = pSpiPrivate->RxSPIregs.FB_CLK_SEL;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
pSPIregs->PACKET_CNT_REG = PACKET_CNT_EN | (pSpiPrivate->dwRxCount);
}
if(dwDmaLen > 0)
{
pSPIregs->MODE_CFG |= RX_DMA_ON|DMA_SINGLE;
pSPIregs->CH_CFG |= RX_CH_ON;
{
DMA_set_channel_source(&pSpiPublic->SPIDMAInfo.g_InputDMA, pSpiPrivate->spi_rx_data_addr, BYTE_UNIT, BURST_1, FIXED);
DMA_set_channel_destination(&pSpiPublic->SPIDMAInfo.g_InputDMA, (UINT)pSpiPrivate->pRxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
DMA_set_channel_transfer_size(&pSpiPublic->SPIDMAInfo.g_InputDMA, dwDmaLen);
DMA_initialize_LLI(&pSpiPublic->SPIDMAInfo.g_InputDMA, 1);
DMA_set_LLI_entry(&pSpiPublic->SPIDMAInfo.g_InputDMA, 0, LLI_FIRST_ENTRY, pSpiPrivate->spi_rx_data_addr,
(UINT)pSpiPrivate->pRxDMABuffer, dwDmaLen);
}
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
}
//SPI_SFR_DUMP(pSpiPublic);
DMA_channel_start(&pSpiPublic->SPIDMAInfo.g_InputDMA);
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_SLAVE_MODE && pSpiPrivate->SetSlaveReady)
{
pSpiPrivate->SetSlaveReady(pSpiPrivate);
}
#endif
//Timeout value setting
TotalTimeOut = READ_TIME_OUT_CONSTANT + (READ_TIME_OUT_MULTIPLIER/1000)*dwRxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hRxDmaDoneEvent, TimeOut);
#ifdef SLAVE_READY
if(pSpiPrivate->dwMode == SPI_SLAVE_MODE && pSpiPrivate->ClrSlaveReady)
{
pSpiPrivate->ClrSlaveReady(pSpiPrivate);
}
#endif
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
ERRMSG ((TEXT("Read timeout!!!\r\n")));
// Stop input DMA
DMA_channel_stop(&pSpiPublic->SPIDMAInfo.g_InputDMA);
goto LEAVEREAD;
}
DMA_clear_interrupt_pending(&pSpiPublic->SPIDMAInfo.g_InputDMA);
DMA_set_interrupt_mask(&pSpiPublic->SPIDMAInfo.g_InputDMA);
InterruptDone(pSpiPublic->dwRxDmaDoneSysIntr);
DMA_clear_interrupt_mask(&pSpiPublic->SPIDMAInfo.g_InputDMA);
pSpiPrivate->dwRxCount -= dwDmaLen;
pSpiPrivate->pRxBuffer = (PBYTE) (((PUINT) pSpiPrivate->pRxBuffer) + dwDmaLen);
}
}
else
{
//POLLING Mode + RX
ULONG Count;
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : USE Polling (RxCount : %d) \r\n"), dwRxCount));
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
pSPIregs->PACKET_CNT_REG = PACKET_CNT_EN | (pSpiPrivate->dwRxCount);
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
}
pSPIregs->CH_CFG |= RX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
}
TotalTimeOut = READ_TIME_OUT_CONSTANT*100*50 + (READ_TIME_OUT_MULTIPLIER)*dwRxCount;
Count = 0;
do
{
while (((pSPIregs ->SPI_STATUS >> 15) & 0x1ff) == FIFO_EMPTY)
{
Count++;
if(TotalTimeOut == Count)
{
// Timeout
ERRMSG ((TEXT("Read timeout!!!\r\n")));
goto LEAVEREAD;
}
}
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer);
}
LEAVEREAD:
#ifdef TEST_MODE
do
{
DBGMSG(SPI_USR2,(TEXT("[SPI] READ BYTE : %02X(dwRxCount %d)\n"), *pTestBuffer, dwTestCount));
} while((--dwTestCount > 0) && ++pTestBuffer);
#endif
DBGMSG(FALSE,(TEXT("[SPI] RX_CH_OFF \n")));
pSPIregs->CH_CFG &= ~RX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
MASTER_CS_DISABLE;
}
UnMapPtr(pRxBuffer);
SetProcPermissions(dwOldPerm);
SetEvent(pSpiPublic->hRxDoneEvent);
#ifdef SPI_COMM_STREAM_IF
pSpiPrivate->dwEventMask |= EV_RXCHAR;
SetEvent(pSpiPrivate->hCommEvent);
#endif
} while(TRUE);
return 0;
}
DWORD ThreadForSpi(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile SPI_REG *pSPIregs = pSpiPublic->pSPIregs; // for HS-SPI
PSPI_PRIVATE_CONTEXT pSpiPrivate;
UINT dwRxCount = 0;
UINT dwTxCount = 0;
DWORD dwOldPerm = 0;
DBGMSG(SPI_USR3,(TEXT("[SPI] ThreadForSpi thread is created \r\n")));
do
{
WaitForSingleObject(pSpiPublic->hSpiEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
dwOldPerm = SetProcPermissions((DWORD)-1);
if(pSpiPrivate->State == STATE_RXINTR)
{
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
dwRxCount = ((pSPIregs ->SPI_STATUS>>15) & 0x1ff) ;
DBGMSG(SPI_USR3,(TEXT("MR %d, %d\r\n"),pSpiPrivate->dwRxCount, dwRxCount));
if (dwRxCount != 0)
{
do
{
// while (((pSPIregs ->SPI_STATUS>>15)&0x1ff)==FIFO_EMPTY);
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
DBGMSG(SPI_USR4,(TEXT("MR %d, %d\r\n"),pSpiPrivate->dwRxCount, dwRxCount));
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer && --dwRxCount > 0);
}
else
{
ERRMSG((TEXT("dwRxCount is zero %d\r\n")));
}
if(pSpiPrivate->dwRxCount ==0)
{
pSPIregs->SPI_INT_EN &= ~(RX_FIFORDY|TX_FIFORDY);
SetEvent(pSpiPublic->hRxIntrDoneEvent);
}
DBGMSG(SPI_USR3,(TEXT("[SPI]MR %d, %d\r\n"),pSpiPrivate->dwRxCount, dwRxCount));
}
else
{
dwRxCount = ((pSPIregs ->SPI_STATUS>>15) & 0x1ff) ;
DBGMSG(SPI_USR3,(TEXT("SR %d, %d\r\n"),pSpiPrivate->dwRxCount, dwRxCount));
if (dwRxCount != 0)
{
do
{
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
DBGMSG(SPI_USR4,(TEXT("SR %d, %d\r\n"),pSpiPrivate->dwRxCount, dwRxCount));
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer && --dwRxCount > 0);
}
else
{
ERRMSG((TEXT("dwRxCount is zero %d\r\n")));
// SetEvent(pSpiPublic->hRxIntrDoneEvent);
}
if(pSpiPrivate->dwRxCount ==0)
{
pSPIregs->SPI_INT_EN &= ~(RX_FIFORDY|TX_FIFORDY);
SetEvent(pSpiPublic->hRxIntrDoneEvent);
}
DBGMSG(SPI_USR3,(TEXT("[SPI]SR %d, %d\r\n"),pSpiPrivate->dwRxCount, dwRxCount));
}
}
else if(pSpiPrivate->State == STATE_TXINTR)
{
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
dwTxCount = GetFifoSize(pSpiPublic->chnum)-((pSPIregs ->SPI_STATUS>>6) & 0x1ff) ;
if (dwTxCount != 0)
{
do
{
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
DBGMSG(SPI_USR4,(TEXT("MT %d, %d\r\n"),pSpiPrivate->dwTxCount, dwTxCount));
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer && --dwTxCount > 0);
}
else
{
ERRMSG((TEXT("dwTxCount is zero %d\r\n")));
// SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
if(pSpiPrivate->dwTxCount ==0)
{
pSPIregs->SPI_INT_EN &= ~(RX_FIFORDY|TX_FIFORDY);
SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
DBGMSG(SPI_USR3,(TEXT("[SPI]MT %d, %d\r\n"),pSpiPrivate->dwTxCount, dwTxCount));
}
else
{
dwTxCount = GetFifoSize(pSpiPublic->chnum) -((pSPIregs ->SPI_STATUS>>6) & 0x1ff) ;
if (dwTxCount != 0)
{
do
{
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
DBGMSG(SPI_USR4,(TEXT("ST %d, %d\r\n"),pSpiPrivate->dwTxCount, dwTxCount));
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer && --dwTxCount > 0);
}
else
{
ERRMSG((TEXT("dwTxCount is zero %d\r\n")));
// SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
if(pSpiPrivate->dwTxCount ==0)
{
pSPIregs->SPI_INT_EN &= ~(RX_FIFORDY|TX_FIFORDY);
SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
DBGMSG(SPI_USR3,(TEXT("[SPI]ST %d, %d\r\n"),pSpiPrivate->dwTxCount, dwTxCount));
}
}
else
{
ERRMSG((TEXT("[SPI] UNSOLVED OPERATION\n")));
}
//END_POINT:
SetProcPermissions(dwOldPerm);
InterruptDone(pSpiPublic->dwSpiSysIntr);
} while(TRUE);
return 0;
}
void SPI_PowerDown (PSPI_PUBLIC_CONTEXT pPublicSpi)
{
DBGMSG(SPI_MSG,(TEXT("[SPI] ++PowerDown()\n\r")));
if((PSPI_PUBLIC_CONTEXT)pPublicSpi == NULL)
{
goto CleanUp;
}
DBGMSG(SPI_MSG,(TEXT("[SPI] --PowerDown()\n\r")));
CleanUp:
return;
}
void SPI_Deinit (PSPI_PUBLIC_CONTEXT pPublicSpi)
{
DBGMSG(SPI_INIT,(TEXT("++[SPI] SPI_Deinit\r\n")));
if((PSPI_PUBLIC_CONTEXT)pPublicSpi == NULL)
{
goto CleanUp;
}
// Delete CS
DeleteCriticalSection(&(pPublicSpi->CsRxAccess));
DeleteCriticalSection(&(pPublicSpi->CsTxAccess));
// Deinitialize Buffer
HalFreeCommonBuffer(0, 0, pPublicSpi->SPIDMAInfo.PhysDmaDstBufferAddr, pPublicSpi->SPIDMAInfo.pVirtDmaDstBufferAddr, FALSE);
HalFreeCommonBuffer(0, 0, pPublicSpi->SPIDMAInfo.PhysDmaSrcBufferAddr, pPublicSpi->SPIDMAInfo.pVirtDmaSrcBufferAddr, FALSE);
// Clear value assigned to DMA physical Address
pPublicSpi->SPIDMAInfo.DmaDstAddress = 0;
pPublicSpi->SPIDMAInfo.DmaSrcAddress = 0;
// DMA Channel Stop
DMA_channel_stop(&pPublicSpi->SPIDMAInfo.g_OutputDMA);
DMA_channel_stop(&pPublicSpi->SPIDMAInfo.g_InputDMA);
DMA_release_channel(&pPublicSpi->SPIDMAInfo.g_OutputDMA);
DMA_release_channel(&pPublicSpi->SPIDMAInfo.g_InputDMA);
// Assign SYSINTR_NOP value
pPublicSpi->dwSpiSysIntr = SYSINTR_NOP;
// Close Handle
if (pPublicSpi->hRxEvent != NULL)
{
CloseHandle(pPublicSpi->hRxEvent);
}
if (pPublicSpi->hRxDoneEvent != NULL)
{
CloseHandle(pPublicSpi->hRxDoneEvent);
}
if (pPublicSpi->hRxIntrDoneEvent != NULL)
{
CloseHandle(pPublicSpi->hRxIntrDoneEvent);
}
if (pPublicSpi->hTxEvent != NULL)
{
CloseHandle(pPublicSpi->hTxEvent);
}
if (pPublicSpi->hTxDoneEvent != NULL)
{
CloseHandle(pPublicSpi->hTxDoneEvent);
}
if (pPublicSpi->hTxIntrDoneEvent != NULL)
{
CloseHandle(pPublicSpi->hTxIntrDoneEvent);
}
if (pPublicSpi->hSpiEvent != NULL)
{
CloseHandle(pPublicSpi->hSpiEvent);
}
if (pPublicSpi->hTxDmaDoneEvent != NULL)
{
CloseHandle(pPublicSpi->hTxDmaDoneEvent);
}
if (pPublicSpi->hRxDmaDoneEvent != NULL)
{
CloseHandle(pPublicSpi->hRxDmaDoneEvent);
}
if (pPublicSpi->hRxThread != NULL)
{
CloseHandle(pPublicSpi->hRxThread);
}
if (pPublicSpi->hTxThread != NULL)
{
CloseHandle(pPublicSpi->hTxThread);
}
if (pPublicSpi->hSpiThread != NULL)
{
CloseHandle(pPublicSpi->hSpiThread);
}
if (pPublicSpi->hTxDmaDoneThread != NULL)
{
CloseHandle(pPublicSpi->hTxDmaDoneThread);
}
if (pPublicSpi->hRxDmaDoneThread != NULL)
{
CloseHandle(pPublicSpi->hRxDmaDoneThread);
}
// VirtualFree
if (pPublicSpi->pGPIOregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pGPIOregs, sizeof(GPIO_REG));
pPublicSpi->pGPIOregs = NULL;
}
if (pPublicSpi->pSPIregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pSPIregs, sizeof(SPI_REG));
pPublicSpi->pSPIregs = NULL;
}
if (pPublicSpi->pDMAC0regs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pDMAC0regs, sizeof(DMAC_REG));
pPublicSpi->pDMAC0regs = NULL;
}
if (pPublicSpi->pDMAC1regs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pDMAC1regs, sizeof(DMAC_REG));
pPublicSpi->pDMAC1regs = NULL;
}
if (pPublicSpi->pSYSCONregs)
{
MmUnmapIoSpace((PVOID)pPublicSpi->pSYSCONregs, sizeof(CMU_CLK_REG));
pPublicSpi->pSYSCONregs = NULL;
}
// Local Free
LocalFree(pPublicSpi);
CleanUp:
DBGMSG(SPI_INIT,(TEXT("--[SPI] SPI_Deinit\r\n")));
return;
}
void SPI_PowerUp (PSPI_PUBLIC_CONTEXT pPublicSpi)
{
DBGMSG(SPI_PM,(TEXT("[SPI] ++PowerUp()\n\r")));
if((PSPI_PUBLIC_CONTEXT)pPublicSpi == NULL)
{
goto CleanUp;
}
DBGMSG(SPI_MSG,(TEXT("[SPI] --PowerUp()\n\r")));
CleanUp:
return;
}
BOOL SPI_Close (DWORD dwOpen)
{
PSPI_PUBLIC_CONTEXT pSpiPublic = NULL;
BOOL bResult = TRUE;
DBGMSG(SPI_INIT,(TEXT("++[SPI] SPI_Close\r\n")));
if(dwOpen != 0)
{
pSpiPublic = (PSPI_PUBLIC_CONTEXT) dwOpen;
}
else
{
bResult = FALSE;
goto CleanUp;
}
// Free all data allocated in open
LocalFree( pSpiPublic );
CleanUp:
DBGMSG(SPI_INIT,(TEXT("--[SPI] SPI_Close\r\n")));
return bResult;
}
DWORD SPI_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return 0;
}
UINT GetFifoSize(DWORD chnum)
{
UINT dwFifoSize = 0;
DBGMSG(SPI_INIT,(TEXT(" ++[SPI] GetFifoSize chnum = %d\r\n"),chnum));
if (chnum == SPI0)
{
dwFifoSize = 64;
}
else if (chnum == SPI1)
{
dwFifoSize = 16;
}
else if (chnum == SPI2)
{
dwFifoSize = 16;
}
else
{
ERRMSG((TEXT(" GetFifoSize Invalid SPI Channel \r\n")));
dwFifoSize = 0;
}
DBGMSG(SPI_INIT,(TEXT(" --[SPI] GetFifoSize\r\n")));
return dwFifoSize;
}
DWORD GetTxTriggerLevel(DWORD chnum)
{
DWORD dwTxTriggerLevel = 0;
DBGMSG(SPI_INIT,(TEXT(" ++[SPI] GetTxTriggerLevel chnum = %d\r\n"),chnum));
if (chnum == SPI0)
{
dwTxTriggerLevel = 10;
}
else if (chnum == SPI1)
{
dwTxTriggerLevel = 15;
}
else if (chnum == SPI2)
{
dwTxTriggerLevel = 15;
}
else
{
ERRMSG((TEXT(" GetTxTriggerLevel Invalid SPI Channel \r\n")));
dwTxTriggerLevel = 0;
}
DBGMSG(SPI_INIT,(TEXT(" --[SPI] GetTxTriggerLevel\r\n")));
return dwTxTriggerLevel;
}
#ifdef SPI_FULL_DUPLEX
BOOL SPI_FullDuplex(PSPI_PRIVATE_CONTEXT pSpiIOPrivate, PBYTE pRxBuf, PBYTE pTxBuf, DWORD dwCount)
{
PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)pSpiIOPrivate;
PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
volatile SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
ULONG WaitReturn;
// Check status
if(pSpiPrivate->State != STATE_IDLE)
{
DBGMSG(1,(TEXT(" [SPI] E : STATE IS NOT IDLE (%d)\r\n"), pSpiPrivate->State));
return FALSE;
}
if((NULL == pTxBuf)||(NULL == pRxBuf))
{
DBGMSG(1,(TEXT(" [SPI] E : In OR Out Buf is NULL \r\n")));
return FALSE;
}
pSpiPrivate->State = STATE_FULLDUPLEX;
// Copy TX buf to DMA buf
memcpy(pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr,(PBYTE)pTxBuf, dwCount);
// Mapping Rx/Tx buf to DMA buf
pSpiPrivate->pTxBuffer = pSpiPublic->SPIDMAInfo.pVirtDmaSrcBufferAddr;
pSpiPrivate->pTxDMABuffer = (LPVOID)pSpiPublic->SPIDMAInfo.DmaSrcAddress;
pSpiPrivate->pRxBuffer = pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr;
pSpiPrivate->pRxDMABuffer = (LPVOID)pSpiPublic->SPIDMAInfo.DmaDstAddress;
//SPI RESET
pSPIregs->CH_CFG |= SW_RST;
while(!(pSPIregs->CH_CFG & SW_RST));
DBGMSG(SPI_USR2,(TEXT("[SPI] HS SPI reset\n")));
pSPIregs->CH_CFG &= ~SW_RST;
if(dwCount>0)
{
// SPI register configuration
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
pSPIregs->MODE_CFG |= TX_DMA_ON|DMA_SINGLE|RX_DMA_ON;
pSPIregs->CH_CFG |= TX_CH_ON|RX_CH_ON;
// RX DMA start
DMA_set_channel_source(&pSpiPublic->SPIDMAInfo.g_InputDMA, pSpiPrivate->spi_rx_data_addr, BYTE_UNIT, BURST_1, FIXED);
DMA_set_channel_destination(&pSpiPublic->SPIDMAInfo.g_InputDMA, (UINT)pSpiPrivate->pRxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
DMA_set_channel_transfer_size(&pSpiPublic->SPIDMAInfo.g_InputDMA, dwCount);
DMA_initialize_LLI(&pSpiPublic->SPIDMAInfo.g_InputDMA, 1);
DMA_set_LLI_entry(&pSpiPublic->SPIDMAInfo.g_InputDMA, 0, LLI_FIRST_ENTRY, pSpiPrivate->spi_rx_data_addr,(UINT)pSpiPrivate->pRxDMABuffer, dwCount);
DMA_channel_start(&pSpiPublic->SPIDMAInfo.g_InputDMA);
// TX DMA start
DMA_set_channel_source(&pSpiPublic->SPIDMAInfo.g_OutputDMA, (UINT)pSpiPrivate->pTxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
DMA_set_channel_destination(&pSpiPublic->SPIDMAInfo.g_OutputDMA, pSpiPrivate->spi_tx_data_addr, BYTE_UNIT, BURST_1, FIXED);
DMA_set_channel_transfer_size(&pSpiPublic->SPIDMAInfo.g_OutputDMA, dwCount);
DMA_initialize_LLI(&pSpiPublic->SPIDMAInfo.g_OutputDMA, 1);
DMA_set_LLI_entry(&pSpiPublic->SPIDMAInfo.g_OutputDMA, 0, LLI_FIRST_ENTRY, (UINT)pSpiPrivate->pTxDMABuffer,pSpiPrivate->spi_tx_data_addr, dwCount);
DMA_channel_start(&pSpiPublic->SPIDMAInfo.g_OutputDMA);
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for FD : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
//Wait DMA done Interrupt
// Waiting for RX DMA done interrupt is enough
WaitReturn=WaitForSingleObject(pSpiPublic->hRxDmaDoneEvent, READ_TIME_OUT_CONSTANT);
if(WAIT_TIMEOUT == WaitReturn)
{
DBGMSG(1,(TEXT("[SPI] E : RX DMA TIMEOUT\r\n")));
}
DMA_clear_interrupt_pending(&pSpiPublic->SPIDMAInfo.g_InputDMA);
DMA_set_interrupt_mask(&pSpiPublic->SPIDMAInfo.g_InputDMA);
InterruptDone(pSpiPublic->dwRxDmaDoneSysIntr);
DMA_clear_interrupt_mask(&pSpiPublic->SPIDMAInfo.g_InputDMA);
while(!(pSPIregs ->SPI_STATUS & TX_DONE));
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
DBGMSG(SPI_USR2,(TEXT("[SPI] Thread for FD : MASTER MODE \r\n")));
MASTER_CS_DISABLE;
}
// Copy RX DMA Buf to RX Buf
memcpy(pRxBuf, pSpiPublic->SPIDMAInfo.pVirtDmaDstBufferAddr, dwCount);
}
else
{
return FALSE;
}
pSpiPrivate->State = STATE_IDLE;
return TRUE;
}
#endif
spi.c
最新推荐文章于 2023-12-24 15:24:10 发布