diff options
Diffstat (limited to 'drivers/misc/gpsip/cgdriver/CgxDriverCore.c')
| -rw-r--r-- | drivers/misc/gpsip/cgdriver/CgxDriverCore.c | 819 |
1 files changed, 819 insertions, 0 deletions
diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverCore.c b/drivers/misc/gpsip/cgdriver/CgxDriverCore.c new file mode 100644 index 00000000..d1045624 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverCore.c @@ -0,0 +1,819 @@ +/****************************************************************************** + * 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 CGsnap driver core logic (OS & CPU independed) + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + +*/ + + +#include <linux/delay.h> + +#include "CgxDriverCore.h" +#include "CgCpu.h" +#include "CgCpuOs.h" +#include "platform.h" +#include "CgxDriverPlatform.h" +#include "CgxDriverOs.h" +#include "CgBuildNumber.h" +#include "CgVersion.h" +#include "CgxDriverCoreCommon.h" + + +/** + Driver version structure + \note this structure is filled automatically on build time, by CellGuide build machine +*/ +const TCgVersion gCgDriverVersion = { + CG_BUILD_VERSION, /**< Software Version number (Text)*/ + CG_BUILD_ORIGINATOR, /**< Build Originator name (Text)*/ + CGX_PLATFORM_NAME, /**< Platform Name (Text), as specified in platform.h file */ + CG_BUILD_NUMBER, /**< Unique Build Number (Text) - automatically assigned by build machine*/ + CG_BUILD_DATE, /**< Build Date (Text)*/ + CG_BUILD_TIME, /**< Build Time (Text)*/ + CG_BUILD_MODE /**< Build Mode (Text) - Release/Test/Debug */ +}; + +extern void gps_chip_power_on(void); +extern void gps_chip_power_off(void); +extern void gps_gpio_request(void); + +#define CG_MATH_ALIGNMENT(__var__,__base__) __var__ = (__base__) * ((U32)(((__var__) + ((__base__)/2)) / (__base__))) + + +TCgCpuDmaTask gChunksList[MAX_DMA_TRANSFER_TASKS]; /**< DMA tasks list */ +S32 CgxDriverSnapLengthExtraBytes = 0; + +extern U32 CGCORE_BASE_ADDR; + +/** CGsnap GPO register offset */ +const U32 CGCORE_REG_OFFSET_GPO = 0x00000040; + +/** CGsnap version register offset */ +const U32 CGCORE_REG_OFFSET_VERSION = 0x00000044; + +/** CGsnap interrupt register offset (KAGPSRawInt)*/ +const U32 CGCORE_REG_RAW_INT = 0x00000080; + +/** CGsnap Soft_CMD register offset */ +const U32 CGCORE_REG_OFFSET_SOFT_CMD = 0x000000CC; +const U32 CGCORE_SOFT_CMD_POWER_DOWN = 0xFDB96420; + +/** CGsnap reset register offset */ + +const U32 CGCORE_REG_OFFSET_CORE_RESETS = 0x000000FC; + +#ifndef RF_POWER_UP_VAL + #define RF_POWER_UP_VAL (0) // ACLYS requires '0' for PU +#endif + +#ifdef CGCORE_ACCESS_VIA_SPI +extern void init_spi_block_var(void); +static unsigned int block_num; +#endif +bool flag_power_up = 0; +TCgReturnCode CgxDriverTcxoControl(u32 aEnable); + +#define CGCORE_ENABLE_CORE (0x00000000) +#define CGCORE_ENABLE_TCXO (0x00000001) +#define CGCORE_ENABLE_RTC (0x00000002) +#define CGCORE_ENABLE_BS (0x00000003) +#define CGCORE_RF_POWER_UP_POL (0x00000004) // RF Power up polarity. "Power UP" GPO[0] value is determined by this bit's value. + // (if bit is '1', during power up, the IP will output '1', and during power down, + // it will output '0'. When this bit is '0', the output is reversed) + +const U32 CGCORE_CORE_RESETS_ENABLE = ((1<<CGCORE_ENABLE_CORE) | (1<<CGCORE_ENABLE_TCXO) | ( RF_POWER_UP_VAL * (1<<CGCORE_RF_POWER_UP_POL))); + // This is the default 'enable' value, to the core_Resets register. + // It needs to be written prior to accessing CGsnap. + // ALL CGCORE_ENABLE_XXX are reset to 0, when the MasterReset pin is toggled + +#define CGCORE_ENABLE_DMA (5) +#define CGCORE_ENABLE_GPS (12) + + +#define CGCORE_ENABLE_SCLK ((1<<CGCORE_ENABLE_DMA) | (1<<CGCORE_ENABLE_GPS)) +#define CGCORE_RESET_DELAY (1000) // Used as a delay between '0' and '1', when reseting the CGsnap + +TCgReturnCode CGCoreReset(U32 aUnitToReset); + +#ifndef CGCORE_ACCESS_VIA_SPI +//bxd add for slck enable +TCgReturnCode CGCoreSclkEnable(int enable) +{ + TCgReturnCode rc = ECgOk; + + if(1 == enable) + { + sci_glb_set(CG_DRIVER_SCLK_VA,BIT_12); + } + else if(0 == enable) + { + sci_glb_clr(CG_DRIVER_SCLK_VA,BIT_12); + } + return rc; +} +#endif + + +TCgReturnCode CgxDriverDestroy(void *pDriver) +{ + DBG_FUNC_NAME("CgxDriverDestroy") + TCgReturnCode rc = ECgOk; + + rc = CgCpuDmaDestroy(CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070); + if (!OK(rc)) DBGMSG("Failed to destroy DMA"); + rc = CgCpuGpioDestroy(); + if (!OK(rc)) DBGMSG("Failed to destroy GPIO"); + rc = CgCpuIntrDestroy(); + if (!OK(rc)) DBGMSG("Failed to destroy INTR"); + rc = CgCpuClockDestroy(); + if (!OK(rc)) DBGMSG("Failed to destroy CLK"); + rc = CgxDriverTransferEndDestroy(pDriver); + return rc; +} + + + +TCgReturnCode CgxDriverConstruct(void *pDriver, TCgxDriverState *pState) +{ + //DBG_FUNC_NAME("CgxDriverConstruct") + TCgReturnCode rc = ECgOk; + rc = CgCpuAllocateVa(); + memset(gChunksList,0,sizeof(TCgCpuDmaTask)*MAX_DMA_TRANSFER_TASKS); + + gps_gpio_request(); + +#if 0 + if (OK(rc)) rc = CgCpuDmaCreate(CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070); + + // set up DMA interrupt handler + if (OK(rc)) rc = CgxDriverDmaInterruptPrepare(); +#endif + + if (OK(rc)) rc = CgxDriverDataReadyInterruptHandlerStart(pDriver); + + // set up internal synchronization mechanism + if (OK(rc)) rc = CgxDriverTransferEndCreate(pDriver); + + + // set up GPS interrupt handler + if (OK(rc)) rc = CgxDriverGpsInterruptPrepare(); + if (OK(rc)) rc = CgxDriverGpsInterruptHandlerStart(pDriver); +#if 0 + // enable IP (not-reset) + if (OK(rc)) rc = CgCpuGpioModeSet(CG_DRIVER_GPIO_GPS_MRSTN, ECG_CPU_GPIO_OUTPUT); + if (OK(rc)) rc = CgCpuIPMasterResetOn(); + if (OK(rc)) rc = CgCpuDelay(CGCORE_RESET_DELAY); + if (OK(rc)) rc = CgCpuIPMasterResetClear(); + + // set up Sclk register + if (OK(rc)) rc = CGCoreSclkEnable(1); + + DBGMSG1("CGCORE_CORE_SCLK_ENABLE = 0x%08X", CGCORE_ENABLE_SCLK); + + // set up core-resets register + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, CGCORE_CORE_RESETS_ENABLE); + + DBGMSG1("CGCORE_CORE_RESETS_ENABLE = 0x%08X", CGCORE_CORE_RESETS_ENABLE); + + // Setup GPIO for RF-Power, and power up RF chip + //if (OK(rc)) rc = CgCpuGpioModeSet(CG_DRIVER_GPIO_RF_PD, ECG_CPU_GPIO_OUTPUT); + //if (OK(rc)) rc = CgxDriverRFPowerUp(); + + if (OK(rc)) rc = CgCpuGpioModeSet(CG_DRIVER_GPIO_TCXO_EN, ECG_CPU_GPIO_OUTPUT); + if (OK(rc)) rc = CgxDriverTcxoControl(TRUE); +#endif + + pState->constructionRc = rc; // For later reference (if needed by application) + pState->flags.resume = FALSE; + #ifdef CGCORE_ACCESS_VIA_SPI + gps_chip_power_off(); + #endif + return rc; +} + + + +TCgReturnCode CgxDriverPowerUp(void) +{ + TCgReturnCode rc = ECgOk; + U32 version = 0; + + // In order to power up the CGsnap, do a dummy access + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_VERSION, &version ); + return rc; +} + +TCgReturnCode CgxDriverPowerDown(void) +{ + TCgReturnCode rc = ECgOk; + + // Write software power-down command to CGsnap + rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_SOFT_CMD, CGCORE_SOFT_CMD_POWER_DOWN ); + + return rc; +} + +#ifdef CGCORE_ACCESS_VIA_SPI +unsigned int get_block_num(void ) +{ + return block_num; +} +#endif + +#if 0 +//gaole add +void CgCoreReleaseRes(void) +{ + printk("\n gaole: run to CgCoreReleaseRes \n"); + memset(gChunksList,0,sizeof(TCgCpuDmaTask)*MAX_DMA_TRANSFER_TASKS); +#ifdef CGCORE_ACCESS_VIA_SPI + block_num = 0; +#endif +} + +void CgGpsReset(void) +{ + CGCORE_WRITE_REG( 0x00000038, 0x0); + + CGCORE_WRITE_REG( 0x0000003c, 0x0); + + CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, CGCORE_CORE_RESETS_ENABLE); +} +#endif +/* +split blocks to chunks +last chunk might be small +last chunk generate app event +start of block aligned to chunk size +*/ + +TCgReturnCode CgxDriverPrepareRecieve( + TCgxDriverState *pState, + unsigned char *apBuf, + U32 aBufPhys, + U32 aBufSize, + unsigned long aLength, + unsigned long aBlockLength, + TCgByteOrder aByteOrder) +{ + DBG_FUNC_NAME("CgxDriverPrepareRecieve") + TCgReturnCode rc = ECgOk; + U32 blockIndex = 0; + U32 chunksInBlock = 0; + U32 chunkSize = 0; + U32 length = aLength + CgxDriverSnapLengthExtraBytes; // Potential patch + U32 numOfBlocksInBuffer = 0; + + memset(gChunksList,0,sizeof(TCgCpuDmaTask)*MAX_DMA_TRANSFER_TASKS); + + DBGMSG1("buffer v-address = 0x%x", apBuf); + DBGMSG1("start address value = 0x%x", *((U32*)apBuf) ); + DBGMSG1("dest address value = 0x%x", *((U32*)apBuf + 128) ); + + pState->transfer.blockSize = ((aBlockLength == 0) || (length < aBlockLength)) ? length : aBlockLength; + /*bxd modify for not limted to 512k Bytes each block*/ + chunkSize = pState->transfer.blockSize; + //chunkSize = MIN(MAX_DMA_CHUNK_SIZE, pState->transfer.blockSize); + chunksInBlock = pState->transfer.blockSize / chunkSize; + + + DBGMSG3("Requested %d bytes, Block=(%d bytes,%d chunks)", length, pState->transfer.blockSize, chunksInBlock); + DBGMSG1("Maximum DMA chunk size is set to %d bytes", chunkSize); + + pState->flags.overrun = FALSE; + pState->transfer.cancel.request = FALSE; + pState->transfer.cancel.onByte = 0; + pState->transfer.cancel.onChunk = 0; + pState->transfer.done = 0; + pState->transfer.originalBuffer = apBuf; + pState->transfer.bufferPhys = pState->buffer.physAddr; + pState->transfer.byteOrder = aByteOrder; + + pState->transfer.bytes.required = length; + pState->transfer.bytes.received = 0; + + pState->transfer.blocks.required = (length + pState->transfer.blockSize - 1) / pState->transfer.blockSize; +#ifdef CGCORE_ACCESS_VIA_SPI + block_num = pState->transfer.blocks.required; +#endif + DBGMSG1("%d blocks required", pState->transfer.blocks.required); + pState->transfer.lastBlockSize = length - (pState->transfer.blocks.required - 1) * pState->transfer.blockSize; + DBGMSG1("last block size: %d bytes", pState->transfer.lastBlockSize); + pState->transfer.blocks.received = 0; + + pState->transfer.chunks.required = 0; + pState->transfer.chunks.received = 0; + pState->transfer.chunks.active = 0; + + // split snap to blocks + ////////////////////////////////////////////////////////////////////////// + + if (pState->transfer.blocks.required * chunksInBlock > MAX_DMA_TRANSFER_TASKS) { + DBGMSG2("ERROR! too many chunks! %d > %d", pState->transfer.blocks.required * chunksInBlock, MAX_DMA_TRANSFER_TASKS); + return ECgErrMemory; + } + + numOfBlocksInBuffer = aBufSize / pState->transfer.blockSize; + DBGMSG2("aBufSize = %d, blockSize = %d", aBufSize, pState->transfer.blockSize ); + for(blockIndex = 0; blockIndex < pState->transfer.blocks.required; blockIndex++) + { + // Init the snap's blocks' offsets + pState->transfer.bufferOffset[blockIndex] = pState->transfer.blockSize * (blockIndex % numOfBlocksInBuffer); // roll-over to start of buffer, + // if we reached end of buffer. + //DBGMSG2("buffer[%d] = 0x%08X", blockIndex, pState->transfer.bufferPhys + pState->transfer.bufferOffset[blockIndex]) + } + + // split blocks to chunks + ////////////////////////////////////////////////////////////////////////// + + for(blockIndex = 0; blockIndex < pState->transfer.blocks.required; blockIndex++) { + U32 chunkIndex = 0; + U32 more, dest; + + more = (blockIndex == (pState->transfer.blocks.required-1)) ? pState->transfer.lastBlockSize : pState->transfer.blockSize; + dest = pState->transfer.bufferPhys + pState->transfer.bufferOffset[blockIndex]; + + // DBGMSG4("Block %02d/%02d: % 6d bytes @ 0x%08X", blockIndex + 1, pState->transfer.blocks.required, + for(chunkIndex = 0; chunkIndex < chunksInBlock-1; chunkIndex++) { + U32 size = MIN(more, chunkSize); + if ((more - size) < chunkSize) + break; + gChunksList[pState->transfer.chunks.required].address = dest; + gChunksList[pState->transfer.chunks.required].length = size; + more -= size; + // DBGMSG5("chunk %02d/%02d in block: length %d bytes @ 0x%08X (%d more)", chunkIndex + 1, chunksInBlock, + dest += size; + pState->transfer.chunks.required++; + } + // last chunk + gChunksList[pState->transfer.chunks.required].address = dest; + gChunksList[pState->transfer.chunks.required].length = more; + DBGMSG3("last chunk out of %02d in block: % 6d bytes @ 0x%08X", chunksInBlock, more, dest); + pState->transfer.chunks.required++; + } + + DBGMSG1("%d chunks required", pState->transfer.chunks.required); + + if (length > pState->transfer.blockSize * pState->transfer.blocks.required) { + // there are leftovers + U32 more = length - pState->transfer.blockSize * pState->transfer.blocks.required; + U32 dest = pState->transfer.bufferPhys + pState->transfer.bufferOffset[pState->transfer.blocks.required]; + DBGMSG4("Extra Block % 2d/% 2d: % 6d bytes @ 0x%08X", pState->transfer.blocks.required, pState->transfer.blocks.required, more, dest); + for (; (more > 0) && (pState->transfer.chunks.required < MAX_DMA_TRANSFER_TASKS); pState->transfer.chunks.required++) { + U32 size = MIN(more, chunkSize); + gChunksList[pState->transfer.chunks.required].address = dest; + gChunksList[pState->transfer.chunks.required].length = size; + more -= size; + dest += size; + DBGMSG4("chunk % 4d: % 4d bytes @ 0x%08X (%d bytes left)", pState->transfer.chunks.required + 1, size, dest, more); + } + DBGMSG1("%d chunks required", pState->transfer.chunks.required); + } + + + // setup 1st DMA chunk + #ifndef CGCORE_ACCESS_VIA_SPI + rc = CgCpuDmaSetupFromGps(gChunksList, pState->transfer.chunks.required, CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070); + rc = CgCpuDmaStart(CG_DRIVER_DMA_CHANNEL_READ); + #else + // rc =CgxCpuSpiReadData(); + #endif + + return rc; +} + + + +TCgReturnCode CgxDriverIsReadCanceled(TCgxDriverState *pState) +{ + DBG_FUNC_NAME("CgxDriverIsReadCanceled") + TCgReturnCode rc = ECgOk; + + + // Check if snap was unconditionally canceled + if (pState->transfer.cancel.request && (pState->transfer.bytes.received > pState->transfer.cancel.onByte)) + { + CGCoreReset(CGCORE_ENABLE_CORE); + CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + return ECgCanceled; + } + + // Check if we have reached the cancel point + if (pState->transfer.cancel.request) { + U32 curDmaCount = 0; + U32 requestedDmaCount = 0; + rc = CgCpuDmaRequestedCount(CG_DRIVER_DMA_CHANNEL_READ, &requestedDmaCount); // how many bursts requested to receive + DBGMSG1("requestedDmaCount = %d", requestedDmaCount); + + rc = CgCpuDmaCurCount(CG_DRIVER_DMA_CHANNEL_READ, &curDmaCount); // how many bursts left to receive + DBGMSG1("curDmaCount = %d", curDmaCount); + + DBGMSG2("%d >= %d ? ==> canceled", pState->transfer.bytes.received + (requestedDmaCount - curDmaCount) , pState->transfer.cancel.onByte); + + if (pState->transfer.bytes.received + (requestedDmaCount - curDmaCount) >= pState->transfer.cancel.onByte) + { + CGCoreReset(CGCORE_ENABLE_CORE); + CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + return ECgCanceled; + } + } + + return ECgOk; +} + +TCgReturnCode CGCoreEnable(U32 aUnitToEnable) +{ + DBG_FUNC_NAME("CGCoreEnable") + TCgReturnCode rc = ECgOk; + + U32 enableValue = 1; + U32 coreResetsReg = 0; + + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_CORE_RESETS, &coreResetsReg); +// DBGMSG1("Read coreResetsReg=0x%08X", coreResetsReg); + REG_SET1(coreResetsReg, aUnitToEnable, enableValue); + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, coreResetsReg); + DBGMSG1("Write [0x%08X]", coreResetsReg); + return rc; +} + +TCgReturnCode CGCoreDisable(U32 aUnitToDisable) +{ + DBG_FUNC_NAME("CGCoreDisable") + TCgReturnCode rc = ECgOk; + + U32 disableValue = 0; + U32 coreResetsReg = 0; + + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_CORE_RESETS,&coreResetsReg); +// DBGMSG1("Read coreResetsReg=0x%08X", coreResetsReg); + REG_SET1(coreResetsReg, aUnitToDisable, disableValue); + if (OK(rc)) rc = CGCORE_WRITE_REG(CGCORE_REG_OFFSET_CORE_RESETS,coreResetsReg); + DBGMSG1("Write [0x%08X]", coreResetsReg); + return ECgOk; +} + +TCgReturnCode CGCoreReset(U32 aUnitToReset) +{ + DBG_FUNC_NAME("CGCoreReset") + TCgReturnCode rc = ECgOk; + U32 coreResetsReg = 0; + U32 coreResetsRegOld = 0; + + ////////////////// Core Disable ////////////// + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_CORE_RESETS,&coreResetsReg); + coreResetsRegOld = coreResetsReg; + REG_SET1(coreResetsReg, aUnitToReset, 0); + if (OK(rc)) rc = CGCORE_WRITE_REG(CGCORE_REG_OFFSET_CORE_RESETS,coreResetsReg); + DBGMSG1("Write [0x%08X]", coreResetsReg); + + if (OK(rc)) rc = CgCpuDelay(CGCORE_RESET_DELAY); + + ////////////////// Core Enable ////////////// + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, coreResetsRegOld); + DBGMSG1("Write [0x%08X]", coreResetsRegOld); + + return rc; +} + + +TCgReturnCode CgxDriverExecuteSpecific( + void *pDriver, + TCgxDriverState *pState, + U32 aRequest, + TCgDriverControl *pControl, + TCgDriverStatus *pResults) +{ + DBG_FUNC_NAME("CgxDriverExecuteSpecific") + DBGMSG1("aRequest =%x",aRequest); + switch (aRequest) { + case CGX_IOCTL_INIT: + DBGMSG("CGX_IOCTL_INIT"); + // This is 1st time initialization, meaning the software is restarted, not resumed, so set the state accordingly. + DBGMSG1("pState = 0x%x", pState); + + pState->flags.resume = FALSE; + DBGMSG("after pState->flags.resume = FALSE;"); + pResults->rc = CgxDriverInit(pDriver); + break; + + case CGX_IOCTL_STOP: + pResults->rc = CgxDriverDestroy(pDriver); + break; + + case CGX_IOCTL_READ_REG: + pState->transfer.cancel.request = FALSE; + // Verify register is of the CGX_sat_ram group + pResults->readReg.value = 0; + DBGMSG1("readReg.offset %x ",pControl->readReg.offset); + if ( pControl->readReg.offset >= CGCORE_REG_OFFSET_SAT_RAM && pControl->readReg.offset <= CGCORE_REG_OFFSET_SAT_RAM_LAST ) + { + // Write read command to the APB (9 bits of the register offset, with 0x80000000, as the read command) + pResults->rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_APB_COMMAND, (0x000001FF & pControl->readReg.offset) | 0x80000000); + + // Wait 4 system clocks + CgCpuDelay(100); // TODO : what is the actual period of this wait. Is it 4 system clocks? + + // Read data from the APB + if (OK(pResults->rc)) + pResults->rc = CGCORE_READ_REG( CGCORE_REG_OFFSET_APB_DATA, &pResults->readReg.value); + } + else + { + // It is not part of the CGX_sat_ram. Read register normaly, via the APB + + pResults->rc = CGCORE_READ_REG( pControl->readReg.offset, &pResults->readReg.value); + } + break; + + case CGX_IOCTL_WRITE_REG: + pState->transfer.cancel.request = FALSE; + // Write to CGsnap register + pResults->rc = CGCORE_WRITE_REG( pControl->writeReg.offset, pControl->writeReg.value); + // DBGMSG2("CGX_IOCTL_WRITE_REG *0x%08X = 0x%08X", CGCORE_BASE_ADDR_VA + pControl->writeReg.offset, pControl->writeReg.value); + break; + + case CGX_IOCTL_PREPARE_RECEIVE: + DBGMSG("CGX_IOCTL_PREPARE_RECEIVE"); + // Prepare driver for massive data receive (snap) + pState->transfer.cancel.request = FALSE; + pResults->rc = CgxDriverPrepareRecieve(pState, pControl->read.buf, pControl->read.bufPhys, + pState->buffer.length, pControl->read.alignedLength, pControl->read.blockLength, + pControl->read.byteOrder); + break; + + case CGX_IOCTL_STATUS: + pResults->rc = pState->constructionRc; + break; + + case CGX_IOCTL_RESUME_CLEAR: + DBGMSG("CGX_IOCTL_RESUME_CLEAR!"); + pState->flags.resume = FALSE; + pState->transfer.cancel.request = FALSE; + break; + case CGX_IOCTL_RESET: + DBGMSG1("CGX_IOCTL_RESET level %d", pControl->reset.resetLevel); + pState->transfer.cancel.request = FALSE; + switch( pControl->reset.resetLevel ) + { + case 0: // Full reset + #if 0 + if (OK(pResults->rc)) pResults->rc = CgCpuIPMasterResetOn(); + if (OK(pResults->rc)) pResults->rc = CgCpuDelay(CGCORE_RESET_DELAY); + if (OK(pResults->rc)) pResults->rc = CgCpuIPMasterResetClear(); + #endif + if (OK(pResults->rc)) pResults->rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, CGCORE_CORE_RESETS_ENABLE); + break; + case 1: // Semi reset + if (OK(pResults->rc)) pResults->rc = CGCoreReset(CGCORE_ENABLE_CORE); + #ifdef CGCORE_ACCESS_VIA_SPI + init_spi_block_var(); + #endif + break; + case 2: // CPU reset + break; + default : // Semi reset, also. + if (OK(pResults->rc)) pResults->rc = CGCoreReset(CGCORE_ENABLE_CORE); + break; + } + pResults->rc = CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + break; + + case CGX_IOCTL_COUNTER_RESET: + DBGMSG("CGX_IOCTL_COUNTER_RESET!"); + pResults->rc = CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + if (OK(pResults->rc)) pResults->rc = CGCoreReset(CGCORE_ENABLE_TCXO); + break; + + case CGX_IOCTL_POWER_DOWN: + DBGMSG("CGX_IOCTL_POWER_DOWN!"); + flag_power_up = 0; + pResults->rc = CgxDriverPowerDown(); + if (OK(pResults->rc)) pResults->rc = CgxDriverRFPowerDown(); + break; + + case CGX_IOCTL_POWER_UP: + flag_power_up = 1; + pState->transfer.cancel.request = FALSE; + pResults->rc = CgxDriverPowerUp(); + if (OK(pResults->rc)) pResults->rc = CgxDriverRFPowerUp(); + break; + + case CGX_IOCTL_POWER_OFF : + pResults->rc = CgxDriverPowerOff(); + break; + + case CGX_IOCTL_POWER_ON : + pResults->rc = CgxDriverPowerOn(); + break; + + case CGX_IOCTL_GPIO_SET: + //DBGMSG2("CGX_IOCTL_GPIO_SET 0x%08X = %d", pControl->GPIO.code, pControl->GPIO.out); + if (pControl->GPIO.out) + pResults->rc = CgCpuGpioSet(pControl->GPIO.code); + else + pResults->rc = CgCpuGpioReset(pControl->GPIO.code); + //rc = CgxDriverDebugGpio((int)pControl->GPIO.code, (int)pControl->GPIO.out); + break; + + case CGX_IOCTL_GPIO_GET: + //DBGMSG1("CGX_IOCTL_GPIO_GET 0x%08X", pControl->GPIO.code); + //pResults->GPIO.in = 0x5a5a; + //DBGMSG2("CGX_IOCTL_GPIO_GET before 0x%08X=0x%08X", pControl->GPIO.code, pResults->GPIO.in) + pResults->rc = CgCpuGpioGet(pControl->GPIO.code, (int *)&(pResults->GPIO.val)); + pResults->GPIO.code = pControl->GPIO.code; + //DBGMSG2("CGX_IOCTL_GPIO_GET after 0x%08X=0x%08X", pControl->GPIO.code, pResults->GPIO.in) + //rc = CgxDriverDebugGpioRead((int)pResults->GPIO.code, (int*)&pResults->GPIO.in); + break; + + case CGX_IOCTL_GET_VERSION: + memcpy(pResults->version.buildVersion, gCgDriverVersion.buildVersion, sizeof(pResults->version.buildVersion)); + memcpy(pResults->version.buildMode, gCgDriverVersion.buildMode, sizeof(pResults->version.buildNumber)); + memcpy(pResults->version.buildNumber, gCgDriverVersion.buildNumber, sizeof(pResults->version.buildNumber)); + memcpy(pResults->version.buildTime, gCgDriverVersion.buildTime, sizeof(pResults->version.buildTime)); + memcpy(pResults->version.buildDate, gCgDriverVersion.buildDate, sizeof(pResults->version.buildDate)); + break; + + case CGX_IOCTL_CANCEL_RECEIVE: + DBGMSG1("Request cancel on byte %d", pControl->cancel.onByteCount); + + // set up receive abort flag. + // the flag is cleared be prepare receive command + + if (pControl->cancel.onByteCount > (U32)CgxDriverSnapLengthExtraBytes) { + pState->transfer.cancel.onByte = pControl->cancel.onByteCount - CgxDriverSnapLengthExtraBytes; + CG_MATH_ALIGNMENT((pState->transfer.cancel.onByte), NUMBER_1K); + DBGMSG1("cancel on Byte: 0x%08X", pState->transfer.cancel.onByte); + } + else { + pState->transfer.cancel.onByte = 0; // Cancel snap req immediately + } + pState->transfer.cancel.request = TRUE; + DBGMSG1("cancel on Byte: 0x%08X", ((pState->transfer.cancel.onByte / 16) & 0x00FFFFF) | 0x0F000000); + CGCORE_WRITE_REG( 0x30, ((pState->transfer.cancel.onByte / 16) & 0x00FFFFF) | 0x0F000000); + CGCORE_WRITE_REG( 0x34, 0); + + // check if cancel point passed + pResults->rc = CgxDriverIsReadCanceled(pState); + if ((pControl->cancel.onByteCount == 0) || // Cancel snap req immediately + (!OK(pResults->rc) && pState->flags.wait)) {// release a waiting thread, if any + CGCoreReset(CGCORE_ENABLE_CORE); + CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + CgxDriverDataReadyInterruptHandler(pDriver, pState); + } + + break; + + case CGX_IOCTL_ALLOC_BUFF: + DBGMSG1("CGX_IOCTL_ALLOC_BUFF, pControl->alloc.length=%d", pControl->alloc.length); + + // pControl->alloc.length = 1 *1024 * 1024; // 1M + + pResults->rc = CgxDriverAllocInternalBuff(pDriver, pControl->alloc.length, + (void**)&(pResults->buffer.bufferPhysAddr), pControl->alloc.processId); + DBGMSG1("alloc p =0x%08X", pState->buffer.virtAddr); + if (OK(pResults->rc)) { + pResults->buffer.size = pControl->alloc.length; + pResults->buffer.bufferAppVirtAddr = pState->buffer.virtAddr; + } + break; + + case CGX_IOCTL_FREE_BUFF: + DBGMSG("CGX_IOCTL_FREE_BUFF"); + pResults->rc = CgxDriverFreeInternalBuff(pDriver, pControl->alloc.processId); + break; + case CGX_IOCTL_READ_MEM: + DBGMSG("CGX_IOCTL_READ_MEM"); + pState->transfer.cancel.request = FALSE; + DBGMSG1("read from 0x%08X", pControl->readReg.offset); + pResults->rc = CgxCpuReadMemory(pControl->readReg.offset, 0, &pResults->readReg.value); + break; + + case CGX_IOCTL_CPU_REVISION: + pResults->rc = CgCpuRevision(pResults->cpuRevision.revisionCode); // TODO - fix CgCpuRevision so it reads from the right address + break; + + case CGX_IOCTL_TCXO_ENABLE: + DBGMSG("CGX_IOCTL_TCXO_ENABLE"); + pResults->rc = CgxDriverTcxoControl(pControl->tcxoControl.enable); + break; + + case CGX_IOCTL_RF_WRITE_CONTROL: + DBGMSG("CGX_IOCTL_RF_WRITE_CONTROL"); + pResults->rc = CgCpuRFControlWriteByte(pControl->writeReg.value); + break; + + default: + return ECgGeneralFailure; + } + + return ECgOk; +} + +TCgReturnCode CgxDriverPowerOn(void) +{ + TCgReturnCode rc = ECgOk; + + gps_chip_power_on(); + + // Enable clock to the GPS device + msleep(1); + rc = CGCoreEnable(CGCORE_ENABLE_TCXO); + + return rc; +} + +TCgReturnCode CgxDriverPowerOff(void) +{ + TCgReturnCode rc = ECgOk; + + // Disable clock to the GPS device + rc = CGCoreDisable(CGCORE_ENABLE_TCXO); + gps_chip_power_off(); + + return rc; +} + +TCgReturnCode CgxDriverTcxoControl(u32 aEnable) +{ + TCgReturnCode rc = ECgOk; + + if(aEnable) + CGCoreEnable(CGCORE_ENABLE_TCXO); + else + CGCoreDisable(CGCORE_ENABLE_TCXO); + + return rc; +} + +TCgReturnCode CgCGCoreGpioSet(U32 aGpioPin, U32 aVal) +{ + TCgReturnCode rc = ECgOk; + U32 valToSet = 0; + + if (aGpioPin <= 0 || aGpioPin > 4) rc = ECgBadArgument; + + if (OK(rc)) rc = CGCORE_READ_REG( CGCORE_REG_OFFSET_GPO, &valToSet); + REG_SET1(valToSet,aGpioPin,aVal ? 1 : 0); + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_GPO, valToSet ); + + return rc; +} + +/* + +TCgReturnCode CgxDriverRFPowerDown(void) +{ + DBG_FUNC_NAME("CgxDriverRFPowerDown") + TCgReturnCode rc = ECgOk; + + #if CG_DRIVER_CG_CORE_CONTROLS_RF_PD + // Do nothing - Core controls RF power down pin + #else + #ifdef RF_POWER_UP_VAL + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, RF_POWER_UP_VAL); + #else + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, 1); + #endif + #endif + + return rc; +} + +TCgReturnCode CgxDriverRFPowerUp(void) +{ + DBG_FUNC_NAME("CgxDriverRFPowerUp"); + TCgReturnCode rc = ECgOk; + + #if CG_DRIVER_CG_CORE_CONTROLS_RF_PD + // Do nothing - Core controls RF power down pin + #else + #ifdef RF_POWER_UP_VAL + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, !RF_POWER_UP_VAL); + #else + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, 0); + #endif + #endif + + return rc; +} + +*/ |
