summaryrefslogtreecommitdiff
path: root/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c')
-rw-r--r--drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c441
1 files changed, 441 insertions, 0 deletions
diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c b/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c
new file mode 100644
index 00000000..727b86b4
--- /dev/null
+++ b/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c
@@ -0,0 +1,441 @@
+/******************************************************************************
+* LEGAL NOTICE *
+* *
+* USE OF THIS SOFTWARE (including any copy or compiled version thereof) AND *
+* DOCUMENTATION IS SUBJECT TO THE SOFTWARE LICENSE AND RESTRICTIONS AND THE *
+* WARRANTY DISLCAIMER SET FORTH IN LEGAL_NOTICE.TXT FILE. IF YOU DO NOT *
+* FULLY ACCEPT THE TERMS, YOU MAY NOT INSTALL OR OTHERWISE USE THE SOFTWARE *
+* OR DOCUMENTATION. *
+* NOTWITHSTANDING ANYTHING TO THE CONTRARY IN THIS NOTICE, INSTALLING OR *
+* OTHERISE USING THE SOFTWARE OR DOCUMENTATION INDICATES YOUR ACCEPTANCE OF *
+* THE LICENSE TERMS AS STATED. *
+* *
+******************************************************************************/
+/* Version: 1.8.9\3686 */
+/* Build : 13 */
+/* Date : 12/08/2012 */
+
+/**
+\file
+\brief CellGuide common driver core logic (OS, CPU and CG_Hardware independent)
+\attention This file should not be modified.
+If you think something is wrong here, please contact CellGuide
+
+*/
+
+
+
+#include "platform.h"
+#include "CgBuildNumber.h"
+#include "CgVersion.h"
+#include "CgCpu.h"
+#include "CgxDriverCore.h"
+#include "CgxDriverCoreCommon.h"
+#include "CgxDriverOs.h"
+
+#ifdef CGCORE_ACCESS_VIA_SPI
+extern void Reset_GPS_RecvAddress(void); //add reset spi rcv address by use space
+extern int data_req_handle (int para, void *param);
+#endif
+extern TCgCpuDmaTask gChunksList[MAX_DMA_TRANSFER_TASKS]; /**< DMA tasks list */
+volatile unsigned int poffset=0;
+/** CGcore base address */
+const U32 CGCORE_BASE_ADDR = CG_DRIVER_CGCORE_BASE_PA; /* Physical */
+
+// Check validity of DMA channel and controller number, for read and write channels
+///////////////////////////////////////////////////////////////////////////////////
+
+//#if (CG_DMA_CONTROLLER(CG_DRIVER_DMA_CHANNEL_READ) > 0)
+#if ( ((CG_DRIVER_DMA_CHANNEL_READ & 0xFFFF0000) >> 16) > 0 )
+#endif
+
+#ifdef CG_DRIVER_DMA_CHANNEL_READ
+ #ifdef CG_DRIVER_DMA_MAX_CONTROLLER
+ #if (CG_DMA_CONTROLLER(CG_DRIVER_DMA_CHANNEL_READ) > CG_DRIVER_DMA_MAX_CONTROLLER)
+ #error DMA controller # is greater than controllers available
+ #endif
+ #else
+ #if ( (CG_DMA_CONTROLLER(CG_DRIVER_DMA_CHANNEL_READ)) > 0)
+ #error DMA controller # is greater than controllers available
+ #endif
+ #endif
+ #ifdef CG_DRIVER_DMA_MAX_CHANNEL
+ #if (CG_DMA_CHANNEL(CG_DRIVER_DMA_CHANNEL_READ) > CG_DRIVER_DMA_MAX_CHANNEL)
+ #error DMA channel # is greater than channels available
+ #endif
+ #else
+ #if (CG_DMA_CHANNEL(CG_DRIVER_DMA_CHANNEL_READ) > 32)
+ #error DMA channel # is greater than channels available
+ #endif
+ #endif
+#endif
+#ifdef CG_DRIVER_DMA_CHANNEL_WRITE
+ #ifdef CG_DRIVER_DMA_MAX_CONTROLLER
+ #if CG_DMA_CONTROLLER(CG_DRIVER_DMA_CHANNEL_WRITE) > CG_DRIVER_DMA_MAX_CONTROLLER
+ #error DMA controller # is greater than controllers available
+ #endif
+ #else
+ #if CG_DMA_CONTROLLER(CG_DRIVER_DMA_CHANNEL_WRITE) > 0
+ #error DMA controller # is greater than controllers available
+ #endif
+ #endif
+ #ifdef CG_DRIVER_DMA_MAX_CHANNEL
+ #if CG_DMA_CHANNEL(CG_DRIVER_DMA_CHANNEL_WRITE) > CG_DRIVER_DMA_MAX_CHANNEL
+ #error DMA channel # is greater than channels available
+ #endif
+ #else
+ #if CG_DMA_CHANNEL(CG_DRIVER_DMA_CHANNEL_WRITE) > 32
+ #error DMA channel # is greater than channels available
+ #endif
+ #endif
+#endif
+
+// Block number starts at 1
+BOOL isBlockCanceled(TCgxDriverState * apState, U32 aBlockNumber)
+{
+ if ( apState->transfer.cancel.request &&
+ aBlockNumber * apState->transfer.blockSize >= apState->transfer.cancel.onByte )
+ return TRUE;
+ return FALSE;
+}
+
+// Block number starts at 1
+BOOL wasBlockReceived(TCgxDriverState * apState, U32 aBlockNumber)
+{
+
+ if ( aBlockNumber <= apState->transfer.blocks.received )
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+#ifdef CGCORE_ACCESS_VIA_SPI
+extern void trigger_gps_timeout(int timeout);
+#endif
+
+
+TCgReturnCode CgxDriverExecute(
+ void *pDriver,
+ TCgxDriverState *pState,
+ U32 aRequest,
+ TCgDriverControl *pControl,
+ TCgDriverStatus *pResults)
+{
+ DBG_FUNC_NAME("CgxDriverExecute")
+ TCgReturnCode rc = ECgOk;
+
+ if (pControl == NULL) return ECgNullPointer;
+ if (pResults == NULL) return ECgNullPointer;
+ if ((pState->flags.resume == TRUE) && (aRequest != CGX_IOCTL_INIT) && (aRequest != CGX_IOCTL_RESUME_CLEAR))
+ {
+ pResults->rc = ECgResume;
+ pResults->state = *pState;
+ DBGMSG1("Resume Need to clear [%d]", aRequest);
+ return ECgOk;
+ }
+ pResults->rc = ECgOk;
+ switch (aRequest)
+ {
+ case CGX_IOCTL_WAIT_RCV:
+
+ // Check if current block was overrun by the DMA
+ //////////////////////////////////////////////////////////////////////////
+
+ if ( ((S32)pState->transfer.blocks.received - (S32)pControl->wait.blockNumber )
+ > ((S32)pState->buffer.length / (S32)pState->transfer.blockSize) )
+
+ {
+ DBGMSG1("pState->transfer.blocks.received = %d", pState->transfer.blocks.received);
+ DBGMSG1("pControl->wait.blockNumber = %d", pControl->wait.blockNumber);
+ DBGMSG1("pState->buffer.length = %d", pState->buffer.length);
+ DBGMSG1("pState->transfer.blockSize = %d", pState->transfer.blockSize);
+
+ pResults->rc = ECgDataOverrun;
+ }
+
+ DBGMSG3("WAIT_RCV : blocks wait/received/total = %d/%d/%d",
+ pControl->wait.blockNumber + 1, pState->transfer.blocks.received, pState->transfer.blocks.required);
+
+
+
+ // Wait for block, if not canceled or already received
+ //////////////////////////////////////////////////////////////////////////
+
+ if ( !isBlockCanceled(pState, pControl->wait.blockNumber + 1))
+ {
+
+ // Check if block was received - if so, return. If not, wait for it
+ if ( !wasBlockReceived(pState, pControl->wait.blockNumber + 1))
+ {
+ pState->flags.wait = TRUE;
+ pResults->rc = CgxDriverTransferEndWait(pDriver, pControl->wait.timeoutMS);
+ }
+ }
+ else
+ {
+
+ pResults->rc = ECgCanceled;
+ if ( !isBlockCanceled(pState, pControl->wait.blockNumber))
+ {
+ printk("kyle last block\n");
+ if ( !wasBlockReceived(pState, pControl->wait.blockNumber + 1))
+ {
+ pState->flags.wait = TRUE;
+ pResults->rc = CgxDriverTransferEndWait(pDriver,pControl->wait.timeoutMS);
+ }
+ }
+ }
+ pState->flags.wait = FALSE;
+ if (!OK(pResults->rc) && (pResults->rc != ECgCanceled))
+ {
+ DBGMSG2("CGX_IOCTL_WAIT_RCV Failed! %d (t.o=%d ms)", pResults->rc, pControl->wait.timeoutMS);
+ }
+ DBGMSG2("App Buffer 0x%08X, phys:0x%08X", pState->transfer.originalBuffer, pState->transfer.bufferPhys);
+ DBGMSG2("received %d blocks %d chunks", pState->transfer.blocks.received, pState->transfer.chunks.received);
+
+ // Store the requested block's address, for use of the application
+ //////////////////////////////////////////////////////////////////////////
+
+ if( pState->transfer.blocks.received == 0 )
+ {
+ // This is an error - we returned from wait(), but no block was received.
+ pResults->buffer.bufferAppVirtAddr = pState->transfer.originalBuffer;
+ //poffset = 0;
+ if ( OK(pResults->rc) )
+ {
+ pResults->rc = ECgOutOfBounds;
+ DBGMSG1("ECgOutOfBounds [received=%d]", pState->transfer.blocks.received);
+
+ }
+ }
+ else
+ {
+ // Release possible event received, so we won't receive a false event - timeout is 0
+ CgxDriverTransferEndWait(pDriver, 0);
+
+ pResults->buffer.bufferAppVirtAddr = pState->transfer.originalBuffer + pState->transfer.bufferOffset[pControl->wait.blockNumber] ;
+ poffset = pState->transfer.bufferOffset[pControl->wait.blockNumber];
+ }
+
+ CgCpuCacheSync();
+ DBGMSG2("received %d blocks %d chunks", pState->transfer.blocks.received, pState->transfer.chunks.received);
+ DBGMSG3("0x%08X,0x%08X,%d", pState->transfer.bufferOffset[0], pState->transfer.bufferOffset[1],(pState->transfer.blocks.received-1) % 2);
+
+ switch( pResults->rc )
+ {
+ case ECgOk:
+ pResults->buffer.size = (pControl->wait.blockNumber == pState->transfer.blocks.required)
+ ? pState->transfer.lastBlockSize
+ : pState->transfer.blockSize;
+ break;
+ case ECgCanceled:
+ pResults->buffer.size = pState->transfer.cancel.onByte;
+ break;
+ default:
+ break;
+ }
+
+ // Reorder bytes
+ //////////////////////////////////////////////////////////////////////////
+
+ //Bug 2981 (Critical) - requires a frame 00/01/02 after downloading- during CS/WS if (OK(pResults->rc))
+ {
+ DBGMSG2("Byte order %d %d", CGX_DRIVER_NATIVE_BYTE_ORDER, pState->transfer.byteOrder);
+ if ((CGX_DRIVER_NATIVE_BYTE_ORDER != pState->transfer.byteOrder) &&
+ (pState->transfer.chunks.received > 0))
+ {
+ U32 length = gChunksList[pControl->wait.blockNumber].length;
+ if(pState->transfer.blocks.required <= 1)
+ length = pState->transfer.blockSize;
+
+ if ( isBlockCanceled(pState, pControl->wait.blockNumber + 1) )
+ {
+ //U32 requestedDmaCount = 0;
+ //CgCpuDmaRequestedCount(CG_DRIVER_DMA_CHANNEL_READ, &requestedDmaCount);
+ //length = (U32) pState->transfer.cancel.onByte % requestedDmaCount;
+ }
+ DBGMSG4("size %d s_vir 0x%x, 0x%x ,0x%x", length,(U32)pState->buffer.virtAddr,
+ gChunksList[pControl->wait.blockNumber].address,pState->transfer.bufferPhys);
+
+// pState->transfer.byteOrder = 0;
+
+ CgSwapBytesInBlock( (void*)((U32)pState->buffer.virtAddr +
+ (gChunksList[pControl->wait.blockNumber].address - pState->transfer.bufferPhys)),
+ (void*)((U32)pState->buffer.virtAddr +
+ (gChunksList[pControl->wait.blockNumber].address - pState->transfer.bufferPhys)),
+ length,
+ pState->transfer.byteOrder,
+ CGX_DRIVER_NATIVE_BYTE_ORDER );
+
+ }
+ CgCpuCacheSync();
+ }
+
+ DBGMSG2("WAIT_RCV : rc = %p, pResults->rc = %p", pResults->buffer.bufferAppVirtAddr, pResults->buffer.bufferPhysAddr);
+ DBGMSG2("WAIT_RCV : rc = %d, pResults->rc = %d", rc, pResults->rc);
+
+ break;
+
+
+ default:
+ rc = CgxDriverExecuteSpecific(pDriver, pState, aRequest, pControl, pResults);
+ }
+ if (OK(rc))
+ {
+ if ((pState->flags.resume == TRUE) || (pResults->rc == ECgResume)){
+ pResults->rc = ECgResume;
+ DBGMSG("Resume!");
+ }
+ DBGMSG1("End %d", aRequest);
+ pResults->state = *pState;
+ DBGMSG1("the lastest %d", aRequest);
+ switch(pResults->rc)
+ {
+ case ECgCanceled:
+ case ECgResume:
+ break;
+ default:DBGERR(pResults->rc);
+ }
+ }
+ return rc;
+}
+
+// this interrupt occur on end of DMA transaction (entire snap, block or sub-block)
+TCgReturnCode CgxDriverDataReadyInterruptHandler(void *pDriver, TCgxDriverState *pState)
+{
+ DBG_FUNC_NAME("CgxDriverDataReadyInterruptHandler")
+ TCgReturnCode rc = ECgOk;
+
+ pState->transfer.blocks.received++;
+
+ // update chunk counters
+ pState->transfer.chunks.received++;
+ pState->transfer.chunks.active++;
+
+ // update total received bytes count
+ pState->transfer.bytes.received += gChunksList[pState->transfer.chunks.active-1].length;
+
+ DBGMSG2("%d/%d", pState->transfer.chunks.active, pState->transfer.chunks.required);
+ #ifdef CGCORE_ACCESS_VIA_SPI
+ //add by wlh for reset the rev address
+ if(gChunksList[pState->transfer.chunks.received].address == gChunksList[0].address )
+ {
+ Reset_GPS_RecvAddress();
+ }
+ //end by wlh for reset the rev address
+ #endif
+ if (pState->flags.wait) // release a waiting thread, if any
+ rc = CgxDriverTransferEndSignal(pDriver);
+
+ // check if end of snap (last block)
+ if (! isBlockCanceled(pState, pState->transfer.blocks.received + 1) )
+ {
+ // DBGMSG2("chunks.active = %d. chunks.received = %d", pState->transfer.chunks.active, pState->transfer.chunks.received);
+ if (pState->transfer.chunks.active >= pState->transfer.chunks.required)
+ {
+ // DBGMSG("last chunk");
+ pState->transfer.done = 0;
+ }
+ #ifdef CG_DRIVER_DMA_MULTI_BLOCK_MODE
+ #if CG_DRIVER_DMA_MULTI_BLOCK_MODE == CG_DRIVER_DMA_MULTI_BLOCK_MODE_PENDING
+ // not last block, so we need to order another chunk
+ else
+ {
+ // sub-block is used when DMA max size is small --> only need to increment the size
+ rc = CgCpuDmaSetupFromGpsNextTask( gChunksList, pState->transfer.chunks.required, pState->transfer.chunks.active,
+ CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070);
+ }
+ #endif
+ #endif
+ }
+
+
+ DBGMSG("Done");
+ return rc;
+}
+
+TCgReturnCode CgxDriverGpsInterruptHandler(void *pDriver, TCgxDriverState *pState)
+{
+ DBG_FUNC_NAME("CgxDriverGpsInterruptHandler")
+ TCgReturnCode rc = ECgOk;
+ U32 intcode = 0;
+ pState->counters.interrupt.all++;
+
+ // read interrupt source register from CGsnap
+ rc = CGCORE_READ_REG( CGCORE_REG_INT_SRC, &intcode);
+ rc = CGCORE_WRITE_REG( CGCORE_REG_INT_CLR, intcode);
+ printk("%s%s%s%s%s%s%s\n",
+ intcode & CGCORE_INT_RTC ? "RTC " : "",
+ intcode & CGCORE_INT_SNAP_START ? "BEG " : "",
+ intcode & CGCORE_INT_SNAP_END ? "END " : "",
+ intcode & CGCORE_INT_TCXO_EXPIRED ? "TCXO " : "",
+ intcode & CGCORE_INT_OVERRUN ? "OVR " : "",
+ intcode & CGCORE_INT_EOT ? "EOT " : "",
+ intcode & CGCORE_INT_EOM ? "EOM " : ""
+ );
+
+ #ifdef CGCORE_ACCESS_VIA_SPI
+ if (intcode & CGCORE_INT_DMA_REQ)
+ {
+ data_req_handle(0,NULL);
+ }
+ #endif
+
+ if (intcode & CGCORE_INT_SNAP_START) { // Indicates snap was started
+ pState->counters.interrupt.snapStart++;
+ DBGMSG1("%d so far\n", pState->counters.interrupt.snapStart);
+ if (!isBlockCanceled(pState,1) && !pState->transfer.done && pState->transfer.bytes.required > 1)
+ {
+ // 1st DMA transfer task already set-up by PrepareReceive.
+ // some DMAC don't have LLI support, but other mechanism that requires setting next block
+ // each time
+ #ifdef CG_DRIVER_DMA_MULTI_BLOCK_MODE
+ #if CG_DRIVER_DMA_MULTI_BLOCK_MODE == CG_DRIVER_DMA_MULTI_BLOCK_MODE_PENDING
+ rc = CgCpuDmaSetupFromGpsNextTask(gChunksList, pState->transfer.chunks.required, pState->transfer.chunks.active, CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070);
+ #endif
+ #endif
+ }
+ else
+ {
+ DBGMSG("problem!\n");
+ // if (pState->transfer.cancel.request)
+ // DBGMSG1("transfer.cancel.request=%d!", pState->transfer.cancel.request);
+ // if (pState->transfer.done)
+ // DBGMSG1("transfer.done=%d!", pState->transfer.done );
+ // if (pState->transfer.bytes.required == 0)
+ // DBGMSG1("transfer.bytes.required=%d!", pState->transfer.bytes.required);
+ }
+ }
+
+ if (intcode & CGCORE_INT_SNAP_END)
+ {
+ if (pState->transfer.cancel.request)
+ {
+ DBGMSG("Snap end due to : cancel\n");
+ rc = CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ);
+ rc = CgxDriverDataReadyInterruptHandler(pDriver, pState);
+ }
+ else
+ {
+ DBGMSG("Snap end due to : normal\n");
+ }
+ }
+
+ if (intcode & CGCORE_INT_OVERRUN) {
+ DBGMSG("Snap overrun\n");
+ pState->flags.overrun = TRUE;
+ pState->counters.interrupt.overrun++;
+ if (pState->flags.wait) // release a waiting thread, if any
+ CgxDriverTransferEndSignal(pDriver);
+ // mark interrupt as handled
+ intcode &= ~CGCORE_INT_OVERRUN;
+ }
+
+ DBGMSG("Done");
+
+ return rc;
+}
+
+