📄 gspx-pxa.c
字号:
pHC->read_desc = (DMADescriptorChannelType *) HalAllocateCommonBuffer(&Adapter, sizeof(DMADescriptorChannelType)*2, &PA, FALSE);
if (pHC->read_desc) {
pHC->read_desc_phys_addr = (DMADescriptorChannelType *) PA.LowPart;
}
pHC->write_desc = (DMADescriptorChannelType *) HalAllocateCommonBuffer(&Adapter, sizeof(DMADescriptorChannelType)*2, &PA, FALSE);
if (pHC->write_desc) {
pHC->write_desc_phys_addr = (DMADescriptorChannelType *) PA.LowPart;
}
pHC->rw_desc = (DMADescriptorChannelType *) HalAllocateCommonBuffer(&Adapter, sizeof(DMADescriptorChannelType)*2, &PA, FALSE);
if (pHC->rw_desc) {
pHC->rw_desc_phys_addr = (DMADescriptorChannelType *) PA.LowPart;
}
#endif ///(USE_DMA == 1)
///Allocate I/O buffers
pHC->iodata = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iodata) {
pHC->phys_addr = (PBYTE)PA.LowPart;
}
pHC->iorw = (PBYTE) HalAllocateCommonBuffer(&Adapter, PXA_SSP_IODATA_SIZE, &PA, FALSE);
if (pHC->iorw) {
pHC->phys_addr_rw = (PBYTE)PA.LowPart;
}
///#if (USE_DMA == 1)
///Get the DMA channel
///==============================================================
///Initialize the DMA channel parameters
pHC->DMAParam[RDDMA_PARAM].pDMARegs = pHC->pDMARegs;
pHC->DMAParam[RDDMA_PARAM].channel = DMA_CH_READ;
if(!(pHC->DMAParam[RDDMA_PARAM].dmaWaitObj = CreateEvent( NULL, FALSE, FALSE,NULL))) {
GSPIMSG(ERRMSG, (TEXT("Init rddmaWaitObj, CreateEvent FAILED")));
result = -1;
goto errFuncRet;
}
pHC->DMAParam[WTDMA_PARAM].pDMARegs = pHC->pDMARegs;
pHC->DMAParam[WTDMA_PARAM].channel = DMA_CH_RW;
if(!(pHC->DMAParam[WTDMA_PARAM].dmaWaitObj = CreateEvent( NULL, FALSE, FALSE,NULL))) {
GSPIMSG(ERRMSG, (TEXT("Init wtdmaWaitObj, CreateEvent FAILED")));
result = -1;
goto errFuncRet;
}
if(DMA_CHMAP_SSP_RX > 63)
{
pHC->pDMARegs->drcmr2[DMA_CHMAP_SSP_RX - 64] = pHC->DMAParam[RDDMA_PARAM].channel | DRCMR_MAPVAL;
}else
{
pHC->pDMARegs->drcmr[DMA_CHMAP_SSP_RX] = pHC->DMAParam[RDDMA_PARAM].channel | DRCMR_MAPVAL;
}
if(DMA_CHMAP_SSP_TX > 63)
{
pHC->pDMARegs->drcmr2[DMA_CHMAP_SSP_TX - 64] = pHC->DMAParam[WTDMA_PARAM].channel | DRCMR_MAPVAL;
}else
{
pHC->pDMARegs->drcmr[DMA_CHMAP_SSP_TX] = pHC->DMAParam[WTDMA_PARAM].channel | DRCMR_MAPVAL;
}
///==============================================================
/// Request the DMA IRQ
#if (USE_DMA == 1) && (USE_DMAIRQ == 1)
pHC->hBusAcceHND = CreateBusAccessHandle( pg_szActiveKey );
{
int i;
for (i=0 ; i<MAXDMA_PARAM ; i++) {
pHC->DMAIntrInfo[i].irq = IRQ_DMAC;
pHC->DMAIntrInfo[i].pIstFunc = (MYISTFUNC) dma_ist;
pHC->DMAIntrInfo[i].param = (LPVOID)&pHC->DMAParam[i];
pHC->DMAIntrInfo[i].IntrMask = 0x04;
if (!BusTransBusAddrToStatic(pHC->hBusAcceHND, Internal, 0, DCSRAddr[i], sizeof(DWORD), &inIoSpace, &pHC->DMAIntrInfo[i].IntrRgPhysAddr)) {
GSPIMSG(ERRMSG, (TEXT("installISR: Failed TransBusAddrToStatic - (read)\r\n")));
}
///RETAILMSG(1, (TEXT("installISR: PhysAddr: %xh\r\n"), pHC->DMAIntrInfo[i].IntrRgPhysAddr));
///Initialize the interrupt, IST
setupInterrupt(&pHC->DMAIntrInfo[i]);
///Load the ISR
installISR(&pHC->DMAIntrInfo[i]);
}
}
#endif ///USE_DMAIRQ
///#endif ///USE_DMA
#if (USE_DMA == 1)
///
///Configure the DMA descriptor
{
union DMACmdReg CmdBuff;
volatile DMADescriptorChannelType* descPt;
// set CMD values with bit fields.
//
CmdBuff.DcmdReg.len = 0; // length of the memory buffer
CmdBuff.DcmdReg.width = 0x2; // binary 10 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x1; // binary 01
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 0; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 0; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 1; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 1; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 0; // 1 means increment the source address (since it's a peripheral)
descPt = pHC->read_desc;
descPt->ddadr = (UINT32)(pHC->read_desc_phys_addr + 1);
descPt->dsadr = (UINT32)(&(phySSPBase->base.ssdr));
descPt->dtadr = (UINT32) (pHC->phys_addr);
descPt->dcmd = CmdBuff.DcmdDword; // size and cmd values of the RcvA buffer
///====================================================================
// set CMD values with bit fields.
//
CmdBuff.DcmdReg.len = 0; // length of the memory buffer
CmdBuff.DcmdReg.width = 0x2; // binary 10 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x1; // binary 01
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 0; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 1; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 0; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 0; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 1; // 1 means increment the source address (since it's a peripheral)
descPt = pHC->write_desc;
///descPt->ddadr = (UINT32)(pHC->write_desc_phys_addr + sizeof(DMADescriptorChannelType));
descPt->ddadr = (UINT32)(pHC->write_desc_phys_addr + 1);
descPt->dsadr = (UINT32) (pHC->phys_addr);
///descPt->dtadr = (UINT32)(&(pHC->pSSPRegs->base.ssdr));
descPt->dtadr = (UINT32)(&(phySSPBase->base.ssdr));
descPt->dcmd = CmdBuff.DcmdDword; // size and cmd values of the RcvA buffer
///====================================================================
// set CMD values with bit fields.
//
CmdBuff.DcmdReg.len = 0; // length of the memory buffer
CmdBuff.DcmdReg.width = 0x2; // binary 10 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x1; // binary 01
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 0; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 1; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 0; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 0; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 1; // 1 means increment the source address (since it's a peripheral)
descPt = pHC->rw_desc;
descPt->ddadr = (UINT32)(pHC->rw_desc_phys_addr + 1);
descPt->dsadr = (UINT32) (pHC->phys_addr_rw);
descPt->dtadr = (UINT32)(&(phySSPBase->base.ssdr));
descPt->dcmd = CmdBuff.DcmdDword; // size and cmd values of the RcvA buffer
}
#endif ///(USE_DMA == 1)
memset(pHC->iorw, 0xff, sizeof(PXA_SSP_IODATA_SIZE));
return result;
errFuncRet:
return result;
}
VOID dma_deinit(PSSP_HARDWARE_CONTEXT pDC)
{
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)pDC;
PHYSICAL_ADDRESS PA = {0};
CloseHandle(pHC->DMAParam[RDDMA_PARAM].dmaWaitObj);
CloseHandle(pHC->DMAParam[WTDMA_PARAM].dmaWaitObj);
if(pHC->iodata != NULL)
{
HalFreeCommonBuffer(NULL,PXA_SSP_IODATA_SIZE, PA, pHC->iodata, FALSE);
}
if(pHC->iorw != NULL)
{
HalFreeCommonBuffer(NULL,PXA_SSP_IODATA_SIZE, PA, pHC->iorw, FALSE);
}
return;
}
///
/// ssp_init_hw: Initialize the H/W
/// Input:
/// pHC - Hard context
/// Output:
/// None
/// Return:
/// None
void ssp_init_hw(PSSP_HARDWARE_CONTEXT pHC)
{
PHYSICAL_ADDRESS Bulverde_GPIO_Base = {BULVERDE_BASE_REG_PA_GPIO};
PHYSICAL_ADDRESS Bulverde_SSP_Base = {SSPREG_PHY_BASE};
PHYSICAL_ADDRESS Bulverde_CLKMGR_Base = {BULVERDE_BASE_REG_PA_CLKMGR};
PHYSICAL_ADDRESS Bulverde_DMA_Base = {BULVERDE_BASE_REG_PA_DMAC};
PHYSICAL_ADDRESS Bulverde_PA_OTS_Base = {BULVERDE_BASE_REG_PA_OST};
PHYSICAL_ADDRESS Bulverde_ICR_Base = {BULVERDE_BASE_REG_PA_INTC};
pHC->pGPIORegs = (BULVERDE_GPIO_REG*)MmMapIoSpace(Bulverde_GPIO_Base, sizeof(BULVERDE_GPIO_REG), FALSE);
if (!pHC->pGPIORegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating GPIO register\n")));
goto funcFinal;
}
pHC->pSSPRegs = (BULVERDE_SSP_EXT_REG*)MmMapIoSpace(Bulverde_SSP_Base, sizeof(BULVERDE_SSP_EXT_REG), FALSE);
if (!pHC->pSSPRegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating SSP register\n")));
goto funcFinal;
}
pHC->pCLKRegs = (BULVERDE_CLKMGR_REG*)MmMapIoSpace(Bulverde_CLKMGR_Base, sizeof(BULVERDE_CLKMGR_REG), FALSE);
if (!pHC->pCLKRegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating CLK register\n")));
goto funcFinal;
}
pHC->pDMARegs = (BULVERDE_DMA_REG*)MmMapIoSpace(Bulverde_DMA_Base, sizeof(BULVERDE_DMA_REG), FALSE);
if (!pHC->pDMARegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating DMA register\n")));
goto funcFinal;
}
pHC->pOSTRegs = (BULVERDE_OST_REG*)MmMapIoSpace(Bulverde_PA_OTS_Base, sizeof(BULVERDE_OST_REG), FALSE);
if (!pHC->pOSTRegs) {
GSPIMSG(ERRMSG, (TEXT("Error in allocating OST register\n")));
goto funcFinal;
}
///
///Configure the GPIO
///
set_GPIO_mode(pHC->pGPIORegs, SSP_SCLK|SSPSCLK_ATTR); ///SCLK
set_GPIO_mode(pHC->pGPIORegs, SSP_SFRM|SSPSFRM_ATTR); ///SFRM
set_GPIO_mode(pHC->pGPIORegs, SSP_RST|SSPRESET_ATTR);
set_GPIO_mode(pHC->pGPIORegs, SSP_TX|SSPTX_ATTR); ///TX
set_GPIO_mode(pHC->pGPIORegs, SSP_RX|SSPRX_ATTR); ///RX
#ifdef USE_TEST_PIN
set_GPIO_mode(pHC->pGPIORegs, SSP_TST1|SSPTST1_ATTR);
set_GPIO_mode(pHC->pGPIORegs, SSP_TST2|SSPTST2_ATTR);
#endif
set_GPIO_signal(pHC->pGPIORegs, SSP_SFRM, SIG_UP);
set_GPIO_signal(pHC->pGPIORegs, SSP_RST, SIG_UP);
pHC->pSSPRegs->base.sscr0 = 0;
pHC->pSSPRegs->base.sscr1 = 0;
Sleep(0); //JKU
///
/// Configure the SSP CLK
///
#if (SSPCTRLER == 1) ///Using SSP controller1
pHC->pCLKRegs->cken |= (1<<23);
#elif (SSPCTRLER == 2) ///Using SSP controller2
pHC->pCLKRegs->cken |= (1<<3);
#elif (SSPCTRLER == 3) ///Using SSP controller3
pHC->pCLKRegs->cken |= (1<<4);
#endif ///SSPCTRLER
pHC->pSSPRegs->base.sscr0 = SSCR0_SCR(clkdiv) | SSCR0_DSS(0x000f) | SSCR0_FRF(3);
pHC->pSSPRegs->base.sscr1 = SSCR1_TTELP | SSCR1_TTE | SSCR1_TSRE | SSCR1_RSRE |
SSCR1_RFT(0x1) | SSCR1_TFT(0x1) | SSCR1_TRAIL;
pHC->pSSPRegs->sspsp = SSPSP_SCMODE(0);
pHC->pSSPRegs->ssto = 1;
pHC->pSSPRegs->base.sscr0 |= SSCR0_SSE;
intr_init(pHC);
dma_init(pHC);
funcFinal:
return;
}
void ssp_deinit_hw(PSSP_HARDWARE_CONTEXT pDC)
{
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)pDC;
// if (pHC->hIntrHandle == NULL) {
// SetEvent(pHC->hIntrHandle);
// pHC->hIntrHandle = NULL;
// }
dma_deinit(pHC);
intr_deinit(pHC);
if(pHC->pGPIORegs != NULL)
{
MmUnmapIoSpace((IN PVOID)pHC->pGPIORegs, sizeof(BULVERDE_GPIO_REG));
}
if(pHC->pSSPRegs != NULL)
{
MmUnmapIoSpace((IN PVOID)pHC->pSSPRegs, sizeof(BULVERDE_SSP_EXT_REG));
}
if(pHC->pCLKRegs != NULL)
{
MmUnmapIoSpace((IN PVOID)pHC->pCLKRegs, sizeof(BULVERDE_CLKMGR_REG));
}
if(pHC->pDMARegs != NULL)
{
MmUnmapIoSpace((IN PVOID)pHC->pDMARegs, sizeof(BULVERDE_DMA_REG));
}
if(pHC->pOSTRegs != NULL)
{
MmUnmapIoSpace((IN PVOID)pHC->pOSTRegs, sizeof(BULVERDE_OST_REG));
}
return;
}
DWORD pxa_gspi_register_isr(PVOID ssphc, void* Adapter, ISRFUNC isrFunc)
{
PSSP_HARDWARE_CONTEXT pHC = (PSSP_HARDWARE_CONTEXT)ssphc;
DWORD result = -1;
if ((pHC == NULL) || (Adapter == NULL) || (isrFunc == NULL)) {
goto funcFinal;
}
pHC->isrContext = (HANDLE) Adapter;
pHC->isrFunc = isrFunc;
result = 0;
funcFinal:
return result;
}
///////////////////////////////////////////////////////////////////////////////
/// SSP_Init - the init entry point
/// Input:
/// dwContext - the context for this init
/// Output:
/// Return: instance context
/// - Returns a DWORD which will be passed to Open & Deinit or NULL if
/// unable to initialize the device
///////////////////////////////////////////////////////////////////////////////
PVOID pxa_gspi_Init(void)
{
PSSP_HARDWARE_CONTEXT pHC = NULL;
ENTERFUNC();
#if (USE_DMA == 1)
GSPIMSG(1, (TEXT("GSPX - Using DMA mode\n")));
#else
GSPIMSG(1, (TEXT("GSPX - Using CPU mode\n\n")));
#endif ///USE_DMA
pHC = LocalAlloc(LPTR, sizeof(SSP_HARDWARE_CONTEXT));
if (pHC == NULL) {
GSPIMSG(ERRMSG, (TEXT("Allocate SSP_HARDWARE_CONTEXT FAILED")));
goto funcFinal;
}
#ifdef USE_TEST_PIN
pLocalHC =pHC;
#endif
///Initialize the member of SSP_HARDWARE_CONTEXT
InitializeCriticalSection(&(pHC->SSPCrit));
ssp_init_hw(pHC);
gspx_power_up(pHC);
gspx_reset_module(pHC);
if(!(pHC->waitqueue = CreateEvent( NULL, FALSE, FALSE,NULL))) {
GSPIMSG(ERRMSG, (TEXT("Init CreateEvent FAILED")));
goto funcFinal;
}
///crlo:verion-check ++
///GSPI8385: (0004, 0013)
///GSPI8686: (000b, 0010)
{
WORD regval;
#if defined (GSPI8385)
const WORD chipid = 0x0004;
#elif defined (GSPI8686)
const WORD chipid = 0x000b;
#else
const WORD chipid = 0x000;
#endif ///GSPI$(CHIPID)
ssp_read_register((PVOID)pHC, ®val, 0x02);
GSPIMSG(1, (TEXT("Reg(0x02)= 0x%04x\r\n"), regval));
///================================================
if (chipid != regval){
GSPIMSG(1, (TEXT("Chip(exp, val)= (%04xh), %04xh)\n"), chipid, regval));
gspx_deinit(pHC);
pHC = NULL;
goto funcFinal;
}
}
///crlo:verion-check --
pHC->DriverShutdown = FALSE;
///Testing....
funcFinal:
GSPIMSG(PROGFLOW, (TEXT("SSP: %s returning 0x%x\r\n"), TEXT(__FUNCTION__), pHC));
return pHC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -