www.pudn.com > DMBDRV.rar > SpiHw.c
#include "SianoSPI.h" #include "PxaRegs.h" #include "PXA_SSP.h" #include "xllp_defs.h" #include "SpiHw.h" #include#include #include "pkfuncs.h" #include "memmap.h" #include "Gpio.h" #include #include #define PXA270 #define SPI_ACTIVATION_PREAMBLE1 0xc1de0000 #define SPI_ACTIVATION_PREAMBLE2 0xedf151a5 #define SPI_COMMAND_PREAMBLE 0x7ee75aa5 typedef struct SmsMsgHdr_S { UINT16 msgType; UINT8 msgSrcId; UINT8 msgDstId; UINT16 msgLength; // Length is of the entire message, including header UINT16 msgFlags; } SmsMsgHdr_ST; typedef struct SmsMsgData_S { SmsMsgHdr_ST xMsgHeader; UINT32 msgData[1]; } SmsMsgData_ST; #define SMS_MAX_PAYLOAD_SIZE 240 typedef struct SmsDataDownload_S { SmsMsgHdr_ST xMsgHeader; UINT32 MemAddr; UINT32 Payload[SMS_MAX_PAYLOAD_SIZE/4]; } SmsDataDownload_ST; #define MSG_SMS_DATA_DOWNLOAD_REQ 660 #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 #define MSG_SMS_SPI_INT_LINE_SET_REQ 710 #define POLLING_TIMEOUT 500000 #define XLLP_SSCR0_SSE (0x1<<7) // 1 -- SSP operation is enabled /* * SSP Serial Port Registers * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different. * PXA255, PXA26x and PXA27x have extra ports, registers and bits. */ /* Common PXA2xx bits first */ #define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ #define SSCR0_Motorola (0x0 << 4) /* Motorola's Serial Peripheral Interface (SPI) */ #define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ #define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ #define SSCR1_LBM (1 << 2) /* Loop-Back Mode */ #define SSCR1_SPO (1 << 3) /* Motorola SPI SSPSCLK polarity setting */ #define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */ #define SSCR1_MWDS (1 << 5) /* Microwire Transmit Data Size */ #define SSCR1_TFT (0x000003c0) /* Transmit FIFO Threshold (mask) */ #define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */ #define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */ #define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ #define SSSR_TNF (1 << 2) /* Transmit FIFO Not Full */ #define SSSR_RNE (1 << 3) /* Receive FIFO Not Empty */ #define SSSR_BSY (1 << 4) /* SSP Busy */ #define SSSR_TFS (1 << 5) /* Transmit FIFO Service Request */ #define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ #define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ #define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run interrupt Mask */ #define SSCR0_NCS (1 << 21) /* Network Clock Select */ #define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */ /* extra bits in PXA255, PXA26x and PXA27x SSP ports */ #define SSCR1_TRAIL (1 << 22) /* Trailing Byte */ #define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */ #define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */ #define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */ #define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interupt Enable */ #define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */ #define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */ #define XLLP_CLKEN_SSP1 (0x1u << 23) #define XLLP_CLKEN_SSP2 (0x1u << 3) #define XLLP_CLKEN_SSP3 (0x1u << 4) #define XLLP_CLKEN_SSP4 (0x1u << 5) typedef struct { XLLP_VUINT32_T cccr; // Core Clock Configuration register XLLP_VUINT32_T cken; // Clock Enable register XLLP_VUINT32_T oscc; // Oscillator Configuration register XLLP_VUINT32_T ccsr; // Core Clock Status register } XLLP_CLKMGR_T, *P_XLLP_CLKMGR_T; #define fwmin(a,b) (a> 8) | \ (((x)&0xff000000) >> 24)) #define MIN_BUFF_PARTITION 256 #define FW_STEP 4 #define GET_GPIOXX_2_IRQ #define CONFIGURE_GPIO #define USE_CONSO_DEFAULT typedef struct { DWORD useSSPPort; CHAR DmaDllName[MAX_REG_PATH_SIZE]; DEVICE_DMA_SERVICE_ST *dmaService; volatile XLLP_SSP_REGS *sspCtrl; DWORD sspDataRegPhy; HANDLE rxEvent; HANDLE SmsInterruptEvent; DWORD spiSysIntr; DWORD RxInterruptCnt; //For debug BOOL drvActive; HANDLE RxIST; PVOID intrContext; BOOL novaDevice; DWORD novaIntrPin; void(*InterruptCallback)(void*); }SPIPHY, *PSPIPHY; volatile XLLP_CLKMGR_T *v_pClkRegs = NULL; volatile XLLP_GPIO_T *v_pGPIORegisters = NULL; // for PXA300 #ifndef PXA270 volatile UINT32 *v_pMFPRRegisters = NULL; #endif DWORD useSSPPort; extern PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress); extern void msWait(UINT ms); static DWORD GetSpiPortNum() { DWORD SpiPortNum; if(SSPCLK==23) SpiPortNum = 1; else if(SSPCLK==36) SpiPortNum = 2; else if(SSPCLK==52) SpiPortNum = 3; else SpiPortNum = 4; return SpiPortNum; } //writing to SPI device static void SSPWriteDWord(PSPIPHY pSpiPhy,DWORD dwVal) { DWORD sb; sb = SWAP32(dwVal); pSpiPhy->sspCtrl->ssdr = sb; } //reading from SPI device static DWORD SSPReadDWord(PSPIPHY pSpiPhy) { DWORD sb; DWORD v = pSpiPhy->sspCtrl->ssdr; sb = SWAP32(v); return sb; } //write and read to/from SPI device static DWORD ReadWriteDWord(PSPIPHY pSpiPhy,DWORD dwInVal) { DWORD dwRetVal; DWORD timeout; timeout = POLLING_TIMEOUT; //Loop while there is any data in the fifo while(!(pSpiPhy->sspCtrl->ssr & SSSR_TNF) && timeout--); if (timeout == -1) return 0; SSPWriteDWord(pSpiPhy,dwInVal); timeout = POLLING_TIMEOUT; while(!(pSpiPhy->sspCtrl->ssr & SSSR_RNE) && timeout--); if (timeout == -1) return 0; //RETAILMSG(1, (TEXT("ReadWriteDWord call read ..\r\n"))); dwRetVal = SSPReadDWord(pSpiPhy); return dwRetVal; } static void endOfDmaTransfer(DWORD transactionId, DWORD status) { //RETAILMSG(1, (TEXT("SmsSpi: DMA transaction end.\r\n"))); SetEvent((HANDLE)transactionId); } static BOOL spiPhyGetRegistrySettings(PVOID Context, PSPIPHY pSpiPhy ) { TCHAR* regKey; BOOL st; HKEY hKey; DWORD dataSize, type; regKey = (TCHAR *)LocalAlloc (LPTR, MAX_REG_KEY_SIZE); if (regKey == NULL) { RETAILMSG(1, (TEXT("Siano SPI - ERROR!! Allocating memory for registry reading failed.\r\n"))); return FALSE; } st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCWSTR)Context, 0, 0, &hKey); if(st != ERROR_SUCCESS) { RETAILMSG(1, (TEXT("Siano SPI - ERROR!! Could not open registry key.\r\n"))); LocalFree(regKey); return (FALSE); } dataSize=MAX_REG_KEY_SIZE; st = RegQueryValueEx( hKey, TEXT("Key"), NULL, &type, (LPBYTE)regKey, &dataSize); RegCloseKey(hKey); if(st!=ERROR_SUCCESS) { RETAILMSG(1, (TEXT("Siano SPI - ERROR!! Could not get registry key name.\r\n"))); LocalFree(regKey); return (FALSE); } // Now - read all the needed parameters for the driver from the registry. st = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKey, 0, 0, &hKey); if(st != ERROR_SUCCESS) { RETAILMSG(1, (TEXT("Siano SPI - ERROR!! Could not open registry key.\r\n"))); LocalFree(regKey); return (FALSE); } dataSize=MAX_REG_PATH_SIZE; st = RegQueryValueEx( hKey, L"DmaServicesPlugin", 0, &type, (LPBYTE)&pSpiPhy->DmaDllName, &dataSize); if(st != ERROR_SUCCESS) { //Set default value if registry entry is not found. pSpiPhy->DmaDllName[0] = 0; } /* dataSize = sizeof(pSpiPhy->useSSPPort); st = RegQueryValueEx( hKey, L"useSSPPort", 0, &type, (LPBYTE)&pSpiPhy->useSSPPort, &dataSize); if(st != ERROR_SUCCESS) { //Set default value if registry entry is not found. pSpiPhy->useSSPPort = 1; RETAILMSG(1, (TEXT("Siano SPI :useSSPPort = 1\r\n"))); } dataSize = sizeof(pSpiPhy->spiSysIntr); st = RegQueryValueEx( hKey, L"useSysIntr", 0, &type, (LPBYTE)&pSpiPhy->spiSysIntr, &dataSize); if(st != ERROR_SUCCESS) { //Set default value if registry entry is not found. pSpiPhy->spiSysIntr = 34; } if (pSpiPhy->spiSysIntr == 0xffff) { DWORD Irq_GpioXX_2; Irq_GpioXX_2 = DEFAULT_IRQ_GPIOXX_2;//consonance irq number RETAILMSG(1, (TEXT("Irq Number = %d!!!\r\n"),DEFAULT_IRQ_GPIOXX_2)); if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq_GpioXX_2, sizeof(DWORD), &pSpiPhy->spiSysIntr, sizeof(DWORD), NULL)) { RETAILMSG(1, (TEXT("SPI : IOCTL_HAL_REQUEST_SYSINTR failed (x%08x)\r\n"), GetLastError())); } else { RETAILMSG(1, (TEXT("SPI : IOCTL_HAL_REQUEST_SYSINTR Succeded SysIntr %d\r\n"), pSpiPhy->spiSysIntr)); } } dataSize = sizeof(pSpiPhy->novaDevice); st = RegQueryValueEx( hKey, L"novaDevice", 0, &type, (LPBYTE)&pSpiPhy->novaDevice, &dataSize); if(st != ERROR_SUCCESS) { //Set default value if registry entry is not found. pSpiPhy->novaDevice = FALSE; } dataSize = sizeof(pSpiPhy->novaIntrPin); st = RegQueryValueEx( hKey, L"novaIntrPin", 0, &type, (LPBYTE)&pSpiPhy->novaIntrPin, &dataSize); if(st != ERROR_SUCCESS) { //Set default value if registry entry is not found. pSpiPhy->novaIntrPin = 16; } */ st = RegCloseKey(hKey); if(st!=ERROR_SUCCESS) { RETAILMSG(1, (TEXT("Siano SPI - ERROR!! Could not get registry key name.\r\n"))); LocalFree(regKey); return (FALSE); } LocalFree(regKey); return (TRUE); } static BOOL activateDMAService(PSPIPHY pSpiPhy) { DMA_INIT_PARAMS_ST dmaSetUp; if (pSpiPhy->DmaDllName[0] == 0) { RETAILMSG(1, (TEXT("SmsSpi: activateDMAService() There is no DMA service name.\r\n"))); return FALSE; } pSpiPhy->dmaService = (DEVICE_DMA_SERVICE_ST*)LocalAlloc(LPTR, sizeof(DEVICE_DMA_SERVICE_ST)); if (pSpiPhy->dmaService == NULL) { RETAILMSG(1, (TEXT("SmsSpi: activateDMAService() Could not allocate DMA service structure.\r\n"))); return FALSE; } pSpiPhy->dmaService->hdl = LoadLibrary((LPCWSTR)pSpiPhy->DmaDllName); if (pSpiPhy->dmaService->hdl == NULL) { RETAILMSG(1, (TEXT("SmsSpi: activateDMAService() Could not load DMA service library.\r\n"))); LocalFree(pSpiPhy->dmaService); pSpiPhy->dmaService = NULL; return FALSE; } pSpiPhy->dmaService->dmaSetUpChannel = (DMA_SetUpChannelF)GetProcAddress(pSpiPhy->dmaService->hdl, TEXT("DMA_SetUpChannel")); pSpiPhy->dmaService->dmaConfigChannel = (DMA_ConfigChannelF)GetProcAddress(pSpiPhy->dmaService->hdl, TEXT("DMA_ConfigChannel")); pSpiPhy->dmaService->dmaRemoveChannel = (DMA_RemoveChannelF)GetProcAddress(pSpiPhy->dmaService->hdl, TEXT("DMA_RemoveChannel")); if (pSpiPhy->dmaService->dmaSetUpChannel == NULL || pSpiPhy->dmaService->dmaConfigChannel == NULL || pSpiPhy->dmaService->dmaRemoveChannel == NULL) { RETAILMSG(1, (TEXT("SmsSpi: activateDMAService() Could not find DMA library routines.\r\n"))); FreeLibrary(pSpiPhy->dmaService->hdl); LocalFree(pSpiPhy->dmaService); pSpiPhy->dmaService = NULL; return FALSE; } dmaSetUp.flags = DMA_USE_HW_FLOW_CTRL; if (useSSPPort == 1) dmaSetUp.dmaReq = SSP1_TX_CMR; else if (useSSPPort == 2) dmaSetUp.dmaReq = SSP2_TX_CMR; else if (useSSPPort == 3) dmaSetUp.dmaReq = SSP3_TX_CMR; else if (useSSPPort == 4) dmaSetUp.dmaReq = SSP4_TX_CMR; dmaSetUp.burstSize = DMA_BURST_8_BYTES; dmaSetUp.busWidth = DMA_BUS_WIDTH_4_BYTE; pSpiPhy->dmaService->txDmaDevice=pSpiPhy->dmaService->dmaSetUpChannel(&dmaSetUp); dmaSetUp.flags = DMA_USE_HW_FLOW_CTRL; if (useSSPPort == 1) dmaSetUp.dmaReq = SSP1_RX_CMR; else if (useSSPPort == 2) dmaSetUp.dmaReq = SSP2_RX_CMR; else if (useSSPPort == 3) dmaSetUp.dmaReq = SSP3_RX_CMR; else if (useSSPPort == 4) dmaSetUp.dmaReq = SSP4_RX_CMR; dmaSetUp.burstSize = DMA_BURST_8_BYTES; dmaSetUp.busWidth = DMA_BUS_WIDTH_4_BYTE; pSpiPhy->dmaService->rxDmaDevice=pSpiPhy->dmaService->dmaSetUpChannel(&dmaSetUp); return TRUE; } static BOOL deactivateDMAService(PSPIPHY pSpiPhy) { if (pSpiPhy->dmaService != NULL) { if (pSpiPhy->dmaService->rxDmaDevice) pSpiPhy->dmaService->dmaRemoveChannel(pSpiPhy->dmaService->rxDmaDevice); if (pSpiPhy->dmaService->txDmaDevice) pSpiPhy->dmaService->dmaRemoveChannel(pSpiPhy->dmaService->txDmaDevice); if (pSpiPhy->dmaService->hdl) FreeLibrary(pSpiPhy->dmaService->hdl); LocalFree(pSpiPhy->dmaService); pSpiPhy->dmaService = NULL; } return TRUE; } VOID SpiRxIST(PVOID pArg) { PSPIPHY pSpiPhy = (PSPIPHY)pArg; pSpiPhy->RxInterruptCnt = 0; while (1) { WaitForSingleObject(pSpiPhy->SmsInterruptEvent,INFINITE); if (pSpiPhy->drvActive == FALSE) { return; } pSpiPhy->RxInterruptCnt++; if (pSpiPhy->InterruptCallback) pSpiPhy->InterruptCallback(pSpiPhy->intrContext); InterruptDone(pSpiPhy->spiSysIntr); } } // loopBackTest1 for spi test BOOL loopBackTest1(PSPIPHY pSpiPhy) { int i; DWORD wrd; DWORD Tx_loopbuf[64]= {0}; DWORD Rx_loopbuf[64]= {0}; DWORD err_cnt=0; for ( i= 0; i< 64; i ++) { Tx_loopbuf[i] = (4*i+3)<<12| (4*i+2)<<8| (4*i+1)<<4|4*i; Rx_loopbuf[i] = 0; } //send 256 bytes for(i=0; i<64; i++) { // wrd=ReadWriteDWord(pSpiPhy,0xa55ae77e+i); wrd=ReadWriteDWord(pSpiPhy, (DWORD)Tx_loopbuf[i]); } Sleep(100); //send and receive 256 bytes for(i=0; i<64; i++) { // wrd = ReadWriteDWord(pSpiPhy,0xa55ae77e+i); wrd=ReadWriteDWord(pSpiPhy, (DWORD)Tx_loopbuf[i]); Rx_loopbuf[i] = wrd; RETAILMSG( 1, (TEXT("%d loopBackTest222 get 0x%x\r\n"),i,wrd)); } for(i=0; i<64; i++) { RETAILMSG( 1, (TEXT("%d loopBackTest222 get 0x%x\r\n"),i, Rx_loopbuf[i])); if (Rx_loopbuf[i] != Tx_loopbuf[i]) { err_cnt ++; RETAILMSG( 1, (TEXT("loop back error cnt :%d\n"),err_cnt)); } } return TRUE; } BOOL loopBackTest2(PSPIPHY pSpiPhy) { int i; DWORD wrd; DWORD Tx_loopbuf[64]= {0}; DWORD Rx_loopbuf[64]= {0}; DWORD err_cnt=0; for ( i= 0; i< 64; i ++) { Tx_loopbuf[i] = (4*i+3)<<24| (4*i+2)<<16| (4*i+1)<<8|4*i; //RETAILMSG( 1, (TEXT("%d TX buffer 0x%x\r\n"),i,Tx_loopbuf[i])); Rx_loopbuf[i] = 0; // RETAILMSG( 1, (TEXT("%d TX buffer 0x%x\r\n"),i,Tx_loopbuf[i])); } //send 256 bytes for(i=0; i<64; i++) { // wrd=ReadWriteDWord(pSpiPhy,0xa55ae77e+i); wrd=ReadWriteDWord(pSpiPhy, (DWORD)Tx_loopbuf[i]); } Sleep(100); //send and receive 256 bytes for(i=0; i<64; i++) { // wrd = ReadWriteDWord(pSpiPhy,0xa55ae77e+i); wrd=ReadWriteDWord(pSpiPhy, (DWORD)Tx_loopbuf[i]); Rx_loopbuf[i] = wrd; // RETAILMSG( 1, (TEXT("%d loopBackTest222 get 0x%x\r\n"),i,wrd)); } for(i=0; i<64; i++) { if (Rx_loopbuf[i] != Tx_loopbuf[i]) { err_cnt ++; RETAILMSG( 1, (TEXT("loop back error cnt :%d\n"),err_cnt)); RETAILMSG( 1, (TEXT("%d, TX buffer 0x%x, RX buffer 0x%x\r\n"), i, Tx_loopbuf[i], Rx_loopbuf[i])); } } return TRUE; } BOOL loopBackTest(PSPIPHY pSpiPhy) { int i; DWORD wrd; //send 256 bytes for(i=0; i<64; i++) { wrd=ReadWriteDWord(pSpiPhy,0xa55ae77e+i); } //send and receive 256 bytes for(i=0; i<64; i++) { wrd = ReadWriteDWord(pSpiPhy,0xa55ae77e+i); RETAILMSG( 1, (TEXT("%d loopBackTest222 get 0x%x\r\n"),i,wrd)); } return TRUE; } //////////////////////////// Internal fucntions ///////////////////////////////// /************************************************************************************* FUNCTION NAME: WriteFW DESCRIPTION: the actual writing to the firmwere *************************************************************************************/ VOID WriteFWtoStellar(PSPIPHY pSpiPhy,BYTE* pFW,DWORD Len) { DWORD Padding; DWORD Cnt = 0; DWORD *pPos = (DWORD*)pFW; int LeftOver; DWORD i=0; // RETAILMSG( 1, (TEXT("SmsSpi: WriteFW :pSpiPhy->sspCtrl->ssr:0x%x ,pSpiPhy->sspCtrl->ssdr:0x%x,*pFW :0x%x ,Len:0x%x.\r\n"),pSpiPhy->sspCtrl->ssr, // pSpiPhy->sspCtrl->ssdr,*pFW,Len)); // RETAILMSG( 1, (TEXT("SmsSpi: WriteFW :pSpiPhy->sspCtrl->sscr0:0x%x,pSpiPhy->sspCtrl->sscr10x%x \r\n"),pSpiPhy->sspCtrl->sscr0,pSpiPhy->sspCtrl->sscr1)); //Data Must be sent in 256 Bytes chuncks --- CHANGED: Pre DMA init in Siano device, pass the exact file size. Padding = Len%MIN_BUFF_PARTITION; if(Padding) Padding = MIN_BUFF_PARTITION - Padding;//to complete to 256; RETAILMSG( 1, (TEXT("SmsSpi: WriteFW :Len %d bytes Padding %d Bytes\r\n"),Len,Padding)); //1st Phaze RETAILMSG( 1, (TEXT("SmsSpi: WriteFW :Entering Phaze 1\r\n"))); while((Cnt+FW_STEP)<=Len) { //actual Device Writing //no need checking the data received from the device DWORD ret = ReadWriteDWord(pSpiPhy,*pPos); //Change Stats Cnt+=fwmin(FW_STEP,Len-Cnt); pPos++;//+4 i++; } //2nd Phaze //Check if we have left over data we didn't send RETAILMSG( 1, (TEXT("SPI!WriteFW :Entering Phaze 2\r\n"))); LeftOver = (Len - Cnt); RETAILMSG( 1, (TEXT("SPI!WriteFW :LeftOver Data Len %d Bytes\r\n"),LeftOver)); if (LeftOver>0) { DWORD dwval; pPos = (DWORD*)(pFW+Cnt); dwval= ReadWriteDWord(pSpiPhy,*pPos); } Sleep(100); #if 0 for ( Cnt = 0 ; Cnt < 100; Cnt++) { RETAILMSG( 1, (TEXT("test time: %d\r\n"),Cnt)); loopBackTest2( pSpiPhy); } while(1); #endif } static BOOL enableDisableSSPClock(PSPIPHY pSpiPhy, BOOL enable) { volatile XLLP_CLKMGR_T *v_pClkRegs = NULL; //volatile XLLP_CLKMGR_T *v_pClkRegs = NULL; PHYSICAL_ADDRESS PhysicalBase; PhysicalBase.QuadPart = CLK_BASE_PHYSICAL; //v_pClkRegs= (XLLP_CLKMGR_T *)MmMapIoSpace(PhysicalBase,sizeof(XLLP_CLKMGR_T),FALSE); v_pClkRegs= (XLLP_CLKMGR_T *)VirtualAllocCopy(sizeof(XLLP_CLKMGR_T),"clk registers",(PVOID)(CLK_BASE_U_VIRTUAL)); if (!v_pClkRegs) { return FALSE; } switch (pSpiPhy->useSSPPort) { case 1: if (enable) v_pClkRegs->cken |= XLLP_CLKEN_SSP1; else v_pClkRegs->cken &= ~XLLP_CLKEN_SSP1; break; case 2: if (enable) v_pClkRegs->cken |= XLLP_CLKEN_SSP2; else v_pClkRegs->cken &= ~XLLP_CLKEN_SSP2; break; case 3: if (enable) v_pClkRegs->cken |= XLLP_CLKEN_SSP3; else v_pClkRegs->cken &= ~XLLP_CLKEN_SSP3; break; default: //other than 4 will fail earlier therefore default = 4. if (enable) v_pClkRegs->cken |= XLLP_CLKEN_SSP4; else v_pClkRegs->cken &= ~XLLP_CLKEN_SSP4; } //MmUnmapIoSpace((PVOID)v_pClkRegs,sizeof(XLLP_CLKMGR_T)); VirtualFree((PVOID)(v_pClkRegs),0,MEM_RELEASE); v_pClkRegs = NULL; return TRUE; } VOID WriteFWtoNova(PSPIPHY pSpiPhy,BYTE* pFW,DWORD Len) { PDWORD fwBuf; PBYTE ptr; DWORD count, dstAddr, i; SmsDataDownload_ST *dnlMsg; SmsMsgData_ST *trigMsg; SmsMsgData_ST *setIntMsg; DWORD entryPoint; pSpiPhy->sspCtrl->sscr0 &= ~XLLP_SSCR0_SSE; /* Reduce the SPI Clock to download speed.*/ if (!enableDisableSSPClock(pSpiPhy, FALSE)) { return; } // Set register SSCR0 pSpiPhy->sspCtrl->sscr0 &= 0xfff000ff; pSpiPhy->sspCtrl->sscr0 |=1<<8; // Divide the clock by 2 if (!enableDisableSSPClock(pSpiPhy, TRUE)) { return; } pSpiPhy->sspCtrl->sscr0 |=XLLP_SSCR0_SSE; ReadWriteDWord(pSpiPhy,SPI_ACTIVATION_PREAMBLE1); ReadWriteDWord(pSpiPhy,SPI_ACTIVATION_PREAMBLE2); fwBuf = LocalAlloc(LPTR, SPI_PACKET_SIZE); entryPoint = ((DWORD*)pFW)[2]; Len -= 12; ptr = pFW + 12; dstAddr = entryPoint; fwBuf[0] = SPI_COMMAND_PREAMBLE; dnlMsg = (SmsDataDownload_ST*)&fwBuf[1]; dnlMsg->xMsgHeader.msgType = MSG_SMS_DATA_DOWNLOAD_REQ; dnlMsg->xMsgHeader.msgSrcId = 0; dnlMsg->xMsgHeader.msgDstId = 11; dnlMsg->xMsgHeader.msgFlags = 0; while (Len > 0) { count = min(Len, SMS_MAX_PAYLOAD_SIZE); dnlMsg->xMsgHeader.msgLength = (UINT16)(count + sizeof(SmsMsgHdr_ST) + sizeof(dnlMsg->MemAddr)); dnlMsg->MemAddr = dstAddr; memcpy(dnlMsg->Payload, ptr, count); ptr += count; dstAddr += count; Len -= count; for (i = 0; i < (SPI_PACKET_SIZE / sizeof(DWORD)); i++) { DWORD ret = ReadWriteDWord(pSpiPhy,fwBuf[i]); } } /*Trigger the downloaded code execution*/ trigMsg = (SmsMsgData_ST*)&fwBuf[1]; trigMsg->xMsgHeader.msgType = MSG_SMS_SWDOWNLOAD_TRIGGER_REQ; trigMsg->xMsgHeader.msgDstId = 11; // to MSGPROC_TASK trigMsg->xMsgHeader.msgSrcId = 0; // to MSGPROC_TASK trigMsg->xMsgHeader.msgFlags = 0; trigMsg->xMsgHeader.msgLength = sizeof(SmsMsgHdr_ST) + 5 * sizeof(UINT32); trigMsg->msgData[0] = entryPoint; // Task function trigMsg->msgData[1] = 3; // Task priority trigMsg->msgData[2] = 0x200; // Task stack trigMsg->msgData[3] = 0; // Task creation parameter trigMsg->msgData[4] = 1; // Task application ID for (i = 0; i < (SPI_PACKET_SIZE / sizeof(DWORD)); i++) { DWORD ret = ReadWriteDWord(pSpiPhy,fwBuf[i]); } Sleep(10); setIntMsg = (SmsMsgData_ST*)&fwBuf[1]; setIntMsg->xMsgHeader.msgType = MSG_SMS_SPI_INT_LINE_SET_REQ; setIntMsg->xMsgHeader.msgDstId = 11; // to MSGPROC_TASK setIntMsg->xMsgHeader.msgSrcId = 0; // to MSGPROC_TASK setIntMsg->xMsgHeader.msgFlags = 0; setIntMsg->xMsgHeader.msgLength = sizeof(SmsMsgHdr_ST) + 3 * sizeof(UINT32); setIntMsg->msgData[0] = 0; // Main Spi Controller (0) setIntMsg->msgData[1] = pSpiPhy->novaIntrPin; // Interrupt GPIO. setIntMsg->msgData[2] = 0; // Default pulse width. for (i = 0; i < (SPI_PACKET_SIZE / sizeof(DWORD)); i++) { DWORD ret = ReadWriteDWord(pSpiPhy,fwBuf[i]); } pSpiPhy->sspCtrl->sscr0 &= ~XLLP_SSCR0_SSE; /* Increase the SPI Clock to working speed.*/ if (!enableDisableSSPClock(pSpiPhy, FALSE)) { return; } // Set register SSCR0 pSpiPhy->sspCtrl->sscr0 &= 0xfff000ff; if (!enableDisableSSPClock(pSpiPhy, TRUE)) { return; } pSpiPhy->sspCtrl->sscr0 |=XLLP_SSCR0_SSE; LocalFree(fwBuf); } void smsspibus_xfer(void* context, unsigned char * txbuf, unsigned long txbuf_phy_addr, unsigned char* rxbuf, unsigned long rxbuf_phy_addr, int len) { PSPIPHY pSpiPhy = (PSPIPHY)context; DWORD timeout; DWORD* pdw; if (txbuf) { //RETAILMSG(1, (TEXT("transfer buf starting with: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x.\r\n"), txbuf[0], //txbuf[1], txbuf[2], txbuf[3], txbuf[4], txbuf[5], txbuf[6], txbuf[7])); } if (pSpiPhy->dmaService == NULL) { //No DMA service - copy using CPU //Loop as long as the TX packet has not been completly trasmitterd, or //until the RX FIFO is emty //RETAILMSG(1, (TEXT("transfer %d bytes without DMA.\r\n"), len)); pdw = (DWORD*)rxbuf; while(len > 0) { //Loop while there is any data in the fifo while(!(pSpiPhy->sspCtrl->ssr & SSSR_TNF)); if(txbuf) { DWORD sb = *((DWORD*)txbuf); SSPWriteDWord(pSpiPhy,sb); txbuf+=4; } else { SSPWriteDWord(pSpiPhy,0); } timeout = POLLING_TIMEOUT; while(!(pSpiPhy->sspCtrl->ssr & SSSR_RNE)&& timeout--); if (timeout == -1) //This is for debugginf - timeout should never expire. If it does - SSP controler is not working. timeout = 0; *pdw = SSPReadDWord(pSpiPhy); pdw++;//pointer to DWORD inc by 4 len-=4; } } else // Using DMA { DMA_PARAMS_ST dmaParams; int i, tmp; if(txbuf) { //Set the Tx buffer DMA transaction. for (i = 0; i < (len+3)>>2; i++) ((DWORD*)txbuf)[i] = SWAP32(((DWORD*)txbuf)[i]); } /*Activate the DMA for the recieve of bytes*/ dmaParams.srcAddr = pSpiPhy->sspDataRegPhy; dmaParams.dstAddr = rxbuf_phy_addr; dmaParams.len = len; dmaParams.flags = DMA_USE_SRC_FLOW_CONTROL | DMA_INC_DST_ADDR; dmaParams.transactionId = (DWORD)pSpiPhy->rxEvent; dmaParams.callBack = endOfDmaTransfer; pSpiPhy->dmaService->dmaConfigChannel((LPVOID)pSpiPhy->dmaService->rxDmaDevice, &dmaParams); //DBGMSG( 1, (TEXT("DMA transfer src=0x%x, dst=0x%x, len=%d \r\n"), dmaParams.srcAddr, dmaParams.dstAddr, len)); /*Activate the DMA for the transmit of bytes*/ dmaParams.srcAddr = txbuf_phy_addr; dmaParams.dstAddr = pSpiPhy->sspDataRegPhy; dmaParams.len = len; dmaParams.flags = DMA_USE_DST_FLOW_CONTROL | DMA_INC_SRC_ADDR; dmaParams.transactionId = 0; dmaParams.callBack = NULL; pSpiPhy->dmaService->dmaConfigChannel((LPVOID)pSpiPhy->dmaService->txDmaDevice, &dmaParams); //DBGMSG( 1, (TEXT("DMA transfer src=0x%x, dst=0x%x, len=%d \r\n"), dmaParams.srcAddr, dmaParams.dstAddr, len)); // Moving 256 Bytes through SPI using 6.5Mbps takes ~0.3mS, so we wait much longer than that. if (WaitForSingleObject(pSpiPhy->rxEvent, 5000) == WAIT_OBJECT_0) { // DBGMSG( ZONE_INFO, (TEXT("-----------DMA transfer ended at %d\r\n"), GetTickCount())); for (i = 0; i < len>>2; i++) { tmp =((DWORD*)rxbuf)[i]; ((DWORD*)rxbuf)[i] = SWAP32(tmp); } } else RETAILMSG(1, (TEXT("SPI!Read from device :Recieved Timeout for DMA transfer.\r\n"))); } } void smsspiphy_deinit(PVOID context) { DWORD exitCode; PSPIPHY pSpiPhy = (PSPIPHY)context; if (pSpiPhy) { pSpiPhy->drvActive = FALSE; if (pSpiPhy->RxIST) { if (pSpiPhy->SmsInterruptEvent) // Set an event to start the thread. SetEvent(pSpiPhy->SmsInterruptEvent); CloseHandle(pSpiPhy->RxIST); while (GetExitCodeThread(pSpiPhy->RxIST, &exitCode) == STILL_ACTIVE); pSpiPhy->RxIST = NULL; } if (pSpiPhy->dmaService) { deactivateDMAService(pSpiPhy); } if (pSpiPhy->rxEvent) { CloseHandle(pSpiPhy->rxEvent); pSpiPhy->rxEvent = NULL; } if (pSpiPhy->SmsInterruptEvent) { CloseHandle(pSpiPhy->SmsInterruptEvent); pSpiPhy->SmsInterruptEvent = NULL; } LocalFree(pSpiPhy); } #ifdef GET_GPIOXX_2_IRQ //disable the hardware interrupt and to deregister the event InterruptDisable(pSpiPhy->spiSysIntr); #endif //cancel all Threads...ISRThread //cancel all Events... //unmapping all physical addresses used to access register.... //unmapping SSP registers /* MmUnmapIoSpace((PVOID)pSpiPhy->sspCtrl ,sizeof(XLLP_SSP_REGS)); MmUnmapIoSpace((PVOID)v_pGPIORegisters,sizeof(XLLP_GPIO_T)); MmUnmapIoSpace((PVOID)v_pClkRegs,sizeof(XLLP_CLKMGR_T)); */ if(v_pGPIORegisters) { VirtualFree((PVOID)(v_pGPIORegisters),0,MEM_RELEASE); v_pGPIORegisters = NULL; } if(pSpiPhy->sspCtrl) { VirtualFree((PVOID)(pSpiPhy->sspCtrl),0,MEM_RELEASE); pSpiPhy->sspCtrl = NULL; } if(v_pClkRegs) { VirtualFree((PVOID)(v_pClkRegs),0,MEM_RELEASE); v_pClkRegs = NULL; } //for PXA300 #ifndef PXA270 if(v_pMFPRRegisters) { MmUnmapIoSpace((PVOID)v_pMFPRRegisters,sizeof(XLLP_GPIO_T)); v_pMFPRRegisters = NULL; } #endif } void* smsspiphy_init(PVOID Context, void(*smsspi_interruptHandler)(void*), PVOID intrContext) { DWORD SPICDSysIntr; PSPIPHY pSpiPhy = (PSPIPHY)LocalAlloc(LPTR,sizeof(SPIPHY)); useSSPPort = GetSpiPortNum(); RETAILMSG(1, (TEXT("useSSPPort = %d.\r\n"), useSSPPort)); v_pGPIORegisters =(volatile XLLP_GPIO_T*)VirtualAllocCopy(sizeof(XLLP_GPIO_T),"GPIO_BASE_U_VIRTUAL",(PVOID)(GPIO_BASE_U_VIRTUAL)); switch(useSSPPort) { case 1: pSpiPhy->sspCtrl= (volatile XLLP_SSP_REGS *)VirtualAllocCopy(sizeof(XLLP_SSP_REGS),"SSP1_BASE_U_VIRTUAL",(PVOID)(SSP1_BASE_U_VIRTUAL)); pSpiPhy->sspDataRegPhy = SSP1_BASE_PHYSICAL+((DWORD)(&pSpiPhy->sspCtrl->ssdr) - (DWORD)(pSpiPhy->sspCtrl)); break; case 2: pSpiPhy->sspCtrl= (volatile XLLP_SSP_REGS *)VirtualAllocCopy(sizeof(XLLP_SSP_REGS),"SSP2_BASE_U_VIRTUAL",(PVOID)(SSP2_BASE_U_VIRTUAL)); pSpiPhy->sspDataRegPhy = SSP2_BASE_PHYSICAL+((DWORD)(&pSpiPhy->sspCtrl->ssdr) - (DWORD)(pSpiPhy->sspCtrl)); break; case 3: pSpiPhy->sspCtrl= (volatile XLLP_SSP_REGS *)VirtualAllocCopy(sizeof(XLLP_SSP_REGS),"SSP3_BASE_U_VIRTUAL",(PVOID)(SSP3_BASE_U_VIRTUAL)); pSpiPhy->sspDataRegPhy = SSP3_BASE_PHYSICAL+((DWORD)(&pSpiPhy->sspCtrl->ssdr) - (DWORD)(pSpiPhy->sspCtrl)); break; #ifndef PXA270 case 4: pSpiPhy->sspCtrl= (volatile XLLP_SSP_REGS *)VirtualAllocCopy(sizeof(XLLP_SSP_REGS),"SSP4_BASE_U_VIRTUAL",(PVOID)(SSP4_BASE_U_VIRTUAL)); pSpiPhy->sspDataRegPhy = SSP4_BASE_PHYSICAL+((DWORD)(&pSpiPhy->sspCtrl->ssdr) - (DWORD)(pSpiPhy->sspCtrl)); break; #endif default: smsspiphy_deinit(pSpiPhy); return NULL; } RETAILMSG(1, (TEXT("lINe %d.\r\n"), __LINE__)); if (!pSpiPhy->sspCtrl) { smsspiphy_deinit(pSpiPhy); return NULL; } v_pClkRegs= (XLLP_CLKMGR_T *)VirtualAllocCopy(sizeof(XLLP_CLKMGR_T),"clk registers",(PVOID)(CLK_BASE_U_VIRTUAL)); pSpiPhy->intrContext = intrContext; spiPhyGetRegistrySettings(Context, pSpiPhy); activateDMAService(pSpiPhy); pSpiPhy->InterruptCallback = smsspi_interruptHandler; pSpiPhy->drvActive = TRUE; pSpiPhy->SmsInterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (pSpiPhy->SmsInterruptEvent == NULL) { RETAILMSG(1, (TEXT("SmsSpi: smsspiphy_init() failed to create SmsInterruptEvent event.\r\n"))); smsspiphy_deinit(pSpiPhy); return NULL; } pSpiPhy->rxEvent = CreateEvent(NULL, FALSE, FALSE, NULL); RETAILMSG(1, (TEXT("lINe %d.\r\n"), __LINE__)); if (pSpiPhy->rxEvent == NULL) { RETAILMSG(1, (TEXT("SmsSpi: smsspiphy_init() failed to create rxEvent event.\r\n"))); smsspiphy_deinit(pSpiPhy); return NULL; } #ifdef PXA270 //for PXA270 GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters,SSPCLK|GPIO_AF2|GPIO_OUT); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters,SSPSFRM|GPIO_AF2|GPIO_OUT); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters,SSPTXD|GPIO_AF2|GPIO_OUT); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters,SSPRXD|GPIO_AF1|GPIO_IN); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters, DMBINT0 | GPIO_AF0 |GPIO_IN); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters, DMB_PWREN | GPIO_AF0 |GPIO_OUT); GPIOSetControllerValue((XLLP_GPIO_T *)v_pGPIORegisters, DMB_PWREN |GPIO_OUT_1); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters, nDMB_PD | GPIO_AF0 |GPIO_OUT); GPIOSetControllerValue((XLLP_GPIO_T *)v_pGPIORegisters, nDMB_PD |GPIO_OUT_1); GPIOSetController( (XLLP_GPIO_T *)v_pGPIORegisters, nDMB_RESET | GPIO_AF0 |GPIO_OUT); GPIOSetControllerValue((XLLP_GPIO_T *)v_pGPIORegisters, nDMB_RESET |GPIO_OUT_1); msWait(10); GPIOSetControllerValue((XLLP_GPIO_T *)v_pGPIORegisters, nDMB_RESET |GPIO_OUT_0); msWait(10); GPIOSetControllerValue((XLLP_GPIO_T *)v_pGPIORegisters, nDMB_RESET |GPIO_OUT_1); msWait(10); #else //for PXA300 switch (useSSPPort) { case 1: v_pMFPRRegisters[SSP1_MFPR_TX ] = SSP1_AF | FAST3MA; v_pMFPRRegisters[SSP1_MFPR_RX ] = SSP1_AF | FAST3MA; v_pMFPRRegisters[SSP1_MFPR_CLK] = SSP1_AF | FAST3MA; v_pMFPRRegisters[SSP1_MFPR_FRM] = SSP1_AF | FAST3MA; v_pGPIORegisters->SSP1_GPDR_TX |= (XLLP_GPIO_BIT_SSP1_TXD); v_pGPIORegisters->SSP1_GPDR_CLK |= (XLLP_GPIO_BIT_SSP1_CLK); v_pGPIORegisters->SSP1_GPDR_FRM |= (XLLP_GPIO_BIT_SSP1_FRM); v_pGPIORegisters->SSP1_GPDR_RX &= ~(XLLP_GPIO_BIT_SSP1_RXD); break; case 2: v_pMFPRRegisters[SSP2_MFPR_TX ] = SSP2_AF | FAST3MA; v_pMFPRRegisters[SSP2_MFPR_RX ] = SSP2_AF | FAST3MA; v_pMFPRRegisters[SSP2_MFPR_CLK] = SSP2_AF | FAST3MA; v_pMFPRRegisters[SSP2_MFPR_FRM] = SSP2_AF | FAST3MA; v_pGPIORegisters->SSP2_GPDR_TX |= (XLLP_GPIO_BIT_SSP2TXD); v_pGPIORegisters->SSP2_GPDR_CLK |= (XLLP_GPIO_BIT_SSP2CLK); v_pGPIORegisters->SSP2_GPDR_FRM |= (XLLP_GPIO_BIT_SSP2FRM); v_pGPIORegisters->SSP2_GPDR_RX &= ~(XLLP_GPIO_BIT_SSP2RXD); break; case 3: v_pMFPRRegisters[SSP3_MFPR_TX ] = SSP3_AF | FAST3MA; v_pMFPRRegisters[SSP3_MFPR_RX ] = SSP3_AF | FAST3MA; v_pMFPRRegisters[SSP3_MFPR_CLK] = SSP3_AF | FAST3MA; v_pMFPRRegisters[SSP3_MFPR_FRM] = SSP3_AF | FAST3MA; v_pGPIORegisters->SSP3_GPDR_TX |= (XLLP_GPIO_BIT_SSP3TXD); v_pGPIORegisters->SSP3_GPDR_CLK |= (XLLP_GPIO_BIT_SSP3CLK); v_pGPIORegisters->SSP3_GPDR_FRM |= (XLLP_GPIO_BIT_SSP3FRM); v_pGPIORegisters->SSP3_GPDR_RX &= ~(XLLP_GPIO_BIT_SSP3RXD); break; default: v_pMFPRRegisters[SSP4_MFPR_TX ] = SSP4_AF | FAST3MA; v_pMFPRRegisters[SSP4_MFPR_RX ] = SSP4_AF | FAST3MA; v_pMFPRRegisters[SSP4_MFPR_CLK] = SSP4_AF | FAST3MA; v_pMFPRRegisters[SSP4_MFPR_FRM] = SSP4_AF | FAST3MA; v_pGPIORegisters->SSP4_GPDR_TX |= (XLLP_GPIO_BIT_SSP4TXD); v_pGPIORegisters->SSP4_GPDR_CLK |= (XLLP_GPIO_BIT_SSP4CLK); v_pGPIORegisters->SSP4_GPDR_FRM |= (XLLP_GPIO_BIT_SSP4FRM); v_pGPIORegisters->SSP4_GPDR_RX &= ~(XLLP_GPIO_BIT_SSP4RXD); } #endif switch (useSSPPort) { case 1: v_pClkRegs->cken &= ~XLLP_CLKEN_SSP1; break; case 2: v_pClkRegs->cken &= ~XLLP_CLKEN_SSP2; break; case 3: v_pClkRegs->cken &= ~XLLP_CLKEN_SSP3; break; default: v_pClkRegs->cken &= ~XLLP_CLKEN_SSP4; } // Set register SSCR0 //pSpiPhy->sspCtrl->sscr0 = 0; //pSpiPhy->sspCtrl->sscr1 = 0; //pSpiPhy->sspCtrl->ssdr = 0; //pSpiPhy->sspCtrl->ssr=0; pSpiPhy->sspCtrl->sscr0 = SSCR0_Motorola | SSCR0_DataSize(16) | SSCR0_EDSS;//32bit words in the fifo pSpiPhy->sspCtrl->sscr0 |=3<<8; // Divide the clock by 3 // Set register SSCR1 pSpiPhy->sspCtrl->sscr1 = (SSCR1_TRAIL|SSCR1_RIE|SSCR1_TIE|SSCR1_TSRE | SSCR1_RSRE |SSCR1_RxTresh(1) | SSCR1_TxTresh(7)); // Set register SSITR pSpiPhy->sspCtrl->ssitr = 0; // Set register SSTO pSpiPhy->sspCtrl->ssto = 0; //No timeout. always send/recieve the same amount of bytes. switch (useSSPPort) { case 1: v_pClkRegs->cken |= XLLP_CLKEN_SSP1; break; case 2: v_pClkRegs->cken |= XLLP_CLKEN_SSP2; break; case 3: v_pClkRegs->cken |= XLLP_CLKEN_SSP3; break; default: v_pClkRegs->cken |= XLLP_CLKEN_SSP4; } //Activate SSP channel pSpiPhy->sspCtrl->sscr0 |=XLLP_SSCR0_SSE; // 1 -- SSP operation is enabled pSpiPhy->spiSysIntr =SYSINTR_DMB; SPICDSysIntr = pSpiPhy->spiSysIntr; DBGMSG(1, (TEXT("SPI : InterruptInitialize(sysInt =%d, Event=0x%x)\r\n"), SPICDSysIntr, pSpiPhy->SmsInterruptEvent)); if (!InterruptInitialize(SPICDSysIntr,pSpiPhy->SmsInterruptEvent,0,0)) { RETAILMSG(1, (TEXT("SPI : InterruptInitialize(sysInt =%d, Event=0x%x) failed (status =%d)\r\n"), pSpiPhy->spiSysIntr, pSpiPhy->SmsInterruptEvent, GetLastError())); } pSpiPhy->RxIST = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)SpiRxIST, pSpiPhy, 0, NULL); RETAILMSG(1, (TEXT("lINe %d.\r\n"), __LINE__)); if (pSpiPhy->RxIST == NULL) { DBGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("SmsSpi: smsspiphy_init() failed to create transferThread thread.\r\n"))); smsspiphy_deinit(pSpiPhy); return 0; } RETAILMSG(1, (TEXT("lINe %d.\r\n"), __LINE__)); if (CeSetThreadPriority(pSpiPhy->RxIST, 0) == FALSE) { RETAILMSG(1, (TEXT("SmsSpi: smsspiphy_init() failed to set Interrupt thread priority.\r\n"))); smsspiphy_deinit(pSpiPhy); return 0; } RETAILMSG(1, (TEXT("SPI init pSpiPhy->sspCtrl->ssdr--2:0x%x\r\n"),pSpiPhy->sspCtrl->ssdr )); return pSpiPhy; } void smschipreset(PVOID context) { }