📄 cspsocspi.c
字号:
return bRet;
}
BOOL SpiSocClose(PVOID pSpiHandle)
{
//check
//if all devices on bus closed, disable clock
BOOL bRet = TRUE;
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocClose Port(%d)\r\n"), pDevHdl->uiHwPort));
if(!SPI_GRABMUTEX(pDevHdl))
{
RETAILMSG (1, (TEXT("+Spi SocClose+ GRABMUTEX failed\r\n") ));
return FALSE;
}
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
if (v_pDriverGlobals->misc.spiDev[0].bSpiOpened)
{
WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi0, 0);
v_pDriverGlobals->misc.spiDev[0].bSpiOpened = FALSE;
}
break;
case SEPARATE_SPI1:
if (v_pDriverGlobals->misc.spiDev[1].bSpiOpened)
{
WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi1, 0);
v_pDriverGlobals->misc.spiDev[1].bSpiOpened = FALSE;
}
break;
default:
bRet = FALSE;
RETAILMSG (1, (TEXT("+Spi SocClose+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
}
pDevHdl->bSpiOpen = FALSE;
SPI_RELEASEMUTEX(pDevHdl);
RETAILMSG (DEBUGPRINT, (TEXT("-Spi SocClose port(%d)\r\n"), pDevHdl->uiHwPort));
return bRet;
}
VOID SpiSocDeinit(PVOID pSpiHandle)
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocDeinit port(%d)\r\n"),pDevHdl->uiHwPort ));
if(!SPI_GRABMUTEX(pDevHdl))
{
RETAILMSG (1, (TEXT("+Spi SocDeinit+ GRABMUTEX failed\r\n") ));
return;
}
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
if (v_pDriverGlobals->misc.spiDev[0].bSpiInited)
{
//RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocDeinit+ tryto StopDispatchThread\r\n") ));
#if SPI_INTR
if (!StopDispatchThread(pDevHdl))
{
RETAILMSG (1, (TEXT("+Spi SocDeinit+ StopDispatchThread failed\r\n")));
return;
}
(HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread = NULL;
(HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent = NULL;
(HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent = NULL;
#endif //SPI_INTR
v_pDriverGlobals->misc.spiDev[0].bSpiInited = FALSE;
WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi0, 0);
//Free memory
FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrR));
(LPVOID)pDevHdl->dwVirtAddrR = NULL;
FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrW));
(LPVOID)pDevHdl->dwVirtAddrW = NULL;
}
break;
case SEPARATE_SPI1:
if (v_pDriverGlobals->misc.spiDev[1].bSpiInited)
{
//RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocDeinit+ tryto StopDispatchThread\r\n") ));
#if SPI_INTR
if (!StopDispatchThread(pDevHdl))
{
RETAILMSG (1, (TEXT("+Spi SocDeinit+ StopDispatchThread failed\r\n")));
return;
}
(HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread = NULL;
(HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent = NULL;
(HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent = NULL;
#endif //SPI_INTR
v_pDriverGlobals->misc.spiDev[1].bSpiInited = FALSE;
WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi1, 0);
//Free memory
FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrR));
(LPVOID)pDevHdl->dwVirtAddrR = NULL;
FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrW));
(LPVOID)pDevHdl->dwVirtAddrW = NULL;
}
break;
default:
RETAILMSG (1, (TEXT("+Spi SocDeinit+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
}
SPI_RELEASEMUTEX(pDevHdl);
RETAILMSG (DEBUGPRINT, (TEXT("-Spi SocDeinit port(%d)\r\n"),pDevHdl->uiHwPort));
}
static BOOL SpiWriteCmdOnly(PVOID pSpiHandle, LPVOID pMosiBuf)
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
BOOL bRet = TRUE;
switch (pDevHdl->SpiDevInfo.CmdByteNum)
{
case SPI_INFO_CMD_BYTE_NUM_1:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PBYTE)pMosiBuf);
break;
case SPI_INFO_CMD_BYTE_NUM_2:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PWORD)pMosiBuf);
break;
case SPI_INFO_CMD_BYTE_NUM_3:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf & 0xffffff);
break;
case SPI_INFO_CMD_BYTE_NUM_4:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf);
break;
default:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf);
break;
}
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxrxen), SPI_CMD_TX_EN);
#if SPI_INTR
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent, INFINITE);
break;
case SEPARATE_SPI1:
WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent, INFINITE);
break;
default:
RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
SPI_RELEASEMUTEX(pDevHdl);
return FALSE;
}
#else //!SPI_INTR
bRet = SPI_POLLING_FRMEND(pDevHdl);
#endif //!SPI_INTR
// Disable the interrupt
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten), 0);
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxrxen), 0);
SPI_RELEASEMUTEX(pDevHdl);
return bRet;
}
BOOL SpiSocReadData(PVOID pSpiHandle, LPVOID pMosiBuf, DWORD uiMosiBufLen, LPVOID pMisoBuf, DWORD uiMisoBufLen)
{
//Do in one Func.
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
BOOL bRet = TRUE;
int i=0, iDMA_DATA_LEN, iDMA_XLEN;
DWORD dwReg=0;
RETAILMSG (DEBUGPRINT,(TEXT("+Spi SocReadData+ entered port(%d)\r\n"),pDevHdl->uiHwPort ));
//Parameter validation
if((pMosiBuf == NULL && pMisoBuf == NULL) || !pDevHdl->bSpiOpen)
{
RETAILMSG (1,(TEXT("+Spi SocReadData+ Parameter Error or Spi not open\r\n") ));
return FALSE;
}
if (SPI_INFO_IO_MODE == pDevHdl->SpiDevInfo.IoMod)
{
if(!SPI_ParametCheck(pDevHdl,FIFO_LENGTH))
{
RETAILMSG (1,(TEXT("+Spi SocReadData+ Parameter Error\r\n") ));
return FALSE;
}
}
else
{
if(!SPI_ParametCheck(pDevHdl,DMA_LENGTH))
{
RETAILMSG (1,(TEXT("+Spi SocReadData+ Parameter Error\r\n") ));
return FALSE;
}
}
//Step1: Get Dev Info
if(!SPI_GRABMUTEX(pDevHdl))
{
RETAILMSG (1,(TEXT("+Spi SocReadData+ GRABMUTEX failed\r\n") ));
return FALSE;
}
//Step1 END
//Config CmdByteNum,MulDataMod and whether have command bit for this read operation.
if (SPI_INFO_NO_COMMAND_DATA == pDevHdl->SpiDevInfo.HaveCmdInFrm)
{
dwReg = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl));
dwReg &= ~(0x1 << 17);
dwReg = dwReg
| pDevHdl->SpiDevInfo.CmdByteNum
| pDevHdl->SpiDevInfo.MulDataMod;
}
else
{
dwReg = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl));
dwReg |= ((0x1 << 17)
| pDevHdl->SpiDevInfo.CmdByteNum
| pDevHdl->SpiDevInfo.MulDataMod);
}
WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl), dwReg);
//Set transfer length
WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxdatalen), pDevHdl->SpiDevInfo.DataLength);
//Step2: clear and enable interrupts
//clear interrupts
WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus), SPI_INT_MASK_ALL);
// Enable the interrupt
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten), SPI_INT_FRM_END_MASK);
//Step2 END
//Step3: RXFIFO RESET/START
WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoop), SPI_FIFO_RESET);
WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoop), SPI_FIFO_START);
//Step3 END
//RETAILMSG (1,(TEXT("+Spi SocR 0x%x\r\n"),(BYTE)READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifodata))));
//Step4: prepare buffers -- Spicommand, pMisoBuf, txfifodata
if (SPI_INFO_HAVE_COMMAND_DATA == pDevHdl->SpiDevInfo.HaveCmdInFrm)
{
switch (pDevHdl->SpiDevInfo.CmdByteNum)
{
case SPI_INFO_CMD_BYTE_NUM_1:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PBYTE)pMosiBuf);
break;
case SPI_INFO_CMD_BYTE_NUM_2:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PWORD)pMosiBuf);
break;
case SPI_INFO_CMD_BYTE_NUM_3:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf & 0xffffff);
break;
case SPI_INFO_CMD_BYTE_NUM_4:
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf);
break;
default:
RETAILMSG (1, (TEXT("+Spi SocReadData+ WRONG command byte number: (%d)\r\n"), pDevHdl->SpiDevInfo.CmdByteNum));
bRet = FALSE;
break;
}
}
//Step4 END
//Step5: DMA
if (pDevHdl->SpiDevInfo.IoMod != SPI_INFO_IO_MODE)
{
//start configure DMA
pDevHdl->m_pRawBufR = (BYTE *)(pDevHdl->dwVirtAddrR); //pointer to read memory
if (pDevHdl->m_pRawBufR == NULL)
{
RETAILMSG(1, (TEXT("+Spi SocReadData+ m_pRawBufR is NULL.\r\n")));
SPI_RELEASEMUTEX(pDevHdl);
return FALSE;
}
switch (pDevHdl->SpiDevInfo.DataFmt)
{
case SPI_INFO_TRAN_DATA_FORMAT_8BIT:
iDMA_DATA_LEN = pDevHdl->SpiDevInfo.DataLength+1;
break;
case SPI_INFO_TRAN_DATA_FORMAT_12BIT:
case SPI_INFO_TRAN_DATA_FORMAT_16BIT:
iDMA_DATA_LEN = 2*(pDevHdl->SpiDevInfo.DataLength+1);
break;
case SPI_INFO_TRAN_DATA_FORMAT_32BIT:
iDMA_DATA_LEN = 4*(pDevHdl->SpiDevInfo.DataLength+1);
break;
default:
RETAILMSG (1, (TEXT("+Spi SocReadData+ WRONG data format. (%d)\r\n"), pDevHdl->SpiDevInfo.DataFmt));
SPI_RELEASEMUTEX(pDevHdl);
return FALSE;
}
iDMA_XLEN = (iDMA_DATA_LEN>>2)+((iDMA_DATA_LEN%4==0)?0:1);
v_pDMAReg->dmaWidth[USP_REV_DMA_WIDTH_ID] = iDMA_XLEN; //?
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
WRITE_BITFIELD(struct RSCDmaMuxBits, &((v_pRscRegs)->rscDmaMux), ch12, 1);
v_pDMAReg->dmaWidth[USP_REV_DMA_WIDTH_ID] = iDMA_XLEN;
WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[12].xlReg), iDMA_XLEN);
WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[12].ylReg), 0); //ylReg = 0, means 1D-DMA
WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[12].ctrlReg), ws, USP_REV_DMA_WIDTH_ID);
WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[12].ctrlReg), dir, 0); //to sdram
WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[12].ctrlReg), burst, 0);
//Enable DMA
WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn12, 1);
WRITE_REGISTER_ULONG(&((v_pDMAReg)->dmaChn[12].addrReg), (DWORD)((pDevHdl->dwPhyAddrR)/4));
break;
case SEPARATE_SPI1:
WRITE_BITFIELD(struct RSCDmaMuxBits, &((v_pRscRegs)->rscDmaMux), ch14, 1);
WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[14].xlReg), iDMA_XLEN);
WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[14].ylReg), 0); //ylReg = 0, means 1D-DMA
WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[14].ctrlReg), ws, USP_REV_DMA_WIDTH_ID);
WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[14].ctrlReg), dir, 0);
WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[14].ctrlReg), burst, 0);
//Enable DMA
WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn14, 1);
WRITE_REGISTER_ULONG(&((v_pDMAReg)->dmaChn[14].addrReg), (DWORD)((pDevHdl->dwPhyAddrR)/4));
break;
default:
RETAILMSG (1, (TEXT("+Spi SocReadData+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
bRet = FALSE;
break;
}
}
else
{
// Do nothing
}
//Step5 END
//Step6: RX_EN(TX_EN) -- do early
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxrxen), SPI_RX_EN);
pDevHdl->StatusReg[0] = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifostat));
//Step6 END
#if SPI_INTR
RETAILMSG (DEBUGPRINT, (TEXT("+Spi READ+ Waiting hFrmendEvent\r\n") ));
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent, INFINITE);
break;
case SEPARATE_SPI1:
WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent, INFINITE);
break;
default:
RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
SPI_RELEASEMUTEX(pDevHdl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -