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

📄 tsc_ssp.c

📁 为TI的TSC2301音频芯片所设计的嵌入式linux驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
// Developped for TI's TSC2301
//
// Copyright (c) 2002, 2003, Texas Instruments

/* ---- 
Module Name:  

  TSC_ssp.c

Abstract:  

  This module contains the functions to communicate with the TSC2200/2301
  device through the ssp functionality of the Cotulla Platform
  
Functions:

  
Revision History:

  Bob Green (Embedded Express for Texas' Intruments) FEB 2002

--*/

#include    <windows.h>
#include	<types.h>
#include    <memory.h>
#include    <nkintr.h>
#include    <oalintr.h>
//#include	<reg.h>
#include	<xsc1.h>
#include	<xsc1bd.h>
#include    <drv_glob.h>
//#include	<macros.h>

#include	<tsc_ssp.h>

#ifdef __cplusplus
extern "C"{
#endif 

PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);
void msWait(unsigned msVal); 
void usWait(unsigned usVal); 

#ifdef __cplusplus
}
#endif 


// Functions to handle the mutex we use to ensure the two drivers don't collide.
BOOL ReleaseOurMutex(HANDLE hOurMutex);
BOOL GrabOurMutex(HANDLE hOurMutex);
void DeleteOurMutex(HANDLE hOurMutex);
HANDLE CreateOurMutex(void);

// Defines for SSP Configuration
// Bg 19JUN02 - modifying these defines from the SA1110 version 

// defines for SSP Control Register 0 (SSCR0)
#define SSE_DISABLE	0x00
#define SSE_ENABLE	0x80

#define ECS_INTERNAL	0x00
#define ESC_EXTERNAL	0x40

#define FRF_MICROWIRE	0x20
#define FRF_TI			0x10
#define FRF_MOTOROLA	0x00

#define DSS_16_BIT	0x0F

#define SCR_1800_KHZ	0x0000	// Really	1.8432 Mbps
#define SCR_900KHZ		0x0100	// Really	921.6 KHz
#define SCR_600_KHZ		0x0200	//			614.4 
#define SCR_300_KHZ		0x0400	//			368.64
#define SCR_200_KHZ		0x0800	//			204.8
#define SCR_100_KHZ		0x1100	//			102.4
#define SCR_50_KHZ		0x2300	//			51.2
#define SCR_7_KHZ		0xFF00  //			7.2


// defines for SSP Control Register 1 (SSCR1)
#define RIE_DISABLE	0x00
#define RIE_ENABLE	0x01

#define TIE_DISABLE	0x00
#define TIE_ENABLE	0x02

#define LBM_DISABLE	0x00
#define LBM_ENABLE	0x40

#define SPO_IDLE_LOW	0x00
#define SPO_IDLE_HIGH	0x80

#define SPH_FULL_DELAY	0x00
#define SPH_HALF_DELAY	0x10

#define MWDS_8_BIT		0x00
#define MWDS_16_BIT		0x20

#define TFT_ZERO	0x0000
#define TFT_SEVEN	0x01C0
#define RFT_SEVEN	0x1C00
#define RFT_FIFTEEN	0x3C00


// defines for SSP Status Register (SSSR)

#define TNF_FULL			0x00
#define TNF_NOT_FULL		0x02

#define RNE_EMPTY			0x00
#define RNE_NOT_EMPTY		0x40

#define BSY_IDLE		0x00
#define BSY_BUSY		0x80

#define TFS_NORMAL		0x00
#define TFS_IRQ_THROWN	0x10

#define RFS_NORMAL		0x00
#define RFS_IRQ_THROWN	0x20

#define ROR_NORMAL		0x00
#define ROR__OVERRUN	0x40


#define SPR_SHARE_COM4	0
#define SPR_USE_GPIO	1


#define GAFR_NORMAL			0
#define GAFR_ALTERNATE		1

#define GPDR_INPUT		0
#define GPDR_OUTPUT	1

#define MUTEX_NAME (TEXT("TSC2200MUTEX"))


// Module level variables

//volatile struct ppcreg  *v_pPPCReg		= NULL;	// from the ADS7846 driver version
PSSP_REGS v_pSSPreg = (PSSP_REGS) SSP_BASE_U_VIRTUAL;	// from the ADS7846 driver version
PGPIO_REGS v_pTSC_GPIOReg = (PGPIO_REGS)GPIO_BASE_U_VIRTUAL;

volatile HANDLE hMutex = NULL;	// our handle to the named mutex used to prevent collision on the SPI communications



HANDLE CreateOurMutex(void)
{
	HANDLE hRetMutex;

	hRetMutex = CreateMutex(NULL, FALSE, MUTEX_NAME);

	return hRetMutex;
}

void DeleteOurMutex(HANDLE hOurMutex)
{
	if (hOurMutex)
		CloseHandle(hOurMutex);
}


BOOL GrabOurMutex(HANDLE hOurMutex)
{
	BOOL bRet = FALSE;
	DWORD dwWaitRet;

	if (hOurMutex)
	{
		dwWaitRet = WaitForSingleObject(hOurMutex, 1000);

//RETAILMSG(1, (TEXT("GrabOurMutex: %08X"), dwWaitRet));

		if ( dwWaitRet != WAIT_TIMEOUT )
		{
			bRet = TRUE;
		}
	} else
	{
		RETAILMSG(1, (TEXT("GrabOurMutex - hOurMutex is NULL")));
	}

	
	return bRet;
}


BOOL ReleaseOurMutex(HANDLE hOurMutex)
{
	BOOL bRet = FALSE;

	if (hOurMutex)
		bRet = ReleaseMutex(hOurMutex);

	return bRet;
}


void setupSSP()
{
	// volatile struct icreg *v_pICReg	= (volatile struct icreg *)IC_BASE_VIRTUAL;
	//PGPIO_REGS v_pTSC_GPIOReg = (PGPIO_REGS)GPIO_BASE_U_VIRTUAL;
	HANDLE hTempMutex;

	hTempMutex = CreateOurMutex();
	// Bg 19FEB02 - changing to using named mutex for protection
	if (hTempMutex)
	{
		if (GrabOurMutex(hTempMutex))
		{

			// Program PPC Pin Assignment Register (PPAR)
			// IOW_REG_FIELD (struct pparBits, &v_pPPCReg->ppar, spr, SPR_USE_GPIO);		// SSP pin reassignment


			// Program GPIO alternate function register (GAFR0_U)
			v_pTSC_GPIOReg->GAFR1_x |= GPIO_23_AF2_SCLK;
//			v_pTSC_GPIOReg->GAFR1_x |= GPIO_24_AF2_SFRM;
			v_pTSC_GPIOReg->GAFR1_x |= GPIO_25_AF2_TXD;
			v_pTSC_GPIOReg->GAFR1_x |= GPIO_26_AF1_RXD;


// Bg 16AUG02 trying to see if we can control SFRM pin ourselves			


			// Program GPIO pin direction register (GPDR)
			v_pTSC_GPIOReg->GPDR_x |= GPIO_23;
			v_pTSC_GPIOReg->GPDR_x |= GPIO_24;
			v_pTSC_GPIOReg->GPDR_x |= GPIO_25;
			v_pTSC_GPIOReg->GPDR_x &= ~GPIO_26;

			
// Bg 16AUG02 trying to see if we can control SFRM pin ourselves			
			v_pTSC_GPIOReg->GPSR_x |= GPIO_24;	// initially it needs to be high.

			
			// Synchronous serial port enable (SET LAST!)
			v_pSSPreg->sscr1 = (RIE_DISABLE | TIE_DISABLE | LBM_DISABLE | SPO_IDLE_LOW | SPH_HALF_DELAY | MWDS_16_BIT | TFT_ZERO | RFT_SEVEN);
			v_pSSPreg->sscr0 = (DSS_16_BIT | FRF_MOTOROLA | ECS_INTERNAL | SSE_ENABLE | SCR_600_KHZ);	

		
			// Bg 19FEB02
			ReleaseOurMutex(hTempMutex);


		} else // GrabOurMutex
		{
			RETAILMSG(1, (TEXT("setupSSP - Failed to grab our mutex\r\n")));
		}

	} else // CreateOurMutex
	{		
		RETAILMSG(1, (TEXT("setupSSP - Failed to grab our mutex\r\n")));
	}
	
	//RETAILMSG(1, (TEXT("setupSSP - 7\r\n")));

}



//copied directly from the ADS7825 version driver
void SetupSSPRegisters(void)
{
	// check to ensure we don't do this more than once per thread
	// but we don't use the start mutex, because each thread need a copy.
//RETAILMSG(1, (TEXT("SetupSSPRegisters - 1\r\n")));

	if (v_pSSPreg == NULL) 
	{

//RETAILMSG(1, (TEXT("SetupSSPRegisters - 2\r\n")));

		v_pSSPreg = (PSSP_REGS) VirtualAllocCopy(sizeof(SSP_REGS),
			(char *)TEXT("TouchPanelEnable: SSP_BASE_VIRTUAL"), (PVOID)SSP_BASE_U_VIRTUAL);

//RETAILMSG(1, (TEXT("SetupSSPRegisters - 3\r\n")));

//		if (v_pSSPreg) 
//		{
//			if (v_pPPCReg == NULL) 
//			{
//				v_pPPCReg = (volatile struct ppcreg *) VirtualAllocCopy(sizeof(struct ppcreg),
//					(char *)TEXT("TouchPanelEnable: PPC_BASE_VIRTUAL"), (PVOID)PPC_BASE_VIRTUAL);
//			}
//		}

	}

//RETAILMSG(1, (TEXT("SetupSSPRegisters - 4\r\n")));
}


void DisableSSP(void)
{

	HANDLE hTempMutex;

	hTempMutex = CreateOurMutex();

	if (hTempMutex)
	{

		if (GrabOurMutex(hTempMutex))
		{
			// disable SPP operation using the SSCR/SSE register
			v_pSSPreg->sscr0 &= ~SSE_ENABLE;
			
			ReleaseOurMutex(hTempMutex);

		} else // GrabOurMutex
		{
			RETAILMSG(1, (TEXT("DisableSSP - Failed to grab our mutex\r\n")));
		}
	}

}


void EnableSSP(void)
{
	HANDLE hTempMutex;

	hTempMutex = CreateOurMutex();

	if (hTempMutex)
	{

		if (GrabOurMutex(hTempMutex))
		{
			// enable SPP operation using the SSCR/SSE register
			v_pSSPreg->sscr0 |= SSE_ENABLE;

			ReleaseOurMutex(hTempMutex);

		} else // GrabOurMutex
		{
			RETAILMSG(1, (TEXT("EnableSSP - Failed to grab our mutex\r\n")));
		}
	}
}


// This should be the first function any driver calls...
void InitSSP(void)
{

	//RETAILMSG(1, (TEXT("InitSSP\r\n")));

	// setup the structures and pointers to the SSP registers
//	SetupSSPRegisters();

	// configure the SSP registers
	setupSSP();

#ifdef XXX
	// setup DMA buffer
    dma_buf = (PUCHAR)VirtualAlloc(0, DMA_BUFFER_SIZE, MEM_RESERVE, PAGE_NOACCESS);

    if (dma_buf)  
	{

		VirtualCopy((LPVOID) dma_page[0], 
						(LPVOID)DMA_BUFFER_VIRTUAL, //this will clobber DMA, itshould be DMA_RCV_A_BUFFER_BASE_VIRTUAL,
                         DMA_BUFFER_SIZE,
                         PAGE_READWRITE | PAGE_NOCACHE);



	} else
	{
      RETAILMSG( 1, (TEXT("dma_buf Allocation Failed")));
      ERRMSG("dma_buf Allocation Failed");
    } 

#endif

	//RETAILMSG(1, (TEXT("InitSSP - exiting\r\n")));


}


/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
///// Start of functions for SPI Transactions   /////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////


void TwoWordSPITransaction(unsigned __int16 *iWord1, unsigned __int16 *iWord2)
{
	unsigned __int16 iData;
	unsigned __int16 iTempData;
	unsigned __int16 iStatus = 0;
	BOOL bRecv = FALSE;


	HANDLE hTempMutex;

	hTempMutex = CreateOurMutex();

	if (hTempMutex)
	{
	
		if (GrabOurMutex(hTempMutex))
		{

			//RETAILMSG(1, (TEXT("TwoWordSPITransaction - Sending(%X, %X)\r\n"), *iWord1, *iWord2));

	// Bg 16AUG02 trying to see if we can control SFRM pin ourselves			
			v_pTSC_GPIOReg->GPCR_x |= GPIO_24;	// need to drop SFRM to signal start of frame.

							
			v_pSSPreg->ssdr = *iWord1;

			// Bg 16AUG02 
			// wait until SSP is no longer busy.				
			usWait(1);
			while (v_pSSPreg->ssr & 0x00000010)
				usWait(1);

			//		usWait(3);

			iData = *iWord2;
			v_pSSPreg->ssdr = iData;	// dummy write

			// Bg 16AUG02 
			// wait until SSP is no longer busy.				
			usWait(1);
			while (v_pSSPreg->ssr & 0x00000010)
				usWait(1);

			// need to wait for SSP tp finish clocking in
			//usWait(60);
							
			iStatus = v_pSSPreg->ssr;
			bRecv = (iStatus & 0x0008);
			while (bRecv)
			{
				iTempData = v_pSSPreg->ssdr;
				*iWord1 = *iWord2;
				*iWord2 = iTempData;

				//RETAILMSG(1, (TEXT("TwoWordSPITransaction -- iTempData:%X\r\n"), iTempData));
				usWait(20);
							
				iStatus = v_pSSPreg->ssr;
				bRecv = (iStatus & 0x0008);
			}


	// Bg 16AUG02 trying to see if we can control SFRM pin ourselves			
			v_pTSC_GPIOReg->GPSR_x |= GPIO_24;	// need to raise SFRM when we are done.

			ReleaseOurMutex(hTempMutex);
		} else // GrabOurMutex
		{
			RETAILMSG(1, (TEXT("TwoWordSPITransaction - Failed to grab our mutex\r\n")));
		}

	} else
	{
		RETAILMSG(1, (TEXT("TwoWordSPITransaction - Failed to create our mutex\r\n")));
	}

}



void ThreeWordSPITransaction(unsigned __int16 *iWord1, unsigned __int16 *iWord2, unsigned __int16  *iWord3)
{
	unsigned __int16 iData;
	unsigned __int16 iTempData;
	unsigned __int16 iStatus = 0;
	BOOL bRecv = FALSE;

	HANDLE hTempMutex;

	hTempMutex = CreateOurMutex();

	if (hTempMutex)
	{
		if (GrabOurMutex(hTempMutex))
		{

	// Bg 16AUG02 trying to see if we can control SFRM pin ourselves			
			v_pTSC_GPIOReg->GPCR_x |= GPIO_24;	// need to drop SFRM to signal start of frame.


			v_pSSPreg->ssdr = *iWord1;

			usWait(2);
			// Bg 16AUG02 
			// wait until SSP is no longer busy.				
			while (v_pSSPreg->ssr & 0x00000010)
				usWait(2);
					
			//usWait(2);

			iData = *iWord2;
			v_pSSPreg->ssdr = iData;	// next word 

			// Bg 16AUG02 
			// wait until SSP is no longer busy.				
			usWait(2);
			while (v_pSSPreg->ssr & 0x00000010)
				usWait(2);

			//usWait(2);

			iData = *iWord3;
			v_pSSPreg->ssdr = iData;	// next word 

			// Bg 16AUG02 
			// wait until SSP is no longer busy.				
			usWait(2);
			while (v_pSSPreg->ssr & 0x00000010)
				usWait(2);

			// need to wait for SSP tp finish clocking in
			// ::TODO need to replace this usWait with a loop checking of the PSI busy bit int the status reg.
	//		usWait(90);

			
			// use the bRecv bit in the status reg to tell us when we've read everything in the FIFO.
			iStatus = v_pSSPreg->ssr;
			bRecv = (iStatus & 0x0008);
			while (bRecv)
			{
				// grab an entry from the receive FIFO			
				iTempData = v_pSSPreg->ssdr;

				// this little round robin below is just an easy way of making sure 
				// that if the SPI recieve FIFO is not empty, we still on return the 
				// three last words corresponding to the three words we sent
				*iWord1 = *iWord2;
				*iWord2 = *iWord3;
				*iWord3 = iTempData;

				//RETAILMSG(1, (TEXT("ThreeWordSPITransaction -- iTempData:%X\r\n"), iTempData));			
				usWait(20);
			
				iStatus = v_pSSPreg->ssr;
				bRecv = (iStatus & 0x0008);
			}


			// Bg 16AUG02 trying to see if we can control SFRM pin ourselves			
			v_pTSC_GPIOReg->GPSR_x |= GPIO_24;	// need to raise SFRM when we are done.


			ReleaseOurMutex(hTempMutex);
		} else // GrabOurMutex
		{
			RETAILMSG(1, (TEXT("TwoWordSPITransaction - Failed to grab our mutex\r\n")));
		}
	} else // CreateOurMutex
	{
		RETAILMSG(1, (TEXT("TwoWordSPITransaction - Failed to create our mutex\r\n")));
	}
}


⌨️ 快捷键说明

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