1 /******************************************************************************
4 * USE OF THIS SOFTWARE (including any copy or compiled version thereof) AND *
5 * DOCUMENTATION IS SUBJECT TO THE SOFTWARE LICENSE AND RESTRICTIONS AND THE *
6 * WARRANTY DISLCAIMER SET FORTH IN LEGAL_NOTICE.TXT FILE. IF YOU DO NOT *
7 * FULLY ACCEPT THE TERMS, YOU MAY NOT INSTALL OR OTHERWISE USE THE SOFTWARE *
9 * NOTWITHSTANDING ANYTHING TO THE CONTRARY IN THIS NOTICE, INSTALLING OR *
10 * OTHERISE USING THE SOFTWARE OR DOCUMENTATION INDICATES YOUR ACCEPTANCE OF *
11 * THE LICENSE TERMS AS STATED. *
13 ******************************************************************************/
14 /* Version: 1.8.9\3686 */
16 /* Date : 12/08/2012 */
25 \brief Linux specific driver code
26 \attention This file should not be modified.
27 If you think something is wrong here, please contact CellGuide
28 Specific code required for the CellGuide GPS driver for Linux.
30 // ===========================================================================
32 #define __CGXLINUXDRIVER_C__
34 #include <linux/version.h>
35 #include <linux/module.h>
36 #include <linux/init.h>
39 #include <linux/pagemap.h>
40 #include <linux/vmalloc.h>
41 #include <linux/delay.h>
42 #include <linux/cdev.h>
43 #include <linux/interrupt.h>
44 #include <linux/workqueue.h>
45 #include <linux/poll.h>
46 #include <linux/device.h>
47 #include <linux/major.h>
48 #include <linux/sched.h>
49 #include <linux/spinlock.h>
50 #include <linux/errno.h>
51 #include <linux/completion.h>
52 #include <linux/dma-mapping.h>
56 #include <linux/of_address.h>
57 #include <linux/of_irq.h>
58 #include <linux/of_gpio.h>
62 #include "CgReturnCodes.h"
64 #include "CgxDriverCore.h"
65 #include "CgxDriverOs.h"
66 #include "CgxDriverPlatform.h"
72 extern U32 CGCORE_REG_OFFSET_CORE_RESETS;
73 extern U32 CGCORE_REG_OFFSET_VERSION;
77 struct class * gps_class;
78 struct device * gps_dev;
84 #ifdef CGCORE_ACCESS_VIA_SPI
85 extern int gpsspidev_init(void);
86 extern void gpsspidev_exit(void);
90 // ===========================================================================
93 // Driver instance structure.
100 struct completion xferCompleted; // was rcvSem
101 TCgxDriverPhysicalMemory chunk;
102 TCgxDriverState state;
103 void *xfer_buff_ptr; // Internal buffer pointer
104 unsigned long xfer_buff_len; // Internal buffer len (bytes)
105 int xfer_buff_pg_order; // Internal buffer page order (log2(n))
106 int xfer_buff_mmapped; // Internal buffer is mapped
107 struct fasync_struct *async_queue;
108 wait_queue_head_t resumeq;
112 // Use a static DriverContext, as only one driver instance is needed
113 static DRVCONTEXT DrvContext;
114 //bxd add for first alloc mem failed from engine
115 static void *init_buff_ptr;
117 static void GpsIntr_BH(struct work_struct *work);
118 DECLARE_WORK(girq_work, GpsIntr_BH);
119 static struct workqueue_struct *girq_wq = NULL;
120 #define GIRQ_WQ_NAME "GIRQ WorkQueue"
122 static void DataReady_BH(struct work_struct *work);
123 DECLARE_WORK(drdy_work, DataReady_BH);
124 static struct workqueue_struct *drdy_wq = NULL;
125 #define DRDY_WQ_NAME "DRDY WorkQueue"
127 // In certain devices, there will not be an irq for DMA ready, but instead, a wait-able, exported sync-object.
128 #ifdef CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT
130 static void DataReady_Completion_WorkQueue(struct work_struct *work);
131 DECLARE_WORK(drdy_completion_work, DataReady_Completion_WorkQueue);
132 static struct workqueue_struct *drdy_completion_wq = NULL;
133 #define DRDY_COMPLETION_WQ_NAME "DRDY Completion WorkQueue"
135 extern struct completion CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT;
138 DataReady Interrupt Handlers:
139 DataReady_BH: The Bottom-Half (Handler Thread)
140 DataReady_TH: The Top-Half (ISR)
141 CgxDriverDataReadyInterruptHandlerStart: Register the DataReady ISR
143 static void DataReady_Completion_WorkQueue(struct work_struct *work)
145 // DBG_FUNC_NAME("DataReady_BH")
149 wait_for_completion( &CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT );
150 CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state);
157 static int cgxdrv_major = 0; /* 0 = dynamic major */
158 #define MODULE_NAME "cgxdrv"
162 DataReady Interrupt Handlers:
163 DataReady_BH: The Bottom-Half (Handler Thread)
164 DataReady_TH: The Top-Half (ISR)
165 CgxDriverDataReadyInterruptHandlerStart: Register the DataReady ISR
167 static void DataReady_BH(struct work_struct *work)
169 // DBG_FUNC_NAME("DataReady_BH")
171 CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state);
172 //enable_irq( DrvContext.DataReady_irq );
176 static irqreturn_t DataReady_TH(int irq, void *dev_id)
178 // DBG_FUNC_NAME("DataReady_TH")
180 //disable_irq_nosync( irq );
182 queue_work(drdy_wq, &drdy_work);
189 #ifdef CGCORE_ACCESS_VIA_SPI
190 u32 GetRequestLen(void)
192 TCgxDriverState *pState = &DrvContext.state;
194 return pState->transfer.bytes.required;
197 void DataReady_TH_start(void )
200 CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state);
204 void* Data_Get_DrvContext(void)
207 return DrvContext.xfer_buff_ptr;
210 void CCgCpuDmaHandle(int irq,void* dev_id)
212 CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state);
216 TCgReturnCode CgxDriverDataReadyInterruptHandlerStart(void *pDriver)
218 DBG_FUNC_NAME("CgxDriverDataReadyInterruptHandlerStart")
219 DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver;
223 // First check if there is an irq dedicated to the DataReady event
224 pDriverInfo->DataReady_irq = CgxDriverDataReadyInterruptCode();
225 if( pDriverInfo->DataReady_irq != 0)
227 drdy_wq = create_singlethread_workqueue(DRDY_WQ_NAME);
229 if (drdy_wq == NULL) {
230 DBGMSG("create_singlethread_workqueue(" DRDY_WQ_NAME ") Failed");
231 return ECgInitFailure;
234 rv = request_irq( pDriverInfo->DataReady_irq, DataReady_TH, IRQF_DISABLED, "drdy-bh", NULL );
236 DBGMSG1("request_irq(%d) Failed", pDriverInfo->DataReady_irq );
237 return ECgInitFailure;
239 DBGMSG1("request_irq(DRDY/%d) OK", pDriverInfo->DataReady_irq );
243 // There is no irq. Lets check if there is an exported sync-object
244 #ifdef CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT
245 drdy_completion_wq = create_singlethread_workqueue(DRDY_COMPLETION_WQ_NAME);
246 if ( OK(drdy_completion_wq) )
247 queue_work(drdy_completion_wq, &drdy_completion_work);
249 return ECgInitFailure;
251 DBGMSG1("request_irq(DRDY/%d) Skipped", pDriverInfo->DataReady_irq );
261 GpsIntr Interrupt Handlers:
262 GpsIntr_BH: The Bottom-Half (Handler Thread)
263 GpsIntr_TH: The Top-Half (ISR)
264 CgxDriverGeneralInterruptHandlerStart: Register the GpsIntr ISR
266 static void GpsIntr_BH(struct work_struct *work)
268 // DBG_FUNC_NAME("GpsIntr_BH")
270 CgxDriverGpsInterruptHandler(&DrvContext, &DrvContext.state);
272 enable_irq( DrvContext.GpsIntr_irq );
275 static irqreturn_t GpsIntr_TH(int irq, void *dev_id)
277 // DBG_FUNC_NAME("GpsIntr_TH")
279 disable_irq_nosync( irq );
281 queue_work(girq_wq, &girq_work);
287 TCgReturnCode CgxDriverGpsInterruptHandlerStart(void *pDriver)
289 DBG_FUNC_NAME("CgxDriverGpsInterruptHandlerStart")
290 DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver;
293 pDriverInfo->GpsIntr_irq = CgxDriverGpsInterruptCode();
294 if (pDriverInfo->GpsIntr_irq != 0)
296 girq_wq = create_singlethread_workqueue(GIRQ_WQ_NAME);
297 if (girq_wq == NULL) {
298 DBGMSG("create_singlethread_workqueue(" GIRQ_WQ_NAME ") Failed");
299 return ECgInitFailure;
301 #ifdef CGCORE_ACCESS_VIA_SPI
302 rv = request_irq( pDriverInfo->GpsIntr_irq, GpsIntr_TH, IRQF_TRIGGER_RISING, "girq-bh", NULL );
304 rv = request_irq( pDriverInfo->GpsIntr_irq, GpsIntr_TH, IRQF_DISABLED, "girq-bh", NULL );
307 DBGMSG1("request_irq(%d) Failed", pDriverInfo->GpsIntr_irq );
308 return ECgInitFailure;
310 DBGMSG1("request_irq(GPS/%d) OK", pDriverInfo->GpsIntr_irq );
313 DBGMSG1("request_irq(GPS/%d) Skipped", pDriverInfo->GpsIntr_irq );
322 TCgReturnCode CgxDriverTransferEndCreate(void *pDriver)
324 DBG_FUNC_NAME("CgxDriverTransferEndCreate")
325 DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver;
327 DBGMSG( "Entering... Initializing completion semaphore" );
329 init_completion( &pDriverInfo->xferCompleted );
331 DBGMSG1( "Initialized Semaphore=%u", pDriverInfo->xferCompleted.done );
338 TCgReturnCode CgxDriverTransferEndSignal(void *pDriver)
340 //DBG_FUNC_NAME("CgxDriverTransferEndSignal")
341 DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver;
343 /* DBGMSG( "Entering" );*/
345 //DBGMSG1( "Marking completion... Semaphore=%u", pDriverInfo->xferCompleted.done );
346 complete( &pDriverInfo->xferCompleted );
347 //DBGMSG1( "Marked completion... After Semaphore=%u", pDriverInfo->xferCompleted.done );
353 TCgReturnCode CgxDriverTransferEndWait(void *pDriver, U32 aTimeoutMS)
355 DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver;
356 TCgReturnCode rc = ECgOk;
357 unsigned long timeout = aTimeoutMS * HZ / 1000;
358 unsigned long rv = 0 ;
359 DBG_FUNC_NAME("CgxDriverTransferEndWait")
361 DBGMSG1( "Timeout=%lu", timeout );
365 if (pDriverInfo->state.flags.resume == 1) {
369 //DBGMSG1( "Waiting for completion... Semaphore=%u", pDriverInfo->xferCompleted.done );
370 /*bxd modify because of can't entry susnpend when use wait_for_completion_interruptible_timeout func */
371 //rv = wait_for_completion_interruptible_timeout( &pDriverInfo->xferCompleted, timeout );
372 rv = wait_for_completion_timeout( &pDriverInfo->xferCompleted, timeout );
373 if (rv != -ERESTARTSYS)
377 if ((rv == 0) && (timeout > 0))
380 DBGMSG( "Timed-out" );
384 DBGMSG1( "wait_for_completion_interruptible_timeout returned=%d", rv );
387 if (pDriverInfo->state.flags.resume == 1) {
396 TCgReturnCode CgxDriverTransferEndDestroy(void *pDriver)
405 unsigned char buf_data[6*1024*1024];
410 #ifndef CGCORE_ACCESS_VIA_SPI
411 void clear_buf_data(void)
413 memset(DrvContext.xfer_buff_ptr,0,DrvContext.xfer_buff_len);
417 TCgReturnCode CgxDriverAllocInternalBuff(void *pDriver, U32 aLength, void **apBuffer, U32 aProcessID)
419 DBG_FUNC_NAME("CgxDriverAllocInternalBuff")
420 DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver;
421 DBGMSG( "Entering..." );
423 /* Already alloc'ed, return error and ask to free 1st */
424 if (DrvContext.xfer_buff_ptr != NULL) {
425 DBGMSG( "Returning ECgNotSupported" );
426 return ECgNotSupported;
431 DrvContext.xfer_buff_pg_order = get_order(aLength);
432 //bxd add for first alloc mem failed from engine
433 if(init_buff_ptr != NULL)
434 DrvContext.xfer_buff_ptr = init_buff_ptr;
436 DrvContext.xfer_buff_ptr = (void *)__get_free_pages(GFP_KERNEL, DrvContext.xfer_buff_pg_order);
437 DrvContext.xfer_buff_len = PAGE_SIZE * (1 << DrvContext.xfer_buff_pg_order);
438 buf_data = DrvContext.xfer_buff_ptr;
440 DrvContext.xfer_buff_pg_order = get_order(aLength);
441 DrvContext.xfer_buff_ptr =(void*)&buf_data[0];
442 DrvContext.xfer_buff_len = 6*1024*1024;
447 if (DrvContext.xfer_buff_ptr == NULL) {
448 DBGMSG( "Returning ECgErrMemory" );
452 pDriverInfo->state.buffer.length = DrvContext.xfer_buff_len;
453 pDriverInfo->state.buffer.virtAddr = DrvContext.xfer_buff_ptr;
454 pDriverInfo->state.buffer.physAddr = __pa((void *)DrvContext.xfer_buff_ptr) ;
455 DBGMSG2( "Returning ECgOk - Requested: %lu - Granted: %lu", aLength, DrvContext.xfer_buff_len );
457 *apBuffer = (void *)pDriverInfo->state.buffer.physAddr;
458 #if defined(CGTEST) || defined(DEBUG)
459 memset(pDriverInfo->state.buffer.virtAddr, 0x43, aLength);
461 DBGMSG3(">>>>>>> memory allocated at DrvContext.xfer_buff_ptr=[0x%08X] buffer.virtAddr=[0x%08X], buffer.physAddr=[0x%08X]",DrvContext.xfer_buff_ptr, pDriverInfo->state.buffer.virtAddr, pDriverInfo->state.buffer.physAddr );
465 #ifdef CGCORE_ACCESS_VIA_SPI
466 int get_blocksize(void)
468 return DrvContext.state.transfer.blockSize;
473 void *CgxDriverGetInternalBuff(void *pSource, U32 length)
475 // if (length != DrvContext.xfer_buff_len)
478 return DrvContext.xfer_buff_ptr;
483 TCgReturnCode CgxDriverFreeInternalBuff(void *pDriver, U32 unUsed)
485 /* Already alloc'ed, return error and ask to free 1st */
486 if (DrvContext.xfer_buff_ptr == NULL)
487 return ECgNotSupported;
489 /* Buffer is mmap'ed. return error and ask to free 1st */
490 if (DrvContext.xfer_buff_mmapped)
491 return ECgNotAllowed;
495 //free_pages((unsigned long)DrvContext.xfer_buff_ptr, DrvContext.xfer_buff_pg_order);
498 DrvContext.xfer_buff_ptr = NULL;
499 DrvContext.xfer_buff_len = 0;
500 DrvContext.xfer_buff_pg_order = 0;
502 //bxd add for first alloc mem failed from engine
503 //if(init_buff_ptr != NULL)
504 // init_buff_ptr = NULL;
511 unsigned long CgxCopyFromUser(void *to, const void *fromuser, unsigned long n)
513 return copy_from_user(to, fromuser, n);
518 static void getdata32_to_data64(TCgDriverControl_32bit *In32,TCgDriverControl *In64)
520 In64->read.alignedLength = In32->read.alignedLength;
521 In64->read.blockLength = In32->read.blockLength;
522 In64->read.byteOrder = In32->read.byteOrder;
523 In64->read.buf = Data_Get_DrvContext();
524 In64->read.bufPhys = In32->read.bufPhys;
525 In64->read.timeoutMS = In32->read.timeoutMS;
526 In64->wait.timeoutMS = In32->wait.timeoutMS;
527 In64->wait.blockNumber = In32->wait.blockNumber;
528 // In64->write.pSource = &In32->write.pSource;
529 In64->write.length = In32->write.length;
530 In64->GPIO.code = In32->GPIO.code;
531 In64->GPIO.out = In32->GPIO.out;
532 In64->GPIO.mode = In32->GPIO.mode;
533 In64->readReg.offset = In32->readReg.offset;
534 In64->writeReg.offset = In32->writeReg.offset;
535 In64->writeReg.value = In32->writeReg.value;
536 In64->cancel.onByteCount = In32->cancel.onByteCount;
537 In64->reset.resetLevel = In32->reset.resetLevel;
538 In64->alloc.length = In32->alloc.length;
539 In64->alloc.processId = In32->alloc.processId;
540 In64->tcxoControl.enable = In32->tcxoControl.enable;
544 printk("read.alignedLength: 0x%x\n", In32->read.alignedLength);
545 printk("read.blockLength: 0x%x\n", In32->read.blockLength);
546 printk("read.byteOrder: 0x%x\n", In32->read.byteOrder);
547 printk("read.buf: 0x%x\n", In32->read.buf);
548 printk("read.bufPhys: 0x%x\n", In32->read.bufPhys);
549 printk("read.timeoutMS: 0x%x\n", In32->read.timeoutMS);
551 printk("wait.timeoutMS: 0x%x\n", In32->wait.timeoutMS);
552 printk("wait.blockNumber: 0x%x\n", In32->wait.blockNumber);
553 printk("write.pSource: 0x%x\n", In32->write.pSource);
554 printk("write.length: 0x%x\n", In32->write.length);
555 printk("GPIO.code: 0x%x\n", In32->GPIO.code);
557 printk("GPIO.out: 0x%x\n", In32->GPIO.out);
558 printk("GPIO.mode: 0x%x\n", In32->GPIO.mode);
559 printk("readReg.offset: 0x%x\n", In32->readReg.offset);
560 printk("writeReg.offset: 0x%x\n", In32->writeReg.offset);
561 printk("writeReg.value: 0x%x\n", In32->writeReg.value);
562 printk("cancel.onByteCount: 0x%x\n", In32->cancel.onByteCount);
563 printk("reset.resetLevel: 0x%x\n", In32->reset.resetLevel);
564 printk("alloc.length: 0x%x\n", In32->alloc.length);
565 printk("alloc.processId: 0x%x\n", In32->alloc.processId);
566 printk("tcxoControl.enable: 0x%x\n", In32->tcxoControl.enable);
569 printk("read.alignedLength In64: 0x%x\n", In64->read.alignedLength);
570 printk("read.blockLength In64: 0x%x\n", In64->read.blockLength);
571 printk("read.byteOrder In64: 0x%x\n", In64->read.byteOrder);
572 printk("read.buf In64: 0x%x\n", In64->read.buf);
573 printk("read.bufPhys In64: 0x%x\n", In64->read.bufPhys);
574 printk("read.timeoutMS In64: 0x%x\n", In64->read.timeoutMS);
576 printk("wait.timeoutMS In64: 0x%x\n", In64->wait.timeoutMS);
577 printk("wait.blockNumber In64: 0x%x\n", In64->wait.blockNumber);
578 printk("write.pSource In64: 0x%x\n", In64->write.pSource);
579 printk("write.length In64: 0x%x\n", In64->write.length);
580 printk("GPIO.code In64: 0x%x\n", In64->GPIO.code);
582 printk("GPIO.out In64: 0x%x\n", In64->GPIO.out);
583 printk("GPIO.mode In64: 0x%x\n", In64->GPIO.mode);
584 printk("readReg.offset In64: 0x%x\n", In64->readReg.offset);
585 printk("writeReg.offset In64: 0x%x\n", In64->writeReg.offset);
586 printk("writeReg.value In64: 0x%x\n", In64->writeReg.value);
587 printk("cancel.onByteCount In64: 0x%x\n", In64->cancel.onByteCount);
588 printk("reset.resetLevel In64: 0x%x\n", In64->reset.resetLevel);
589 printk("alloc.length In64: 0x%x\n", In64->alloc.length);
590 printk("alloc.processId In64: 0x%x\n", In64->alloc.processId);
591 printk("tcxoControl.enable In64: 0x%x\n", In64->tcxoControl.enable);
597 static void putdata64_to_data32(TCgDriverStatus_32bit *Out32,TCgDriverStatus *Out64)
599 Out32->rc = Out64->rc;
600 Out32->buffer.bufferPhysAddr = (unsigned int)Out64->buffer.bufferPhysAddr;
601 Out32->buffer.bufferAppVirtAddr = poffset;
602 Out32->buffer.size = Out64->buffer.size;
603 Out32->GPIO.code = Out64->GPIO.code;
604 Out32->GPIO.val = Out64->GPIO.val;
605 //Out32->version.buildVersion = &Out64->version.buildVersion[0];
606 //Out32->version.buildNumber = &Out64->version.buildNumber[0];
607 //Out32->version.buildDate = &Out64->version.buildDate[0];
608 //Out32->version.buildTime = &Out64->version.buildTime[0];
609 //Out32->version.buildMode = &Out64->version.buildMode[0];
610 //Out32->version.buildName = &Out64->version.buildName[0];
611 Out32->readReg.offset = Out64->readReg.offset;
612 Out32->readReg.value = Out64->readReg.value;
613 //Out32->cpuRevision.revisionCode = &Out64->cpuRevision.revisionCode[0];
614 Out32->readRtc.year = Out64->readRtc.year;
615 Out32->readRtc.month = Out64->readRtc.month;
616 Out32->readRtc.day = Out64->readRtc.day;
617 Out32->readRtc.hour = Out64->readRtc.hour;
618 Out32->readRtc.minute = Out64->readRtc.minute;
619 Out32->readRtc.second = Out64->readRtc.second;
620 Out32->readRtc.dayInWeek = Out64->readRtc.dayInWeek;
621 Out32->readRtc.tick = Out64->readRtc.tick;
622 Out32->state.flags.terminate = Out64->state.flags.terminate;
623 Out32->state.flags.wait = Out64->state.flags.wait;
624 Out32->state.flags.overrun = Out64->state.flags.overrun;
625 Out32->state.flags.resume = Out64->state.flags.resume;
626 Out32->state.counters.interrupt.all = Out64->state.counters.interrupt.all;
627 Out32->state.counters.interrupt.snapStart = Out64->state.counters.interrupt.snapStart;
628 Out32->state.counters.interrupt.overrun = Out64->state.counters.interrupt.overrun;
629 Out32->state.transfer.bufferPhys = Out64->state.transfer.bufferPhys;
630 Out32->state.transfer.originalBuffer = (unsigned int)( Out64->state.transfer.originalBuffer);
631 Out32->state.transfer.byteOrder = Out64->state.transfer.byteOrder;
632 Out32->state.transfer.done = Out64->state.transfer.done;
633 Out32->state.transfer.bytes.required = Out64->state.transfer.bytes.required;
634 Out32->state.transfer.bytes.received = Out64->state.transfer.bytes.received;
635 Out32->state.transfer.blocks.required = Out64->state.transfer.blocks.required;
636 Out32->state.transfer.blocks.received = Out64->state.transfer.blocks.received;
637 Out32->state.transfer.chunks.required = Out64->state.transfer.blocks.received;
638 Out32->state.transfer.chunks.received = Out64->state.transfer.chunks.received;
639 Out32->state.transfer.chunks.active = Out64->state.transfer.chunks.active;
640 Out32->state.transfer.cancel.request = Out64->state.transfer.cancel.request;
641 Out32->state.transfer.cancel.onByte = Out64->state.transfer.cancel.onByte;
642 Out32->state.transfer.cancel.onChunk = Out64->state.transfer.cancel.onChunk;
643 //Out32->state.transfer.bufferOffset = Out64->state.transfer.bufferOffset;
644 Out32->state.transfer.blockSize = Out64->state.transfer.blockSize;
645 Out32->state.transfer.lastBlockSize = Out64->state.transfer.lastBlockSize;
646 Out32->state.buffer.physAddr = Out64->state.buffer.physAddr;
647 Out32->state.buffer.virtAddr = (unsigned int)(Out64->state.buffer.virtAddr);
648 Out32->state.buffer.length = Out64->state.buffer.length;
649 Out32->state.buffer.driverContextVirtBufferAddr = (unsigned int)(Out64->state.buffer.driverContextVirtBufferAddr);
650 Out32->state.constructionRc = Out64->state.constructionRc;
652 printk("Out64.readReg.offset: 0x%x\n", Out64->readReg.offset);
653 printk("Out64.readReg.value: 0x%x\n", Out64->readReg.value);
654 printk("Out32.readReg.offset: 0x%x\n", Out32->readReg.offset);
655 printk("Out32.readReg.value: 0x%x\n", Out32->readReg.value);
659 static void printdata32(TCgDriverStatus_32bit *Out32)
662 printk(" Out32->rc: 0x%x\n", Out32->rc);
663 printk(" Out32->buffer.bufferPhysAddr: 0x%x\n", Out32->buffer.bufferPhysAddr);
664 printk(" Out32->buffer.bufferAppVirtAddr: 0x%x\n", Out32->buffer.bufferAppVirtAddr);
665 printk(" Out32->buffer.size : 0x%x\n", Out32->buffer.size );
666 printk(" Out32->GPIO.code : 0x%x\n", Out32->GPIO.code );
667 printk(" Out32->GPIO.val: 0x%x\n", Out32->GPIO.val);
669 printk(" Out32->version.buildVersion: 0x%x\n", Out32->version.buildVersion);
670 printk(" Out32->version.buildNumber: 0x%x\n", Out32->version.buildNumber);
671 printk(" Out32->version.buildDate : 0x%x\n", Out32->version.buildDate );
672 printk(" Out32->version.buildTime: 0x%x\n", Out32->version.buildTime);
673 printk(" Out32->version.buildMode : 0x%x\n", Out32->version.buildMode );
674 printk(" Out32->version.buildName: 0x%x\n", Out32->version.buildName);
676 printk(" Out32->readReg.offset: 0x%x\n", Out32->readReg.offset);
677 printk(" Out32->readReg.value: 0x%x\n", Out32->readReg.value);
678 printk(" Out32->readRtc.year : 0x%x\n", Out32->readRtc.year );
679 printk(" Out32->readRtc.month: 0x%x\n", Out32->readRtc.month);
680 printk(" Out32->readRtc.day: 0x%x\n", Out32->readRtc.day);
681 printk(" Out32->readRtc.hour: 0x%x\n", Out32->readRtc.hour);
682 printk(" Out32->readRtc.minute: 0x%x\n", Out32->readRtc.minute);
683 printk(" Out32->readRtc.second: 0x%x\n", Out32->readRtc.second);
684 printk(" Out32->readRtc.dayInWeek: 0x%x\n", Out32->readRtc.dayInWeek);
685 printk(" Out32->readRtc.tick: 0x%x\n", Out32->readRtc.tick);
690 printk(" Out32->state.flags.terminate: 0x%x\n", Out32->state.flags.terminate);
691 printk(" Out32->state.flags.wait: 0x%x\n", Out32->state.flags.wait);
692 printk(" Out32->state.flags.overrun: 0x%x\n", Out32->state.flags.overrun);
693 printk(" Out32->state.flags.resume: 0x%x\n", Out32->state.flags.resume);
694 printk(" Out32->state.counters.interrupt.all: 0x%x\n", Out32->state.counters.interrupt.all);
695 printk(" Out32->state.counters.interrupt.snapStart: 0x%x\n", Out32->state.counters.interrupt.snapStart);
696 printk(" Out32->state.counters.interrupt.overrun: 0x%x\n", Out32->state.counters.interrupt.overrun);
697 printk(" Out32->state.transfer.bufferPhys: 0x%x\n", Out32->state.transfer.bufferPhys);
698 printk(" Out32->state.transfer.originalBuffer: 0x%x\n", Out32->state.transfer.originalBuffer);
699 printk(" Out32->state.transfer.byteOrder: 0x%x\n", Out32->state.transfer.byteOrder);
700 printk(" Out32->state.transfer.done: 0x%x\n", Out32->state.transfer.done);
701 printk(" Out32->state.transfer.bytes.required: 0x%x\n", Out32->state.transfer.bytes.required);
702 printk(" Out32->state.transfer.bytes.received: 0x%x\n", Out32->state.transfer.bytes.received);
703 printk(" Out32->state.transfer.blocks.required: 0x%x\n", Out32->state.transfer.blocks.required);
704 printk(" Out32->state.transfer.blocks.received: 0x%x\n", Out32->state.transfer.blocks.received);
705 printk(" Out32->state.transfer.chunks.required: 0x%x\n", Out32->state.transfer.chunks.required);
706 printk(" Out32->state.transfer.chunks.received: 0x%x\n", Out32->state.transfer.chunks.received);
707 printk(" Out32->state.transfer.chunks.active: 0x%x\n", Out32->state.transfer.chunks.active);
708 printk(" Out32->state.transfer.cancel.request: 0x%x\n", Out32->state.transfer.cancel.request);
709 printk(" Out32->state.transfer.cancel.onByte: 0x%x\n", Out32->state.transfer.cancel.onByte);
710 printk(" Out32->state.transfer.cancel.onChunk : 0x%x\n", Out32->state.transfer.cancel.onChunk );
711 printk(" Out32->state.transfer.bufferOffset: 0x%x\n", Out32->state.transfer.bufferOffset);
712 printk(" Out32->state.transfer.blockSize: 0x%x\n", Out32->state.transfer.blockSize);
713 printk(" Out32->state.transfer.lastBlockSize: 0x%x\n", Out32->state.transfer.lastBlockSize);
714 printk(" Out32->state.buffer.physAddr: 0x%x\n", Out32->state.buffer.physAddr);
715 printk(" Out32->state.buffer.virtAddr: 0x%x\n", Out32->state.buffer.virtAddr);
717 printk(" Out32->state.buffer.length: 0x%x\n", Out32->state.buffer.length);
718 printk(" Out32->state.buffer.driverContextVirtBufferAddr: 0x%x\n", Out32->state.buffer.driverContextVirtBufferAddr);
719 printk(" Out32->state.constructionRc: 0x%x\n", Out32->state.constructionRc);
720 printk(" Out32->rc: 0x%x\n", Out32->rc);
721 printk(" Out32->rc: 0x%x\n", Out32->rc);
732 //Out32->cpuRevision.revisionCode = &Out64->cpuRevision.revisionCode[0];
736 //======================================================================
737 // CGX_IOControl - Called when DeviceIOControl called
739 //static int CGX_IOControl(struct inode *inode,struct file *filp,
740 static long CGX_IOControl(struct file *filp,
742 unsigned int cmd, unsigned long arg)
744 DBG_FUNC_NAME("CGX_IOControl")
745 TCgReturnCode rc = ECgOk;
749 TCgDriverControl_32bit In_32;
750 TCgDriverStatus_32bit Out_32;
752 //printk("cmd:0x%x,arg:0x%x\n",cmd,arg);
753 /* DBGMSG1( "Entering...[%d]" , cmd); */
756 // Check we can read the TCgDriverControl from User Space
757 if ( !access_ok( VERIFY_READ, (void __user *)arg, sizeof(TCgDriverControl_32bit) ) ) {
758 DBGMSG( "Returning -EFAULT 1" );
762 // Check we can write the TCgDriverStatus to User Space
763 if ( !access_ok( VERIFY_WRITE, (void __user *)arg, sizeof(TCgDriverStatus_32bit) ) ) {
764 DBGMSG( "Returning -EFAULT 2" );
768 if ( copy_from_user( &In_32, (void __user *)arg, sizeof(In_32) ) ) {
769 DBGMSG( "Returning -EFAULT 3" );
773 getdata32_to_data64(&In_32,&In);
775 rc = CgxDriverExecute( &DrvContext, &DrvContext.state, cmd, &In, &Out);
777 putdata64_to_data32(&Out_32,&Out);
779 if ( copy_to_user( (void __user *)arg, &Out_32, sizeof(Out_32) ) ) {
780 DBGMSG( "Returning -EFAULT 4" );
784 DBGMSG1( "Returning %d", (OK(rc)) ? 0 : -ENOTTY );
785 return (OK(rc)) ? 0 : -ENOTTY;
790 int CGX_CompleteDrv(void)
792 complete(&DrvContext.xferCompleted);
796 EXPORT_SYMBOL_GPL(CGX_CompleteDrv);
798 //======================================================================
799 // CGX_Fasync - Called when driver closed
801 static int CGX_Fasync( int fd, struct file *filp, int mode)
803 return fasync_helper(fd, filp, mode, &DrvContext.async_queue);
806 unsigned int CgxDriverCheckAllocInternalBuff(void)
809 if (DrvContext.xfer_buff_ptr != NULL) {
810 printk( "\n already alloc page \n" );
818 //======================================================================
819 // CGX_Close - Called when driver closed
821 static int CGX_Close( struct inode *inode, struct file *filp)
823 /* DBGMSG( "Entering..." ); */
830 if (CgxDriverCheckAllocInternalBuff() == 0)
832 printk("\n gaole: close check if old page be released \n");
834 rc = CgxDriverFreeInternalBuff(NULL, 0);
838 printk("\n gaole: close run CgxDriverFreeInternalBuff error,error code is %d \n",rc);
843 rc = CgCpuDmaStop(0);
846 printk("\n gaole: run CgCpuDmaStop error,error code is %d \n",rc);
852 CgCpuDmaDestroy(0,0);
856 if (DrvContext.nNumOpens)
857 DrvContext.nNumOpens--;
859 if ( filp->f_flags & FASYNC) {
860 CGX_Fasync(-1, filp, 0); /* Remove from async queue */
863 /* DBGMSG( "Returning 0" ); */
868 //======================================================================
869 // CGX_Read - Called when driver read
871 static ssize_t CGX_Read( struct file *filp, char __user *buff, size_t count, loff_t *offp)
873 while (DrvContext.pm_resumed == 0) {
874 if (filp->f_flags & O_NONBLOCK)
876 //DBGMSG( "Waiting for resume to take place... Going to sleep\n" );
877 if (wait_event_interruptible(DrvContext.resumeq, (DrvContext.pm_resumed != 0)))
882 * Copy 1 char sizeof(*(char*)) from DrvContext.pm_resumed to buff
884 if (put_user(DrvContext.pm_resumed, (char __user *)buff)) {
888 DrvContext.pm_resumed = 0;
893 //======================================================================
894 // CGX_Write - Called when driver written
896 static ssize_t CGX_Write( struct file *filp, const char __user *buff, size_t count, loff_t *offp)
902 //======================================================================
903 // CGX_Poll - Called when driver select()/poll()
905 static unsigned int CGX_Poll(struct file *filp, poll_table *wait)
907 poll_wait(filp, &DrvContext.resumeq, wait);
909 if (DrvContext.pm_resumed == 'R')
910 return (POLLIN | POLLRDNORM);
915 //======================================================================
916 // CGX_Seek - Called when SetFilePtr called
918 static loff_t CGX_Seek (struct file *filp, loff_t off, int whence)
928 //======================================================================
929 // CGX_Open - Called when driver opened
931 static int CGX_Open( struct inode *inode, struct file *filp )
935 * XXX-PK-XXX: Hold lock on DrvContext
939 /* DBGMSG( "Entering..." ); */
941 // Count the number of opens.
942 DrvContext.nNumOpens++;
944 /* DBGMSG( "Returning 0" ); */
950 * CGX_vma_open and CGX_vma_close keep track of how many times
951 * the buffer is mapped, to avoid Freeing it while in use.
953 static void CGX_vma_open(struct vm_area_struct *vma)
955 DBG_FUNC_NAME("CGX_vma_open")
956 DrvContext.xfer_buff_mmapped++;
957 DBGMSG4("vma open [%d]: virt 0x%lx, Offs %lu, Len %lu",
958 DrvContext.xfer_buff_mmapped,
959 vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, vma->vm_end - vma->vm_start );
962 static void CGX_vma_close(struct vm_area_struct *vma)
964 DBG_FUNC_NAME("CGX_vma_close")
965 /* DBGMSG( "Entering..." ); */
967 DrvContext.xfer_buff_mmapped--;
968 DBGMSG1("vma close [%d]", DrvContext.xfer_buff_mmapped );
970 /* DBGMSG( "Exit" ); */
973 #if LINUX_VERSION_CODE >= 132634
974 static int CGX_vma_nopage(struct vm_area_struct *vma, struct vm_fault *vmf)
976 return VM_FAULT_SIGBUS; // Remapping is not allowed !
979 static struct page *CGX_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
981 return NOPAGE_SIGBUS; // Remapping is not allowed !
985 static struct vm_operations_struct cgx_remap_ops = {
986 .open = CGX_vma_open,
987 .close = CGX_vma_close,
988 #if LINUX_VERSION_CODE >= 132634
989 .fault = CGX_vma_nopage,
991 .nopage = CGX_vma_nopage,
995 static int CGX_Mmap(struct file *filp, struct vm_area_struct *vma)
997 DBG_FUNC_NAME("CGX_Mmap")
999 unsigned long len = (vma->vm_end - vma->vm_start);
1000 unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
1001 unsigned long physical = __pa((void *)DrvContext.xfer_buff_ptr) + off;
1003 DBGMSG3( "Entering... len=%lu off=%lu DrvContext.xfer_buff_len=%lu", len, off, DrvContext.xfer_buff_len );
1005 if ( len > (DrvContext.xfer_buff_len - off) ) {
1006 DBGMSG( "Returning -EINVAL" );
1010 #ifdef CGCORE_ACCESS_VIA_SPI
1011 rv = remap_pfn_range(vma, vma->vm_start,
1012 physical >> PAGE_SHIFT, len,
1013 (vma->vm_page_prot));
1016 rv = remap_pfn_range(vma, vma->vm_start,
1017 physical >> PAGE_SHIFT, len,
1018 pgprot_noncached(vma->vm_page_prot));
1025 DBGMSG1( "Returning %d", rv );
1029 vma->vm_ops = &cgx_remap_ops;
1031 /* DBGMSG( "Returning 0" ); */
1037 #warning CGX_AddSysDev is needed only for debugging !
1038 static int CGX_AddSysDev(struct sys_device *dev)
1040 DBGMSG( "Got to CGX_AddSysDev\n" );
1046 static int CGX_PMSuspend(struct device *dev, pm_message_t state)
1049 //DBGMSG( "Got to CGX_PMSuspend\n" );
1050 printk("%s\n",__func__);
1051 //if (DrvContext.nNumOpens > 0)
1052 if(flag_power_up == 1)
1054 CgxDriverPowerDown();
1055 CgxDriverRFPowerDown();
1062 static int CGX_PMResume(struct device *dev)
1065 //DBGMSG( "Got to CGX_PMResume\n" );
1066 printk("%s\n",__func__);
1067 //if (DrvContext.nNumOpens > 0)
1068 if(flag_power_up == 1)
1071 DrvContext.state.flags.resume = 1;
1073 DrvContext.pm_resumed = 'R';
1075 /* awake read()ers and poll()ers (select) */
1076 wake_up_interruptible(&DrvContext.resumeq);
1078 /* signal async readers */
1079 if (DrvContext.async_queue)
1080 kill_fasync(&DrvContext.async_queue, SIGIO, POLL_IN);
1083 CgxDriverRFPowerUp();
1091 //======================================================================
1092 // CGX_Init - Driver initialization function
1094 struct file_operations cgx_fops = {
1095 .owner = THIS_MODULE,
1101 //.ioctl = CGX_IOControl,
1102 .unlocked_ioctl = CGX_IOControl,
1103 #ifdef CONFIG_COMPAT
1104 .compat_ioctl = CGX_IOControl,
1107 .fasync = CGX_Fasync,
1108 .release = CGX_Close,
1113 #ifndef CGCORE_ACCESS_VIA_SPI
1114 struct gps_2351_addr gps_2351;
1115 u32 gps_get_core_base(void)
1117 return gps_2351.gps_base;
1120 u32 gps_get_ahb_base(void)
1122 return gps_2351.ahb_base;
1125 u32 gps_get_irq(void)
1127 return gps_2351.irq_num;
1130 u32 gps_get_lna_gpio(void)
1132 return gps_2351.lna_gpio;
1135 #ifdef CONFIG_ARCH_SCX30G
1136 u32 gps_get_pmu_base(void)
1138 return gps_2351.pmu_base;
1142 static int cgxdrv_gps_source_init(void)
1146 struct device_node *np;
1147 struct resource res;
1149 np = of_find_node_by_name(NULL, "gps_2351");
1151 printk("Can't get the gps_2351 node!\n");
1154 printk(" find the gps_2351 node!\n");
1156 ret = of_address_to_resource(np, 0, &res);
1158 printk("Can't get the gps reg base!\n");
1161 gps_2351.gps_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
1162 printk("gps reg base is 0x%x\n", gps_2351.gps_base);
1164 ret = of_address_to_resource(np, 1, &res);
1166 printk("Can't get the ahbreg base!\n");
1169 gps_2351.ahb_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
1170 printk("ahb reg base is 0x%x\n", gps_2351.ahb_base);
1172 #ifdef CONFIG_ARCH_SCX30G
1173 ret = of_address_to_resource(np, 2, &res);
1175 printk("Can't get the pmu base!\n");
1178 gps_2351.pmu_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
1179 printk("pmu_base base is 0x%x\n", gps_2351.pmu_base);
1182 gps_2351.irq_num = irq_of_parse_and_map(np, 0);
1183 if (gps_2351.irq_num == 0) {
1184 printk("Can't get the gps irq_num!\n");
1187 printk(" gps_2351.gps_irq_num is %d\n", gps_2351.irq_num);
1189 gps_2351.lna_gpio = of_get_gpio(np, 0);
1190 if(gps_2351.lna_gpio < 0){
1191 printk("fail to get gps lna gpio\n");
1197 static int __init CGX_Init(void)
1199 DBG_FUNC_NAME("CGX_Init")
1201 dev_t devno = MKDEV(cgxdrv_major, 0);
1203 /* DBGMSG( "Entering..." ); */
1205 DBGMSG("Initializing");
1208 #ifndef CGCORE_ACCESS_VIA_SPI
1209 cgxdrv_gps_source_init();
1213 //bxd add for first alloc mem failed from engine
1214 init_buff_ptr = (void *)__get_free_pages(GFP_KERNEL, 8);
1215 if(init_buff_ptr == NULL)
1216 printk("init_buff_ptr alloc failed\n");
1218 #ifndef CGCORE_ACCESS_VIA_SPI
1219 sprd_get_rf2351_ops(&gps_rf_ops);
1222 #ifdef CGCORE_ACCESS_VIA_SPI
1226 /* Init structure */
1227 memset (&(DrvContext), 0, sizeof (DRVCONTEXT));
1228 init_waitqueue_head(&DrvContext.resumeq);
1230 /* Register char dev (Major can be provided at load time) */
1232 rv = register_chrdev_region(devno, 1, "cgxdrv");
1233 printk(KERN_ERR "[CGX|%s] register_chrdev_region \r\n", __FUNCTION__);
1235 rv = alloc_chrdev_region(&devno, 0, 1, "cgxdrv");
1236 cgxdrv_major = MAJOR(devno);
1237 printk(KERN_ERR "[CGX|%s] alloc_chrdev_region, cgxdrv_major=%d \r\n", __FUNCTION__, cgxdrv_major);
1241 printk(KERN_ERR MODULE_NAME " Error can't get major %d\r\n", cgxdrv_major);
1245 if ( CgxDriverConstruct(&DrvContext, &DrvContext.state) != ECgOk ) {
1246 DBGMSG("CgxDriverConstruct Failed");
1251 // Device is ready... Activate it
1252 cdev_init(&DrvContext.cdev, &cgx_fops);
1253 DrvContext.cdev.owner = THIS_MODULE;
1254 DrvContext.cdev.ops = &cgx_fops;
1255 rv = cdev_add (&DrvContext.cdev, devno, 1);
1258 DBGMSG1(" Error %d adding cgxdrv device\r\n", rv);
1262 /* Create the device class. */
1263 gps_class = class_create(THIS_MODULE, "cgxdrv_class");
1264 if (IS_ERR(gps_class))
1266 DBGMSG(" Error: create cgxdrv class failed\r\n");
1270 gps_class->suspend = CGX_PMSuspend;
1271 gps_class->resume = CGX_PMResume;
1273 /* register in /dev */
1274 gps_dev = device_create(gps_class, NULL, devno, NULL, "cgxdrv");
1275 if (IS_ERR(gps_dev))
1277 DBGMSG(" Error: device_create failed\r\n");
1278 class_destroy(gps_class);
1281 DBGMSG1(" Driver Ready... Major DevId: %d", cgxdrv_major );
1282 DBGMSG1(" Driver Byte order %d", CGX_DRIVER_NATIVE_BYTE_ORDER);
1288 * XXX-PK-XXX: FIXME: Add CgxDriverConstruct Cleanup
1289 * For example: free IRQs, destroy workqueues, etc.
1292 unregister_chrdev_region( devno, 1 );
1298 //======================================================================
1299 // CGX_Deinit - Driver de-initialization function
1301 static void __exit CGX_Deinit(void)
1303 printk(KERN_ERR "[CGX|%s] in\r\n", __FUNCTION__);
1305 // Free the driver state buffer.
1306 if (DrvContext.GpsIntr_irq != 0)
1308 free_irq(DrvContext.GpsIntr_irq, NULL);
1309 printk(KERN_ERR "free_irq GpsIntr_irq");
1312 if (DrvContext.DataReady_irq != 0)
1314 free_irq(DrvContext.DataReady_irq, NULL);
1315 printk(KERN_ERR "free_irq DataReady_irq");
1319 flush_workqueue(girq_wq);
1320 destroy_workqueue(girq_wq);
1321 printk(KERN_ERR "destroy_workqueue girq_wq");
1324 flush_workqueue(drdy_wq);
1325 destroy_workqueue(drdy_wq);
1326 printk(KERN_ERR "destroy_workqueue drdy_wq");
1329 #ifdef CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT
1330 if (drdy_completion_wq) {
1331 printk(KERN_ERR "CGX_Deinit (1)");
1332 //flush_workqueue(drdy_completion_wq); //commented for debug, because this function blocks !
1333 //destroy_workqueue(drdy_completion_wq);
1334 printk(KERN_ERR "CGX_Deinit (2)");
1338 DrvContext.state.request.terminate = TRUE;
1339 if(DrvContext.chunk.ptr) {
1340 BOOL boo = FreePhysMem(DrvContext.chunk.ptr);
1343 printk(KERN_ERR "CGX_Deinit (3)");
1345 //free_irq(TEMPLATE_CPU_DMA_IRQ, NULL);
1347 #ifndef CGCORE_ACCESS_VIA_SPI
1348 sprd_put_rf2351_ops(&gps_rf_ops);
1350 CgxDriverFreeInternalBuff(&DrvContext, 0);
1352 cdev_del(&DrvContext.cdev);
1354 device_destroy(gps_class, MKDEV(cgxdrv_major, 0));
1355 class_destroy(gps_class);
1357 unregister_chrdev_region(MKDEV(cgxdrv_major, 0), 1);
1358 #ifdef CGCORE_ACCESS_VIA_SPI
1361 printk(KERN_ERR "CGX_Deinit out");
1365 late_initcall(CGX_Init);
1366 module_exit(CGX_Deinit);
1369 MODULE_LICENSE("GPL and additional rights");
1370 MODULE_AUTHOR("Pablo 'merKur' Kohan <pablo@ximpo.com> - for CellGuide Ltd.");
1371 MODULE_DESCRIPTION("CellGuide GPSense CGX3XXX/CGX5XXX GPS CoProcessor driver");