From 8e4bff4cab0ddac6060645b0715210484d02ff40 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Wed, 30 Aug 2017 08:25:59 +0000 Subject: Initial file dump from open source release --- drivers/misc/gpsip/Kconfig | 23 + drivers/misc/gpsip/Makefile | 2 + drivers/misc/gpsip/VirtualCom/Makefile | 53 + drivers/misc/gpsip/VirtualCom/README.txt | 9 + drivers/misc/gpsip/VirtualCom/bld.sh | 28 + drivers/misc/gpsip/VirtualCom/virt_uart.c | 666 +++++++++ drivers/misc/gpsip/cgdriver/CgBuildNumber.h | 7 + drivers/misc/gpsip/cgdriver/CgCpu.c | 180 +++ drivers/misc/gpsip/cgdriver/CgCpu.h | 1644 +++++++++++++++++++++ drivers/misc/gpsip/cgdriver/CgCpuLinux.c | 229 +++ drivers/misc/gpsip/cgdriver/CgCpuOs.h | 176 +++ drivers/misc/gpsip/cgdriver/CgReturnCodes.h | 172 +++ drivers/misc/gpsip/cgdriver/CgTypes.h | 227 +++ drivers/misc/gpsip/cgdriver/CgVersion.h | 72 + drivers/misc/gpsip/cgdriver/CgxDriverApi.h | 436 ++++++ drivers/misc/gpsip/cgdriver/CgxDriverCore.c | 819 ++++++++++ drivers/misc/gpsip/cgdriver/CgxDriverCore.h | 255 ++++ drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c | 441 ++++++ drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.h | 66 + drivers/misc/gpsip/cgdriver/CgxDriverLinux.c | 1373 +++++++++++++++++ drivers/misc/gpsip/cgdriver/CgxDriverOs.h | 206 +++ drivers/misc/gpsip/cgdriver/CgxDriverPlatform.h | 138 ++ drivers/misc/gpsip/cgdriver/Makefile | 98 ++ drivers/misc/gpsip/cgdriver/gps_dma.c | 302 ++++ drivers/misc/gpsip/cgdriver/gps_dma.h | 89 ++ drivers/misc/gpsip/cgdriver/gps_gpio.c | 201 +++ drivers/misc/gpsip/cgdriver/gpsspi.c | 459 ++++++ drivers/misc/gpsip/cgdriver/platform.c | 770 ++++++++++ drivers/misc/gpsip/cgdriver/platform.h | 250 ++++ 29 files changed, 9391 insertions(+) create mode 100644 drivers/misc/gpsip/Kconfig create mode 100644 drivers/misc/gpsip/Makefile create mode 100644 drivers/misc/gpsip/VirtualCom/Makefile create mode 100644 drivers/misc/gpsip/VirtualCom/README.txt create mode 100644 drivers/misc/gpsip/VirtualCom/bld.sh create mode 100644 drivers/misc/gpsip/VirtualCom/virt_uart.c create mode 100644 drivers/misc/gpsip/cgdriver/CgBuildNumber.h create mode 100644 drivers/misc/gpsip/cgdriver/CgCpu.c create mode 100644 drivers/misc/gpsip/cgdriver/CgCpu.h create mode 100644 drivers/misc/gpsip/cgdriver/CgCpuLinux.c create mode 100644 drivers/misc/gpsip/cgdriver/CgCpuOs.h create mode 100644 drivers/misc/gpsip/cgdriver/CgReturnCodes.h create mode 100644 drivers/misc/gpsip/cgdriver/CgTypes.h create mode 100644 drivers/misc/gpsip/cgdriver/CgVersion.h create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverApi.h create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverCore.c create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverCore.h create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.c create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.h create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverLinux.c create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverOs.h create mode 100644 drivers/misc/gpsip/cgdriver/CgxDriverPlatform.h create mode 100644 drivers/misc/gpsip/cgdriver/Makefile create mode 100644 drivers/misc/gpsip/cgdriver/gps_dma.c create mode 100644 drivers/misc/gpsip/cgdriver/gps_dma.h create mode 100644 drivers/misc/gpsip/cgdriver/gps_gpio.c create mode 100644 drivers/misc/gpsip/cgdriver/gpsspi.c create mode 100644 drivers/misc/gpsip/cgdriver/platform.c create mode 100644 drivers/misc/gpsip/cgdriver/platform.h (limited to 'drivers/misc/gpsip') diff --git a/drivers/misc/gpsip/Kconfig b/drivers/misc/gpsip/Kconfig new file mode 100644 index 00000000..8e631144 --- /dev/null +++ b/drivers/misc/gpsip/Kconfig @@ -0,0 +1,23 @@ +config CGX + bool "Sprd gps" + default n + help + GPS can locate you position + +config CGX_DRIVER + tristate "Sprd gps driver" + depends on CGX + help + GPS can locate you position + +config CGX_VIRTUALCOM + tristate "Sprd gps virtual com" + depends on CGX + help + GPS can locate you position + +config CGX_GE_GPS + tristate "Sprd greeneye gps use spi interface" + depends on CGX + help + GPS can locate you position diff --git a/drivers/misc/gpsip/Makefile b/drivers/misc/gpsip/Makefile new file mode 100644 index 00000000..e526efd0 --- /dev/null +++ b/drivers/misc/gpsip/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_CGX_DRIVER) += cgdriver/ +obj-$(CONFIG_CGX_VIRTUALCOM) += VirtualCom/ diff --git a/drivers/misc/gpsip/VirtualCom/Makefile b/drivers/misc/gpsip/VirtualCom/Makefile new file mode 100644 index 00000000..578b7b23 --- /dev/null +++ b/drivers/misc/gpsip/VirtualCom/Makefile @@ -0,0 +1,53 @@ +############################################################################### +# 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 + + +ANDROID_NDK_ROOT := $(ROOT)/android/ndk +ANDROID_SDK_ROOT := $(ROOT)/android/sdk +PATH := $(PREBUILD)/bin:$(PATH) + +obj-$(CONFIG_CGX_VIRTUALCOM) := cgvuart.o + +# C Object Files: +cgvuart-c-objs += virt_uart.o +cgvuart-objs += $(cgvuart-c-objs) + +# EXTRA_CFLAGS += -I$(PWD) + + +ifeq ($(KERNELRELEASE),) +# on first call from remote location we get into this path +# whilst on second call all is managed by the embedding kernel makefile + +cgvuart-cfiles = ${cgvuart-c-objs:.o=.c} + +default:: kmod_build + +kmod_build:: $(cgvuart-cfiles) $(cgvuart-hdrs) + $(MAKE) -C $(CG_KERNEL_DIR) SUBDIRS=$(CURDIR) modules + +# distclean:: clean + +clean:: + rm -f *.o *.ko .*.cmd cgvuart.mod.c + rm -rf .tmp_versions + +tags:: + $(MAKE) -C $(CG_KERNEL_DIR) SUBDIRS=$(CURDIR) tags +endif + +# ### EOF ### diff --git a/drivers/misc/gpsip/VirtualCom/README.txt b/drivers/misc/gpsip/VirtualCom/README.txt new file mode 100644 index 00000000..4598a116 --- /dev/null +++ b/drivers/misc/gpsip/VirtualCom/README.txt @@ -0,0 +1,9 @@ +This is what is needed, in order to build the cgvuart driver : + +1. edit bld.sh, and change the following exports: + a. ROOT holds under it, "/android/ndk/" and "/android/sdk". + b. CG_KERNEL_DIR holds under it, the kernel source tree + c. Set ARCH=arm + d. Set CROSS_COMPILE= + An example : $ export CROSS_COMPILE="/home/cellguide/android/froyo/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-" +2. Run bld.sh diff --git a/drivers/misc/gpsip/VirtualCom/bld.sh b/drivers/misc/gpsip/VirtualCom/bld.sh new file mode 100644 index 00000000..7fdf4194 --- /dev/null +++ b/drivers/misc/gpsip/VirtualCom/bld.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +export ROOT=/home/cellguide +export CG_KERNEL_DIR=/home/cellguide/android/kernel/Telechips/tcc8900_2010_06_22/kernel +export ARCH=arm +export CROSS_COMPILE=/home/cellguide/android/froyo/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi- +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +echo +make -f Makefile $* diff --git a/drivers/misc/gpsip/VirtualCom/virt_uart.c b/drivers/misc/gpsip/VirtualCom/virt_uart.c new file mode 100644 index 00000000..780fa454 --- /dev/null +++ b/drivers/misc/gpsip/VirtualCom/virt_uart.c @@ -0,0 +1,666 @@ +/****************************************************************************** + * 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 */ + +#define __VIRT_UART_C__ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "virt_uart" +#define DRIVER_NAME "virt_uart" +#define DEVICE_NAME "ttyV" + +/* 0 = dynamic major */ +#define XVU_MAJOR 0 + +/* Number of Virtual UART pairs */ +#define XVU_PAIRS 1 + +#define XVU_ERR( fmt, arg...) do { printk(KERN_ERR MODULE_NAME " %s:%d [%s]... " fmt, __FILE__, __LINE__, __func__, ## arg ); } while (0) + +#if defined(CGTEST) || defined(DEBUG) +# define XVU_DBG( fmt, arg...) do { printk(KERN_ERR MODULE_NAME " %s:%d [%s]... " fmt, __FILE__, __LINE__, __func__, ## arg ); } while (0) +#else +# define XVU_DBG( fmt, arg...) do { } while (0) +#endif + +typedef struct xvu_endpoint_s { + int open_count; + struct tty_struct *tty; + int mcr; /* Modem Control Register */ + int msr; /* Modem Status Register */ + wait_queue_head_t msr_wait; + spinlock_t sercnt_lock; + struct serial_icounter_struct ser_cnt; +} xvu_endpoint_t; + +typedef struct xvu_dev_s { + struct semaphore sem; + xvu_endpoint_t endpoint[XVU_PAIRS * 2]; +} xvu_dev_t; + + +static struct tty_driver *xvu_ttydriver = NULL; +static xvu_dev_t xvu_dev; +static struct tty_port xvu_port[2]; + + +#define __XVU_GetPeerIdx(idx) ( (idx) ^ 0x01 ) + +//bxd +#define init_MUTEX(sem) sema_init(sem, 1) + +/* + * __XVU_SetMSR + * + * This sets the MSR (Modem Status Register), upon its peer's MCR (Modem Control + * Register). + * It also updates counters accordingly, and awakes potential TIOCMIWAITers. + * **** It should be called with the xvu_dev.sem held ! **** + */ +static void __XVU_SetMSR( unsigned int idx ) +{ + unsigned int peermcr = 0; + unsigned int oldmsr = 0; + unsigned int msr = 0; + unsigned long flags = 0; + + peermcr = xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].mcr; + msr = oldmsr = xvu_dev.endpoint[idx].msr; + + XVU_DBG( "msr[%d] = 0x%08x\n", idx, msr ); + + /* Peer is closed, set msr to 0 */ + if ( !xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].open_count) { + XVU_DBG( "Peer(%d) is closed... Setting msr as 0\n", __XVU_GetPeerIdx(idx) ); + msr = 0; + goto out; + } + + /* + * Peer is open. + * Update MSR upon peer's MCR + */ + if ( peermcr & TIOCM_DTR ) + msr |= (TIOCM_DSR | TIOCM_CAR); + else + msr &= ~(TIOCM_DSR | TIOCM_CAR); + + if ( peermcr & TIOCM_RTS ) + msr |= (TIOCM_CTS); + else + msr &= ~(TIOCM_CTS); + +out: + xvu_dev.endpoint[idx].msr = msr; + + /* Mask transitions (unchanged bits will be 0) */ + msr ^= oldmsr; + if (msr) { + XVU_DBG( "Transitioning...\n" ); + /* Update counters for TIOCGICOUNT */ + spin_lock_irqsave(&xvu_dev.endpoint[idx].sercnt_lock, flags); + if ( msr & TIOCM_DSR ) xvu_dev.endpoint[idx].ser_cnt.dsr++; + if ( msr & TIOCM_CAR ) xvu_dev.endpoint[idx].ser_cnt.dcd++; + if ( msr & TIOCM_CTS ) xvu_dev.endpoint[idx].ser_cnt.cts++; + spin_unlock_irqrestore(&xvu_dev.endpoint[idx].sercnt_lock, flags); + + /* MSR changed. Awake TIOCMIWAITers */ + wake_up_interruptible(&xvu_dev.endpoint[idx].msr_wait); + } +} + + +/* + * __XVU_SetMCR + * + * This sets the MCR (Modem Control Register), and updates its peer's MSR (Modem + * Status Register). + * **** It should be called with the xvu_dev.sem held ! **** + */ +static void __XVU_SetMCR( unsigned int idx, unsigned int val ) +{ + /* Set MSR */ + xvu_dev.endpoint[idx].mcr = val; + + XVU_DBG( "Setting MCR[%d]=0x%08x\n", idx, val ); + + /* Update peer's MSR */ + __XVU_SetMSR( __XVU_GetPeerIdx(idx) ); +} + +static int XVU_write(struct tty_struct *tty, const unsigned char *buffer, + int count) +{ + int idx = 0; + struct tty_struct *peer = NULL; + int rv = -EINVAL; + unsigned long flags = 0; + + if (down_interruptible(&xvu_dev.sem)) + return -ERESTARTSYS; + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + goto out; + } + + if (buffer == NULL) { + XVU_ERR( "Invalid (NULL) buffer\n"); + goto out; + } + + if (count <= 0 ) { + XVU_ERR( ": Invalid count = 0\n"); + goto out; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( "Index %d out of range.\n", idx); + goto out; + } + + + /* Is endpoint open ? */ + if (! xvu_dev.endpoint[idx].open_count ) { + XVU_ERR( "Endpoint %d doesn't seem to be open.\n", idx); + goto out; + } + + /* + * Send string to peer + * If peer is closed, discard the string... + * ...but return count as if we sent it. + */ + + /* Is peer open ? */ + if (! xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].open_count ) { + /* Discard sent bytes ! */ + rv = count; + goto out; + } + + /* Safety ! Shouldn't happen !!! */ + peer = xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].tty; + if (! peer ) { + /* Discard sent bytes ! */ + XVU_ERR( "endpoint[%d].tty is NULL\n", __XVU_GetPeerIdx(idx)); + rv = count; + goto out; + } + + rv = tty_buffer_request_room(tty->port, count); + if (unlikely(rv == 0)) { + XVU_ERR("tty_buffer_request_room rv:%d\n",rv); + } + rv = tty_insert_flip_string(peer->port, buffer, count); + tty_schedule_flip(peer->port); + +out: + /* Update counters */ + if (rv > 0) { + spin_lock_irqsave(&xvu_dev.endpoint[idx].sercnt_lock, flags); + xvu_dev.endpoint[ idx ].ser_cnt.tx += rv; + spin_unlock_irqrestore(&xvu_dev.endpoint[idx].sercnt_lock, flags); + + spin_lock_irqsave(&xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].sercnt_lock, flags); + xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].ser_cnt.rx += rv; + spin_unlock_irqrestore(&xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].sercnt_lock, flags); + } + + up(&xvu_dev.sem); + return rv; +} + + +static int XVU_open(struct tty_struct *tty, struct file *filp) +{ + int idx = 0; + int rv = -EINVAL; + int idx2 = 0; + + if (down_interruptible(&xvu_dev.sem)) + return -ERESTARTSYS; + + if (tty == NULL) { + XVU_ERR( ": Invalid (NULL) tty_struct\n"); + goto out; + } + + idx = tty->index; + idx2 = (int)(idx/2); + + if ( (idx<0) || (idx >= XVU_PAIRS*2) ) { + XVU_ERR( "Index %d out of range.\n", idx); + goto out; + } + + tty->driver_data = (void *)idx; + + /* Safety ! Shouldn't happen !!! */ + if ( (xvu_dev.endpoint[idx].tty) && (xvu_dev.endpoint[idx].tty != tty) ) { + XVU_ERR( "Endpoint[%d].tty=%p != tty=%p\n", + idx, xvu_dev.endpoint[idx].tty, tty); + } + + xvu_dev.endpoint[idx].tty = tty; + xvu_dev.endpoint[idx].open_count++; + + XVU_DBG( "Opening %d(count=%d)... TTY=%p\n", idx, xvu_dev.endpoint[idx].open_count, tty ); + + __XVU_SetMCR(idx, TIOCM_DTR | TIOCM_RTS); + rv = 0; + +out: + up(&xvu_dev.sem); + + + return rv; +} + + +static void XVU_close(struct tty_struct *tty, struct file *filp) +{ + int idx = 0; + int idx2 = 0; + down(&xvu_dev.sem); + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + goto out; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( "Index %d out of range.\n", idx); + goto out; + } + + /* Is endpoint open ? */ + if (! xvu_dev.endpoint[idx].open_count ) { + XVU_ERR( "Endpoint %d doesn't seem to be open.\n", idx); + goto out; + } + + XVU_DBG( "Closing %d\n", idx ); + xvu_dev.endpoint[idx].open_count--; + + idx2 = (int)(idx/2); + if ((xvu_dev.endpoint[idx2].open_count <= 0) && (xvu_dev.endpoint[idx2+1].open_count <= 0)) { + /* No more users holding this device */ + XVU_ERR( "No more users holding this device\n"); + xvu_dev.endpoint[idx].tty = NULL; + wake_up_interruptible(&xvu_dev.endpoint[idx].msr_wait); + __XVU_SetMCR(idx, 0); + } + +out: + up(&xvu_dev.sem); +} + + +static int XVU_write_room(struct tty_struct *tty) +{ + int idx = 0; + struct tty_struct *peer = NULL; + struct tty_buffer *b = NULL; + unsigned long flags = 0; + int rv = -EINVAL; + + down(&xvu_dev.sem); + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + goto out; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( "Index %d out of range.\n", idx); + goto out; + } + + /* is endpoint open ? */ + if (! xvu_dev.endpoint[idx].open_count ) { + XVU_ERR( "Endpoint %d doesn't seem to be open.\n", idx); + goto out; + } + + /* Is peer open ? */ + if (! xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].open_count ) { + /* We'll discard sent bytes anyway, so... lie ! */ + rv = 255; + goto out; + } + + /* Safety ! Shouldn't happen !!! */ + peer = xvu_dev.endpoint[__XVU_GetPeerIdx(idx)].tty; + if (! peer ) { + /* We'll discard sent bytes anyway, so... lie ! */ + XVU_ERR( "Endpoint[%d].tty is NULL\n", __XVU_GetPeerIdx(idx)); + rv = 255; + goto out; + } + + /* + * Calculate how much room is left in the peer buffer + */ + spin_lock_irqsave(&peer->port->buf.lock, flags); + + b = peer->port->buf.tail; + if (b != NULL) + rv = b->size - b->used; + else + rv = 0; + + spin_unlock_irqrestore(&peer->port->buf.lock, flags); + +out: + up(&xvu_dev.sem); + + return rv; +} + + +/* + * Needed to avoid Oops on poll ! + */ +static int XVU_chars_in_buffer(struct tty_struct *tty) +{ + return 0; +} + + +//static int XVU_tiocmget(struct tty_struct *tty, struct file *filp) +static int XVU_tiocmget(struct tty_struct *tty) +{ + int idx = 0; + int rv = -EINVAL; + + if (down_interruptible(&xvu_dev.sem)) + return -ERESTARTSYS; + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + goto out; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( ": Index %d out of range.\n", idx); + goto out; + } + + rv = (xvu_dev.endpoint[idx].mcr | xvu_dev.endpoint[idx].msr); + + XVU_DBG( "In tiocmget(%d) returning: 0x%08x\n", idx, rv ); + +out: + up(&xvu_dev.sem); + + return rv; +} + + +//static int XVU_tiocmset(struct tty_struct *tty, struct file *filp, +// unsigned int set, unsigned int clear) +static int XVU_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) + +{ + int idx = 0; + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + return -EINVAL; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( "Index %d out of range.\n", idx); + return -EINVAL; + } + + /* Only accept RTS and DTR flag changes */ + set &= (TIOCM_RTS | TIOCM_DTR); + clear &= (TIOCM_RTS | TIOCM_DTR); + + XVU_DBG( "In tiocmset(%d) SET=0x%08x CLR=0x%08x\n", idx, set, clear ); + + if (down_interruptible(&xvu_dev.sem)) + return -ERESTARTSYS; + __XVU_SetMCR( idx, ( (xvu_dev.endpoint[idx].mcr | set) & (~clear) ) ); + up(&xvu_dev.sem); + + return 0; +} + + +static int __XVU_tiocmiwait(struct tty_struct *tty, unsigned long arg) +{ + int idx = 0; + int rv= -EINVAL; + struct serial_icounter_struct cnow = {0}; + struct serial_icounter_struct cprev = {0}; + unsigned long flags = 0; + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + return -EINVAL; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( "Index %d out of range.\n", idx); + return -EINVAL; + } + + spin_lock_irqsave(&xvu_dev.endpoint[idx].sercnt_lock, flags); + cnow = xvu_dev.endpoint[idx].ser_cnt; + + XVU_DBG( "In tiocmiwait(%d) waiting: 0x%08lx now={CTS=%d, DCD=%d, RNG=%d, DSR=%d}\n", idx, arg, cnow.cts, cnow.dcd, cnow.rng, cnow.dsr ); + + spin_unlock_irqrestore(&xvu_dev.endpoint[idx].sercnt_lock, flags); + + rv = wait_event_interruptible( xvu_dev.endpoint[idx].msr_wait, ({ + cprev = cnow; + spin_lock_irqsave(&xvu_dev.endpoint[idx].sercnt_lock, flags); + cnow = xvu_dev.endpoint[idx].ser_cnt; + spin_unlock_irqrestore(&xvu_dev.endpoint[idx].sercnt_lock, flags); + + /* Device closed or serial counters changed */ + (xvu_dev.endpoint[idx].open_count == 0) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) || + ((arg & TIOCM_CAR) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)); + })); + + XVU_DBG( "In tiocmiwait(%d) done wait: 0x%08lx now={CTS=%d, DCD=%d, RNG=%d, DSR=%d}\n", idx, arg, cnow.cts, cnow.dcd, cnow.rng, cnow.dsr ); + + if (rv < 0) { + XVU_DBG( "In tiocmiwait(%d) rv=%d, returning: ERESTARTSYS\n", idx, rv ); + return -ERESTARTSYS; + } + + /* + * return -EIO if we were awoken by device being closed + */ + if (xvu_dev.endpoint[idx].open_count == 0) { + XVU_DBG( "In tiocmiwait(%d) returning: EIO\n", idx ); + return -EIO; + } + + return 0; +} + + +//static int XVU_ioctl(struct tty_struct *tty, struct file *filp, +// unsigned int cmd, unsigned long arg) +static int XVU_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) + +{ + int idx = 0; + struct serial_icounter_struct icnt = {0}; + unsigned long flags = 0; + + if (tty == NULL) { + XVU_ERR( "Invalid (NULL) tty_struct\n"); + return -EINVAL; + } + + idx = tty->index; + + if ( (idx<0) || (idx >= XVU_PAIRS*2) || (idx != (int)tty->driver_data) ) { + XVU_ERR( "Index %d out of range.\n", idx); + return -EINVAL; + } + + if (cmd == TIOCMIWAIT) + return __XVU_tiocmiwait( tty, arg ); + + if (cmd == TIOCGICOUNT) { + spin_lock_irqsave(&xvu_dev.endpoint[idx].sercnt_lock, flags); + icnt = xvu_dev.endpoint[idx].ser_cnt; + spin_unlock_irqrestore(&xvu_dev.endpoint[idx].sercnt_lock, flags); + + if ( copy_to_user( (void __user *)arg, &icnt, sizeof(icnt)) ) + return -EFAULT; + else + return 0; + } + + return -ENOIOCTLCMD; +} + + +static struct tty_operations serial_ops = { + open: XVU_open, + close: XVU_close, + write: XVU_write, + write_room: XVU_write_room, + chars_in_buffer: XVU_chars_in_buffer, + tiocmget: XVU_tiocmget, + tiocmset: XVU_tiocmset, + ioctl: XVU_ioctl, +}; + + +/* + * Module Initialization and Cleanup + */ +static int __init XVU_Init(void) +{ + int rv = -EINVAL; + int i = 0; + + memset(&xvu_dev, 0, sizeof(xvu_dev)); + init_MUTEX(&xvu_dev.sem); + for (i=0;iowner = THIS_MODULE; + xvu_ttydriver->driver_name = DRIVER_NAME; + xvu_ttydriver->name = DEVICE_NAME; + xvu_ttydriver->major = XVU_MAJOR; + xvu_ttydriver->minor_start = 0; + xvu_ttydriver->type = TTY_DRIVER_TYPE_SERIAL; + xvu_ttydriver->subtype = SERIAL_TYPE_NORMAL; + xvu_ttydriver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; + xvu_ttydriver->init_termios = tty_std_termios; + xvu_ttydriver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; + tty_set_operations(xvu_ttydriver, &serial_ops); + tty_port_link_device(&xvu_port[0], xvu_ttydriver, 0); + tty_port_link_device(&xvu_port[1], xvu_ttydriver, 1); + + /* register the tty driver */ + rv = tty_register_driver(xvu_ttydriver); + if (rv) { + printk(KERN_ERR MODULE_NAME ": Failed to register Virtual UART tty driver"); + put_tty_driver(xvu_ttydriver); + return rv; + } + + down(&xvu_dev.sem); + for (i=0;imajor ); + printk(KERN_INFO MODULE_NAME ": Created %d Virtual UARTs. /dev/ttyV0 -> /dev/ttyV%d\n", XVU_PAIRS*2, XVU_PAIRS*2 -1 ); + return 0; +} + + +static void __exit XVU_Deinit(void) +{ + int idx = 0; + + down(&xvu_dev.sem); + + /* Report unclosed pending endpoints (in case of forced unload) */ + for (idx = 0; idx < XVU_PAIRS * 2; idx++) + if ( xvu_dev.endpoint[idx].open_count ) + XVU_ERR( "Endpoint[%d].open_count=%d != 0\n", + idx, xvu_dev.endpoint[idx].open_count ); + + if (xvu_ttydriver) + tty_unregister_driver(xvu_ttydriver); + + put_tty_driver(xvu_ttydriver); + + up(&xvu_dev.sem); + + printk(KERN_INFO MODULE_NAME ": Virtual UART Device Unloaded...\n" ); +} + +module_init(XVU_Init); +module_exit(XVU_Deinit); + +MODULE_AUTHOR("Pablo 'merKur' Kohan "); +MODULE_DESCRIPTION("Virtual UART-pair"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/gpsip/cgdriver/CgBuildNumber.h b/drivers/misc/gpsip/cgdriver/CgBuildNumber.h new file mode 100644 index 00000000..ae99f989 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgBuildNumber.h @@ -0,0 +1,7 @@ +/* this file is automatically updated on build - DO NOT CHANGE! */ + +#define CG_BUILD_NUMBER "13" +#define CG_BUILD_DATE "12/08/2012" +#define CG_BUILD_TIME "18:56:47" +#define CG_BUILD_VERSION "1.8.9/3686" +#define CG_BUILD_ORIGINATOR "Koby" diff --git a/drivers/misc/gpsip/cgdriver/CgCpu.c b/drivers/misc/gpsip/cgdriver/CgCpu.c new file mode 100644 index 00000000..955ba980 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgCpu.c @@ -0,0 +1,180 @@ +/****************************************************************************** + * 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 code + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + +*/ + +#include +#include +#include "CgxDriverCore.h" +#include "CgCpu.h" +// Swap helper functions +TCgByteSwapType CgGetByteSwapTypeU32(TCgByteOrder aFrom, TCgByteOrder aTo); +void * CgGetSwapFunctionU32(TCgByteSwapType type); + + +static const U32 fullMask[32] = { + 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, + 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, + 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, + 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, + 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, + 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; + +U32 CgGetU32Mask(U32 bitsInU32) +{ + return fullMask[bitsInU32]; +} + +TCgReturnCode CgSetRegisterBits(volatile U32 *aReg, TCgBitField aBitFieldDef, U32 aValue) +{ + + U32 value = aValue & fullMask[aBitFieldDef.length-1]; + U32 mask = (fullMask[aBitFieldDef.length-1]) & ~value; + + // clear + *aReg &= ~(mask << aBitFieldDef.start); + // set + *aReg |= (value << aBitFieldDef.start); + return ECgOk; +} + + +TCgReturnCode CgGetRegisterBits(volatile U32 aReg, TCgBitField aBitFieldDef, U32 *apValue) +{ + + *apValue = ((aReg) >> aBitFieldDef.start) & fullMask[aBitFieldDef.length-1]; + + return ECgOk; +} + + +TCgByteSwapType CgGetByteSwapTypeU32(TCgByteOrder aFrom, TCgByteOrder aTo) +{ + switch (aFrom){ + case ECG_BYTE_ORDER_1234 : + switch( aTo ){ + case ECG_BYTE_ORDER_1234 : return ECG_SWAP_NONE; + case ECG_BYTE_ORDER_2143 : return ECG_SWAP_BYTES; + case ECG_BYTE_ORDER_3412 : return ECG_SWAP_WORDS; + case ECG_BYTE_ORDER_4321 : return ECG_SWAP_BYTES_AND_WORDS; + } + break; + case ECG_BYTE_ORDER_2143 : + switch( aTo ){ + case ECG_BYTE_ORDER_1234 : return ECG_SWAP_BYTES; + case ECG_BYTE_ORDER_2143 : return ECG_SWAP_NONE; + case ECG_BYTE_ORDER_3412 : return ECG_SWAP_BYTES_AND_WORDS; + case ECG_BYTE_ORDER_4321 : return ECG_SWAP_WORDS; + } + break; + case ECG_BYTE_ORDER_3412 : + switch( aTo ) { + case ECG_BYTE_ORDER_1234 : return ECG_SWAP_WORDS; + case ECG_BYTE_ORDER_2143 : return ECG_SWAP_BYTES_AND_WORDS; + case ECG_BYTE_ORDER_3412 : return ECG_SWAP_NONE; + case ECG_BYTE_ORDER_4321 : return ECG_SWAP_BYTES; + } + break; + case ECG_BYTE_ORDER_4321 : + switch( aTo ) { + case ECG_BYTE_ORDER_1234 : return ECG_SWAP_BYTES_AND_WORDS; + case ECG_BYTE_ORDER_2143 : return ECG_SWAP_WORDS; + case ECG_BYTE_ORDER_3412 : return ECG_SWAP_BYTES; + case ECG_BYTE_ORDER_4321 : return ECG_SWAP_NONE; + } + break; + default : + return ECG_SWAP_NONE; + break; + } + + return ECG_SWAP_NONE; +} + + + +TCgReturnCode CgSwapBytesInBlock(void * aSource,void * aDest, long aSizeInBytes, TCgByteOrder aFrom, TCgByteOrder aTo) +{ + TCgReturnCode rc = ECgOk; + + long index = 0, sizeInDword = 0; + u32* source = NULL, * dest = NULL; + TCgByteSwapType swapType = CgGetByteSwapTypeU32(aFrom, aTo); + + sizeInDword = aSizeInBytes / 4; + source = (u32*)aSource; + dest = (u32*)aDest; + + switch (swapType) { + case ECG_SWAP_NONE : + break; + + case ECG_SWAP_BYTES : + for ( ; index < sizeInDword; index ++ ) + dest[index] = CgSwapBytesU32(source[index]); + break; + + case ECG_SWAP_WORDS : + for ( ; index < sizeInDword; index ++ ) + dest[index] = CgSwapWordsU32(source[index]); + break; + + case ECG_SWAP_BYTES_AND_WORDS : + for ( ; index < sizeInDword; index ++ ) + dest[index] = CgSwapBytesAndWordsU32(source[index]); + break; + } + + + return rc; +} + +TCgReturnCode CgCpuDelay(unsigned long aCount) +{ + volatile unsigned long cnt = 0; + volatile unsigned long z =2 ; + for(cnt = 0; cnt> aPin) & 0x0001) + +#define REG_GET2(aReg, aPin) \ + ((aReg >> (aPin/2)) & 0x0003) + +#define REG_GET4(aReg, aPin) \ + ((aReg >> (aPin/4)) & 0x000F) + +#define REG_GET8(aReg, aPin) \ + ((aReg >> (aPin/8)) & 0x00FF) + + +#define REG_SET(aReg, aOffset, aMask, aVal) {\ + U32 regval = ((aVal) << ((aOffset))); \ + U32 mask = ~((U32)aMask << ((aOffset))); \ + if ((aReg & ~mask) != regval) {\ + aReg &= (mask); \ + aReg |= regval; \ + }\ + } + +#define REG_SET1(aReg, aPin, aVal) {\ + U32 regval = ((aVal) << ((aPin))); \ + U32 mask = ~((U32)1 << ((aPin))); \ + if(aVal == 0) aReg &= (mask); \ + else aReg |= regval; \ + } + + +#define REG_SET2(aReg, aPin, aVal) {\ + U32 regval = ((aVal) << ((aPin)*2)); \ + U32 mask = ~((U32)3 << ((aPin)*2)); \ + if ((aReg & ~mask) != regval) {\ + aReg &= (mask); \ + aReg |= regval; \ + }\ + } + +#define REG_SET4(aReg, aPin, aVal) {\ + U32 regval = ((aVal) << ((aPin)*4)); \ + U32 mask = ~((U32)0xF << ((aPin)*4)); \ + if ((aReg & ~mask) != regval) {\ + aReg &= (mask); \ + aReg |= regval; \ + }\ + } + + +#define REG_SET8(aReg, aPin, aVal) {\ + U32 regval = ((aVal) << ((aPin)*8)); \ + U32 mask = ~((U32)0xFF << ((aPin)*8)); \ + if ((aReg & ~mask) != regval) {\ + aReg &= (mask); \ + aReg |= regval; \ + }\ +} + + +/*********************************************************** CLOCK *************************/ +/** \defgroup cg_cpu_clk Clock control + Define the API to access the CPU clock configuration. This API is used to enable/disable generated clocks + to required hardware units like SPI controller, UART controller etc. +*/ + + + + +/** + \ingroup cg_cpu_clk + Create access to 'clock' registers. + + \if OS_WCE + in windows CE, usually use VirtualAlloc/VirtualCopy to generate an access to the DMA registers. + \endif + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuClockCreate(void); + + +/** + \ingroup cg_cpu_clk + Destroy access to 'clock' registers + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuClockDestroy(void); + + +/** + \ingroup cg_cpu_clk + Enable the clock to specific CPU unit + Logical unit codes are defined per CPU. each unit may have sub-units. + + \attention Requires porting + + \param[in] aUnit Logical unit code to enable + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuClockEnable(U32 aUnit); + + +/** + \ingroup cg_cpu_clk + Disable the clock to specific CPU unit. + Logical unit codes are defined per CPU. Each unit may have sub-units. + + \attention Requires porting + + \param[in] aUnit Logical unit code to disable + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuClockDisable(U32 aUnit); + + +/*********************************************************** DMA ***************************/ + +/** + \section DMA_CH_CODE DMA channel code + code = DMA Controller code + channel number + + example: CG_CPU_DMA_CONTROLLER_0 + 4 ==> DMA controller 1, channel 4 +*/ +#define CG_CPU_DMA_CONTROLLER_0 (0x00000000) +#define CG_CPU_DMA_CONTROLLER_1 (0x00010000) +#define CG_CPU_DMA_CONTROLLER_2 (0x00020000) +#define CG_CPU_DMA_CONTROLLER_3 (0x00030000) +#define CG_CPU_DMA_CONTROLLER_4 (0x00040000) + +#define CG_DMA_CONTROLLER(ch) ((ch & 0xFFFF0000) >> 16) +#define CG_DMA_CHANNEL(ch) (ch & 0x0000FFFF) +#define CG_DMA_IS_VALID(ch) +/** DMA multi block mode + Defines the method of executing consecutive DMA transfers. + There are 3 different possible methods : + LLI - means that the DMA needs to be configured only once, and no extra tx commands should be issued + PENDING - means that after receiving the first GPS data interrupt, the DMA should issue the next task, so it is prepared for it. + NONE - means that the DMA should prepared for the next task, only after receiving the DMA interrupt for tx-done. +*/ + +#define CG_DRIVER_DMA_MULTI_BLOCK_MODE_NONE 0 +#define CG_DRIVER_DMA_MULTI_BLOCK_MODE_PENDING 1 +#define CG_DRIVER_DMA_MULTI_BLOCK_MODE_LLI 2 + +typedef struct { + U32 address; + U32 length; +} TCgCpuDmaTask; + + +/** \defgroup cg_cpu_dma DMA control + Define the API to access Direct Memory Access unit for specific CPU. +*/ + +/** + \ingroup cg_cpu_dma + Create access to DMA controller. + Depending on OS, CPU and platform implementation, this might require remapping physical + address space into virtual address space. However, on some systems the virtual address is + statically allocated, so this function should be left empty (for example, for Linux driver). + + In the CellGuide provided implementation, if \ref CG_DRIVER_DMA_BASE_VA is defined in platform.h, then + a static virtual address should be used, otherwise, the physical address (CG_DRIVER_DMA_BASE_PA) + is mapped to a virtual address. + + The function assigns gpDMA with the DMA controller virtual address. + + \if OS_WCE + \note in windows CE, usually use VirtualAlloc/VirtualCopy to generate an access to the DMA registers. + if a consist storage is needed, it should be global. + \endif + + \attention DMA channel number is a 'logical' number, a combination of the controller and channel, and + should be parsed before used directly with hardware registers + \note On some implementations, the CGsnap read port address is required for proper DMA setup, + and therefore it is passed as an argument. If it is not required, then it should be ignored, + but not removed from the function prototype. + + \param[in] dmaChannel : The DMA channel to create + \param[in] ipDataSourceAddress : The address of the IP, from which the DMA should read data + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaCreate(U32 dmaChannel, U32 ipDataSourceAddress); + + +/** + \ingroup cg_cpu_dma + Destroy DMA access + + \param[in] aDmaChannel Logical channel number + \param[in] aIpDataSourceAddress Address + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaDestroy(U32 aDmaChannel, U32 aIpDataSourceAddress); + + +/** + \ingroup cg_cpu_dma + Check if the DMA channel is ready for next operation. + + \param[in] aDmaChannel Logical channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success + \retval ECgBadArgument On invalid channel + \retval ECgBusy if not ready +*/ +TCgReturnCode CgCpuDmaIsReady(U32 aDmaChannel); + + + +/** + \ingroup cg_cpu_dma + Get the DMA channel current bytes count + + \param[in] aDmaChannel Channel number + \param[out] apCount Bytes count + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success + \retval ECgBadArgument On invalid channel + \retval ECgBusy When channel is not ready +*/ +TCgReturnCode CgCpuDmaCurCount(U32 aDmaChannel, U32 *apCount); + +/** + \ingroup cg_cpu_dma + Get the DMA channel requested bytes count + + \param[in] aDmaChannel Logical channel number + \param[out] apCount Bytes count + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success + \retval ECgBadArgument On invalid channel + \retval ECgBusy When channel is not ready +*/ +TCgReturnCode CgCpuDmaRequestedCount(U32 aDmaChannel, U32 *apCount); + +/** + \ingroup cg_cpu_dma + Wait for the DMA channel to finish its current transfer + + \param[in] aDmaChannel Logical channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success + \retval ECgBadArgument On invalid channel + \retval ECgBusy When channel is not ready +*/TCgReturnCode CgCpuDmaWaitFinish(U32 aDmaChannel); + + +/** + \ingroup cg_cpu_dma + Stop DMA channel + + \param[in] aDmaChannel Logical channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success + \retval ECgBadArgument On invalid channel +*/ +TCgReturnCode CgCpuDmaStop(U32 aDmaChannel); + + +/** + \ingroup cg_cpu_dma + Start the specified DMA channel. + The channel initialization (setting source, destination, etc) is done in another function. + + \param[in] aDmaChannelCode DMA channel code. + \ref DMA_CH_CODE + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success + \retval ECgBadArgument On invalid channel +*/ +TCgReturnCode CgCpuDmaStart(U32 aDmaChannelCode); + + +/** + \ingroup cg_cpu_dma + Configure DMA to write data to SPI + + \param pSource Source memory address to write from + \param aLength Number of bytes to write + \param aWriteDmaChannel DMA channel to use + \param aDeviceChannel SPI channel to use + + \note The function checks that the DMA channel selected is the right one for the SPI channel. + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaSetupToDevice(U32 pSource, U32 aLength, U32 aWriteDmaChannel, int aDeviceChannel); + + + + +/** + \ingroup cg_cpu_dma + Configure DMA to read data from SPI + + \param pTarget Source memory address to write to + \param aLength Number of bytes to transfer + \param aBlockLength Number of bytes in a block + \param aReadDmaChannel DMA channel to use for read + \param aWriteDmaChannel DMA channel to use for write + \param aDeviceChannel SPI channel to use + + \note if SPI has 'auto output' generator, there is no need to use the 'write' channel. + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaSetupFromDevice(U32 pTarget, U32 aLength, U32 aBlockLength, U32 aReadDmaChannel, U32 aWriteDmaChannel, int aDeviceChannel); + + + +/** + \ingroup cg_cpu_dma + Configure DMA to read data from CGsnap + + \param apDmaTask DMA tasks list + \param aDmaTaskCount Total number of DMA tasks + \param aDmaChannelCode DMA channel to use for read (\ref DMA_CH_CODE) + \param aDeviceCode Device code + + \note if SPI has 'auto output' generator, there is no need to use the 'write' channel. + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaSetupFromDeviceFirstTask(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aDmaChannelCode, U32 aDeviceCode); + + +/** + \ingroup cg_cpu_dma + Configure DMA to read data from SPI + + \param apDmaTask DMA tasks list + \param aDmaTaskCount Total number of DMA tasks + \param aActiveTaskIndex Active DMA task number + \param aDmaChannel DMA channel to use for read + \param aDeviceCode Device code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaSetupFromDeviceNextTask(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aActiveTaskIndex, U32 aDmaChannel, U32 aDeviceCode); + +/** + \ingroup cg_cpu_dma + Configure DMA to read data from GPS device. + This handles the initial transfer setup, and is called by the application prior to CgCpuDmaStart. + Configure DMA to read data from CGsnap. + - DMA source + - Device is CGsnap IP + - Address is 'aDeviceAddress' + - Non increment + - Use handshake + - Burst transfer (burst = 16 bytes) + - Word (32bit) transfer mode + - Enable interrupt at end of transfer + + If the FMA supports LLI (Linked List Interface), then a proper DMA tasks list should be generated from the generic + tasks list. + + \param apDmaTask DMA tasks list + Since the destination buffer maybe smaller than the transfer size, it is required to split the DMA + transfer into several DMA tasks. The destination of each task will take into consideration the buffer size. + The application sets the buffer size on init. + The application decides on transfer size, transfer task size and task destination address, for every transfer. + + For example, if the transfer size is 1500KB, and the buffer size is 500KB, and the task size is 100KB, + then there will be 15 transfer tasks, each of 100KB, and the destination addresses in each task will be 0, 100KB, 200KB, + 300KB, 400KB, 0KB, 100KB, etc. + + In case the DMAC supports LLI, all required tasks shall be set in the DMAC. + Otherwise, the tasks are stored temporarily, and will be used by CgCpuDmaSetupFromGpsNextTask. + + \param apDmaTask DMA tasks list (pairs of addresses and lengths) + \param aDmaTaskCount Total number of DMA tasks + \param aDmaChannel DMA channel to use for read (\ref DMA_CH_CODE) + \param aDeviceAddress Device address + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaSetupFromGps(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aDmaChannel, U32 aDeviceAddress); + + + + +/** + \ingroup cg_cpu_dma + Configure DMA to read next DMA task from GPS device. + This function is only required when the DMA controller does not support LLI + This function is only required when the DMA controller does not support LLI + This sets up the DMA to perform the 2nd and above transfer tasks, of the same transfer. + + In case the DMAC doesn't support LLI, this function is called by the the DMA interrupt handler, to set-up the + next transfer task. + Otherwise, this function is never called. + + + \param apDmaTask DMA tasks list (the same + \param aDmaTaskCount Total number of DMA tasks + \param aActiveTaskIndex Active DMA task number + \param aDmaChannel DMA channel to use for read + \param aDeviceAddress Device address + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDmaSetupFromGpsNextTask(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aActiveTaskIndex, U32 aDmaChannel, U32 aDeviceAddress); + +/*********************************************************** GPIO **************************/ +/** \defgroup cg_cpu_gpio GPIO control + Configure, set and read GPIO + + + CellGuide GPIO code is an abstract number, combination of group constant and pin number. + The number is translated to specific CPU values by specific implementation. +*/ + + +/** GPIO pin configuration modes */ +typedef enum { + ECG_CPU_GPIO_INPUT, /**< GPIO to act as input */ + ECG_CPU_GPIO_OUTPUT, /**< GPIO to act as output */ + ECG_CPU_GPIO_SPECIAL, /**< GPIO to act as special function */ + ECG_CPU_GPIO_FALLING_INT, /**< GPIO to act as falling edge interrupt*/ + ECG_CPU_GPIO_SPECIAL2, /**< GPIO to act as special function */ + ECG_CPU_GPIO_SPECIAL3, /**< GPIO to act as special function */ + ECG_CPU_GPIO_MODE___ +} TCgCpuGpioMode; + +/** GPIO pin configuration modes */ +typedef enum { + ECG_CPU_GPIO_PULL_NONE, /**< GPIO with no pull */ + ECG_CPU_GPIO_PULL_DOWN, /**< GPIO with pull down */ + ECG_CPU_GPIO_PULL_UP, /**< GPIO with pull up */ + ECG_CPU_GPIO_PULL___ +} TCgCpuGpioPull; + +/** + \ingroup cg_cpu_gpio + Create access to GPIO controller. + Depending on OS, CPU and platform implementation, this might require remapping physical + address space into virtual address space. However, on some systems the virtual address is + statically allocated, so this function should be left empty (for example, for Linux driver). + + In the 'standard' implementation, if CG_DRIVER_GPIO_BASE_VA is defined in platform.h, then + a static virtual address should be used, otherwise, the physical address (CG_DRIVER_GPIO_BASE_PA) + is mapped to a virtual address. + + The function assigns gpGpio with the GPIO controller virtual address. + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioCreate(void); + + +/** + \ingroup cg_cpu_gpio + Destroy access to GPIO controller. + The implementation depends on the method used for allocation (see CgCpuGpioCreate) + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioDestroy(void); + + +/** + \ingroup cg_cpu_gpio + Set a specific GPIO to 'output' mode and set it to '1' value + + \param[in] aPinCode GPIO pin code + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioSet(U32 aPinCode); + + +/** + \ingroup cg_cpu_gpio + Set a specific GPIO to 'output' mode and set it to '0' value + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \param[in] aPinCode GPIO pin code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioReset(U32 aPinCode); + + +/** + \ingroup cg_cpu_gpio + Set a specific GPIO to 'input' mode, read the value and return it + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \param[in] aPinCode GPIO pin code + \param[out] aPinValue current value + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioGet(U32 aPinCode, int *aPinValue); + + +/** + \ingroup cg_cpu_gpio + Return IRQ code for the specific GPIO pin + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \param[in] aPin GPIO pin code + \param[out] aCode IRQ code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioIntCode(U32 aPin, U32 *aCode); + + +/** + \ingroup cg_cpu_gpio + Set a specific GPIO mode + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \param[in] aPinCode GPIO pin code + \param[in] aPinMode Requested mode + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioModeSet(U32 aPinCode, TCgCpuGpioMode aPinMode); + +/** + \ingroup cg_cpu_gpio + + Set a specific GPIO strength + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \attention Not all CPUs support internal drive level. If the CPU does not support this feature, this function should be left empty. + + \param[in] aPinCode GPIO pin code + \param[in] aStrength Requested strength + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioStrength(U32 aPinCode, U32 aStrength); + +/** + \ingroup cg_cpu_gpio + Set a specific GPIO pull up/down + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \attention Not all CPUs support internal pull, if the CPU does not support this feature, this function should be left empty. + + \param[in] aPinCode GPIO pin code + \param[in] aPull Requested + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioPull(U32 aPinCode, TCgCpuGpioPull aPull); + +/** + \ingroup cg_cpu_gpio + Set a specific GPIO direction + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \param[in] aPinCode GPIO pin code + \param[in] aPinMode Requested mode + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioDirection(U32 aPinCode, TCgCpuGpioMode aPinMode); + + +/** + \ingroup cg_cpu_gpio + Clear interrupt bit + + \note Pin code is CellGuide internal code for each GPIO, which is a combination of the + GPIO group offset and the number inside the group. + + \param[in] aPinCode GPIO pin code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuGpioIntClear(U32 aPinCode); + +/*********************************************************** SPI ***************************/ +/** \defgroup cg_cpu_spi SPI control + SPI programming +*/ + + + + +/** + \ingroup cg_cpu_spi + Delay for specific time + + \param aCount + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuDelay(U32 aCount); + + +typedef enum { + ECG_CPU_SPI_INPUT_DMA, + ECG_CPU_SPI_INPUT_POLLING, + ECG_CPU_SPI_OUTPUT_DMA, + ECG_CPU_SPI_OUTPUT_POLLING, + ECG_CPU_SPI_INIT, + ECG_CPU_SPI_SLAVE_INPUT_DMA, + ECG_CPU_SPI_SLEEP, + ECG_CPU_SPI_MODE___ +} TCgCpuSpiMode; + + + +/** + \ingroup cg_cpu_spi + Create access to SPI + + \param[in] aChannelCode SPI Channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiCreate(U32 aChannelCode); + + +/** + \ingroup cg_cpu_spi + Destroy access to SPI + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiDestroy(void); + + +/** + \ingroup cg_cpu_spi + Enable SPI controller for specific channel + + \param[in] aDeviceChannel SPI Channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiEnable(int aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Disable SPI controller for specific channel + + \param[in] aDeviceChannel SPI Channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiDisable(int aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Check if SPI channel number is valid for the specific system + + \param[in] aDeviceChannel SPI Channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiIsValid(int aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Setup SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[in] aPrescale SPI clock divider + \param[in] aMode SPI mode + \param[in] aLengthBytes Number of bytes + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiConfig(U32 aDeviceChannel, U32 aPrescale, TCgCpuSpiMode aMode, U32 aLengthBytes); + +/** + \ingroup cg_cpu_spi + Setup SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[in] aLengthBytes Number of bytes + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiSlaveConfig(U32 aDeviceChannel, U32 aLengthBytes); + +/** + \ingroup cg_cpu_spi + Setup SPI channel GPIO + + \param[in] aDeviceChannel SPI channel number + \param[in] aPrescale SPI clock divider + \param[in] aMode SPI mode + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiSetup(U32 aDeviceChannel, U32 aPrescale, TCgCpuSpiMode aMode); + +/** + \ingroup cg_cpu_spi + Return number of words waiting in receive FIFO + + \param[in] aDeviceChannel SPI channel number + \param[out] pCount number of words (word width is according to config) + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiReadCount(U32 aDeviceChannel, U32 *pCount); + + +/** + \ingroup cg_cpu_spi + Loop until SPI write is finished. + + \param[in] aDeviceChannel SPI channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiTxFinishWait(U32 aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Rx FIFO is empty + + \param[in] aDeviceChannel SPI channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +BOOL CgCpuSpiRxFifoEmpty(U32 aDeviceChannel); + + +/** + \ingroup cg_cpu_spi + Clear SPI receive FIFO + + \param[in] aDeviceChannel SPI channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiClearFifo(U32 aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Loop until SPI read is finished. + + \param[in] aDeviceChannel SPI channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiRxFinishWait(U32 aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Read one byte from SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[out] aByte Data read from SPI + + \return Value read from SPI +*/ +TCgReturnCode CgCpuSpiReadByte(U32 aDeviceChannel, volatile unsigned char *aByte); + +/** + \ingroup cg_cpu_spi + Read one Word from SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[out] aValue Data read from SPI + + \return Value read from SPI +*/ +TCgReturnCode CgCpuSpiReadU16(U32 aDeviceChannel, volatile U16 *aValue); + +/** + \ingroup cg_cpu_spi + Read one DWord from SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[out] aValue Data read from SPI + + \return Value read from SPI +*/ +TCgReturnCode CgCpuSpiReadU32(U32 aDeviceChannel, volatile U32 *aValue); + +/** + \ingroup cg_cpu_spi + Read one byte from SPI channel (read 2nd FIFO byte) + + \param[in] aDeviceChannel SPI channel number + \param[out] aByte Data read from SPI + + \return Value read from SPI +*/ +TCgReturnCode CgCpuSpiReadByte2(U32 aDeviceChannel, volatile unsigned char *aByte); + + +/** + \ingroup cg_cpu_spi + Write one byte to SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[in] aValue Value to write + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiWriteByte(U32 aDeviceChannel, unsigned char aValue); + +/** + \ingroup cg_cpu_spi + Write one Word to SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[in] aValue Value to write + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiWriteU16(U32 aDeviceChannel, U16 aValue); + +/** + \ingroup cg_cpu_spi + Write one DWord to SPI channel + + \param[in] aDeviceChannel SPI channel number + \param[in] aValue Value to write + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiWriteU32(U32 aDeviceChannel, U32 aValue); + + +/** + \ingroup cg_cpu_spi + Return the GPIO code for selected SPI channel MOSI + + \param[in] aDeviceChannel channel number + \param[out] aGpioCode gpio code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiMosi(U32 aDeviceChannel, U32 *aGpioCode); + + +/** + \ingroup cg_cpu_spi + Return the GPIO number for selected SPI channel MISO + + \param[in] aDeviceChannel channel number + \param[out] aGpio gpio code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiMiso(U32 aDeviceChannel, U32 *aGpio); + + +/** + \ingroup cg_cpu_spi + Return the GPIO number for selected SPI channel CLK + + \param[in] aDeviceChannel channel number + \param[out] aGpio gpio code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiClk(U32 aDeviceChannel, U32 *aGpio); + + +/** + \ingroup cg_cpu_spi + Return the GPIO number for selected SPI channel CS (Chip Select) + + \param[in] aDeviceChannel channel number + \param[out] aGpio gpio code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiCs(U32 aDeviceChannel, U32 *aGpio); + + +/** + \ingroup cg_cpu_spi + Start DMA transaction + + \param[in] aDeviceChannel SPI Channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiDmaStart(int aDeviceChannel); + +/** + \ingroup cg_cpu_spi + Stop DMA transaction + + \param[in] aDeviceChannel SPI Channel number + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuSpiDmaStop(int aDeviceChannel); + + +/*********************************************************** INTR **************************/ +/** \defgroup cg_cpu_interrupt Interrupt control + Access to interrupt controller +*/ + +/** + \ingroup cg_cpu_interrupt + Create access to INTC controller. + Depending on OS, CPU and platform implementation, this might require remapping physical + address space into virtual address space. However, on some systems the virtual address is + statically allocated, so this function should be left empty (for example, for Linux driver). + + In the 'standard' implementation, if CG_DRIVER_INT_BASE_VA is defined in platform.h, then + a static virtual address should be used, otherwise, the physical address (CG_DRIVER_INT_BASE_PA) + is mapped to a virtual address. + + The function assigns pINT with the INT controller virtual address. + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIntrCreate(void); + +/** + \ingroup cg_cpu_interrupt + Destroy access to INTC + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIntrDestroy(void); + + +/** + \ingroup cg_cpu_interrupt + Register IRQ interrupt as OS interrupt + + \param[in] aIRQ requested IRQ interrupt code + \param[in] apOSIntCode requested software interrupt code + \param[out] apOSIntCode registered OS interrupt code + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIntrRequestOsInterrupt(U32 aIRQ, U32 *apOSIntCode); +/** + \ingroup cg_cpu_interrupt + Initialize interrupt + + \param[in] aRequestCode requested interrupt code (os specific) + \param[in] apEvent event to tie with interrupt + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIntrAttachEvent(U32 aRequestCode, void *apEvent); + +/** + \ingroup cg_cpu_interrupt + Disable registered interrupt + + \param[in] aInterruptCode interrupt code (os specific) + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIntrDisable(U32 aInterruptCode); + + +/** + \ingroup cg_cpu_interrupt + Signals to the kernel that interrupt processing has been completed + + \param[in] aInterruptCode interrupt code (os specific) + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ + +TCgReturnCode CgCpuIntrDone(U32 aInterruptCode); + + +/** Interrupt Service Thread information structure */ +typedef struct { + void *hThread; /**< Handle to thread object */ + U32 intCode; /**< Interrupt code */ + void *event; /**< Handle to Interrupt event */ + S32 priority; /**< Thread priority */ +} TCgCpuIST; + + +/** + \ingroup cg_cpu_interrupt + If apSharedISRInfo == NULL ===> Create and start interrupt service thread + Else ===> Initialize an event, and connect it to the EXISTING ISR + + \param[in] apIstInfo Thread info structure + \param[in] aFunc Main function for the thread + \param[in] aPriority Requested thread priority + \param[in] aIntCode Required interrupt code + \param[in] aIrqCode Required IRQ code (may be 0) + \param[in] aParam IST data structure pointer + \param[in] aEventName Event name to use for interrupt/IST communication + only need to supply name if the event is created by BSP. + for systems where the event is internally tied to specific GPI interrupt, + NULL can be set here + \param[in] apSharedISRInfo if the interrupt is shared, this will contain the info on + the shared interrupt + \param[in] apSharedISRLibrary if the interrupt is shared, this will indicate what library + holds the shared interrupt handler + \param[in] apSharedISR if the interrupt is shared, this will indicate the name of the + interrupt service routine + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuISTStart(TCgCpuIST *apIstInfo, void *aFunc, S32 aPriority, U32 aIntCode, U32 aIrqCode, + void *aParam, const char *aEventName, void * apSharedISRInfo, + const void * apSharedISRLibrary, const void * apSharedISR); + + +/** + \ingroup cg_cpu_interrupt + Stop interrupt service thread + + \param[in] apIstInfo Thread info structure + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuISTStop(TCgCpuIST *apIstInfo); + + + +/*********************************************************** RTC ***************************/ +/** \defgroup cg_cpu_rtc RTC control + Access to RTC +*/ + +/** + \ingroup cg_cpu_rtc + Create access to RTC controller by mapping it to virtual memory. + + \note On some operating systems (Linux) and platforms, this step is static, i.e., + the virtual address is pre defined. + CellGuide standard implementation of this function uses CG_DRIVER_RTC_BASE_VA + and CG_DRIVER_RTC_BASE_PA defines to select the proper method. + + \if OS_WCE + in windows CE, usually use VirtualAlloc/VirtualCopy to generate an access to the DMA registers. + if a consist storage is needed, it should be global. + \endif + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuRtcCreate(void); + + + +/** + \ingroup cg_cpu_rtc + Destroy access to RTC controller by un-mapping virtual memory. + + \note CellGuide standard implementation of this function uses CG_DRIVER_RTC_BASE_VA + and CG_DRIVER_RTC_BASE_PA defines to select the proper method. + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuRtcDestroy(void); + + +/** + \ingroup cg_cpu_rtc + RTC time structure +*/ +typedef struct { + U32 year; /**< Year (1970-2100) */ + U32 month; /**< Month in year (0-11) */ + U32 day; /**< Day in month (0-30) */ + U32 hour; /**< Hour in day (0-23) */ + U32 minute; /**< Minute in Hour (0-59) */ + U32 second; /**< Second in minute (0-59) */ + U32 dayInWeek; /**< Day in week (0-6) */ + U32 tick; /**< internal tick counter (units are CPU specific) */ +} TCgCpuRtcTime; + +/** + \ingroup cg_cpu_rtc + + Read current time from RTC unit + + \\attention Implementation is required + + \param[out] apTime Pointer to time structure + + \return System wide return code (see CgReturnCodes.h) + + \retval ECgOk On success +*/ +TCgReturnCode CgCpuRtcRead(TCgCpuRtcTime *apTime); + +/*********************************************************** RF control *************************/ + +/** \defgroup cg_cpu_rf RF functions*/ + +/** + \ingroup cg_cpu_rf + + Read one byte from RF control via specific protocol + \param[out] aValue Pointer to received byte + + \return system error code +*/ +TCgReturnCode CgCpuRFControlReadbyte(volatile unsigned char *aValue); + +/** + \ingroup cg_cpu_rf + + Write one byte to RF control via specific protocol + \param[in] aValue Byte to send + + \return system error code +*/ +TCgReturnCode CgCpuRFControlWriteByte(unsigned char aValue); + +/*********************************************************** Miscellanies *************************/ +/** \defgroup cg_cpu_miscellanies Miscellanies functions*/ + +/** + \ingroup cg_cpu_miscellanies + Get last error code for this unit + + \return system error code +*/ +U32 CgCpuLastErrorCode(void); + + + +/** + \ingroup cg_cpu_miscellanies + Clear CPU cache + + \param[in] pSource Source memory address + \param[in] aDmaChannel DMA channel + + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuClearCache(U32 pSource, U32 aDmaChannel); + + + +/** + \ingroup cg_cpu_miscellanies + Set bits in bit-field register + + \param[in] aReg pointer to register + \param[in] aBitFieldDef bit field definition + \param[in] aValue value to set + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgSetRegisterBits(volatile U32 *aReg, TCgBitField aBitFieldDef, U32 aValue); + +U32 CgGetU32Mask(U32 bitsInU32); + + +/** + \ingroup cg_cpu_miscellanies + Get bits from bit-field register + + \param[in] aReg register + \param[in] aBitFieldDef bit field definition + \param[in] apValue pointer to returned value + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgGetRegisterBits(volatile U32 aReg, TCgBitField aBitFieldDef, U32 *apValue); + +/** + \ingroup cg_cpu_miscellanies + Global virtual memory allocation. + This function is used on some platforms, where a global initialization of virtual memory is required. + It is called as one of the first initialization steps in CgxDriverConstruct. + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuAllocateVa(void); + +/** + Reset a CPU sub-unit + \param[in] aUnitIndex unit id (see specific CPU documentation) + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuReset(U32 aUnitIndex); + +/** + Set the CGsnap IP Master reset to 'reset' state (device is not active) + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIPMasterResetOn(void); + +/** + Set the CGsnap IP Master reset to 'clear' state (device is active) + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgCpuIPMasterResetClear(void); + +/** + Get CPU revision code. + \note Used mainly for debug. + + \param[out] apRevisionCode CPU revision code + + \return CPU revision information as null terminated text. +*/ +TCgReturnCode CgCpuRevision(char *apRevisionCode); + + +/** + byte and word swap + + \param[in] aSource Pointer to source buffer + \param[out] aDest Pointer to destination buffer + \param[in] aSizeInBytes Size of memory, in bytes + \param[in] aFrom Source byte order + \param[in] aTo Destination byte order + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk On success +*/ +TCgReturnCode CgSwapBytesInBlock(void * aSource,void * aDest, long aSizeInBytes, TCgByteOrder aFrom, TCgByteOrder aTo); + + +#if defined(CGTEST) || defined(DEBUG) + #define TRACE_ON +#endif +#define TRACE_ON + +/** + Debug facility - to show error messages +*/ +#ifdef TRACE_ON + TCgReturnCode CgxCpuMsg(const char *aFuncName, const char *aFileName, U32 aLineNum, char *aFormat, ...); + TCgReturnCode CgxCpuPrint(char *aText); + #define DBG_FUNC_NAME(name) const char *__funcname__ = name; + #define DBGMSG(format) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format); + #define DBGMSG1(format,a) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a); + #define DBGMSG2(format,a,b) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b); + #define DBGMSG3(format,a,b,c) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c); + #define DBGMSG4(format,a,b,c,d) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c,d); + #define DBGMSG5(format,a,b,c,d,e) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c,d,e); + #define DBGMSG6(format,a,b,c,d,e,f) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c,d,e,f); + #define DBGMSG7(format,a,b,c,d,e,f,g) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c,d,e,f,g); + #define DBGMSG8(format,a,b,c,d,e,f,g,h) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c,d,e,f,g,h); + #define DBGMSG9(format,a,b,c,d,e,f,g,h,i) CgxCpuMsg(__funcname__, __FILE__, __LINE__, format, a,b,c,d,e,f,g,h,i); + #define DBGDONE {DBGMSG("Done");} + #define DBGSTAT(title,s) {DbgStat##s(title);} + +#else + #define DBG_FUNC_NAME(name) + #define DBGMSG(format) do {} while(0) + #define DBGMSG1(format,a) do {} while(0) + #define DBGMSG2(format,a,b) do {} while(0) + #define DBGMSG3(format,a,b,c) do {} while(0) + #define DBGMSG4(format,a,b,c,d) do {} while(0) + #define DBGMSG5(format,a,b,c,d,e) do {} while(0) + #define DBGMSG6(format,a,b,c,d,e,f) do {} while(0) + #define DBGMSG7(format,a,b,c,d,e,f,g) do {} while(0) + #define DBGMSG8(format,a,b,c,d,e,f,g,h) do {} while(0) + #define DBGMSG9(format,a,b,c,d,e,f,g,h,i) do {} while(0) + #define DBGDONE do {} while(0) + #define DBGSTAT(title,s) do {} while(0) +#endif + +#define CgSwapBytesU32( aSource )\ + (((0xFF00FF00 & aSource) >> 8) | ((0x00FF00FF & aSource) << 8)) + + +#define CgSwapWordsU32( aSource )\ + (((0xFFFF0000 & aSource) >> 16) | ((0x0000FFFF & aSource) << 16)) + + +#define CgSwapBytesAndWordsU32( aSource )\ + ( CgSwapWordsU32(CgSwapBytesU32(aSource)) ) + +#ifdef TRACE_ON + #define DBGERR(rc) if (!OK(rc)) { DBGMSG3("Error : (%ld) [%s:%d]", rc, __FILE__, __LINE__); } +#else + #define DBGERR(rc)do {} while(0) +#endif + + +#ifdef TRACE_ON + void DbgStatSPI(const char *aTitle); + void DbgStatDMA(const char *aTitle); + void DumpGpioState(U32 aGpio); +#else + #define DbgStatSPI(x) do {} while(0) + #define DbgStatDMA(x) do {} while(0) + #define DumpGpioState(x) do {} while(0) +#endif + + +// =========================================================================== +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif diff --git a/drivers/misc/gpsip/cgdriver/CgCpuLinux.c b/drivers/misc/gpsip/cgdriver/CgCpuLinux.c new file mode 100644 index 00000000..7dc9f6b7 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgCpuLinux.c @@ -0,0 +1,229 @@ +/****************************************************************************** + * 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 */ + +/** + \cond OS_LINUX +*/ + + +/** + \file + \brief Linux implementation of OS depended CellGuide CPU API + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + + + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "CgCpuOs.h" +#include "CgCpu.h" +#include "platform.h" + + + + + + +TCgReturnCode CgCpuIntrDone(U32 aInterruptCode) +{ + TCgReturnCode rc = ECgOk; + //InterruptDone(aInterruptCode); + return rc; +} + + + +TCgReturnCode CgCpuVirtualAllocate(volatile void **pObject, unsigned long aBaseAddr, unsigned long aSize) +{ + ASSERT_NOT_NULL(pObject); + + *pObject = ioremap_nocache(aBaseAddr, aSize); + + return (*pObject != NULL) ? ECgOk : ECgErrMemory; +} + + +TCgReturnCode CgCpuVirtualFree(volatile void **pObject) +{ + ASSERT_NOT_NULL(pObject); + + iounmap((void *)*pObject); + *pObject = NULL; + + return ECgOk; +} + + +TCgReturnCode CgCpuPhysicalAllocate(void **pObject, U32 *pAddress, U32 aSize) +{ + DBG_FUNC_NAME("CgCpuPhysicalAllocate") + TCgReturnCode rc = ECgOk; + ASSERT_NOT_NULL(pObject); + //DBGMSG1("Trying to allocate %d bytes", aSize); + + //*pObject = dma_alloc_writecombine(0, aSize + 32, (dma_addr_t *)pAddress, GFP_KERNEL); + + if(*pObject == NULL) { + DBGMSG("Error! Failed allocating buffer"); + rc = ECgErrMemory; + } + else { + DBGMSG2("buffer allocated: ptr=0x%08X, addr=0x%08X", *pObject, *pAddress); +// memset((void *)*pObject, 0, aSize); + } + + *pObject = (unsigned char *)((((unsigned long)*pObject + 32 - 1) / 32) * 32); + *pAddress = ((*pAddress + 32 - 1) / 32) * 32; + + return rc; +} + +TCgReturnCode CgCpuPhysicalFree(void **pObject, U32 *pAddress, unsigned long aSize) +{ + DBG_FUNC_NAME("CgCpuPhysicalFree") + TCgReturnCode rc = ECgOk; + ASSERT_NOT_NULL(pObject); + DBGMSG1("pObject=0x%08X", *pObject); + + if (*pAddress != 0) + // dma_free_writecombine(0, aSize + 32, *pObject, *pAddress); + + *pObject = NULL; + + return rc; +} + + + + +TCgReturnCode CgxCpuReadMemory(U32 aBaseAddr, U32 aOffset, U32 *apValue) +{ + DBG_FUNC_NAME("CgxCpuReadMemory") + + DBGMSG1("read addd ress %x",aBaseAddr); + + + *apValue = sci_glb_read((aBaseAddr + aOffset),-1UL); + return ECgOk; +} + +TCgReturnCode CgxCpuWriteMemory(U32 aBaseAddr, U32 aOffset, U32 aValue) +{ + DBG_FUNC_NAME("CgxCpuWriteMemory") + + DBGMSG1("addd ress %x",aBaseAddr); + + sci_glb_write((aBaseAddr + aOffset), aValue, -1UL); + + return ECgOk; +} + +TCgReturnCode CgCpuKernelModeEnter(void) +{ + return ECgOk; +} + + +TCgReturnCode CgCpuKernelModeExit(void) +{ + return ECgOk; +} + + +TCgReturnCode CgCpuCacheSync(void) +{ + //DBG_FUNC_NAME("CgCpuCacheSync") +#ifndef ACP_PORT + flush_cache_all(); +#else + DBGMSG("enable ACP"); +#endif + + return ECgOk; +} + + + +#ifdef TRACE_ON +#define MAX_LINE_LENGTH 256 + + +TCgReturnCode CgxCpuPrint(char *aText) +{ + printk(KERN_EMERG "%s", aText); + + return ECgOk; +} + +TCgReturnCode CgxCpuMsg(const char *aFuncName, const char *aFileName, U32 aLineNum, char *aFormat, ...) +{ +#if 0 + va_list args; + char buf[MAX_LINE_LENGTH]= {0}; + int n = 0; + U32 curTickMSec = 0; + va_start(args, aFormat); // prepare the arguments + n = vsnprintf(buf, MAX_LINE_LENGTH, aFormat, args); + va_end(args); // clean the stack + + // Get current tick + CgxCpuTick(&curTickMSec); + + if (n > 0) + printk(KERN_EMERG ">>> %d.%03d %s[%d]: %s\n", curTickMSec / 1000, curTickMSec % 1000, aFuncName, (int)aLineNum, buf); + #endif + return ECgOk; +} +#endif + +TCgReturnCode CgxCpuSleep(U32 milliSeconds) +{ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout (milliSeconds); + return ECgOk; +} +#ifndef CG_HAS_CPU_TICK + TCgReturnCode CgxCpuTick(U32 * apTickMSec) + { + struct timespec t = current_kernel_time(); + *apTickMSec = t.tv_sec * 1000 + t.tv_nsec / 1000000; + return ECgOk; + } +#endif + +/** \endcond */ diff --git a/drivers/misc/gpsip/cgdriver/CgCpuOs.h b/drivers/misc/gpsip/cgdriver/CgCpuOs.h new file mode 100644 index 00000000..ab201d96 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgCpuOs.h @@ -0,0 +1,176 @@ +/****************************************************************************** + * 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 Os depended services requires by CgCpu + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + +*/ + +#ifndef CG_CPU_OS_H +#define CG_CPU_OS_H + +#ifdef __cplusplus + extern "C" + { +#endif + +// =========================================================================== + +#include "CgReturnCodes.h" + + +// =========================================================================== + + + +/** + \ingroup cg_cpu_os + Map physical address space to virtual one + + \param[out] pObject Pointer to virtual address for physical memory region + \param[in] aBaseAddr Base address (physical) + \param[in] aSize Number of bytes + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +TCgReturnCode CgCpuVirtualAllocate(volatile void **pObject, unsigned long aBaseAddr, unsigned long aSize); + + +/** + \ingroup cg_cpu_os + Un-map physical address space to virtual one + + \param pObject Pointer to virtual address for physical memory region + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +TCgReturnCode CgCpuVirtualFree(volatile void **pObject); + +/** + \ingroup cg_cpu_os + Allocate physical memory + + \param[out] pObject Pointer to virtual address of allocated memory + \param[in] pAddress Address of allocated memory (physical) + \param[in] aSize Number of bytes + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +TCgReturnCode CgCpuPhysicalAllocate(void **pObject, U32 *pAddress, U32 aSize); + +/** + \ingroup cg_cpu_os + Free physical memory + + \param[out] pObject Pointer to virtual address of allocated memory + \param[out] pAddress physical address + \param[in] aSize size in bytes + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +TCgReturnCode CgCpuPhysicalFree(void **pObject, U32 *pAddress, unsigned long aSize); + + +/** + \ingroup cg_cpu_os + Enter Kernel mode + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +TCgReturnCode CgCpuKernelModeEnter(void); + +/** + \ingroup cg_cpu_os + Exit Kernel mode + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +TCgReturnCode CgCpuKernelModeExit(void); + +/** + \ingroup cg_cpu_os + Cache sync + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk Success +*/ +//TCgReturnCode strinsCgCpuCacheSync(void); +TCgReturnCode CgCpuCacheSync(void); + +/** + Read value from host memory location + Used to read CGsnap memory mapped registers and other memories, as required. + + \param[in] aBaseAddr Base address (Virtual Memory) + \param[in] aOffset Offset from base address + \param[out] apValue Read value + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxCpuReadMemory(U32 aBaseAddr, U32 aOffset, U32 *apValue); + +/** + Write value to host memory location + Used to write CGsnap memory mapped registers and other memories, as required. + + \param[in] aBaseAddr Base address (Virtual Memory) + \param[in] aOffset Offset from base address + \param[in] aValue Value to write + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxCpuWriteMemory(U32 aBaseAddr, U32 aOffset, U32 aValue); + + +/** + Sleep for the specified time. + + \param[in] milliSeconds time in miliseconds + + \return System wide return code (see CgReturnCodes.h) +*/ +TCgReturnCode CgxCpuSleep(U32 milliSeconds); + + +/** + Return the CPU tick counter (mostly in mSec) + \note tick counter units are different for each CPU + + \return System wide return code (see CgReturnCodes.h) +*/ +TCgReturnCode CgxCpuTick(U32 * apTickMSec); + + +// =========================================================================== + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/drivers/misc/gpsip/cgdriver/CgReturnCodes.h b/drivers/misc/gpsip/cgdriver/CgReturnCodes.h new file mode 100644 index 00000000..470e9ca0 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgReturnCodes.h @@ -0,0 +1,172 @@ +/****************************************************************************** + * 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 Cell-Guide common return codes + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + + This file define the infrastructure and common error codes for cell-guide projects + */ +#ifndef CG_RETURN_CODES_H +#define CG_RETURN_CODES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "CgTypes.h" /**< CellGuide Types */ + +#define CG_RETURN_CODE_SUB_RANGE (0x400) +#define RANGE_MASK ~(CG_RETURN_CODE_SUB_RANGE-1) + +#define ECgCommonErrorBase (0) +#define ECgPrivateErrorBase (-1 * CG_RETURN_CODE_SUB_RANGE) +#define ECgPrivateMsgBase (+1 * CG_RETURN_CODE_SUB_RANGE) + + +/* System-wide positives */ + +/** OK status */ +#define ECgOk (0) +#define ECgProgressNotification ( ECgCommonErrorBase + 1 ) + +/* System-wide errors */ +#define ECgBadArgument ( ECgCommonErrorBase - 1 ) +#define ECgNotSupported ( ECgCommonErrorBase - 2 ) +#define ECgGeneralFailure ( ECgCommonErrorBase - 3 ) +#define ECgInitFailure ( ECgCommonErrorBase - 4 ) +#define ECgErrMemory ( ECgCommonErrorBase - 5 ) +#define ECgErrGeneral ( ECgCommonErrorBase - 6 ) +#define ECgErrNotInitialized ( ECgCommonErrorBase - 7 ) +#define ECgOutOfBounds ( ECgCommonErrorBase - 8 ) +#define ECgDataNotFound ( ECgCommonErrorBase - 9 ) +#define ECgPermissionDenied ( ECgCommonErrorBase - 10 ) +#define ECgNullPointer ( ECgCommonErrorBase - 11 ) +#define ECgFileOpen ( ECgCommonErrorBase - 12 ) +#define ECgFileRead ( ECgCommonErrorBase - 13 ) +#define ECgFileChecksum ( ECgCommonErrorBase - 14 ) +#define ECgTimeout ( ECgCommonErrorBase - 15 ) +#define ECgTimeNotValid ( ECgCommonErrorBase - 16 ) +#define ECgEndOfFile ( ECgCommonErrorBase - 17 ) +#define ECgInvalidCharacter ( ECgCommonErrorBase - 18 ) +#define ECgFatalError ( ECgCommonErrorBase - 19 ) +#define ECgBadConfiguration ( ECgCommonErrorBase - 20 ) +#define ECgReadOnlyProperty ( ECgCommonErrorBase - 21 ) +#define ECgExitModeFlag ( ECgCommonErrorBase - 22 ) +#define ECgFatalInternalError ( ECgCommonErrorBase - 23 ) + + +#define ECgPropertiesMissingLevel ( ECgCommonErrorBase - 24 ) +#define ECgPropertiesMissingGetMethod ( ECgCommonErrorBase - 25 ) + +#define ECgNotAllowed ( ECgCommonErrorBase - 26 ) + +#define ECgDataNotValid ( ECgCommonErrorBase - 27 ) +#define ECgDataNotEqual ( ECgCommonErrorBase - 28 ) + +#define ECgDataNotAvailable ( ECgCommonErrorBase - 30 ) +#define ECgFileNotFound ( ECgCommonErrorBase - 31 ) +#define ECgPathNotFound ( ECgCommonErrorBase - 32 ) +#define ECgNoMoreFiles ( ECgCommonErrorBase - 33 ) +#define ECgNoMoreSlots ( ECgCommonErrorBase - 34 ) +#define ECgInvalidData ( ECgCommonErrorBase - 35 ) +#define ECgPathExists ( ECgCommonErrorBase - 36 ) +#define ECgNotEnoughData ( ECgCommonErrorBase - 37 ) +#define ECgBusy ( ECgCommonErrorBase - 38 ) +#define ECgAnyErrCode ( ECgCommonErrorBase - 39 ) + +#define ECgNetworkNotInitialized ( ECgCommonErrorBase - 40 ) +#define ECgNetworkSubsysFailed ( ECgCommonErrorBase - 41 ) +#define ECgNetworkPortInUse ( ECgCommonErrorBase - 42 ) +#define ECgNetworkInvalidAddress ( ECgCommonErrorBase - 43 ) +#define ECgNetworkPortAlreadyInUse ( ECgCommonErrorBase - 44 ) +#define ECgNetworkTooManyConnections ( ECgCommonErrorBase - 45 ) +#define ECgInvalidFileName ( ECgCommonErrorBase - 46 ) +#define ECgDeviceOpenFail ( ECgCommonErrorBase - 47 ) +#define ECgDataOverrun ( ECgCommonErrorBase - 48 ) +#define ECgNetworkInvalidPort ( ECgCommonErrorBase - 49 ) +#define ECgNetworkSocketNotConnected ( ECgCommonErrorBase - 50 ) + +#define ECgResume ( ECgCommonErrorBase - 61 ) +#define ECgPowerOff ( ECgCommonErrorBase - 62 ) + +#define ECgGreater ( ECgCommonErrorBase - 100 ) +#define ECgSmaller ( ECgCommonErrorBase - 101 ) + +#define ECgTerminate ( ECgCommonErrorBase - 102 ) +#define ECgNotOwner ( ECgCommonErrorBase - 103 ) +#define ECgCanceled ( ECgCommonErrorBase - 104 ) + +#define ECgIoPending ( ECgCommonErrorBase - 105 ) +#define ECgSingularMatrix ( ECgCommonErrorBase - 106 ) + +#define ECgIntegerOverFlow ( ECgCommonErrorBase - 107 ) +#define EcgInSufficientWorkPadSize ( ECgCommonErrorBase - 108 ) +#define ECgSatelliteOverflow ( ECgCommonErrorBase - 109 ) +#define ECgLastItem ( ECgCommonErrorBase - 110 ) + + +typedef S32 TCgReturnCode; + + +//#if (CG_USE_MAX_LOG_LEVEL >= CGLOG_FATAL) +//#ifdef CG_LOG_H // CG_LOG_H_USED indicates CgLog.h is included in the compilation +#ifndef CGXDRIVER_EXPORTS + #ifdef CGTEST + #define CG_STORE_ERROR_LINE + #elif defined DEBUG + #define CG_STORE_ERROR_LINE + #elif defined _DEBUG + #define CG_STORE_ERROR_LINE + #endif +#endif + +#ifdef CG_STORE_ERROR_LINE + #undef CG_STORE_ERROR_LINE +#endif + +//#endif +//#endif + +BOOL cgRetCode_store_error_line(const char * aFileName, long lineNumber, TCgReturnCode rc); +BOOL cglog_wrn_file_and_line(const char * aFileName, long aLineNumber, long rc); + +#ifdef CG_STORE_ERROR_LINE + #define OK(rc) (rc >= ECgOk ? TRUE : cgRetCode_store_error_line(__FILE__,__LINE__,rc)) + #define FAIL(rc) (rc < ECgOk ? !cgRetCode_store_error_line(__FILE__,__LINE__,rc) : FALSE) + //#define OK(rc) (rc >= ECgOk ? TRUE : cglog_wrn_file_and_line(__FILE__,__LINE__,rc)) + //#define FAIL(rc) (rc < ECgOk ? !cglog_wrn_file_and_line(__FILE__,__LINE__,rc) : FALSE) +#else + #define OK(rc) (rc >= ECgOk) + #define FAIL(rc) (rc < ECgOk) +#endif + +#define SELECT_FIRST_ERROR2(rc1,rc2) (rc1 == ECgOk) ? rc2 : rc1 +#define SELECT_FIRST_ERROR3(rc1,rc2,rc3) SELECT_FIRST_ERROR2((SELECT_FIRST_ERROR2(rc1,rc2)),rc3) +#define SELECT_FIRST_ERROR4(rc1,rc2,rc3,rc4) SELECT_FIRST_ERROR2((SELECT_FIRST_ERROR3(rc1,rc2,rc3)),rc4) +#define SELECT_FIRST_ERROR5(rc1,rc2,rc3,rc4,rc5)SELECT_FIRST_ERROR2((SELECT_FIRST_ERROR4(rc1,rc2,rc3,rc4)),rc5) + +// 0 indicates no error. index starts at 1. +#define INDEX_FIRST_ERROR2(rc1,rc2) ((rc1 == ECgOk) ? ((rc2 == ECgOk) ? 0 : 2) : 1) +#define INDEX_FIRST_ERROR3(rc1,rc2,rc3) ((rc3 == ECgOk) ? INDEX_FIRST_ERROR2(rc1,rc2) : 3) + +#ifdef __cplusplus +} +#endif + +#endif // CG_RETURN_CODES_H diff --git a/drivers/misc/gpsip/cgdriver/CgTypes.h b/drivers/misc/gpsip/cgdriver/CgTypes.h new file mode 100644 index 00000000..0e4d1332 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgTypes.h @@ -0,0 +1,227 @@ +/****************************************************************************** + * 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 global types + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide +*/ +#ifndef _CG_TYPES_H +#define _CG_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +/** Unsigned 8 bit data */ +typedef unsigned char U8; +/** Unsigned 16 bit data */ +typedef unsigned short U16; +/** Unsigned 32 bit data*/ +typedef unsigned long U32; +/** Signed 8 bit data */ +typedef signed char S8; +/** Signed 16 bit data */ +typedef signed short S16; +/** Signed 32 bit data */ +typedef signed long S32; +/** 8-bit text data */ +typedef char T8; +/** 16-bit text data */ +typedef U16 T16; + +#define CG_MAX_S32 (0x7FFFFFFF) +#define CG_MAX_S16 (0x7FFF) + +#if !(defined (__BORLANDC__)) && !(defined (_MSC_VER)) && !(defined(TCC7801)) +/** Boolean, TRUE/FALSE */ + #define BOOL U8 +#endif /* !(defined (__BORLANDC__) && defined (_MSC_VER)) */ + +#if !(defined (__BORLANDC__)) && !(defined (_MSC_VER)) && !(defined (APPROACH5C)) + /** void */ + typedef void VOID; +#endif /* !(defined (__BORLANDC__) && defined (_MSC_VER)) */ + + +#ifdef __BORLANDC__ + typedef int BOOL; +#endif + +#ifdef _MSC_VER + typedef int BOOL; +#endif + + +#ifdef TCC7801 + typedef int BOOL; +#endif + + +#if defined (_MSC_VER) + //#define U64_ZERO 0 + // typedef unsigned __int64 U64_32; /* unsigned 64 bit data */ // TODO Noam - made problems in hardware files... + #define U64_ZERO {0,0} + typedef struct { + U32 low; + U32 high; + } U64_32; + typedef __int64 S64; /* signed 64 bit data */ + typedef __int64 SINT64; /* signed 64 bit data */ + typedef unsigned __int64 U64; /* signed 64 bit data */ +#elif defined (__LINUX__) + #define U64_ZERO {0,0} + typedef struct { + U32 low; + U32 high; + } U64_32; + typedef signed long long int S64; /* signed 64 bit data */ + typedef signed long long int SINT64; /* signed 64 bit data */ + typedef unsigned long long int U64; /* signed 64 bit data */ +#elif /*defined (__BORLANDC__) || */defined(EN_64BIT_INTEGER) + #define U64_ZERO 0 + typedef unsigned long long U64; /* unsigned 64 bit data */ + typedef long long S64; /* signed 64 bit data */ + typedef long long SINT64; /* signed 64 bit data */ +#else + // All that are not WCE not Linux (ADS1_2 for instance) + #define U64_ZERO {0,0} +/** a structure for 64-bit integer */ + typedef struct { + U32 low; + U32 high; + } U64_32; + typedef unsigned long long U64; /* unsigned 64 bit data */ +/** a structure for 64-bit signed integer */ + typedef struct { + S32 low; + S32 high; + } S64; + typedef long long SINT64; /* signed 64 bit data */ +#endif + +/** Single-precision floating point */ +typedef float FLOAT; +/** Double-precision floating point */ +typedef double DOUBLE; + +typedef S16 DATA; +typedef S32 LDATA; + +#ifndef NULL + #define NULL 0 +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#if (defined(__TARGET_ARCH_4T) ||defined (__CW32__) || defined (__GCC32__) || defined (__UCSO__) || defined (__LINUX__) ||\ + defined (__SYMBIAN__) ||defined (__NUCLEUS__) || defined (__BORLANDC__) || defined (_MSC_VER) || defined(MP_211) || defined(APPROACH5C)) ||\ + defined (__ARMEL__ ) +#ifndef LITTLE_ENDIAN + #define LITTLE_ENDIAN +#endif +#else + #define BIG_ENDIAN +#endif /* */ + +/** file types for ADM (Assistance Data Manager)*/ +typedef enum +{ + ECgAgpsBinaryFile = 0, + ECgAgpsRawBinaryFile, + ECgAgpsAsciiFile, + ECgAgpsAlmanacSemFile, + ECgAgpsAlmanacYumaFile +} TCgFileType; + + +/* This type will be added if it is not exists in our target compiler */ +typedef enum { + cgFALSE = 0 , + cgTRUE = 0x7FFF +} cgBool ; + +typedef U16 USHORT; +typedef U8 UCHAR; +typedef U32 ULONG; + +// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// TEMPORARY CODE - NOAM +//@@ +/************************************************************************************************* + Type: TCgAgpsIonosphere + Description: Ionosphere data +*************************************************************************************************/ + +//@@ +/************************************************************************************************* + Type: TCgAgpsPosition + Description: Geographical position +*************************************************************************************************/ +// TODO NG 22/6/2010 should be replaced with TCgCoordinatesLLA (from CgCoordinates.h) +typedef struct SCgAgpsPosition +{ + DOUBLE latitude; /** geographical latitude */ + DOUBLE longitude; /** geographical longitude */ + DOUBLE altitude; /** geographical altitude */ +} TCgAgpsPosition; + +#define ALTITUDE_NOT_VALID (0xFFFF) +typedef struct +{ + S16 altitude; /** height (from database) [meters] */ + U16 err; /** Height expected error [meters] */ +}TCgHeightData; + +#ifdef __GCC32__ + #define __STRUCT_PACKED__ __attribute__ ((packed)) +#else + #define __STRUCT_PACKED__ +#endif + + +typedef enum { + ECG_BYTE_ORDER_1234 = 0x0, + ECG_BYTE_ORDER_2143 = 0x1, + ECG_BYTE_ORDER_3412 = 0x2, + ECG_BYTE_ORDER_4321 = 0x3 +} TCgByteOrder; + +typedef enum { + ECG_SWAP_NONE, + ECG_SWAP_BYTES, + ECG_SWAP_WORDS, + ECG_SWAP_BYTES_AND_WORDS +}TCgByteSwapType; + +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_CG_AGPS_GENERAL_TYPES_H*/ diff --git a/drivers/misc/gpsip/cgdriver/CgVersion.h b/drivers/misc/gpsip/cgdriver/CgVersion.h new file mode 100644 index 00000000..fba143d7 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgVersion.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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 CgVersion.h + \brief + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + + Defines +*/ +#ifndef CG_VERSION_H +#define CG_VERSION_H + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +#include "CgTypes.h" /**< CellGuide Types */ + +#ifdef CGTEST + #define CG_BUILD_MODE "TEST" +#elif defined(DEBUG) || defined (_DEBUG) + #define CG_BUILD_MODE "DEBUG" +#else + #define CG_BUILD_MODE "RELEASE" +#endif + + +/** + * VERSION type to pass VERSION types of information using one union +*/ +typedef struct SCgVersion{ + const char *buildVersion; + const char *buildOriginator; + const char *buildName; + const char *buildNumber; + const char *buildDate; + const char *buildTime; + const char *buildMode; +} TCgVersion; + + + +const char *CgVersionBuildNumber(const TCgVersion *apVersion); +const char *CgVersionBuildDate(const TCgVersion *apVersion); +const char *CgVersionBuildTime(const TCgVersion *apVersion); + + + + +/*@}*/ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + + +#endif diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverApi.h b/drivers/misc/gpsip/cgdriver/CgxDriverApi.h new file mode 100644 index 00000000..352ae68b --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverApi.h @@ -0,0 +1,436 @@ +/****************************************************************************** + * 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 CGsnap driver API + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + This file defines the application interface to interact with the CGsnap device driver. + +*/ + +#ifndef _CGX_DRIVER_API_H__ +#define _CGX_DRIVER_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +#include "CgTypes.h" +#include "CgReturnCodes.h" +#include "CgCpu.h" + + + +/** IOCTL codes:*/ +#define CGX_IOCTL_INIT 0x0001 /**< Initialize driver */ +#define CGX_IOCTL_STOP 0x0002 /**< Driver stop and de-initialize */ +#define CGX_IOCTL_WRITE 0x0003 /**< ACLYS only: Write data */ +#define CGX_IOCTL_PREPARE_RECEIVE 0x0004 /**< Prepare for massive data (snap) transfer */ +#define CGX_IOCTL_RESET 0x0005 /**< Reset device */ +#define CGX_IOCTL_POWER_UP 0x0006 /**< Power up device */ +#define CGX_IOCTL_STATUS 0x0007 /**< Get driver status */ +#define CGX_IOCTL_GPIO_SET 0x0008 /**< Set Host GPIO */ +#define CGX_IOCTL_GPIO_GET 0x0009 /**< Get Host GPIO */ +#define CGX_IOCTL_GPIO_MODE_SET 0x000A /**< Set Host GPIO mode */ + +#define CGX_IOCTL_GET_VERSION 0x001A /**< Get driver version */ +#define CGX_IOCTL_CLEAR_OVERRUN 0x001B /**< ACLYS only */ +#define CGX_IOCTL_WAIT_RCV 0x001C /**< Wait for massive transfer to finish */ +#define CGX_IOCTL_CANCEL_RECEIVE 0x001D /**< Cancel massive transfer */ +#define CGX_IOCTL_ALLOC_BUFF 0x001E /**< Allocate kernel work memory buffer */ +#define CGX_IOCTL_FREE_BUFF 0x001F /**< Free kernel work memory buffer */ +#define CGX_IOCTL_READ_REG 0x0020 /**< CGsnap only: Read device register */ +#define CGX_IOCTL_WRITE_REG 0x0021 /**< CGsnap only: Write device register */ +#define CGX_IOCTL_POWER_DOWN 0x0022 /**< Power down device */ +#define CGX_IOCTL_COUNTER_RESET 0x0023 /**< Reset counters */ +#define CGX_IOCTL_READ_MEM 0x0024 /**< Read memory address */ +#define CGX_IOCTL_RECORD_START 0x0015 /**< Setup and start raw data recording */ +#define CGX_IOCTL_RECORD_WAIT 0x0016 /**< Wait for recording block */ +#define CGX_IOCTL_RECORD_STOP 0x0017 /**< Stop raw data recording */ +#define CGX_IOCTL_READ_RTC 0x0028 +#define CGX_IOCTL_CPU_REVISION 0x0029 /**< Detect CPU revision */ +#define CGX_IOCTL_RESUME_CLEAR 0x002A /**< clear resume mode */ + +#define CGX_IOCTL_TCXO_ENABLE 0x0030 /**< TCXO Enable/Disable control */ + +#define CGX_IOCTL_POWER_OFF 0x0040 /**< Cut power completely from the device */ +#define CGX_IOCTL_POWER_ON 0x0041 /**< Restore power fully to the device */ + +#define CGX_IOCTL_RF_WRITE_CONTROL 0x0050 /**< Write to RF control channel */ + +#define CGX_IOCTL_DMA_TEST 0x0100 /**< DMA test */ + + + + + +/** Driver transfer control structure */ + +typedef struct { + U32 physAddr; /**< Physical address */ + U8 *virtAddr; /**< Virtual address, in the application process' address space */ + U32 length; /**< Length, in bytes */ + U8 * driverContextVirtBufferAddr; /**< virtual address, of buffer used between the DMA and the driver */ + /**< in the driver process' context */ +} TCgxDriverPhysicalMemory; + +#ifndef MAX_NUM_OF_BLOCKS_IN_SINGLE_DMA_XFER + /** + Define the maximum number of blocks in a single DMA transfer + **/ + #define MAX_NUM_OF_BLOCKS_IN_SINGLE_DMA_XFER 64 // For now, same as MAX_DMA_TRANSFER_TASKS +#endif + +/** Driver state structure */ +typedef struct { + struct { + BOOL terminate; /**< Termination flag (for IST) */ + BOOL wait; /**< Wait for transfer complete flag */ + BOOL overrun; /**< Overrun indication */ + BOOL resume; /**< Resume indication */ + } flags; /**< Flags */ + struct { + struct { + U32 all; /**< Total interrupts counter */ + U32 snapStart; /**< Snap start interrupts counter */ + U32 overrun; /**< Overrun interrupts counter */ + } interrupt; /**< Interrupts counters*/ + } counters; /**< Counters */ + struct { + U32 bufferPhys; /**< physical memory address of receive buffer */ + U8 *originalBuffer; /**< pointer to original received data buffer (as passed by caller) */ + TCgByteOrder byteOrder; /**< required byte order for active transfer*/ + BOOL done; /**< active transfer done flag*/ + struct { + U32 required; /**< total number of bytes required for active transfer*/ + U32 received; /**< number of bytes received in active transfer*/ + } bytes; + struct { + U32 required; /**< total number of blocks to receive */ + U32 received; /**< number of blocks already received */ + } blocks; + struct { + U32 required; /**< total number of DMA tasks */ + U32 received; /**< number of DMA tasks processed */ + U32 active; /**< active task index */ + } chunks; + struct { + BOOL request; /**< Abort transfer flag */ + U32 onByte; /**< if cancel is requested, indicate the cancel position*/ + U32 onChunk; + } cancel; + U32 bufferOffset[MAX_NUM_OF_BLOCKS_IN_SINGLE_DMA_XFER]; /**< Internal buffer addresses (for DMA) */ + U32 blockSize; /**< Current transfer block size */ + U32 lastBlockSize; /**< Current transfer last block size (might be smaller or larger)*/ + } transfer; + TCgxDriverPhysicalMemory buffer; /**< Snap buffer information*/ + TCgReturnCode constructionRc;/**< What return code was returned from the driver construction*/ +} TCgxDriverState; + + + + +/** Driver control structure, passed from application on IOCTL call*/ +typedef union +{ + struct { + U32 alignedLength; /**< Number of bytes to write (aligned to hardware requirements) */ + U32 blockLength; /**< Block length (zero for single block snap) */ + TCgByteOrder byteOrder; /**< Required byte order */ + unsigned char *buf; /**< pointer to memory allocated for the data */ + U32 bufPhys; /**< CGsnap only: */ + U32 timeoutMS; /**< Timeout in mili-seconds */ + } read; /**< Read data */ + + struct { + U32 timeoutMS; /**< Timeout in milli-seconds */ + U32 blockNumber; /**< Block number to wait for */ + } wait; + + struct { + unsigned char *pSource; /**< Source address to write from */ + U32 length; /**< Number of bytes to write */ + } write; /**< ACLYS only: Write data to ACLYS */ + + struct { + U32 code; /**< GPIO code (CellGuide conventions)*/ + U32 out; /**< GPIO value for output (write) operation*/ + TCgCpuGpioMode mode; /**< GPIO mode to set */ + } GPIO; /**< Manual Read/Write GPIO */ + + struct { + U32 offset; /**< register offset from CGsnap base address */ + } readReg; /**< CGsnap only: Read CGsnap register */ + + struct { + U32 offset; /**< Register offset from CGsnap base address */ + U32 value; /**< Value to write */ + } writeReg; /**< CGsnap only: Write CGsnap register */ + + struct { + U32 onByteCount; /**< Position to cancel the transfer + 0 = Transfer will be canceled as soon as possible + n = Transfer will be canceled as soon as possible After n bytes have been received + */ + } cancel; /**< Cancel transfer request */ + struct { + U32 resetLevel; /**< Reset level: + 0 = Normal-Reset + 1 = Semi-Reset + */ + } reset; /**< Reset transfer request */ + + struct { + U32 length; /**< Number of bytes to allocate */ + U32 processId; /**< ID of process that requested the buffer allocation */ + } alloc; /**< Allocate In-Kernel Transfer Buffer */ + + struct { + BOOL enable; /**< enable power to TCXO */ + } tcxoControl; /**< Control TCXO power */ + +} TCgDriverControl; + + + + +/** Driver results structure, returned from driver on IOCTL call finish*/ +typedef struct +{ + TCgReturnCode rc; /**< Last operation detailed return code*/ + struct { + void *bufferPhysAddr; /**< Pointer to buffer start */ + void *bufferAppVirtAddr; /**< Pointer to buffer start virtual address, in application's process' context*/ + U32 size; /**< Number of bytes*/ + } buffer; /**< Retrieve incoming data buffer details */ + + struct { + U32 code; /**< GPIO code (CellGuide conventions)*/ + U32 val; /**< GPIO value for output (write) operation*/ + } GPIO; /**< Result for GPIO Read request*/ + + struct { + char buildVersion[32]; /**< Build version ("1.8") */ + char buildNumber[32]; /**< Build number ("1747") */ + char buildDate[32]; /**< Build date ("10/04/2007")*/ + char buildTime[32]; /**< Build time ("03:49")*/ + char buildMode[32]; /**< Build mode ("RELEASE", "DEBUG", "TEST")*/ + char buildName[32]; /**< Driver platform name*/ + } version; /**< Retrieve driver version info*/ + + struct { + U32 offset; /**< Register offset from CGsnap base address */ + U32 value; /**< REgister value */ + } readReg; /**< CGsnap only: Result for CGsnap register read request*/ + + struct { + char revisionCode[32]; /**< CPU revision code */ + } cpuRevision; /**< Detect CPU revision */ + + struct { + U32 year; + U32 month; + U32 day; + U32 hour; + U32 minute; + U32 second; + U32 dayInWeek; + U32 tick; + } readRtc; + + TCgxDriverState state; /**< Driver internal state information (for debug) */ +} TCgDriverStatus; + + + +/*for 64 bit system struct*/ + +typedef struct { + unsigned int physAddr; /**< Physical address */ + unsigned int virtAddr; /**< Virtual address, in the application process' address space */ + unsigned int length; /**< Length, in bytes */ + unsigned int driverContextVirtBufferAddr; /**< virtual address, of buffer used between the DMA and the driver */ + /**< in the driver process' context */ +} TCgxDriverPhysicalMemory_32bit; + + +/** Driver state structure */ +typedef struct { + struct { + BOOL terminate; /**< Termination flag (for IST) */ + BOOL wait; /**< Wait for transfer complete flag */ + BOOL overrun; /**< Overrun indication */ + BOOL resume; /**< Resume indication */ + } flags; /**< Flags */ + struct { + struct { + unsigned int all; /**< Total interrupts counter */ + unsigned int snapStart; /**< Snap start interrupts counter */ + unsigned int overrun; /**< Overrun interrupts counter */ + } interrupt; /**< Interrupts counters*/ + } counters; /**< Counters */ + struct { + unsigned int bufferPhys; /**< physical memory address of receive buffer */ + unsigned int originalBuffer; /**< pointer to original received data buffer (as passed by caller) */ + TCgByteOrder byteOrder; /**< required byte order for active transfer*/ + BOOL done; /**< active transfer done flag*/ + struct { + unsigned int required; /**< total number of bytes required for active transfer*/ + unsigned int received; /**< number of bytes received in active transfer*/ + } bytes; + struct { + unsigned int required; /**< total number of blocks to receive */ + unsigned int received; /**< number of blocks already received */ + } blocks; + struct { + unsigned int required; /**< total number of DMA tasks */ + unsigned int received; /**< number of DMA tasks processed */ + unsigned int active; /**< active task index */ + } chunks; + struct { + BOOL request; /**< Abort transfer flag */ + unsigned int onByte; /**< if cancel is requested, indicate the cancel position*/ + unsigned int onChunk; + } cancel; + unsigned int bufferOffset[MAX_NUM_OF_BLOCKS_IN_SINGLE_DMA_XFER]; /**< Internal buffer addresses (for DMA) */ + unsigned int blockSize; /**< Current transfer block size */ + unsigned int lastBlockSize; /**< Current transfer last block size (might be smaller or larger)*/ + } transfer; + TCgxDriverPhysicalMemory_32bit buffer; /**< Snap buffer information*/ + signed int constructionRc;/**< What return code was returned from the driver construction*/ +} TCgxDriverState_32bit; + + +/** Driver results structure, returned from driver on IOCTL call finish*/ +typedef struct +{ + signed int rc; /**< Last operation detailed return code*/ + struct { + unsigned int bufferPhysAddr; /**< Pointer to buffer start */ + unsigned int bufferAppVirtAddr; /**< Pointer to buffer start virtual address, in application's process' context*/ + unsigned int size; /**< Number of bytes*/ + } buffer; /**< Retrieve incoming data buffer details */ + + struct { + unsigned int code; /**< GPIO code (CellGuide conventions)*/ + unsigned int val; /**< GPIO value for output (write) operation*/ + } GPIO; /**< Result for GPIO Read request*/ + + struct { + char buildVersion[32]; /**< Build version ("1.8") */ + char buildNumber[32]; /**< Build number ("1747") */ + char buildDate[32]; /**< Build date ("10/04/2007")*/ + char buildTime[32]; /**< Build time ("03:49")*/ + char buildMode[32]; /**< Build mode ("RELEASE", "DEBUG", "TEST")*/ + char buildName[32]; /**< Driver platform name*/ + } version; /**< Retrieve driver version info*/ + + struct { + unsigned int offset; /**< Register offset from CGsnap base address */ + unsigned int value; /**< REgister value */ + } readReg; /**< CGsnap only: Result for CGsnap register read request*/ + + struct { + char revisionCode[32]; /**< CPU revision code */ + } cpuRevision; /**< Detect CPU revision */ + + struct { + unsigned int year; + unsigned int month; + unsigned int day; + unsigned int hour; + unsigned int minute; + unsigned int second; + unsigned int dayInWeek; + unsigned int tick; + } readRtc; + + TCgxDriverState_32bit state; /**< Driver internal state information (for debug) */ +} TCgDriverStatus_32bit; + + +/** Driver control structure, passed from application on IOCTL call*/ +typedef union +{ + struct { + unsigned int alignedLength; /**< Number of bytes to write (aligned to hardware requirements) */ + unsigned int blockLength; /**< Block length (zero for single block snap) */ + TCgByteOrder byteOrder; /**< Required byte order */ + unsigned int buf; /**< pointer to memory allocated for the data */ + unsigned int bufPhys; /**< CGsnap only: */ + unsigned int timeoutMS; /**< Timeout in mili-seconds */ + } read; /**< Read data */ + + struct { + unsigned int timeoutMS; /**< Timeout in milli-seconds */ + unsigned int blockNumber; /**< Block number to wait for */ + } wait; + + struct { + unsigned int pSource; /**< Source address to write from */ + unsigned int length; /**< Number of bytes to write */ + } write; /**< ACLYS only: Write data to ACLYS */ + + struct { + unsigned int code; /**< GPIO code (CellGuide conventions)*/ + unsigned int out; /**< GPIO value for output (write) operation*/ + TCgCpuGpioMode mode; /**< GPIO mode to set */ + } GPIO; /**< Manual Read/Write GPIO */ + + struct { + unsigned int offset; /**< register offset from CGsnap base address */ + } readReg; /**< CGsnap only: Read CGsnap register */ + + struct { + unsigned int offset; /**< Register offset from CGsnap base address */ + unsigned int value; /**< Value to write */ + } writeReg; /**< CGsnap only: Write CGsnap register */ + + struct { + unsigned int onByteCount; /**< Position to cancel the transfer + 0 = Transfer will be canceled as soon as possible + n = Transfer will be canceled as soon as possible After n bytes have been received + */ + } cancel; /**< Cancel transfer request */ + struct { + unsigned int resetLevel; /**< Reset level: + 0 = Normal-Reset + 1 = Semi-Reset + */ + } reset; /**< Reset transfer request */ + + struct { + unsigned int length; /**< Number of bytes to allocate */ + unsigned int processId; /**< ID of process that requested the buffer allocation */ + } alloc; /**< Allocate In-Kernel Transfer Buffer */ + + struct { + BOOL enable; /**< enable power to TCXO */ + } tcxoControl; /**< Control TCXO power */ + +} TCgDriverControl_32bit; + + + +#ifdef __cplusplus +} // extern "C" +#endif //__cplusplus + + +#endif // _CGXDRIVERAPI_H__ 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 + +#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<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; +} + +*/ diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverCore.h b/drivers/misc/gpsip/cgdriver/CgxDriverCore.h new file mode 100644 index 00000000..fdf41bc7 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverCore.h @@ -0,0 +1,255 @@ +/****************************************************************************** + * 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 CGX5900 driver core prototypes (non-OS depended) + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + +*/ + +#ifndef CGX_DRIVR_CORE_H +#define CGX_DRIVR_CORE_H + + +#include "CgReturnCodes.h" +#include "CgxDriverApi.h" + +#define CG_CG_CORE_REG_BASE_ADDRESS (0) + +/** + Stop driver. + The function is called as a result of GPSenseEngine CGX_IOCTL_STOP request. + Stop the driver current operations, destroy all memory structures and release system resources. + this function is the counterpart of CgxDriverConstruct. + + \note Generic function : Not required to be ported + + \param[in] pDriver Global driver structure pointer + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) +*/ +TCgReturnCode CgxDriverDestroy( + void *pDriver); + + + +/** + Setup driver structure + + \param[in] pDriver Global driver structure pointer + \param[in] pState Driver state structure pointer + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverConstruct( + void *pDriver, + TCgxDriverState *pState); + + + + + + +/** + Execute request + + \param[in] pDriver Global driver structure pointer + \param[in] pState Driver state structure pointer + \param[in] aRequest + \param[in] pControl + \param[in] pResults + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverExecute( + void *pDriver, + TCgxDriverState *pState, + U32 aRequest, + TCgDriverControl *pControl, + TCgDriverStatus *pResults); + +/** + Execute request, specific to IP/Core + + \param[in] pDriver Global driver structure pointer + \param[in] pState Driver state structure pointer + \param[in] aRequest + \param[in] pControl + \param[in] pResults + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverExecuteSpecific( + void *pDriver, + TCgxDriverState *pState, + U32 aRequest, + TCgDriverControl *pControl, + TCgDriverStatus *pResults); + + +/** + Check if request canceled + + \param[in] pState Driver state structure pointer + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverIsReadCanceled(TCgxDriverState *pState); + + + +/** + Handle GPS interrupt + + \param[in] pDriver Global driver structure pointer + \param[in] pState Driver state structure pointer + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverGpsInterruptHandler( + void *pDriver, + TCgxDriverState *pState); + + + +/** + Handle DMA interrupt + + \param[in] pDriver Global driver structure pointer + \param[in] pState Driver state structure pointer + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverDataReadyInterruptHandler( + void *pDriver, + TCgxDriverState *pState); + +TCgReturnCode CgxDriverHardwareReset(unsigned long aResetLevel); + +/** + Move chip to power down mode + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if chip finished power-down + +*/ +TCgReturnCode CgxDriverPowerDown(void); + +/** + Move chip to power up mode + + \return System wide return code (see CgReturnCodes.h) + \retval ECgOk if chip finished power-down + +*/ +TCgReturnCode CgxDriverPowerUp(void); + +/** +Cut power from the CellGuide device + +\return System wide return code (see CgReturnCodes.h) +\retval ECgOk if chip finished power-down + +*/ +TCgReturnCode CgxDriverPowerOn(void); + +/** +Connect power to the CellGuide device + +\return System wide return code (see CgReturnCodes.h) +\retval ECgOk if chip finished power-down + +*/ +TCgReturnCode CgxDriverPowerOff(void); + +/** +Move RF chip to power down mode + +\return System wide return code (see CgReturnCodes.h) +\retval ECgOk if RF chip finished power-down + +*/ +TCgReturnCode CgxDriverRFPowerDown(void); + +/** +Move RF chip to power down mode + +\return System wide return code (see CgReturnCodes.h) +\retval ECgOk if RF chip finished power-up + +*/ +TCgReturnCode CgxDriverRFPowerUp(void); + +/** + Set output of CGsnap's GPO aGpioPin, to aVal + + \return System wide return code (see CgReturnCodes.h) +*/ +TCgReturnCode CgCGCoreGpioSet(U32 aGpioPin, U32 aVal); + + +#if 0 +//gaole add +void CgCoreReleaseRes(void); +void CgGpsReset(void); +#endif + + + +#ifndef MIN + #define MIN(__a__, __b__) ((__a__) < (__b__) ? (__a__) : (__b__)) +#endif + +//#define CGCORE_ACCESS_VIA_SPI +extern bool flag_power_up; +extern void gps_gpio_request(void); + +#ifdef CGCORE_ACCESS_VIA_SPI +extern int gps_spi_sysreg_write_bytes (u32 len, u32 addr, u32 data); +extern int gps_spi_sysreg_read_bytes (u32 len, u32 addr, u32 * data); + +extern int gps_spi_write_bytes( unsigned int len, unsigned int addr,unsigned int data); + #define CGCORE_WRITE_REG(addr,val) \ + gps_spi_write_bytes(1,(U32)addr,val) + + +extern int gps_spi_read_bytes( unsigned int len,unsigned int addr,unsigned int *data); + #define CGCORE_READ_REG(addr,val) \ + gps_spi_read_bytes(1,(U32)addr,(unsigned int *)val) + +#else + #define CGCORE_WRITE_REG(addr,val) CgxCpuWriteMemory((U32)CG_DRIVER_CGCORE_BASE_VA, (U32)addr, val); + #define CGCORE_READ_REG(addr,val) CgxCpuReadMemory((U32)CG_DRIVER_CGCORE_BASE_VA, (U32)addr, val); +#endif + + + +#endif 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; +} + + diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.h b/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.h new file mode 100644 index 00000000..c3084a2a --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverCoreCommon.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * 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 CGX5900 driver core prototypes (non-OS depended) + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + +*/ + +#ifndef CGX_DRIVR_CORE_COMMON_H +#define CGX_DRIVR_CORE_COMMON_H + + +#include "CgReturnCodes.h" +#include "CgxDriverApi.h" + +// Access to the APB +#define CGCORE_REG_OFFSET_SAT_RAM (0x100) +#define CGCORE_REG_OFFSET_SAT_RAM_LAST (0x1FC) +#define CGCORE_REG_OFFSET_APB_COMMAND (0x090) +#define CGCORE_REG_OFFSET_APB_DATA (0x094) + +// CG Core interrupt codes +#define CGCORE_INT_RTC (0x00000001) // RTC timer has reached its threshold Interrupt +#define CGCORE_INT_SNAP_START (0x00000002) // StartSnap occurred Interrupt +#define CGCORE_INT_SNAP_END (0x00000004) // Snap completed successfully Interrupt +#define CGCORE_INT_TCXO_EXPIRED (0x00000008) // TCXO timer has reached its threshold Interrupt +#define CGCORE_INT_OVERRUN (0x00000010) // A buffer overrun occurred interrupt. Hence the last snap is invalid. +#define CGCORE_INT_EOT (0x00000020) // End of BS tracking period Interrupt +#define CGCORE_INT_EOM (0x00000040) // End of drift meas measurement period Interrupt + +#ifdef CGCORE_ACCESS_VIA_SPI +#define CGCORE_INT_DMA_REQ (0x00002000) +#define CGCORE_INT_DMA_OVERRUN (0x00004000) +#endif + +#define CGCORE_REG_INT_RAW (0x80) +#define CGCORE_REG_INT_SRC (0x84) +#define CGCORE_REG_INT_EN (0x88) +#define CGCORE_REG_INT_CLR (0x8C) + + +/** + Define the incoming data byte order +*/ +extern const TCgByteOrder CGX_DRIVER_NATIVE_BYTE_ORDER; + +BOOL isBlockCanceled(TCgxDriverState * apState, U32 aBlockNumber); + +#endif diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverLinux.c b/drivers/misc/gpsip/cgdriver/CgxDriverLinux.c new file mode 100644 index 00000000..7d9cdc3c --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverLinux.c @@ -0,0 +1,1373 @@ +/****************************************************************************** + * 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 */ + + +/** + \cond OS_LINUX +*/ + +/** + \file + \brief Linux specific driver code + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + Specific code required for the CellGuide GPS driver for Linux. +*/ +// =========================================================================== + +#define __CGXLINUXDRIVER_C__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif + +#include "CgTypes.h" +#include "CgReturnCodes.h" +#include "CgCpu.h" +#include "CgxDriverCore.h" +#include "CgxDriverOs.h" +#include "CgxDriverPlatform.h" + +#include "platform.h" +#include "CgCpuOs.h" + + +extern U32 CGCORE_REG_OFFSET_CORE_RESETS; +extern U32 CGCORE_REG_OFFSET_VERSION; +extern U32 poffset; + + +struct class * gps_class; +struct device * gps_dev; + + + +/*paulluo add test*/ +//#define FIX_MEMORY +#ifdef CGCORE_ACCESS_VIA_SPI +extern int gpsspidev_init(void); +extern void gpsspidev_exit(void); +#endif + + +// =========================================================================== + +// +// Driver instance structure. +// +typedef struct { + struct cdev cdev; + int nNumOpens; + int DataReady_irq; + int GpsIntr_irq; + struct completion xferCompleted; // was rcvSem + TCgxDriverPhysicalMemory chunk; + TCgxDriverState state; + void *xfer_buff_ptr; // Internal buffer pointer + unsigned long xfer_buff_len; // Internal buffer len (bytes) + int xfer_buff_pg_order; // Internal buffer page order (log2(n)) + int xfer_buff_mmapped; // Internal buffer is mapped + struct fasync_struct *async_queue; + wait_queue_head_t resumeq; + char pm_resumed; +} DRVCONTEXT; + +// Use a static DriverContext, as only one driver instance is needed +static DRVCONTEXT DrvContext; +//bxd add for first alloc mem failed from engine +static void *init_buff_ptr; + +static void GpsIntr_BH(struct work_struct *work); +DECLARE_WORK( girq_work, GpsIntr_BH ); +static struct workqueue_struct *girq_wq = NULL; +#define GIRQ_WQ_NAME "GIRQ WorkQueue" + +static void DataReady_BH(struct work_struct *work); +DECLARE_WORK( drdy_work, DataReady_BH ); +static struct workqueue_struct *drdy_wq = NULL; +#define DRDY_WQ_NAME "DRDY WorkQueue" + +// In certain devices, there will not be an irq for DMA ready, but instead, a wait-able, exported sync-object. +#ifdef CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT + + static void DataReady_Completion_WorkQueue(struct work_struct *work); + DECLARE_WORK( drdy_completion_work, DataReady_Completion_WorkQueue ); + static struct workqueue_struct *drdy_completion_wq = NULL; + #define DRDY_COMPLETION_WQ_NAME "DRDY Completion WorkQueue" + + extern struct completion CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT; + + /* + DataReady Interrupt Handlers: + DataReady_BH: The Bottom-Half (Handler Thread) + DataReady_TH: The Top-Half (ISR) + CgxDriverDataReadyInterruptHandlerStart: Register the DataReady ISR + */ + static void DataReady_Completion_WorkQueue(struct work_struct *work) + { + // DBG_FUNC_NAME("DataReady_BH") + // DBGMSG("START"); + while (1) + { + wait_for_completion( &CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT ); + CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state); + } + + // DBGMSG("END"); + } +#endif + +static int cgxdrv_major = 0; /* 0 = dynamic major */ +#define MODULE_NAME "cgxdrv" + + +/* + DataReady Interrupt Handlers: + DataReady_BH: The Bottom-Half (Handler Thread) + DataReady_TH: The Top-Half (ISR) + CgxDriverDataReadyInterruptHandlerStart: Register the DataReady ISR + */ +static void DataReady_BH(struct work_struct *work) +{ + // DBG_FUNC_NAME("DataReady_BH") + // DBGMSG("START"); + CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state); + //enable_irq( DrvContext.DataReady_irq ); + // DBGMSG("END"); +} + +static irqreturn_t DataReady_TH(int irq, void *dev_id) +{ + // DBG_FUNC_NAME("DataReady_TH") + // DBGMSG("START"); + //disable_irq_nosync( irq ); + + queue_work(drdy_wq, &drdy_work); + // DBGMSG("END"); + + return IRQ_HANDLED; +} + + +#ifdef CGCORE_ACCESS_VIA_SPI +u32 GetRequestLen(void) +{ + TCgxDriverState *pState = &DrvContext.state; + + return pState->transfer.bytes.required; +} + +void DataReady_TH_start(void ) +{ + + CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state); + +} +#endif +void* Data_Get_DrvContext(void) +{ + + return DrvContext.xfer_buff_ptr; +} + +void CCgCpuDmaHandle(int irq,void* dev_id) +{ + CgxDriverDataReadyInterruptHandler(&DrvContext, &DrvContext.state); +} + + +TCgReturnCode CgxDriverDataReadyInterruptHandlerStart(void *pDriver) +{ + DBG_FUNC_NAME("CgxDriverDataReadyInterruptHandlerStart") + DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver; + + int rv = 0; + + // First check if there is an irq dedicated to the DataReady event + pDriverInfo->DataReady_irq = CgxDriverDataReadyInterruptCode(); + if( pDriverInfo->DataReady_irq != 0) + { + drdy_wq = create_singlethread_workqueue(DRDY_WQ_NAME); + + if (drdy_wq == NULL) { + DBGMSG("create_singlethread_workqueue(" DRDY_WQ_NAME ") Failed"); + return ECgInitFailure; + } + + rv = request_irq( pDriverInfo->DataReady_irq, DataReady_TH, IRQF_DISABLED, "drdy-bh", NULL ); + if (rv != 0) { + DBGMSG1("request_irq(%d) Failed", pDriverInfo->DataReady_irq ); + return ECgInitFailure; + } + DBGMSG1("request_irq(DRDY/%d) OK", pDriverInfo->DataReady_irq ); + } + else + { + // There is no irq. Lets check if there is an exported sync-object + #ifdef CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT + drdy_completion_wq = create_singlethread_workqueue(DRDY_COMPLETION_WQ_NAME); + if ( OK(drdy_completion_wq) ) + queue_work(drdy_completion_wq, &drdy_completion_work); + else + return ECgInitFailure; + #else + DBGMSG1("request_irq(DRDY/%d) Skipped", pDriverInfo->DataReady_irq ); + #endif + } + + return ECgOk; +} + + + +/* + GpsIntr Interrupt Handlers: + GpsIntr_BH: The Bottom-Half (Handler Thread) + GpsIntr_TH: The Top-Half (ISR) + CgxDriverGeneralInterruptHandlerStart: Register the GpsIntr ISR + */ +static void GpsIntr_BH(struct work_struct *work) +{ + // DBG_FUNC_NAME("GpsIntr_BH") + // DBGMSG("START"); + CgxDriverGpsInterruptHandler(&DrvContext, &DrvContext.state); + // DBGMSG("END"); + enable_irq( DrvContext.GpsIntr_irq ); +} + +static irqreturn_t GpsIntr_TH(int irq, void *dev_id) +{ + // DBG_FUNC_NAME("GpsIntr_TH") + // DBGMSG("START"); + disable_irq_nosync( irq ); + + queue_work(girq_wq, &girq_work); + + // DBGMSG("END"); + return IRQ_HANDLED; +} + +TCgReturnCode CgxDriverGpsInterruptHandlerStart(void *pDriver) +{ + DBG_FUNC_NAME("CgxDriverGpsInterruptHandlerStart") + DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver; + + int rv = 0; + pDriverInfo->GpsIntr_irq = CgxDriverGpsInterruptCode(); + if (pDriverInfo->GpsIntr_irq != 0) + { + girq_wq = create_singlethread_workqueue(GIRQ_WQ_NAME); + if (girq_wq == NULL) { + DBGMSG("create_singlethread_workqueue(" GIRQ_WQ_NAME ") Failed"); + return ECgInitFailure; + } + #ifdef CGCORE_ACCESS_VIA_SPI + rv = request_irq( pDriverInfo->GpsIntr_irq, GpsIntr_TH, IRQF_TRIGGER_RISING, "girq-bh", NULL ); + #else + rv = request_irq( pDriverInfo->GpsIntr_irq, GpsIntr_TH, IRQF_DISABLED, "girq-bh", NULL ); + #endif + if (rv != 0) { + DBGMSG1("request_irq(%d) Failed", pDriverInfo->GpsIntr_irq ); + return ECgInitFailure; + } + DBGMSG1("request_irq(GPS/%d) OK", pDriverInfo->GpsIntr_irq ); + } + else + DBGMSG1("request_irq(GPS/%d) Skipped", pDriverInfo->GpsIntr_irq ); + + return ECgOk; +} + + + + + +TCgReturnCode CgxDriverTransferEndCreate(void *pDriver) +{ + DBG_FUNC_NAME("CgxDriverTransferEndCreate") + DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver; + + DBGMSG( "Entering... Initializing completion semaphore" ); + + init_completion( &pDriverInfo->xferCompleted ); + + DBGMSG1( "Initialized Semaphore=%u", pDriverInfo->xferCompleted.done ); + + return ECgOk; +} + + + +TCgReturnCode CgxDriverTransferEndSignal(void *pDriver) +{ + //DBG_FUNC_NAME("CgxDriverTransferEndSignal") + DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver; + +/* DBGMSG( "Entering" );*/ + + //DBGMSG1( "Marking completion... Semaphore=%u", pDriverInfo->xferCompleted.done ); + complete( &pDriverInfo->xferCompleted ); + //DBGMSG1( "Marked completion... After Semaphore=%u", pDriverInfo->xferCompleted.done ); + + return ECgOk; +} + + +TCgReturnCode CgxDriverTransferEndWait(void *pDriver, U32 aTimeoutMS) +{ + DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver; + TCgReturnCode rc = ECgOk; + unsigned long timeout = aTimeoutMS * HZ / 1000; + unsigned long rv = 0 ; + DBG_FUNC_NAME("CgxDriverTransferEndWait") + + DBGMSG1( "Timeout=%lu", timeout ); + + + for (;;) { + if (pDriverInfo->state.flags.resume == 1) { + DBGMSG("Resume!"); + return ECgResume; + } + //DBGMSG1( "Waiting for completion... Semaphore=%u", pDriverInfo->xferCompleted.done ); + /*bxd modify because of can't entry susnpend when use wait_for_completion_interruptible_timeout func */ + //rv = wait_for_completion_interruptible_timeout( &pDriverInfo->xferCompleted, timeout ); + rv = wait_for_completion_timeout( &pDriverInfo->xferCompleted, timeout ); + if (rv != -ERESTARTSYS) + break; + } + + if ((rv == 0) && (timeout > 0)) + { + rc = ECgTimeout; + DBGMSG( "Timed-out" ); + } + else + { + DBGMSG1( "wait_for_completion_interruptible_timeout returned=%d", rv ); + } + + if (pDriverInfo->state.flags.resume == 1) { + DBGMSG("Resume!"); + rc = ECgResume; + } + + return rc; +} + + +TCgReturnCode CgxDriverTransferEndDestroy(void *pDriver) +{ + return ECgOk; +} + + +//#define FIX_MEMORY + +#ifdef FIX_MEMORY +unsigned char buf_data[6*1024*1024]; +#else + void* buf_data; +#endif + +#ifndef CGCORE_ACCESS_VIA_SPI +void clear_buf_data(void) +{ + memset(DrvContext.xfer_buff_ptr,0,DrvContext.xfer_buff_len); +} +#endif + +TCgReturnCode CgxDriverAllocInternalBuff(void *pDriver, U32 aLength, void **apBuffer, U32 aProcessID) +{ + DBG_FUNC_NAME("CgxDriverAllocInternalBuff") + DRVCONTEXT *pDriverInfo = (DRVCONTEXT *)pDriver; + DBGMSG( "Entering..." ); + + /* Already alloc'ed, return error and ask to free 1st */ + if (DrvContext.xfer_buff_ptr != NULL) { + DBGMSG( "Returning ECgNotSupported" ); + return ECgNotSupported; + } + + + #ifndef FIX_MEMORY + DrvContext.xfer_buff_pg_order = get_order(aLength); + //bxd add for first alloc mem failed from engine + if(init_buff_ptr != NULL) + DrvContext.xfer_buff_ptr = init_buff_ptr; + else + DrvContext.xfer_buff_ptr = (void *)__get_free_pages(GFP_KERNEL, DrvContext.xfer_buff_pg_order); + DrvContext.xfer_buff_len = PAGE_SIZE * (1 << DrvContext.xfer_buff_pg_order); + buf_data = DrvContext.xfer_buff_ptr; + #else + DrvContext.xfer_buff_pg_order = get_order(aLength); + DrvContext.xfer_buff_ptr =(void*)&buf_data[0]; + DrvContext.xfer_buff_len = 6*1024*1024; + + #endif + + + if (DrvContext.xfer_buff_ptr == NULL) { + DBGMSG( "Returning ECgErrMemory" ); + return ECgErrMemory; + } + + pDriverInfo->state.buffer.length = DrvContext.xfer_buff_len; + pDriverInfo->state.buffer.virtAddr = DrvContext.xfer_buff_ptr; + pDriverInfo->state.buffer.physAddr = __pa((void *)DrvContext.xfer_buff_ptr) ; + DBGMSG2( "Returning ECgOk - Requested: %lu - Granted: %lu", aLength, DrvContext.xfer_buff_len ); + + *apBuffer = (void *)pDriverInfo->state.buffer.physAddr; +#if defined(CGTEST) || defined(DEBUG) + memset(pDriverInfo->state.buffer.virtAddr, 0x43, aLength); +#endif + 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 ); + return ECgOk; +} + +#ifdef CGCORE_ACCESS_VIA_SPI +int get_blocksize(void) +{ + return DrvContext.state.transfer.blockSize; +} +#endif + + +void *CgxDriverGetInternalBuff(void *pSource, U32 length) +{ +// if (length != DrvContext.xfer_buff_len) +// return NULL; + + return DrvContext.xfer_buff_ptr; +} + + + +TCgReturnCode CgxDriverFreeInternalBuff(void *pDriver, U32 unUsed) +{ + /* Already alloc'ed, return error and ask to free 1st */ + if (DrvContext.xfer_buff_ptr == NULL) + return ECgNotSupported; + + /* Buffer is mmap'ed. return error and ask to free 1st */ + if (DrvContext.xfer_buff_mmapped) + return ECgNotAllowed; + +#ifndef FIX_MEMORY +//bxd + //free_pages((unsigned long)DrvContext.xfer_buff_ptr, DrvContext.xfer_buff_pg_order); +#endif + + DrvContext.xfer_buff_ptr = NULL; + DrvContext.xfer_buff_len = 0; + DrvContext.xfer_buff_pg_order = 0; + + //bxd add for first alloc mem failed from engine + //if(init_buff_ptr != NULL) + // init_buff_ptr = NULL; + + return ECgOk; +} + + + +unsigned long CgxCopyFromUser(void *to, const void *fromuser, unsigned long n) +{ + return copy_from_user(to, fromuser, n); +} + + + +static void getdata32_to_data64(TCgDriverControl_32bit *In32,TCgDriverControl *In64) +{ + In64->read.alignedLength = In32->read.alignedLength; + In64->read.blockLength = In32->read.blockLength; + In64->read.byteOrder = In32->read.byteOrder; + In64->read.buf = Data_Get_DrvContext(); + In64->read.bufPhys = In32->read.bufPhys; + In64->read.timeoutMS = In32->read.timeoutMS; + In64->wait.timeoutMS = In32->wait.timeoutMS; + In64->wait.blockNumber = In32->wait.blockNumber; +// In64->write.pSource = &In32->write.pSource; + In64->write.length = In32->write.length; + In64->GPIO.code = In32->GPIO.code; + In64->GPIO.out = In32->GPIO.out; + In64->GPIO.mode = In32->GPIO.mode; + In64->readReg.offset = In32->readReg.offset; + In64->writeReg.offset = In32->writeReg.offset; + In64->writeReg.value = In32->writeReg.value; + In64->cancel.onByteCount = In32->cancel.onByteCount; + In64->reset.resetLevel = In32->reset.resetLevel; + In64->alloc.length = In32->alloc.length; + In64->alloc.processId = In32->alloc.processId; + In64->tcxoControl.enable = In32->tcxoControl.enable; + + +#if 0 + printk("read.alignedLength: 0x%x\n", In32->read.alignedLength); + printk("read.blockLength: 0x%x\n", In32->read.blockLength); + printk("read.byteOrder: 0x%x\n", In32->read.byteOrder); + printk("read.buf: 0x%x\n", In32->read.buf); + printk("read.bufPhys: 0x%x\n", In32->read.bufPhys); + printk("read.timeoutMS: 0x%x\n", In32->read.timeoutMS); + + printk("wait.timeoutMS: 0x%x\n", In32->wait.timeoutMS); + printk("wait.blockNumber: 0x%x\n", In32->wait.blockNumber); + printk("write.pSource: 0x%x\n", In32->write.pSource); + printk("write.length: 0x%x\n", In32->write.length); + printk("GPIO.code: 0x%x\n", In32->GPIO.code); + + printk("GPIO.out: 0x%x\n", In32->GPIO.out); + printk("GPIO.mode: 0x%x\n", In32->GPIO.mode); + printk("readReg.offset: 0x%x\n", In32->readReg.offset); + printk("writeReg.offset: 0x%x\n", In32->writeReg.offset); + printk("writeReg.value: 0x%x\n", In32->writeReg.value); + printk("cancel.onByteCount: 0x%x\n", In32->cancel.onByteCount); + printk("reset.resetLevel: 0x%x\n", In32->reset.resetLevel); + printk("alloc.length: 0x%x\n", In32->alloc.length); + printk("alloc.processId: 0x%x\n", In32->alloc.processId); + printk("tcxoControl.enable: 0x%x\n", In32->tcxoControl.enable); + + + printk("read.alignedLength In64: 0x%x\n", In64->read.alignedLength); + printk("read.blockLength In64: 0x%x\n", In64->read.blockLength); + printk("read.byteOrder In64: 0x%x\n", In64->read.byteOrder); + printk("read.buf In64: 0x%x\n", In64->read.buf); + printk("read.bufPhys In64: 0x%x\n", In64->read.bufPhys); + printk("read.timeoutMS In64: 0x%x\n", In64->read.timeoutMS); + + printk("wait.timeoutMS In64: 0x%x\n", In64->wait.timeoutMS); + printk("wait.blockNumber In64: 0x%x\n", In64->wait.blockNumber); + printk("write.pSource In64: 0x%x\n", In64->write.pSource); + printk("write.length In64: 0x%x\n", In64->write.length); + printk("GPIO.code In64: 0x%x\n", In64->GPIO.code); + + printk("GPIO.out In64: 0x%x\n", In64->GPIO.out); + printk("GPIO.mode In64: 0x%x\n", In64->GPIO.mode); + printk("readReg.offset In64: 0x%x\n", In64->readReg.offset); + printk("writeReg.offset In64: 0x%x\n", In64->writeReg.offset); + printk("writeReg.value In64: 0x%x\n", In64->writeReg.value); + printk("cancel.onByteCount In64: 0x%x\n", In64->cancel.onByteCount); + printk("reset.resetLevel In64: 0x%x\n", In64->reset.resetLevel); + printk("alloc.length In64: 0x%x\n", In64->alloc.length); + printk("alloc.processId In64: 0x%x\n", In64->alloc.processId); + printk("tcxoControl.enable In64: 0x%x\n", In64->tcxoControl.enable); +#endif +} + + + +static void putdata64_to_data32(TCgDriverStatus_32bit *Out32,TCgDriverStatus *Out64) +{ + Out32->rc = Out64->rc; + Out32->buffer.bufferPhysAddr = (unsigned int)Out64->buffer.bufferPhysAddr; + Out32->buffer.bufferAppVirtAddr = poffset; + Out32->buffer.size = Out64->buffer.size; + Out32->GPIO.code = Out64->GPIO.code; + Out32->GPIO.val = Out64->GPIO.val; + //Out32->version.buildVersion = &Out64->version.buildVersion[0]; + //Out32->version.buildNumber = &Out64->version.buildNumber[0]; + //Out32->version.buildDate = &Out64->version.buildDate[0]; + //Out32->version.buildTime = &Out64->version.buildTime[0]; + //Out32->version.buildMode = &Out64->version.buildMode[0]; + //Out32->version.buildName = &Out64->version.buildName[0]; + Out32->readReg.offset = Out64->readReg.offset; + Out32->readReg.value = Out64->readReg.value; + //Out32->cpuRevision.revisionCode = &Out64->cpuRevision.revisionCode[0]; + Out32->readRtc.year = Out64->readRtc.year; + Out32->readRtc.month = Out64->readRtc.month; + Out32->readRtc.day = Out64->readRtc.day; + Out32->readRtc.hour = Out64->readRtc.hour; + Out32->readRtc.minute = Out64->readRtc.minute; + Out32->readRtc.second = Out64->readRtc.second; + Out32->readRtc.dayInWeek = Out64->readRtc.dayInWeek; + Out32->readRtc.tick = Out64->readRtc.tick; + Out32->state.flags.terminate = Out64->state.flags.terminate; + Out32->state.flags.wait = Out64->state.flags.wait; + Out32->state.flags.overrun = Out64->state.flags.overrun; + Out32->state.flags.resume = Out64->state.flags.resume; + Out32->state.counters.interrupt.all = Out64->state.counters.interrupt.all; + Out32->state.counters.interrupt.snapStart = Out64->state.counters.interrupt.snapStart; + Out32->state.counters.interrupt.overrun = Out64->state.counters.interrupt.overrun; + Out32->state.transfer.bufferPhys = Out64->state.transfer.bufferPhys; + Out32->state.transfer.originalBuffer = (unsigned int)( Out64->state.transfer.originalBuffer); + Out32->state.transfer.byteOrder = Out64->state.transfer.byteOrder; + Out32->state.transfer.done = Out64->state.transfer.done; + Out32->state.transfer.bytes.required = Out64->state.transfer.bytes.required; + Out32->state.transfer.bytes.received = Out64->state.transfer.bytes.received; + Out32->state.transfer.blocks.required = Out64->state.transfer.blocks.required; + Out32->state.transfer.blocks.received = Out64->state.transfer.blocks.received; + Out32->state.transfer.chunks.required = Out64->state.transfer.blocks.received; + Out32->state.transfer.chunks.received = Out64->state.transfer.chunks.received; + Out32->state.transfer.chunks.active = Out64->state.transfer.chunks.active; + Out32->state.transfer.cancel.request = Out64->state.transfer.cancel.request; + Out32->state.transfer.cancel.onByte = Out64->state.transfer.cancel.onByte; + Out32->state.transfer.cancel.onChunk = Out64->state.transfer.cancel.onChunk; + //Out32->state.transfer.bufferOffset = Out64->state.transfer.bufferOffset; + Out32->state.transfer.blockSize = Out64->state.transfer.blockSize; + Out32->state.transfer.lastBlockSize = Out64->state.transfer.lastBlockSize; + Out32->state.buffer.physAddr = Out64->state.buffer.physAddr; + Out32->state.buffer.virtAddr = (unsigned int)(Out64->state.buffer.virtAddr); + Out32->state.buffer.length = Out64->state.buffer.length; + Out32->state.buffer.driverContextVirtBufferAddr = (unsigned int)(Out64->state.buffer.driverContextVirtBufferAddr); + Out32->state.constructionRc = Out64->state.constructionRc; +#if 0 + printk("Out64.readReg.offset: 0x%x\n", Out64->readReg.offset); + printk("Out64.readReg.value: 0x%x\n", Out64->readReg.value); + printk("Out32.readReg.offset: 0x%x\n", Out32->readReg.offset); + printk("Out32.readReg.value: 0x%x\n", Out32->readReg.value); + #endif +} +#if 0 +static void printdata32(TCgDriverStatus_32bit *Out32) +{ + + printk(" Out32->rc: 0x%x\n", Out32->rc); + printk(" Out32->buffer.bufferPhysAddr: 0x%x\n", Out32->buffer.bufferPhysAddr); + printk(" Out32->buffer.bufferAppVirtAddr: 0x%x\n", Out32->buffer.bufferAppVirtAddr); + printk(" Out32->buffer.size : 0x%x\n", Out32->buffer.size ); + printk(" Out32->GPIO.code : 0x%x\n", Out32->GPIO.code ); + printk(" Out32->GPIO.val: 0x%x\n", Out32->GPIO.val); + + printk(" Out32->version.buildVersion: 0x%x\n", Out32->version.buildVersion); + printk(" Out32->version.buildNumber: 0x%x\n", Out32->version.buildNumber); + printk(" Out32->version.buildDate : 0x%x\n", Out32->version.buildDate ); + printk(" Out32->version.buildTime: 0x%x\n", Out32->version.buildTime); + printk(" Out32->version.buildMode : 0x%x\n", Out32->version.buildMode ); + printk(" Out32->version.buildName: 0x%x\n", Out32->version.buildName); + + printk(" Out32->readReg.offset: 0x%x\n", Out32->readReg.offset); + printk(" Out32->readReg.value: 0x%x\n", Out32->readReg.value); + printk(" Out32->readRtc.year : 0x%x\n", Out32->readRtc.year ); + printk(" Out32->readRtc.month: 0x%x\n", Out32->readRtc.month); + printk(" Out32->readRtc.day: 0x%x\n", Out32->readRtc.day); + printk(" Out32->readRtc.hour: 0x%x\n", Out32->readRtc.hour); + printk(" Out32->readRtc.minute: 0x%x\n", Out32->readRtc.minute); + printk(" Out32->readRtc.second: 0x%x\n", Out32->readRtc.second); + printk(" Out32->readRtc.dayInWeek: 0x%x\n", Out32->readRtc.dayInWeek); + printk(" Out32->readRtc.tick: 0x%x\n", Out32->readRtc.tick); + + + + + printk(" Out32->state.flags.terminate: 0x%x\n", Out32->state.flags.terminate); + printk(" Out32->state.flags.wait: 0x%x\n", Out32->state.flags.wait); + printk(" Out32->state.flags.overrun: 0x%x\n", Out32->state.flags.overrun); + printk(" Out32->state.flags.resume: 0x%x\n", Out32->state.flags.resume); + printk(" Out32->state.counters.interrupt.all: 0x%x\n", Out32->state.counters.interrupt.all); + printk(" Out32->state.counters.interrupt.snapStart: 0x%x\n", Out32->state.counters.interrupt.snapStart); + printk(" Out32->state.counters.interrupt.overrun: 0x%x\n", Out32->state.counters.interrupt.overrun); + printk(" Out32->state.transfer.bufferPhys: 0x%x\n", Out32->state.transfer.bufferPhys); + printk(" Out32->state.transfer.originalBuffer: 0x%x\n", Out32->state.transfer.originalBuffer); + printk(" Out32->state.transfer.byteOrder: 0x%x\n", Out32->state.transfer.byteOrder); + printk(" Out32->state.transfer.done: 0x%x\n", Out32->state.transfer.done); + printk(" Out32->state.transfer.bytes.required: 0x%x\n", Out32->state.transfer.bytes.required); + printk(" Out32->state.transfer.bytes.received: 0x%x\n", Out32->state.transfer.bytes.received); + printk(" Out32->state.transfer.blocks.required: 0x%x\n", Out32->state.transfer.blocks.required); + printk(" Out32->state.transfer.blocks.received: 0x%x\n", Out32->state.transfer.blocks.received); + printk(" Out32->state.transfer.chunks.required: 0x%x\n", Out32->state.transfer.chunks.required); + printk(" Out32->state.transfer.chunks.received: 0x%x\n", Out32->state.transfer.chunks.received); + printk(" Out32->state.transfer.chunks.active: 0x%x\n", Out32->state.transfer.chunks.active); + printk(" Out32->state.transfer.cancel.request: 0x%x\n", Out32->state.transfer.cancel.request); + printk(" Out32->state.transfer.cancel.onByte: 0x%x\n", Out32->state.transfer.cancel.onByte); + printk(" Out32->state.transfer.cancel.onChunk : 0x%x\n", Out32->state.transfer.cancel.onChunk ); + printk(" Out32->state.transfer.bufferOffset: 0x%x\n", Out32->state.transfer.bufferOffset); + printk(" Out32->state.transfer.blockSize: 0x%x\n", Out32->state.transfer.blockSize); + printk(" Out32->state.transfer.lastBlockSize: 0x%x\n", Out32->state.transfer.lastBlockSize); + printk(" Out32->state.buffer.physAddr: 0x%x\n", Out32->state.buffer.physAddr); + printk(" Out32->state.buffer.virtAddr: 0x%x\n", Out32->state.buffer.virtAddr); + + printk(" Out32->state.buffer.length: 0x%x\n", Out32->state.buffer.length); + printk(" Out32->state.buffer.driverContextVirtBufferAddr: 0x%x\n", Out32->state.buffer.driverContextVirtBufferAddr); + printk(" Out32->state.constructionRc: 0x%x\n", Out32->state.constructionRc); + printk(" Out32->rc: 0x%x\n", Out32->rc); + printk(" Out32->rc: 0x%x\n", Out32->rc); + + + + + + + + + + + //Out32->cpuRevision.revisionCode = &Out64->cpuRevision.revisionCode[0]; + +} +#endif +//====================================================================== +// CGX_IOControl - Called when DeviceIOControl called +// +//static int CGX_IOControl(struct inode *inode,struct file *filp, +static long CGX_IOControl(struct file *filp, + + unsigned int cmd, unsigned long arg) +{ + DBG_FUNC_NAME("CGX_IOControl") + TCgReturnCode rc = ECgOk; + TCgDriverControl In; + TCgDriverStatus Out; + + TCgDriverControl_32bit In_32; + TCgDriverStatus_32bit Out_32; + +//printk("cmd:0x%x,arg:0x%x\n",cmd,arg); + /* DBGMSG1( "Entering...[%d]" , cmd); */ + + + // Check we can read the TCgDriverControl from User Space + if ( !access_ok( VERIFY_READ, (void __user *)arg, sizeof(TCgDriverControl_32bit) ) ) { + DBGMSG( "Returning -EFAULT 1" ); + return -EFAULT; + } + + // Check we can write the TCgDriverStatus to User Space + if ( !access_ok( VERIFY_WRITE, (void __user *)arg, sizeof(TCgDriverStatus_32bit) ) ) { + DBGMSG( "Returning -EFAULT 2" ); + return -EFAULT; + } + + if ( copy_from_user( &In_32, (void __user *)arg, sizeof(In_32) ) ) { + DBGMSG( "Returning -EFAULT 3" ); + return -EFAULT; + } + + getdata32_to_data64(&In_32,&In); + + rc = CgxDriverExecute( &DrvContext, &DrvContext.state, cmd, &In, &Out); + + putdata64_to_data32(&Out_32,&Out); + + if ( copy_to_user( (void __user *)arg, &Out_32, sizeof(Out_32) ) ) { + DBGMSG( "Returning -EFAULT 4" ); + return -EFAULT; + } + + DBGMSG1( "Returning %d", (OK(rc)) ? 0 : -ENOTTY ); + return (OK(rc)) ? 0 : -ENOTTY; + +} + + +int CGX_CompleteDrv(void) +{ + complete(&DrvContext.xferCompleted); + return 0; +} + +EXPORT_SYMBOL_GPL(CGX_CompleteDrv); + +//====================================================================== +// CGX_Fasync - Called when driver closed +// +static int CGX_Fasync( int fd, struct file *filp, int mode) +{ + return fasync_helper(fd, filp, mode, &DrvContext.async_queue); +} + +unsigned int CgxDriverCheckAllocInternalBuff(void) +{ + + if (DrvContext.xfer_buff_ptr != NULL) { + printk( "\n already alloc page \n" ); + return 0; + } + return 1; +} + + + +//====================================================================== +// CGX_Close - Called when driver closed +// +static int CGX_Close( struct inode *inode, struct file *filp) +{ +/* DBGMSG( "Entering..." ); */ + +#if 0 + //gaole add begin + int rc = 0; + + CgCoreReleaseRes(); + if (CgxDriverCheckAllocInternalBuff() == 0) + { + printk("\n gaole: close check if old page be released \n"); + + rc = CgxDriverFreeInternalBuff(NULL, 0); + + if(ECgOk != rc) + { + printk("\n gaole: close run CgxDriverFreeInternalBuff error,error code is %d \n",rc); + } + + } + + rc = CgCpuDmaStop(0); + if(ECgOk != rc) + { + printk("\n gaole: run CgCpuDmaStop error,error code is %d \n",rc); + + } + CgGpsReset(); +#endif + + CgCpuDmaDestroy(0,0); + // gaole add end + + + if (DrvContext.nNumOpens) + DrvContext.nNumOpens--; + + if ( filp->f_flags & FASYNC) { + CGX_Fasync(-1, filp, 0); /* Remove from async queue */ + } + +/* DBGMSG( "Returning 0" ); */ + return 0; +} + + +//====================================================================== +// CGX_Read - Called when driver read +// +static ssize_t CGX_Read( struct file *filp, char __user *buff, size_t count, loff_t *offp) +{ + while (DrvContext.pm_resumed == 0) { + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + //DBGMSG( "Waiting for resume to take place... Going to sleep\n" ); + if (wait_event_interruptible(DrvContext.resumeq, (DrvContext.pm_resumed != 0))) + return -ERESTARTSYS; + } + + /* + * Copy 1 char sizeof(*(char*)) from DrvContext.pm_resumed to buff + */ + if (put_user(DrvContext.pm_resumed, (char __user *)buff)) { + return -EFAULT; + } + + DrvContext.pm_resumed = 0; + return 1; +} + + +//====================================================================== +// CGX_Write - Called when driver written +// +static ssize_t CGX_Write( struct file *filp, const char __user *buff, size_t count, loff_t *offp) +{ + return 0; +} + + +//====================================================================== +// CGX_Poll - Called when driver select()/poll() +// +static unsigned int CGX_Poll(struct file *filp, poll_table *wait) +{ + poll_wait(filp, &DrvContext.resumeq, wait); + + if (DrvContext.pm_resumed == 'R') + return (POLLIN | POLLRDNORM); + + return 0; +} + +//====================================================================== +// CGX_Seek - Called when SetFilePtr called +// +static loff_t CGX_Seek (struct file *filp, loff_t off, int whence) +{ + return 0; +} + + + + + + +//====================================================================== +// CGX_Open - Called when driver opened +// +static int CGX_Open( struct inode *inode, struct file *filp ) +{ + + /* + * XXX-PK-XXX: Hold lock on DrvContext + */ + CgCpuDmaCreate(0,0); + +/* DBGMSG( "Entering..." ); */ + + // Count the number of opens. + DrvContext.nNumOpens++; + +/* DBGMSG( "Returning 0" ); */ + return 0; +} + + +/* + * CGX_vma_open and CGX_vma_close keep track of how many times + * the buffer is mapped, to avoid Freeing it while in use. + */ +static void CGX_vma_open(struct vm_area_struct *vma) +{ + DBG_FUNC_NAME("CGX_vma_open") + DrvContext.xfer_buff_mmapped++; + DBGMSG4("vma open [%d]: virt 0x%lx, Offs %lu, Len %lu", + DrvContext.xfer_buff_mmapped, + vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, vma->vm_end - vma->vm_start ); +} + +static void CGX_vma_close(struct vm_area_struct *vma) +{ + DBG_FUNC_NAME("CGX_vma_close") +/* DBGMSG( "Entering..." ); */ + + DrvContext.xfer_buff_mmapped--; + DBGMSG1("vma close [%d]", DrvContext.xfer_buff_mmapped ); + +/* DBGMSG( "Exit" ); */ +} + +#if LINUX_VERSION_CODE >= 132634 +static int CGX_vma_nopage(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + return VM_FAULT_SIGBUS; // Remapping is not allowed ! +} +#else +static struct page *CGX_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type) +{ + return NOPAGE_SIGBUS; // Remapping is not allowed ! +} +#endif + +static struct vm_operations_struct cgx_remap_ops = { + .open = CGX_vma_open, + .close = CGX_vma_close, + #if LINUX_VERSION_CODE >= 132634 + .fault = CGX_vma_nopage, + #else + .nopage = CGX_vma_nopage, + #endif +}; + +static int CGX_Mmap(struct file *filp, struct vm_area_struct *vma) +{ + DBG_FUNC_NAME("CGX_Mmap") + int rv; + unsigned long len = (vma->vm_end - vma->vm_start); + unsigned long off = vma->vm_pgoff << PAGE_SHIFT; + unsigned long physical = __pa((void *)DrvContext.xfer_buff_ptr) + off; + + DBGMSG3( "Entering... len=%lu off=%lu DrvContext.xfer_buff_len=%lu", len, off, DrvContext.xfer_buff_len ); + + if ( len > (DrvContext.xfer_buff_len - off) ) { + DBGMSG( "Returning -EINVAL" ); + return -EINVAL; + } + +#ifdef CGCORE_ACCESS_VIA_SPI + rv = remap_pfn_range(vma, vma->vm_start, + physical >> PAGE_SHIFT, len, + (vma->vm_page_prot)); +#else + + rv = remap_pfn_range(vma, vma->vm_start, + physical >> PAGE_SHIFT, len, + pgprot_noncached(vma->vm_page_prot)); + +#endif + + + + if (rv < 0) { + DBGMSG1( "Returning %d", rv ); + return rv; + } + + vma->vm_ops = &cgx_remap_ops; + CGX_vma_open(vma); +/* DBGMSG( "Returning 0" ); */ + return 0; +} + + +#if 0 +#warning CGX_AddSysDev is needed only for debugging ! +static int CGX_AddSysDev(struct sys_device *dev) +{ + DBGMSG( "Got to CGX_AddSysDev\n" ); + return 0; +} +#endif + + +static int CGX_PMSuspend(struct device *dev, pm_message_t state) +{ + #if 0 + //DBGMSG( "Got to CGX_PMSuspend\n" ); + printk("%s\n",__func__); + //if (DrvContext.nNumOpens > 0) + if(flag_power_up == 1) + { + CgxDriverPowerDown(); + CgxDriverRFPowerDown(); + } + #endif + return 0; +} + + +static int CGX_PMResume(struct device *dev) +{ + #if 0 + //DBGMSG( "Got to CGX_PMResume\n" ); + printk("%s\n",__func__); + //if (DrvContext.nNumOpens > 0) + if(flag_power_up == 1) + { + + DrvContext.state.flags.resume = 1; + #if 0 + DrvContext.pm_resumed = 'R'; + + /* awake read()ers and poll()ers (select) */ + wake_up_interruptible(&DrvContext.resumeq); + + /* signal async readers */ + if (DrvContext.async_queue) + kill_fasync(&DrvContext.async_queue, SIGIO, POLL_IN); + #endif + CgxDriverPowerUp(); + CgxDriverRFPowerUp(); + } +#endif + return 0; +} + + + +//====================================================================== +// CGX_Init - Driver initialization function +// +struct file_operations cgx_fops = { + .owner = THIS_MODULE, + .llseek = CGX_Seek, + .read = CGX_Read, + .write = CGX_Write, + .poll = CGX_Poll, + //bxd + //.ioctl = CGX_IOControl, + .unlocked_ioctl = CGX_IOControl, + #ifdef CONFIG_COMPAT + .compat_ioctl = CGX_IOControl, + #endif + .open = CGX_Open, + .fasync = CGX_Fasync, + .release = CGX_Close, + .mmap = CGX_Mmap, +}; + +#ifdef CONFIG_OF +#ifndef CGCORE_ACCESS_VIA_SPI +struct gps_2351_addr gps_2351; +u32 gps_get_core_base(void) +{ + return gps_2351.gps_base; +} + +u32 gps_get_ahb_base(void) +{ + return gps_2351.ahb_base; +} + +u32 gps_get_irq(void) +{ + return gps_2351.irq_num; +} + +u32 gps_get_lna_gpio(void) +{ + return gps_2351.lna_gpio; +} + +#ifdef CONFIG_ARCH_SCX30G +u32 gps_get_pmu_base(void) +{ + return gps_2351.pmu_base; +} +#endif + +static int cgxdrv_gps_source_init(void) +{ + int ret; + + struct device_node *np; + struct resource res; + + np = of_find_node_by_name(NULL, "gps_2351"); + if (!np) { + printk("Can't get the gps_2351 node!\n"); + return -ENODEV; + } + printk(" find the gps_2351 node!\n"); + + ret = of_address_to_resource(np, 0, &res); + if (ret < 0) { + printk("Can't get the gps reg base!\n"); + return -EIO; + } + gps_2351.gps_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res)); + printk("gps reg base is 0x%x\n", gps_2351.gps_base); + + ret = of_address_to_resource(np, 1, &res); + if (ret < 0) { + printk("Can't get the ahbreg base!\n"); + return -EIO; + } + gps_2351.ahb_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res)); + printk("ahb reg base is 0x%x\n", gps_2351.ahb_base); + + #ifdef CONFIG_ARCH_SCX30G + ret = of_address_to_resource(np, 2, &res); + if (ret < 0) { + printk("Can't get the pmu base!\n"); + return -EIO; + } + gps_2351.pmu_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res)); + printk("pmu_base base is 0x%x\n", gps_2351.pmu_base); + #endif + + gps_2351.irq_num = irq_of_parse_and_map(np, 0); + if (gps_2351.irq_num == 0) { + printk("Can't get the gps irq_num!\n"); + return -EIO; + } + printk(" gps_2351.gps_irq_num is %d\n", gps_2351.irq_num); + + gps_2351.lna_gpio = of_get_gpio(np, 0); + if(gps_2351.lna_gpio < 0){ + printk("fail to get gps lna gpio\n"); + } + return ret; +} +#endif +#endif +static int __init CGX_Init(void) +{ + DBG_FUNC_NAME("CGX_Init") + int rv; + dev_t devno = MKDEV(cgxdrv_major, 0); + +/* DBGMSG( "Entering..." ); */ + + DBGMSG("Initializing"); + + #ifdef CONFIG_OF + #ifndef CGCORE_ACCESS_VIA_SPI + cgxdrv_gps_source_init(); + #endif + #endif + + //bxd add for first alloc mem failed from engine + init_buff_ptr = (void *)__get_free_pages(GFP_KERNEL, 8); + if(init_buff_ptr == NULL) + printk("init_buff_ptr alloc failed\n"); + +#ifndef CGCORE_ACCESS_VIA_SPI + sprd_get_rf2351_ops(&gps_rf_ops); +#endif + +#ifdef CGCORE_ACCESS_VIA_SPI + gpsspidev_init(); +#endif + + /* Init structure */ + memset (&(DrvContext), 0, sizeof (DRVCONTEXT)); + init_waitqueue_head(&DrvContext.resumeq); + + /* Register char dev (Major can be provided at load time) */ + if (cgxdrv_major) { + rv = register_chrdev_region(devno, 1, "cgxdrv"); + printk(KERN_ERR "[CGX|%s] register_chrdev_region \r\n", __FUNCTION__); + } else { + rv = alloc_chrdev_region(&devno, 0, 1, "cgxdrv"); + cgxdrv_major = MAJOR(devno); + printk(KERN_ERR "[CGX|%s] alloc_chrdev_region, cgxdrv_major=%d \r\n", __FUNCTION__, cgxdrv_major); + } + + if (rv < 0) { + printk(KERN_ERR MODULE_NAME " Error can't get major %d\r\n", cgxdrv_major); + goto out; + } + + if ( CgxDriverConstruct(&DrvContext, &DrvContext.state) != ECgOk ) { + DBGMSG("CgxDriverConstruct Failed"); + rv = -ENOMEM; + goto out1; + } + + // Device is ready... Activate it + cdev_init(&DrvContext.cdev, &cgx_fops); + DrvContext.cdev.owner = THIS_MODULE; + DrvContext.cdev.ops = &cgx_fops; + rv = cdev_add (&DrvContext.cdev, devno, 1); + if (rv) { + // Cleanup + DBGMSG1(" Error %d adding cgxdrv device\r\n", rv); + goto out2; + } + + /* Create the device class. */ + gps_class = class_create(THIS_MODULE, "cgxdrv_class"); + if (IS_ERR(gps_class)) + { + DBGMSG(" Error: create cgxdrv class failed\r\n"); + } + + //bxd + gps_class->suspend = CGX_PMSuspend; + gps_class->resume = CGX_PMResume; + + /* register in /dev */ + gps_dev = device_create(gps_class, NULL, devno, NULL, "cgxdrv"); + if (IS_ERR(gps_dev)) + { + DBGMSG(" Error: device_create failed\r\n"); + class_destroy(gps_class); + } + + DBGMSG1(" Driver Ready... Major DevId: %d", cgxdrv_major ); + DBGMSG1(" Driver Byte order %d", CGX_DRIVER_NATIVE_BYTE_ORDER); + + goto out; + +out2: + /* + * XXX-PK-XXX: FIXME: Add CgxDriverConstruct Cleanup + * For example: free IRQs, destroy workqueues, etc. + */ +out1: + unregister_chrdev_region( devno, 1 ); +out: + return rv; +} + + +//====================================================================== +// CGX_Deinit - Driver de-initialization function +// +static void __exit CGX_Deinit(void) +{ + printk(KERN_ERR "[CGX|%s] in\r\n", __FUNCTION__); + + // Free the driver state buffer. + if (DrvContext.GpsIntr_irq != 0) + { + free_irq(DrvContext.GpsIntr_irq, NULL); + printk(KERN_ERR "free_irq GpsIntr_irq"); + } + + if (DrvContext.DataReady_irq != 0) + { + free_irq(DrvContext.DataReady_irq, NULL); + printk(KERN_ERR "free_irq DataReady_irq"); + } + + if (girq_wq) { + flush_workqueue(girq_wq); + destroy_workqueue(girq_wq); + printk(KERN_ERR "destroy_workqueue girq_wq"); + } + if (drdy_wq) { + flush_workqueue(drdy_wq); + destroy_workqueue(drdy_wq); + printk(KERN_ERR "destroy_workqueue drdy_wq"); + } + + #ifdef CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT + if (drdy_completion_wq) { + printk(KERN_ERR "CGX_Deinit (1)"); + //flush_workqueue(drdy_completion_wq); //commented for debug, because this function blocks ! + //destroy_workqueue(drdy_completion_wq); + printk(KERN_ERR "CGX_Deinit (2)"); + } + #endif +#if 0 + DrvContext.state.request.terminate = TRUE; + if(DrvContext.chunk.ptr) { + BOOL boo = FreePhysMem(DrvContext.chunk.ptr); + } +#endif + printk(KERN_ERR "CGX_Deinit (3)"); + + //free_irq(TEMPLATE_CPU_DMA_IRQ, NULL); + +#ifndef CGCORE_ACCESS_VIA_SPI + sprd_put_rf2351_ops(&gps_rf_ops); +#endif + CgxDriverFreeInternalBuff(&DrvContext, 0); + + cdev_del(&DrvContext.cdev); + + device_destroy(gps_class, MKDEV(cgxdrv_major, 0)); + class_destroy(gps_class); + + unregister_chrdev_region(MKDEV(cgxdrv_major, 0), 1); +#ifdef CGCORE_ACCESS_VIA_SPI + gpsspidev_exit(); +#endif + printk(KERN_ERR "CGX_Deinit out"); +} + + +late_initcall(CGX_Init); +module_exit(CGX_Deinit); + + +MODULE_LICENSE("GPL and additional rights"); +MODULE_AUTHOR("Pablo 'merKur' Kohan - for CellGuide Ltd."); +MODULE_DESCRIPTION("CellGuide GPSense CGX3XXX/CGX5XXX GPS CoProcessor driver"); + +/** \endcond */ diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverOs.h b/drivers/misc/gpsip/cgdriver/CgxDriverOs.h new file mode 100644 index 00000000..9f0793ea --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverOs.h @@ -0,0 +1,206 @@ +/****************************************************************************** + * 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 OS depended prototypes + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + + \addtogroup CGX_DRIVER_OS_API + \@{ + +*/ + +#ifndef CGX_DRIVR_OS_H +#define CGX_DRIVR_OS_H + +#include "CgReturnCodes.h" + + + + + + +/** + Get driver allocated buffer and convert it for application + + \param[in] pSource Map pointer passed from application to the driver space + \param[in] aLength Length allocated (bytes) + + \return Mapped pointer + \retval NULL on error + +*/ +void *CgxDriverGetInternalBuff(void *pSource, U32 aLength); + + + +/** + Allocate a kernel buffer + + \param[in] pDriver Pointer to driver global structure + \param[in] aLength Length to allocate (bytes) + \param[out] apBuffer allocated buffer address + \param[in] aProcessID process id + + \return System wide return code +*/ +TCgReturnCode CgxDriverAllocInternalBuff(void *pDriver, U32 aLength, void **apBuffer, U32 aProcessID); + + + + +/** + Free a kernel buffer + + \param[in] pDriver Pointer to drivers global data + \param[in] aProcessId process id + + \return System wide return code +*/ +TCgReturnCode CgxDriverFreeInternalBuff(void *pDriver, U32 aProcessId); + + + + +/** + Copy Memory from User Space + + \param[in] to Target address (Kernel Space) + \param[in] fromuser Source address (User Space) + \param[in] n Length to copy + + + \return Number of bytes NOT copied (0=success) + +*/ +unsigned long CgxCopyFromUser( + void *to, + const void *fromuser, + unsigned long n ); + + + + + + +/** + Create transfer end signaling object. + the object will be used for blocking the application until transfer is finished. + + \param[in] pDriver Global driver structure pointer + + \return System wide return code + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverTransferEndCreate( + void *pDriver); + + +/** + Destroy transfer end signaling object. + + \param[in] pDriver Global driver structure pointer + + \return System wide return code + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverTransferEndDestroy( + void *pDriver); + + +/** + Signal transfer end object + + \param[in] pDriver Global driver structure pointer + + \return System wide return code + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverTransferEndSignal( + void *pDriver); + + +/** + Wait for transfer end object + \param pDriver Global driver structure pointer + \param aTimeoutMS timeout for the wait, in mili seconds. + if the object is not singled after this time, the function will + return with ECgTimeout error code. + \return System wide return code + \retval ECgOk if data ready is 0 (low active) +*/ +TCgReturnCode CgxDriverTransferEndWait( + void *pDriver, + U32 aTimeoutMS); + + + + +/** + Start data ready interrupt handle + + \param[in] pDriver Global driver structure pointer + + \return System wide return code + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverDataReadyInterruptHandlerStart( + void *pDriver); + + + +/** + Start general interrupt handler + + \param[in] pDriver Global driver structure pointer + + \return System wide return code + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverGpsInterruptHandlerStart( + void *pDriver); + + +/** + Initialize the driver. + + This function is called as a result of GPSenseEngine specific CGX_IOCTL_INIT request, + and is used to initialize the driver and hardware for the first time. + + \param pDriver Global driver structure pointer + + \return System wide return code + \retval ECgOk if data ready is 0 (low active) + +*/ +TCgReturnCode CgxDriverInit( + void *pDriver); + + + + +#endif +/** + \@} +*/ diff --git a/drivers/misc/gpsip/cgdriver/CgxDriverPlatform.h b/drivers/misc/gpsip/cgdriver/CgxDriverPlatform.h new file mode 100644 index 00000000..ec38ab1f --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgxDriverPlatform.h @@ -0,0 +1,138 @@ +/****************************************************************************** + * 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 Driver platform depended API + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + +*/ + +#ifndef _CGX_DRIVER_PLATFORM_H__ +#define _CGX_DRIVER_PLATFORM_H__ + +#include "CgReturnCodes.h" +#include "CgxDriverApi.h" + +/** + Define the incoming data byte order +*/ +extern const TCgByteOrder CGX_DRIVER_NATIVE_BYTE_ORDER; + +/** + Return the interrupt code for DMA interrupt + \if OS_LINUX + On Linux, request_irq uses this value to register the specified interrupt handler + \endif + \if OS_ANDROID + On Android, request_irq uses this value to register the specified interrupt handler + \endif + \return interrupt code + \retval 0 Don't use interrupt +*/ +U32 CgxDriverDataReadyInterruptCode(void); + + + +/** + 0 means no IRQ code + + \return IRQ # of DMA +*/ +U32 CgxDriverDataReadyIrqCode(void); + + + +/** + Return the interrupt code for CGsnap interrupt + \if OS_LINUX + On Linux, request_irq uses this value to register the specified interrupt handler + \endif + \if OS_ANDROID + On Android, request_irq uses this value to register the specified interrupt handler + \endif + \return interrupt code + \retval 0 Don't use interrupt +*/ +U32 CgxDriverGpsInterruptCode(void); + + + +/** + 0 means no IRQ code + + \return IRQ # of GPS +*/ +U32 CgxDriverGpsIrqCode(void); + + + +/** + Configure Data Ready (DMA) interrupt pin & directions + this function is called once, on driver startup (\ref CgxDriverConstruct) + + \return System wide return code + \retval ECgOk Success +*/ +TCgReturnCode CgxDriverDmaInterruptPrepare(void); + + + +/** + Initial setup for CGsnap interrupt + this function is called once, on driver startup (\ref CgxDriverConstruct) + + \return System wide return code + \retval ECgOk Success +*/ +TCgReturnCode CgxDriverGpsInterruptPrepare(void); + + + + +/** + Return GPIO code for specific control line(for debug only) + + \param[in] aPinNumber GPIO code (CellGuide format) + \param[out] aGpioCode Pointer to returned value + + \return System wide return code + \retval ECgOk Success +*/ +TCgReturnCode CgxDriverGpioCode(int aPinNumber, int *aGpioCode); + + +TCgReturnCode CGxDriverGpsInterruptDone(U32 aIntCode); +TCgReturnCode CGxDriverDataReadyInterruptDone(U32 aIntCode); + + + +/** + Enable/Disable TCXO power + + \param[in] aEnable 1 = Enable TCXO, 0 =Disable TCXO + + \note If required, use platform.h to define specific device pins, + and keep the actual function generic. + + \return System wide return code + \retval ECgOk Success +*/ +TCgReturnCode CgxDriverTcxoEnable(U32 aEnable); + +#endif /* _CGX_DRIVER_PLATFORM_H__ */ diff --git a/drivers/misc/gpsip/cgdriver/Makefile b/drivers/misc/gpsip/cgdriver/Makefile new file mode 100644 index 00000000..e1144bb3 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/Makefile @@ -0,0 +1,98 @@ +#PATH := $(PREBUILD)/bin:$(PATH) + +obj-$(CONFIG_CGX_DRIVER) := cgxdrv.o + +# C Object Files: +cgxdrv-c-objs += CgxDriverLinux.o +cgxdrv-c-objs += CgxDriverCore.o +cgxdrv-c-objs += CgxDriverCoreCommon.o +cgxdrv-c-objs += CgCpuLinux.o +cgxdrv-c-objs += CgCpu.o +cgxdrv-c-objs += platform.o + + +#cgxdrv-c-objs += SPRD_FPGA_CPU.o +#cgxdrv-c-objs += SPRD_FPGA_GPIO.o +#cgxdrv-c-objs += SPRD_FPGA_DMA.o +#cgxdrv-c-objs += SPRD_FPGA_CLK.o +#cgxdrv-c-objs += SPRD_FPGA_INT.o +#cgxdrv-c-objs += SPRD_FPGA_RF.o +#cgxdrv-c-objs += gpsspi.o + +cgxdrv-c-objs += gps_gpio.o +cgxdrv-c-objs += gps_dma.o + +#bxd +ifeq ($(CONFIG_CGX_GE_GPS),y) +cgxdrv-objs += gpsspi.o +EXTRA_CFLAGS += -DCGCORE_ACCESS_VIA_SPI +endif +cgxdrv-objs += $(cgxdrv-c-objs) + + + + + +#LOCAL_CFLAGS := \ +#-DCGCORE_ACCESS_VIA_SPI +# Headers: +# Unused: CgFeatures.h pkfuncs.h toolhelp.h +cgxdrv-hdrs += CgBuildNumber.h +cgxdrv-hdrs += CgReturnCodes.h +cgxdrv-hdrs += CgTypes.h +cgxdrv-hdrs += CgVersion.h +cgxdrv-hdrs += CgCpu.h +cgxdrv-hdrs += CgCpuOs.h +cgxdrv-hdrs += SPRD_FPGA_CPU.h +cgxdrv-hdrs += SPRD_FPGA_CLK.h +cgxdrv-hdrs += SPRD_FPGA_DMA.h +cgxdrv-hdrs += SPRD_FPGA_GPIO.h +cgxdrv-hdrs += SPRD_FPGA_INT.h +cgxdrv-hdrs += CgxDriverCoreCommon.h +cgxdrv-hdrs += CgxDriverApi.h +cgxdrv-hdrs += CgxDriverCore.h +cgxdrv-hdrs += CgxDriverOs.h +cgxdrv-hdrs += CgxDriverPlatform.h +cgxdrv-hdrs += platform.h + + +#EXTRA_CFLAGS += \ +# -I. \ +# -I. \ +# -I. \ +# -I. \ +# -I. \ +# -I. \ +# -D__LINUX__ \ +# -D$(MODE) \ +# $(CG_CPPFLAGS) + + +ifeq ($(KERNELRELEASE),) +# on first call from remote location we get into this path +# whilst on second call all is managed by the embedding kernel makefile + +cgxdrv-cfiles = ${cgxdrv-c-objs:.o=.c} + +#default:: kmod_build + +#kmod_build:: $(cgxdrv-cfiles) $(cgxdrv-hdrs) + + +# distclean:: clean + +#grep:: +# grep $(G) $(cgxdrv-cfiles) + +#hgrep:: +# grep $(G) $(cgxdrv-hdrs) + +#clean:: +# rm -f *.o *.ko .*.cmd cgxdrv.mod.c $(cgxdrv-c-objs) $(obj-m) +# rm -rf .tmp_versions + +#tags:: +# $(MAKE) -C $(CG_KERNEL_DIR) SUBDIRS=$(CURDIR) tags +endif + +# ### EOF ### diff --git a/drivers/misc/gpsip/cgdriver/gps_dma.c b/drivers/misc/gpsip/cgdriver/gps_dma.c new file mode 100644 index 00000000..52371b5d --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/gps_dma.c @@ -0,0 +1,302 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "CgCpu.h" +#include "platform.h" + +#ifndef CGCORE_ACCESS_VIA_SPI +#define INVALIDE_DMA_CHN (-1) + +static struct sci_dma_cfg *cfg_list; +static struct reg_cfg_addr cfg_addr; +static int node_size; +static int cg_GpsDma_channel = INVALIDE_DMA_CHN; +static char *CgGps_Dev_name = "CgGps_Dev"; + +extern void clear_buf_data(void); +extern void CCgCpuDmaHandle(int irq,void* dev_id); + + +TCgReturnCode CgCpuDmaCreate(U32 aDmaChannel, U32 aIpDataSourceAddress) +{ + DBG_FUNC_NAME("CgCpuDmaCreate"); + DBGMSG("entry"); + if(cg_GpsDma_channel == INVALIDE_DMA_CHN) + { + cg_GpsDma_channel = sci_dma_request(CgGps_Dev_name, FULL_DMA_CHN); + + if(cg_GpsDma_channel < 0) + { + + printk("CgCpuDmaCreate fail err code = %d\n",cg_GpsDma_channel); + return cg_GpsDma_channel; + + } + printk("CgCpuDmaCreate succ chn = %d\n",cg_GpsDma_channel); + } + + return ECgOk; +} + + +TCgReturnCode CgCpuDmaDestroy(U32 aDmaChannel, U32 aIpDataSourceAddress) +{ + int rc; + printk("%s cg_GpsDma_channel:%d\n",__func__,cg_GpsDma_channel); + + if(cg_GpsDma_channel != INVALIDE_DMA_CHN) + { + rc = sci_dma_stop(cg_GpsDma_channel, DMA_GPS); + if(rc < 0) + { + printk("CgCpuDmaDestroy stop chn fail, chn num = %d, err code = %d\n",cg_GpsDma_channel,rc); + } + + rc = sci_dma_free(cg_GpsDma_channel); + if(rc < 0) + { + printk("CgCpuDmaDestroy free chn fail, chn num = %d, err code = %d\n",cg_GpsDma_channel,rc); + } + + cg_GpsDma_channel = INVALIDE_DMA_CHN; + } + return ECgOk ; +} + + + +TCgReturnCode CgCpuDmaIsReady(U32 aDmaChannel) +{ + TCgReturnCode rc = ECgOk; + DBG_FUNC_NAME("CgCpuDmaIsReady"); + DBGMSG("entry"); + + return rc; +} + +TCgReturnCode CgCpuDmaStop(U32 aDmaChannel) +{ + int rc; + + if(cfg_list != NULL) + { + kfree(cfg_list); + cfg_list = NULL; + } + + if(cfg_addr.virt_addr) + { + dma_free_coherent(NULL, sizeof(struct sci_dma_cfg) * node_size, (void *)cfg_addr.virt_addr, cfg_addr.phys_addr); + cfg_addr.virt_addr = 0; + cfg_addr.phys_addr = 0; + node_size = 0; + + } + + rc = sci_dma_stop(cg_GpsDma_channel, DMA_GPS); + if(rc < 0) + { + printk("CgCpuDmaStop stop chn fail, chn num = %d, err code = %d\n",cg_GpsDma_channel,rc); + } + + return ECgOk; + +} + +TCgReturnCode CgCpuDmaCurCount(U32 aDmaChannel, U32 *apCount) +{ + TCgReturnCode rc = ECgOk; + DBG_FUNC_NAME("CgCpuDmaCurCount"); + DBGMSG("entry"); + + return rc; +} + +// Get the DMA channel requested bytes count. +TCgReturnCode CgCpuDmaRequestedCount(U32 aDmaChannel, U32 *apCount) +{ + + TCgReturnCode rc = ECgOk; + DBG_FUNC_NAME("CgCpuDmaRequestedCount"); + DBGMSG("entry"); + + return rc; +} + +TCgReturnCode CgCpuDmaStart(U32 aDmaChannel) +{ + int rc; + printk("%s\n",__func__); + CgCpuCacheSync(); + rc = sci_dma_start(cg_GpsDma_channel, DMA_GPS); + if(rc < 0) + { + printk("CgCpuDmaStart start chn fail, chn num = %d, err code = %d\n",cg_GpsDma_channel,rc); + } + //CgCpuCacheSync(); + + return ECgOk; +} + +// Configure DMA to read data from GPS device. +TCgReturnCode CgCpuDmaSetupFromGps(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aDmaChannel, U32 aDeviceAddress) +{ + dma_addr_t cfg_p; + void * cfg_v; + int i,ret; + + clear_buf_data(); + + if(aDmaTaskCount == 0) + { + return ECgBadArgument; + } + + if(cfg_list != NULL) + { + kfree(cfg_list); + cfg_list = NULL; + } + if(cfg_addr.virt_addr != 0) + { + dma_free_coherent(NULL, sizeof(struct sci_dma_cfg) * node_size, (void *)cfg_addr.virt_addr, cfg_addr.phys_addr); + cfg_addr.virt_addr = 0; + cfg_addr.phys_addr = 0; + node_size = 0; + } + + node_size = aDmaTaskCount; + if(cfg_list == NULL) + { + cfg_list = kzalloc(sizeof(struct sci_dma_cfg) * node_size, GFP_KERNEL); + if (!cfg_list) { + printk("alloc memory failed!\n"); + return -ENOMEM; + } + } + + cfg_v = dma_alloc_coherent(NULL, sizeof(struct sci_dma_cfg) * node_size, + &cfg_p, GFP_KERNEL); + if (!cfg_v) { + printk("alloc cfg list mem failed!\n"); + return -ENOMEM; + } + + cfg_addr.phys_addr = (u32)cfg_p; + cfg_addr.virt_addr = (u32)cfg_v; + + /*must init the config with 0x0*/ + memset((void *)cfg_list, 0x0, sizeof(struct sci_dma_cfg) * node_size); + + for (i = 0; i < node_size; i++) { + /*the data width, byte short or word*/ + cfg_list[i].datawidth = WORD_WIDTH; + cfg_list[i].src_step = 4; + cfg_list[i].des_step = 4; + cfg_list[i].wrap_ptr = 0x21c0007c; + cfg_list[i].wrap_to = 0x21c00070; + cfg_list[i].fragmens_len = 16; + + + /* request mode: + * when receive an hardware or software dma request + * the dma will transfer a fragment, block or a transcation data + */ + cfg_list[i].req_mode = FRAG_REQ_MODE; + cfg_list[i].src_addr = aDeviceAddress; + + + cfg_list[i].des_addr = apDmaTask[i].address; + cfg_list[i].block_len = apDmaTask[i].length >= 65536 ? 65536 :apDmaTask[i].length; + cfg_list[i].transcation_len = apDmaTask[i].length; + + //printk("\n cfg_list[%d].block_len = %d\n",i,cfg_list[i].block_len); + //printk("\n cfg_list[%d].transcation_len = %d\n",i,cfg_list[i].transcation_len); + //printk("\n cfg_list[%d].src_addr = 0x%x\n",i,cfg_list[i].src_addr); + //printk("\n cfg_list[%d].des_addr = 0x%x\n",i,cfg_list[i].des_addr); + } + + /*indicate this the last node*/ + cfg_list[node_size - 1].is_end = 1; + + ret = sci_dma_config(cg_GpsDma_channel, cfg_list, node_size, &cfg_addr); + if (ret < 0) { + printk("dma config failed!\n"); + } + + sci_dma_register_irqhandle(cg_GpsDma_channel,TRANS_DONE,CCgCpuDmaHandle,NULL); + + return ECgOk; +} +#else +TCgReturnCode CgCpuDmaCreate(U32 aDmaChannel, U32 aIpDataSourceAddress) +{ + return ECgOk; +} + +TCgReturnCode CgCpuDmaDestroy(U32 aDmaChannel, U32 aIpDataSourceAddress) +{ + return ECgOk ; +} + +TCgReturnCode CgCpuDmaIsReady(U32 aDmaChannel) +{ + return ECgOk; +} + +TCgReturnCode CgCpuDmaStop(U32 aDmaChannel) +{ + return ECgOk; +} + +TCgReturnCode CgCpuDmaCurCount(U32 aDmaChannel, U32 *apCount) +{ + return ECgOk; +} + +TCgReturnCode CgCpuDmaRequestedCount(U32 aDmaChannel, U32 *apCount) +{ + return ECgOk; +} + +TCgReturnCode CgCpuDmaStart(U32 aDmaChannel) +{ + return ECgOk; +} + +TCgReturnCode CgCpuDmaSetupFromGps(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aDmaChannel, U32 aDeviceAddress) +{ + return ECgOk; +} + +#endif + +#ifdef TRACE_ON +void DbgStatDMA(const char *aTitle) +{ + //DBG_FUNC_NAME("DbgStatDMA"); + //DBGMSG1("%s", aTitle); + + +} +#endif + + diff --git a/drivers/misc/gpsip/cgdriver/gps_dma.h b/drivers/misc/gpsip/cgdriver/gps_dma.h new file mode 100644 index 00000000..13168d93 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/gps_dma.h @@ -0,0 +1,89 @@ +#ifndef GPS_DMA_H +#define GPS_DMA_H + +#include + +#ifdef __cplusplus + extern "C" + { +#endif + +#define MAX_DMA_CHUNK_SIZE (0x80000) + +#define MAX_DMA_TRANSFER_TASKS (64) + +#define DMAC_STATUS_SUCCESS (0) +#define DMAC_STATUS_ERROR (-1) + +#define SPRD_GPS_DMA_IRQ (44) + +#define DMAC_BLOCK_SIZE (0xffff) + +#define CH_STAT_MASK (0x0000000f) + +#define CHANNEL_ENABLE (1) +#define CHANNEL_DISABLE (0) + +#define DMAC_REMAP_NOACP 1 + +#define REG_PERI_CTRL0 (IO_ADDRESS(0xFCA09000)) + +#define RCHAIN_EN (0x02) +#define RCHAIN_EN_MASK (0xfffffffc) + +//#define NUMBER_1K (1024) + +#define NUMBER_16K (16*1024) + +#define NUMBER_64K (64*1024) + +#define REG_DMAC_BASE CG_DRIVER_DMA_BASE_PA + + +#define REG_DMAC_CX_CURR_CNT0 (IO_ADDRESS(REG_DMAC_BASE) + 0x0704) + +typedef struct DMA_CFG_S +{ + unsigned int src_addr; + unsigned int dma_phys; + unsigned int dma_size; + void __iomem *dma_virt; + + unsigned int lli_count; + unsigned int lli_size; + unsigned int lli_addr_pa; + void *lli_addr_va; + +}GPS_DMAC_CFG; + +typedef union{ + unsigned int cx_config_arg; + struct cx_config_bits + { + unsigned int ch_en : 1; + unsigned int itc_en : 1; + unsigned int flow_ctrl : 2; + unsigned int peri : 6; + unsigned int reserve1 : 2; + unsigned int dw : 3; + unsigned int reserve2 : 1; + unsigned int sw : 3; + unsigned int reserve3 : 1; + unsigned int dl : 4; + unsigned int sl : 4; + unsigned int dmode : 1; + unsigned int smode : 1; + unsigned int di : 1; + unsigned int si : 1; + }bits; +}cx_config_reg_s; + +int CgCpuDmaLLIDataCopyFromGps(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aDeviceAddress, U32 aDestAddress); + +int CgCpuDmaDataCopyFromGps(TCgCpuDmaTask *apDmaTask, U32 aDmaTaskCount, U32 aDeviceAddress, U32 aDestAddress); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/drivers/misc/gpsip/cgdriver/gps_gpio.c b/drivers/misc/gpsip/cgdriver/gps_gpio.c new file mode 100644 index 00000000..fd550143 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/gps_gpio.c @@ -0,0 +1,201 @@ +/****************************************************************************** + * 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 SPRD_FPGA GPIO support + + Functions to access GPIO unit in SPRD_FPGA CPU, allowing GPSenseEngine to control GPIO lines. + \attention This file is not completed, and must be updated for SPRD_FPGA (Please verify all 'TODO' comments are handled) + +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + +//#include +#include +//#include +#include +#include +#include +#include +// =========================================================================== +//Kernel Ioctl +#include "CgTypes.h" /**< CellGuide Types */ +#include "CgCpu.h" + +/** OK status */ +#define ECgOk (0) + + + + +// =========================================================================== + + + + + + +// =========================================================================== + + +/** + Internal function, set/reset a GPIO. + + This function is used by API functions CgCpuGpioSet & CgCpuGpioReset +*/ +#if 0 +static TCgReturnCode GpioSet(U32 aPin, U32 aValue) +{ + //DBG_FUNC_NAME("GpioSet"); + TCgReturnCode rc = ECgOk; + // unsigned long gpio_addr = 0; + return rc; +} +#endif + + +TCgReturnCode CgCpuGpioSet(U32 aPin) +{ + + U32 gpio_num; + gpio_num = aPin; + __gpio_set_value(gpio_num,1); + + return ECgOk; +} + + +TCgReturnCode CgCpuGpioReset(U32 aPin) +{ + U32 gpio_num; + + gpio_num = aPin; + __gpio_set_value(gpio_num,0); + return ECgOk ; +} + + +TCgReturnCode CgCpuGpioGet(U32 aPin, int *aValue) +{ + U32 rc = 0; + //DBG_FUNC_NAME("CgCpuGpioGet"); + + + *aValue = __gpio_get_value(aPin); + *aValue = 0; + return rc; +} + + +TCgReturnCode CgCpuGpioModeSet(U32 aPin, TCgCpuGpioMode aMode) +{ + //U32 extint = 0; + TCgReturnCode rc = ECgOk; + // unsigned long gpio_dir = 0; +//bxd add + if(aMode == ECG_CPU_GPIO_INPUT) + gpio_direction_input (aPin); + else if(aMode == ECG_CPU_GPIO_OUTPUT) + gpio_direction_output(aPin,1); + + //DBG_FUNC_NAME("CgCpuGpioModeSet") + + return rc; + +} + +TCgReturnCode CgCpuGpioPull(U32 aPinCode, TCgCpuGpioPull aPull) +{ + // U32 group = (aPinCode / CG_CPU_GPIO_GROUP_SIZE) - 1; + // U32 pin = aPinCode % CG_CPU_GPIO_GROUP_SIZE; + + return ECgOk; +} + + +TCgReturnCode CgCpuGpioStrength(U32 aPinCode, U32 aStrength) +{ + //U32 group = (aPinCode / CG_CPU_GPIO_GROUP_SIZE) - 1; + //U32 pin = aPinCode % CG_CPU_GPIO_GROUP_SIZE; + + + return ECgOk; +} + + +TCgReturnCode CgCpuGpioCreate(void) +{ + TCgReturnCode rc = ECgOk; + + #if 0 + + gpio_request(GPIO_GPS_IRQ, "gps_irq"); + gpio_direction_input(GPIO_GPS_IRQ); + + gps_irq = gpio_to_irq(GPIO_RESET_IRQ); + + gpio_request(GPIO_GPS_RESET , "gps_rst"); + printk("%s oob_irq:%d\n", __func__, oob_irq); + #endif + + return rc; +} + + + +TCgReturnCode CgCpuGpioDestroy(void) +{ + u32 rc = 0; + + #if 0 + gpio_free(GPIO_GPS_IRQ); + gpio_free(GPIO_GPS_RESET); + #endif + + return rc; +} + + + +int SPRD_FPGA_gpio_set_regvalue(unsigned long addr, unsigned int bit, unsigned int data) +{ + + + return 0; +} + +int SPRD_FPGA_gpio_get_regvalue(unsigned long addr, unsigned int bit) +{ + unsigned int value = 0; + + + return value; +} + +#ifdef __cplusplus +} +#endif + + + + + diff --git a/drivers/misc/gpsip/cgdriver/gpsspi.c b/drivers/misc/gpsip/cgdriver/gpsspi.c new file mode 100644 index 00000000..a5dfe7d4 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/gpsspi.c @@ -0,0 +1,459 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CgCpuOs.h" +#include "platform.h" +#include "CgxDriverCore.h" +#include "CgxDriverCoreCommon.h" + + + +#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP) + + +#define SPI_READ_CMD(len,addr) ((1 << 30) | (addr & 0x1FFFF)|(((len-1) & 0x1FF) << 20)) +#define SPI_WRITE_CMD(len,addr) ((1 << 30) |(1 << 31) | (addr & 0x1FFFF)|(((len-1) & 0x1FF) << 20)) +#define SPI_BLOCK_READ_CMD(len) ( (len-1) & 0xF ) +#define SPI_BLOCK_WRITE_CMD(len) ( (1 << 9) | (len-1) & 0xF ) + +#define SPI_BLOCK_DATA_ENC(len,addr) (( ((len-1)&0x7FFF) << 17 ) | ( addr & 0x1FFFF)) +//#define SPI_BLOCK_DATA_ENC(len,addr) (( ((len-1)&0x7FFF) << 17 ) | ( addr & 0x1FFFF)) + + +#define SPI_READ_SYS_CMD(len,addr) ((1 << 30) | (1 << 29) | (addr & 0x1FFFF)|(((len-1) & 0x1FF) << 20)) +#define SPI_WRITE_SYS_CMD(len,addr) ((1 << 30) | (1 << 29) | (1 << 31) | (addr & 0x1FFFF)|(((len-1) & 0x1FF) << 20)) + +extern void DataReady_TH_start (void); +extern int get_blocksize (void); +extern unsigned int get_block_num (void); +extern void* Data_Get_DrvContext(void); +extern u32 GetRequestLen(void); + + +struct spi_device *gps_spi_dev = NULL; +static int irq_number, addr_flag_side; +//static u32 count_block = 0; +static u32 Revcount_block = 0; +static u32 RevtotalLen = 0; + + +//#define FIX_MEMORY +#ifdef FIX_MEMORY +extern unsigned char buf_data[6 * 1024 * 1024]; +static u8 *read_buf = (u8 *) buf_data; + +#else +extern void *buf_data; +static u8 *read_buf; +#endif + + +static void +spi_transfer (unsigned char *tx1_buf, int write_len, + unsigned char *tx2_buf, int tx2_len, + unsigned char *rx_buf, int rx_len, bool cs_change) +{ + int status; + struct spi_message m; + + struct spi_transfer _tx_1 = { + .tx_buf = tx1_buf, + .rx_buf = NULL, + .len = write_len, + .cs_change = 0, + .bits_per_word = 32, + // .delay_usecs = 200, + }; + struct spi_transfer _tx_2 = { + .tx_buf = tx2_buf, + .rx_buf = NULL, + .len = tx2_len, + .cs_change = 0, + .bits_per_word = 32, + // .delay_usecs = 200, + }; + + struct spi_transfer _rx = { + .rx_buf = rx_buf, + .tx_buf = NULL, + .len = rx_len, + + .bits_per_word = 32, + .cs_change = 0, + }; + gpio_direction_output(CG_DRIVER_GPIO_GPS_SPI_CS, 0); + + spi_message_init (&m); + if (write_len) + spi_message_add_tail (&_tx_1, &m); + if (tx2_len) + spi_message_add_tail (&_tx_2, &m); + if (rx_len) + spi_message_add_tail (&_rx, &m); + + if (!list_empty (&m.transfers)) + { + status = spi_sync (gps_spi_dev, &m); + } + gpio_direction_output(CG_DRIVER_GPIO_GPS_SPI_CS, 1); +} + + +int gps_spi_write_bytes (u32 len, u32 addr, u32 data) +{ + u32 write_cmd[2]; + + //printk ("%s addr:%x len:%x data:0x%x\n",__func__, addr, len, data); + + //Because of the HwTest not enable the gps dma req,so force to set it. + if((addr == 0x88)&&(data == 0x06)) + data = 0x6016; + if (addr > 0x6000) + { + BUG_ON (1); + return 0; + } + if (len == 1) + { + write_cmd[0] = SPI_WRITE_CMD (len * 1, (addr / 4 + 0x3000)); + write_cmd[1] = data; + spi_transfer ((u8 *)&write_cmd[0], 8, NULL, 0, NULL, 0, true); + } + return 0; +} + +EXPORT_SYMBOL_GPL (gps_spi_write_bytes); + + + +/*make sure len is word units*/ +int +gps_spi_read_bytes (u32 len, u32 addr, u32 * data) +{ + u32 read_cmd[2] = {0}; + + if (len == 1) /*one block all way */ + { + read_cmd[0] = SPI_READ_CMD (len, (addr / 4 + 0x3000)); + spi_transfer (NULL, 0, (u8 *) & read_cmd[0], 4, + (u8 *) & read_cmd[1], 4, true); + + *data = read_cmd[1]; + } + else /*more than one word,block */ + { + u32 read_cmd_block[2]; + + /*len word unit */ + read_cmd_block[0] = SPI_BLOCK_READ_CMD (1); + read_cmd_block[1] = SPI_BLOCK_DATA_ENC (len, addr); + + spi_transfer (NULL, 0, (u8 *)&read_cmd_block[0], 8, (u8 *) data,len*4, + true); + + read_cmd[1] = data[0]; + } + return 0; +} + +EXPORT_SYMBOL_GPL (gps_spi_read_bytes); + + +int gps_spi_sysreg_write_bytes (u32 len, u32 addr, u32 data) +{ + u32 write_cmd[2]; + + //printk ("%s addr:%x len:%x data:0x%x\n",__func__, addr, len, data); + if (len == 1) + { + write_cmd[0] = SPI_WRITE_SYS_CMD (len, addr); + write_cmd[1] = data; + spi_transfer ((u8 *)&write_cmd[0], 8, NULL, 0, NULL, 0, true); + } + return 0; +} + + +/*make sure len is word units*/ +int gps_spi_sysreg_read_bytes (u32 len, u32 addr, u32 * data) +{ + u32 read_cmd[2] = {0}; + + if (len == 1) /*one block all way */ + { + read_cmd[0] = SPI_READ_SYS_CMD(len, addr); + spi_transfer (NULL, 0, (u8 *) & read_cmd[0], 4, + (u8 *) & read_cmd[1], 4, true); + + *data = read_cmd[1]; + } + + return 0; +} +#define SYSREG_BIT3_BIT4_BIT5_BIT7 (1<<3|1<<4|1<<5|1<<7) +#define SYS_BIT10 (1<<10) + +void PowerUpOtherClk(void) +{ + u32 value = 0; + + gps_spi_sysreg_read_bytes(1,0x03,&value); + value |= SYSREG_BIT3_BIT4_BIT5_BIT7; + value &= ~SYS_BIT10; + gps_spi_sysreg_write_bytes(1,0x03,value); + gps_spi_sysreg_read_bytes(1,0x03,&value); + printk("PowerUpOtherClk:0x03=0x%x\n",(unsigned int)value); + +} + +void PowerDownOtherClk(void) +{ + u32 value = 0; + + gps_spi_sysreg_read_bytes(1,0x03,&value); + value &= ~SYSREG_BIT3_BIT4_BIT5_BIT7; + value |= SYS_BIT10; + gps_spi_sysreg_write_bytes(1,0x03,value ); + gps_spi_sysreg_read_bytes(1,0x03,&value); + printk("PowerDownOtherClk :0x03=0x%x\n",(unsigned int)value); + +} + +void Reset_GPS_RecvAddress(void) +{ + irq_number = 0; +} + +int irq_count = 0; + +void init_spi_block_var(void) +{ + addr_flag_side = 0; + irq_number = 0; + Revcount_block = 0; + RevtotalLen = 0; + buf_data = Data_Get_DrvContext(); +} + +void gps_GetDataFromFPGA(void) +{ + u32 read_len=1024*4; + u32 block_size = get_blocksize(); + + // the use space reset rcv address and spi has rcv part data ,not conside the block szie less 4K size + if(irq_number ==1) + { + + u32 len = RevtotalLen - Revcount_block * block_size; + void * pStart = Data_Get_DrvContext(); + + if(len) + { + printk (" SPI has rcv but not submit len = %d $$$$$$$\n", len); + memcpy(pStart, (void*)(read_buf + read_len*4 -len) ,len); + } + buf_data = (u8*)(pStart+ len); + } + + read_buf = (u8*)((u8*)buf_data + (irq_number -1)* read_len*4); + gps_spi_read_bytes(read_len,0x5000+addr_flag_side*read_len,(u32*)read_buf); + if(addr_flag_side) + { + addr_flag_side = 0 ; + } + else + { + addr_flag_side = 1 ; + } + // recv all data len from FPGA + RevtotalLen = RevtotalLen + read_len*4; + // GPS_DEBUG_TRACE ("gps_GetDataFromFPGA buf=0x%p 0x%p rcvtotalLen = 0x%x, irq_number = %d &&&&& \n", + //buf_data,read_buf,RevtotalLen,irq_number); +} + +// BlockNum: all total number +static int submitLastBlock(int BlockNum) +{ + int lastFlag = FALSE; + u32 requestLen = GetRequestLen(); // user requset data len + + if(Revcount_block ==(BlockNum -1)) + { + if((requestLen < RevtotalLen ) ||(requestLen ==RevtotalLen)) + { + Revcount_block++; + //GPS_DEBUG_TRACE ("sbumit last blocks Rev count_block =%d requestLen = 0x%x ,RevtotalLen = 0x%x&&&&&& \n", + //Revcount_block,requestLen,RevtotalLen); + DataReady_TH_start(); + Revcount_block = 0; + lastFlag = TRUE; + } + } + return lastFlag; +} + +void gps_DealWithBlocks(void) +{ + u32 dataLen = 0; + int lastfrag = 0; + int count = 0; + int i; + + u32 block_size = get_blocksize(); + u32 block_num = get_block_num(); + + if(0 == Revcount_block) + { + if((RevtotalLen > block_size) || (RevtotalLen == block_size)) + { + count= RevtotalLen /block_size; + for(i = 0; i < count; i++) + { + Revcount_block ++; + DataReady_TH_start(); + //GPS_DEBUG_TRACE ("gps_DealWithBocks Rev count_block = %d &&& \n",Revcount_block); + } + //check last blocks + submitLastBlock(block_num); + } + else + { + // GPS_DEBUG_TRACE ("gps_DealWithBocks no blocks submit $$$$$$ \n"); + } + } + else + { + + dataLen = RevtotalLen - Revcount_block * block_size; + //check the last datalen + lastfrag = submitLastBlock(block_num); + if(!lastfrag) + { + count= dataLen /block_size; + for( i = 0; i < count; i++) + { + Revcount_block++; + DataReady_TH_start(); + // GPS_DEBUG_TRACE ("gps_DealWithBocks sbumit Revcount_block = %d &&&\n",Revcount_block); + } + //check the last block + submitLastBlock(block_num); + } + } + } + + // the bottle interrupt deal with user data +void gps_spi_recv_handle(void * data) +{ + gps_GetDataFromFPGA(); + gps_DealWithBlocks(); +} + +/*gpio inturrupt handle*/ +int data_req_handle (int para, void *param) +{ + irq_number++; + //printk("irq_number:%d\n",irq_number); + //bxd test + irq_count++; + gps_spi_recv_handle (0); + + return 0; +} + +static int +gpsspidev_probe (struct spi_device *spi) +{ + if(spi->master->bus_num != 2) + return -EINVAL; + gps_spi_dev = spi; + + spi->max_speed_hz = 24000*1000; + spi->mode = SPI_MODE_0; + spi->bits_per_word = 32; + + spi_setup(gps_spi_dev); + + return 0; +} +static int +gpsspidev_remove (struct spi_device *spi) +{ + + return 0; +} + + +static struct spi_board_info spi_boardinfo[] = { + { + .modalias = "spidev_gps", + .bus_num = 2, + .chip_select = 0, + .max_speed_hz = 24000 * 1000, + .mode = SPI_MODE_0, + } +}; + + +static void sprd_spi_device_init(void) +{ + struct spi_board_info *info = spi_boardinfo; + spi_register_board_info(info, ARRAY_SIZE(spi_boardinfo)); +} + + +static struct spi_driver gpsspidev_spi = { + .driver = { + .name = "spidev_gps", + .owner = THIS_MODULE, + }, + .probe = gpsspidev_probe, + .remove = gpsspidev_remove, +}; + +int gpsspidev_init (void) +{ + + int major; + sprd_spi_device_init(); + major = spi_register_driver (&gpsspidev_spi); + if (major < 0) + { + unregister_chrdev (major, gpsspidev_spi.driver.name); + printk ("spi_register_driver fail !!major = %d\n", major); + } + printk ("gpsspidev_init end major=%d!\n", major); + + return major; +} + + +void gpsspidev_exit (void) +{ + spi_unregister_driver (&gpsspidev_spi); +} + + diff --git a/drivers/misc/gpsip/cgdriver/platform.c b/drivers/misc/gpsip/cgdriver/platform.c new file mode 100644 index 00000000..44f9e64d --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/platform.c @@ -0,0 +1,770 @@ +/****************************************************************************** + * 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 platform/CPU specific code + + \defgroup CGX_DRIVER_PLATFORM_ANDROID CPU/Android platform specific defines + \{ +*/ + +#include +#include +#include +#include +#include +#include + +#include "CgxDriverApi.h" +#include "CgCpu.h" +#include "platform.h" +#include "CgReturnCodes.h" +#include "CgxDriverOs.h" +#include "CgxDriverCore.h" + +#ifdef CONFIG_ARCH_SCX20 +#include +#endif + +#ifndef CGCORE_ACCESS_VIA_SPI +extern TCgReturnCode CGCoreSclkEnable(int enable); +struct sprd_2351_interface *gps_rf_ops; +#endif + +/** Native byte order for this CPU */ +const TCgByteOrder CGX_DRIVER_NATIVE_BYTE_ORDER = ECG_BYTE_ORDER_4321; // SPRD_FPGA is little endian + +/* + Reset the core and timers and initialize GPIO (direction and special function) +*/ +TCgReturnCode CgxDriverInit(void *pDriver) +{ + // Check all addresses are defined + /* + #if CG_DRIVER_CGSNAP_BASE_PA == CG_UNDEFINED_ADDRESS + #error please define CG_DRIVER_CGSNAP_BASE_PA with correct address + #endif + #if CG_DRIVER_REVISION_BASE_PA == CG_UNDEFINED_ADDRESS + #error please define CG_DRIVER_REVISION_BASE_PA with correct address + #endif + #if CG_DRIVER_GPIO_BASE_PA == CG_UNDEFINED_ADDRESS + #error please define CG_DRIVER_GPIO_BASE_PA with correct address + #endif + #if CG_DRIVER_DMA_BASE_PA == CG_UNDEFINED_ADDRESS + #error please define CG_DRIVER_DMA_BASE_PA with correct address + #endif + #if CG_DRIVER_INTR_BASE_PA == CG_UNDEFINED_ADDRESS + #error please define CG_DRIVER_INTR_BASE_PA with correct address + #endif + #if CG_DRIVER_CLK_BASE_PA == CG_UNDEFINED_ADDRESS + #error please define CG_DRIVER_CLK_BASE_PA with correct address + #endif + */ + // TODO 1st time initialization + + return ECgOk; +} + + + + + + +TCgReturnCode CgxDriverDataReadyPrepare(void) +{ + return CgCpuGpioModeSet(CGX5000_DR, ECG_CPU_GPIO_FALLING_INT); +} + + +TCgReturnCode CgxDriverInterruptPrepare(void) +{ + TCgReturnCode rc = ECgOk; + + // not using 'GPS' interrupt, so there is nothing to do + + return rc; +} + +TCgReturnCode CgxDriverDmaInterruptPrepare(void) +{ + // TODO initial setup for DMA interrupt. + // if no special work is required, leave this function empty + return ECgOk; +} + + + + +TCgReturnCode CgxDriverGpsInterruptPrepare(void) +{ + // TODO return the interrupt code for 'CGsnap' interrupt + // if no special work is required, leave this function empty + return ECgOk; +} + + + + +U32 CgxDriverDataReadyInterruptCode(void) +{ + // TODO return the interrupt code for 'DMA end of transfer' interrupt + + return 0; +} + + +U32 CgxDriverGpsInterruptCode(void) +{ + // TODO return the interrupt code for 'CGsnap' interrupt +#ifndef CGCORE_ACCESS_VIA_SPI + return SPRD_GPS_INT; +#else + gpio_direction_input (CG_DRIVER_GPIO_GPS_INT); + return gpio_to_irq(CG_DRIVER_GPIO_GPS_INT); +#endif +} + + +TCgReturnCode CgxDriverWriteData(unsigned char *aSourceVirtualAddress, unsigned long aSourcePhysicalAddress, unsigned long aLengthBytes) +{ + //DBG_FUNC_NAME("CgxDriverWriteData") + TCgReturnCode rc = ECgOk; + +// #if WRITE_MODE == CG_CPU_SPI_MODE_DMA +// if (OK(rc)) rc = CgCpuSpiDmaStop(SPI_CHANNEL); +// CgCpuCacheSync(); +// CgCpuSpiSetup(SPI_CHANNEL, SPI_PRESCALE, ECG_CPU_SPI_OUTPUT_DMA); +// CgCpuDmaSetupToDevice(aSourcePhysicalAddress,aLengthBytes,0,0); +// if (OK(rc)) rc = CgCpuSpiDmaStart(SPI_CHANNEL); +// if (OK(rc)) rc = CgCpuDmaWaitFinish(CG_DRIVER_DMA_CHANNEL_WRITE); +// #elif WRITE_MODE == CG_CPU_SPI_MODE_MANUAL +// U32 i; +// CgCpuSpiSetup(SPI_CHANNEL, SPI_PRESCALE, ECG_CPU_SPI_OUTPUT_POLLING); +// +// for(i = 0; i < aLengthBytes; i++) { +// CgCpuSpiTxFinishWait(SPI_CHANNEL); +// CgCpuSpiWriteByte(SPI_CHANNEL, aSourceVirtualAddress[i]); +// } +// #endif + + return rc; +} + + +TCgReturnCode CgxDriverGpioCode(int aControlLine, int *aGpioCode) +{ + *aGpioCode = 0; + return ECgNotSupported; +} + +TCgReturnCode CgxDriverReadData(unsigned char *aTargetVirtualAddress, unsigned long aTargetPhysicalAddress, unsigned long aLengthBytes) +{ + //DBG_FUNC_NAME("CgxDriverReadData") + TCgReturnCode rc = ECgOk; + +// #if READ_MODE==CG_CPU_SPI_MODE_DMA +// // memset(aTargetVirtualAddress, 0x55, aLengthBytes); //NG! debug +// CgCpuCacheSync();//NG! debug +// // Buffer data (not register data) is written in DMA mode +// if (OK(rc)) rc = CgCpuSpiDmaStop(SPI_CHANNEL); +// +// CgCpuCacheSync(); +// if (OK(rc)) rc = CgCpuSpiSetup(SPI_CHANNEL, SPI_PRESCALE, ECG_CPU_SPI_INPUT_DMA); +// if (OK(rc)) rc = CgCpuDmaSetupFromDevice(aTargetPhysicalAddress, aLengthBytes, SPI_PRESCALE, CG_DRIVER_DMA_CHANNEL_READ, CG_DRIVER_DMA_CHANNEL_WRITE, SPI_CHANNEL); +// if (OK(rc)) rc = CgCpuSpiDmaStart(SPI_CHANNEL); +// // no need to wait for DMA to finish +// +// #elif READ_MODE==CG_CPU_SPI_MODE_MANUAL +// unsigned long i; +// CgCpuSpiSetup(SPI_CHANNEL, SPI_PRESCALE, ECG_CPU_SPI_INPUT_POLLING); +// for(i = 0; i < aLengthBytes; i++) { +// CgCpuSpiWriteByte(SPI_CHANNEL, 0); //dummy transmit +// CgCpuSpiRxFinishWait(SPI_CHANNEL); +// CgCpuSpiReadByte(SPI_CHANNEL, (volatile unsigned char *)(aTargetVirtualAddress + i)); +// } +// #endif + + return rc; + +} + + +TCgReturnCode CgxDriverClearData(unsigned char *aTargetVirtualAddress, unsigned long aTargetPhysicalAddress, unsigned long aLengthBytes) +{ + return CgxDriverReadData(aTargetVirtualAddress, aTargetPhysicalAddress, aLengthBytes); +} + + +TCgReturnCode CgxDriverIsDataReady(void) +{ + unsigned int val = 0; + CgCpuGpioModeSet(CGX5000_DR, ECG_CPU_GPIO_INPUT); + CgCpuGpioGet(CGX5000_DR, &val); + return (val == 0) ? ECgOk : ECgGeneralFailure; +} + + +TCgReturnCode CgxDriverReadDataTail(unsigned char *aTargetVirtualAddress, unsigned long aTargetPhysicalAddress, unsigned long aLengthBytes) +{ + // no tail reading is required for SPRD_FPGA + + return ECgOk; +} + +#ifdef CGCORE_ACCESS_VIA_SPI +static void CgxDriverRFInit(void) +{ + unsigned int value; + + value = 0x005f8420; + gps_spi_write_bytes(1, 0x82*4, value); + gps_spi_read_bytes(1, 0x82*4, &value); + + value = 0x00010003; + gps_spi_write_bytes(1, 0x83*4, value); + + /*RF4in1 */ + value = 0x006f0609; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x007b8020; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x07000001;//GPS Mode 0:Idle 1:Rx + gps_spi_write_bytes(1, 0x80*4, value); + +#if 0 + value = 0x004af417; + gps_spi_write_bytes(1, 0x80*4, value); +#endif + value = 0x07385400; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x076c0721; + gps_spi_write_bytes(1, 0x80*4, value); + + /*for 26M/16M TCXO AGC 1bit*/ + value = 0x07635140;//0x07635141; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x0704ef00;//max gain + gps_spi_write_bytes(1, 0x80*4, value); + +#if 1 //def CGCORE_GPS_26M /*for 26M TCXO*/ + value = 0x073c08d2; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x07023d61; + gps_spi_write_bytes(1, 0x80*4, value); +#else /*for 16M TCXO*/ + value = 0x073c0000; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x07026180; + gps_spi_write_bytes(1, 0x80*4, value); +#endif + + //for dma block size + gps_spi_sysreg_read_bytes(1,0x01,&value);; + value = 0; + value = ((1<<28)|(1<<26)|(1<<25)); + gps_spi_sysreg_write_bytes(1,0x01,value ); + gps_spi_sysreg_read_bytes(1,0x01,&value); + +#if 1 + /*When for RX Analog test such as GAIN and IF frequency , + we will add following configuration*/ + value = 0x077b0112;//0x077b0101; + gps_spi_write_bytes(1, 0x80*4, value); +#endif + +#if 0 //for RF Test + value = 0x075d88e6; + gps_spi_write_bytes(1, 0x80*4, value); + + value = 0x070a7835; + gps_spi_write_bytes(1, 0x80*4, value); +#endif + + //read reg + value = 0x806f0000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x006f0609:0x%x\n",value); + + value = 0x807b0000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x007b8020:0x%x\n",value); + + value = 0x87000000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x07000001:0x%x\n",value); + + value = 0x87380000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x07385400:0x%x\n",value); + + value = 0x876c0000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x076c0721:0x%x\n",value); + + + value = 0x87630000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x07635140:0x%x\n",value); + + value = 0x87040000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x0704ef00:0x%x\n",value); + +#if 1 /*for 26M TCXO*/ + value = 0x873c0000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x073c08d2:0x%x\n",value); + + value = 0x87020000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x07023d61:0x%x\n",value); +#else + value = 0x873c0000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x073c0000:0x%x\n",value); + + value = 0x87020000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x07026180:0x%x\n",value); +#endif + + value = 0x877b0000; + gps_spi_write_bytes(1, 0x80*4, value); + gps_spi_read_bytes(1, 0x81*4, &value); + printk("rf 0x077b0112:0x%x\n",value); + +} + +void gps_gpio_request(void) +{ + int ret; + ret = gpio_request (CG_DRIVER_GPIO_GPS_PDN, "gps_pdn"); + if (ret){ + printk ("gps_pdn request err: %d\n", CG_DRIVER_GPIO_GPS_PDN); + } + + ret = gpio_request (CG_DRIVER_GPIO_GPS_MRSTN, "gps_reset"); + if (ret){ + printk ("gps_reset request err: %d\n", CG_DRIVER_GPIO_GPS_MRSTN); + } + + ret = gpio_request (CG_DRIVER_GPIO_GPS_SPI_CS, "gps_spi_cs"); + if (ret){ + printk ("gps_spi_cs request err: %d\n", CG_DRIVER_GPIO_GPS_SPI_CS); + } + + ret = gpio_request (CG_DRIVER_GPIO_GPS_INT, "gps-req-int"); + if (ret) + { + printk ("gps-req- int err: %d\n", CG_DRIVER_GPIO_GPS_INT); + } +} + +static struct regulator *greeneye_vdd = NULL; +static void greeneye_vddsim2_enable(bool on) +{ + int ret; + if (greeneye_vdd == NULL) { + greeneye_vdd = regulator_get(NULL, "vddsim2"); + + if (IS_ERR(greeneye_vdd)) { + pr_err("Get regulator of vddsim2 error!\n"); + return; + } + } + if (on) { + regulator_set_voltage(greeneye_vdd, 2800000, 2800000); + ret = regulator_enable(greeneye_vdd); + } + else if (regulator_is_enabled(greeneye_vdd)) { + ret = regulator_disable(greeneye_vdd); + } +} + + +static void gps_clk_init(bool enable) +{ + static struct clk *gps_clk_32k=NULL; + + if (gps_clk_32k == NULL) { + gps_clk_32k = clk_get(NULL, "ext_32k"); + if (IS_ERR(gps_clk_32k)) { + printk("failed to get parent ext_32k\n"); + return; + } + } + if (enable) { + #ifndef CONFIG_OF + clk_enable(gps_clk_32k); + #else + clk_prepare_enable(gps_clk_32k); + #endif + }else{ + #ifndef CONFIG_OF + clk_disable(gps_clk_32k); + #else + clk_disable_unprepare(gps_clk_32k); + #endif + } +} + +TCgReturnCode CgxDriverRFPowerDown(void) +{ + //DBG_FUNC_NAME("CgxDriverRFPowerDown") + TCgReturnCode rc = ECgOk; + unsigned int value; + + printk("%s\n",__func__); + + /*RF4in1 */ + value = 0x07000000;//GPS Mode 0:Idle 1:Rx + gps_spi_write_bytes(1, 0x80*4, value); + return rc; +} + +TCgReturnCode CgxDriverRFPowerUp(void) +{ + //DBG_FUNC_NAME("CgxDriverRFPowerDown") + TCgReturnCode rc = ECgOk; + + printk("%s\n",__func__); + CgxDriverRFInit(); + return rc; +} + +void gps_chip_power_on(void) +{ + printk("%s\n",__func__); + + greeneye_vddsim2_enable(1); + gps_clk_init(1); + + //pdn pin pull high + CgCpuGpioModeSet(CG_DRIVER_GPIO_GPS_PDN, ECG_CPU_GPIO_OUTPUT); + CgCpuGpioSet(CG_DRIVER_GPIO_GPS_PDN); + CgCpuDelay(1000); + + //reset + CgCpuGpioModeSet(CG_DRIVER_GPIO_GPS_MRSTN, ECG_CPU_GPIO_OUTPUT); + CgCpuIPMasterResetClear(); + msleep(1); + CgCpuIPMasterResetOn(); + msleep(5); + CgCpuIPMasterResetClear(); + msleep(1); + + //gps core reset + gps_spi_write_bytes(1, 0Xfc, 0x0); + gps_spi_write_bytes(1, 0Xfc, 0x0f); + msleep(1); + CgxDriverRFPowerUp(); +} + +void gps_chip_power_off(void) +{ + printk("%s\n",__func__); + + //pdn pin pull low + CgCpuGpioModeSet(CG_DRIVER_GPIO_GPS_PDN, ECG_CPU_GPIO_OUTPUT); + CgCpuGpioReset(CG_DRIVER_GPIO_GPS_PDN); + CgCpuDelay(1000); + msleep(1); + + //reset pin pull low + CgCpuIPMasterResetOn(); + + //spi2 pin pull low + gpio_direction_output(CG_DRIVER_GPIO_GPS_SPI_CS, 0); + greeneye_vddsim2_enable(0); + gps_clk_init(0); +} + +#else +static TCgReturnCode CgxDriverRFInit(void) +{ + u32 value; + gps_rf_ops->write_reg(0x0700,0x0001); + gps_rf_ops->write_reg(0x004a,0xf417); + gps_rf_ops->write_reg(0x076c,0x0721); + gps_rf_ops->write_reg(0x0763,0x5141); + gps_rf_ops->write_reg(0x0738,0x5400); + gps_rf_ops->write_reg(0x0704,0xef00); + gps_rf_ops->write_reg(0X077b,0x0102); + + #if 1 /*for 26M TCXO*/ + gps_rf_ops->write_reg(0X073c,0x08d2); + gps_rf_ops->write_reg(0X0702,0x3d61); + #else /*for 16M TCXO*/ + gps_rf_ops->write_reg(0x073c,0x0000); + gps_rf_ops->write_reg(0X0702,0x6180); + #endif + + /* for IF*/ + #if 0 + gps_rf_ops->write_reg(0x075d,0x88e6); + gps_rf_ops->write_reg(0x070a,0x7835); + #endif + +#if 1 + /*for debug log */ + gps_rf_ops->read_reg(0x004a,&value); + printk("0x004af417 value: %x\n", value); + + gps_rf_ops->read_reg(0x076c,&value); + printk("0x076c0721 value: %x\n", value); + + gps_rf_ops->read_reg(0x0763,&value); + printk("0x07635141 value: %x\n", value); + + gps_rf_ops->read_reg(0x0738,&value); + printk("0x07385400 value: %x\n", value); + + gps_rf_ops->read_reg(0x0704,&value); + printk("0x0704ef00 value: %x\n", value); + + gps_rf_ops->read_reg(0X077b,&value); + printk("0x077b0102 value: %x\n", value); + + gps_rf_ops->read_reg(0x0700,&value); + printk("0x07000001 value: %x\n", value); + + #if 1 /*for 26M TCXO*/ + gps_rf_ops->read_reg(0X073c,&value); + printk("0x073c08d2 value: %x\n", value); + + gps_rf_ops->read_reg(0X0702,&value); + printk("0x07023d61 value: %x\n", value); + #else /*for 16M TCXO*/ + gps_rf_ops->read_reg(0x073c,&value); + printk("0x073c0000 value: %x\n", value); + + gps_rf_ops->read_reg(0X0702,&value); + printk("0x07026180 value: %x\n", value); + #endif + + /* for IF*/ + #if 0 + gps_rf_ops->read_reg(0x075d,&value); + printk("0x075d88e6 value: %x\n", value); + + gps_rf_ops->read_reg(0x070a,&value); + printk("0x070a7835 value: %x\n", value); + #endif +#endif + + return 0; + +} + +void gps_gpio_request(void) +{ + int ret; + ret = gpio_request (SPRD_GPS_LNA_EN, "gps_lna"); + if (ret){ + printk ("GPS_LNE request err: %d\n", SPRD_GPS_LNA_EN); + } +} + +static void gps_lna_enable(void) +{ + gpio_direction_output(SPRD_GPS_LNA_EN,1); +} + +static void gps_lna_disable(void) +{ + gpio_direction_output(SPRD_GPS_LNA_EN,0); +} + +static void gps_reg_init(void) +{ +#ifdef CONFIG_ARCH_SCX30G + /*GPS Clock Select to CLK_SINE0*/ + sci_glb_clr(SPRD_GPS_CLK_SEL,BIT_3); + + /*Disable 26M Clock Gating*/ + sci_glb_clr(SPRD_GPS_CLK_AUTO_GATING,BIT_0); +#endif +} + +TCgReturnCode CgxDriverRFPowerDown(void) +{ + //DBG_FUNC_NAME("CgxDriverRFPowerDown") + TCgReturnCode rc = ECgOk; + + printk("%s\n",__func__); + + gps_rf_ops->mspi_enable(); + gps_rf_ops->write_reg(0x0700,0x0000); + gps_lna_disable(); + gps_rf_ops->mspi_disable(); + return rc; +} + +TCgReturnCode CgxDriverRFPowerUp(void) +{ + //DBG_FUNC_NAME("CgxDriverRFPowerDown") + TCgReturnCode rc = ECgOk; + + printk("%s\n",__func__); + gps_rf_ops->mspi_enable(); + gps_lna_enable(); + gps_reg_init(); + CgxDriverRFInit(); + gps_rf_ops->mspi_disable(); + return rc; +} + +void gps_chip_power_on(void) +{ + printk("%s\n",__func__); +#ifdef CONFIG_ARCH_SCX20 + rf2351_vddwpa_ctrl_power_enable(1); +#endif + //enable gps sysclk + CGCoreSclkEnable(1); + + //gps core reset + CgxCpuWriteMemory((U32)CG_DRIVER_CGCORE_BASE_VA, 0xfc,0xf); + CgxDriverRFPowerUp(); +} + +void gps_chip_power_off(void) +{ + printk("%s\n",__func__); + CgxDriverRFPowerDown(); + + //gps core reset + CgxCpuWriteMemory((U32)CG_DRIVER_CGCORE_BASE_VA, 0xfc,0x0); + CGCoreSclkEnable(0); +#ifdef CONFIG_ARCH_SCX20 + rf2351_vddwpa_ctrl_power_enable(0); +#endif +} +#endif + +TCgReturnCode CgxDriverTcxoEnable(U32 aEnable) +{ + // default implementation assumes direct manipulation of TCXO LDO via a dedicated GPIO pin. + // either CG_DRIVER_GPIO_TCXO_ENABLE or CG_DRIVER_GPIO_TCXO_DISABLE should be defined depending + // on the LDO control level (active high / active low) + + #if defined(CG_DRIVER_GPIO_TCXO_ENABLE) + if (aEnable) + CgCpuGpioSet(CG_DRIVER_GPIO_TCXO_ENABLE); + else + CgCpuGpioReset(CG_DRIVER_GPIO_TCXO_ENABLE); + #elif defined(CG_DRIVER_GPIO_TCXO_DISABLE) + if (aEnable) + CgCpuGpioReset(CG_DRIVER_GPIO_TCXO_DISABLE); + else + CgCpuGpioSet(CG_DRIVER_GPIO_TCXO_DISABLE); + #endif + + return ECgOk; +} + + + +TCgReturnCode CgCpuRevision(char *apRevisionCode) +{ + + //sprintf(apRevisionCode,"SPRD_FPGA-R255",0); + sprintf(apRevisionCode,"SPRD_FPGA-R255"); + + return ECgOk; + +} + + +TCgReturnCode CgCpuClockDestroy(void) +{ + TCgReturnCode rc = ECgOk; + return rc; +} + +TCgReturnCode CgCpuIntrDestroy(void) +{ + TCgReturnCode rc = ECgOk; + // #if defined(CG_DRIVER_INTR_BASE_PA) && !defined(CG_DRIVER_INTR_BASE_VA) +// rc = CgCpuVirtualFree((volatile void **)&gpINTR); + // #endif + return rc; +} + + +TCgReturnCode CgCpuIPMasterResetClear(void) +{ + TCgReturnCode rc = ECgOk; + DBG_FUNC_NAME("CgCpuIPMasterResetClear"); + + DBGMSG("start"); + // Set master reset pin to '1' (reset off - device active) + #ifdef CGCORE_ACCESS_VIA_SPI + CgCpuGpioSet(CG_DRIVER_GPIO_GPS_MRSTN); + #else + // CgCpuGpioSet(CG_DRIVER_GPIO_GPS_MRSTN); + #endif + + return rc; +} + + + + +TCgReturnCode CgCpuIPMasterResetOn(void) +{ + TCgReturnCode rc = ECgOk; + DBG_FUNC_NAME("CgCpuIPMasterResetOn"); + + DBGMSG("start"); + // Set master reset pin to '0' (reset on - device inactive) + + #ifdef CGCORE_ACCESS_VIA_SPI + CgCpuGpioReset(CG_DRIVER_GPIO_GPS_MRSTN); + #else + //CgCpuGpioReset(CG_DRIVER_GPIO_GPS_MRSTN); + #endif + + return rc; +} + + +TCgReturnCode CgCpuAllocateVa(void) +{ + // Nothing to do for SPRD_FPGA + return ECgOk; +} + + diff --git a/drivers/misc/gpsip/cgdriver/platform.h b/drivers/misc/gpsip/cgdriver/platform.h new file mode 100644 index 00000000..df8d0e81 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/platform.h @@ -0,0 +1,250 @@ +/****************************************************************************** + * 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 SPRD_FPGA specific defines + + \defgroup CGX_DRIVER_PLATFORM_ANDROID SPRD_FPGA/Android platform specific defines + \{ + The following values are specific to the SPRD_FPGA / Android implementation. + For other platforms, please select appropriate values. + + */ +#ifndef PLATFORM_H +#define PLATFORM_H + +/// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifndef CGCORE_ACCESS_VIA_SPI +#include +#endif +#include "CgxDriverCore.h" + + +#define CGX_PLATFORM_NAME "SPRD_FPGA_FPGA" + +/*************************************************************************************/ + +/*New add by paul*/ + +#define NUMBER_1K (1 *1024) +#define NUMBER_16K (16*1024) +#define NUMBER_64K (64*1024) + + +#define MAX_DMA_CHUNK_SIZE (0x80000) // 512K +#define MAX_DMA_TRANSFER_TASKS (64) /**< Maximum number of DMA tasks */ + +/** + CGsnap IP physical address + \attention Need to be ported + \ingroup SPRD_FPGA_cpu_specific + + TODO: modify by sprd + +*/ +#define CG_DRIVER_CGCORE_BASE_PA (0x21C00000) /* cg ip base */ +#define CG_DRIVER_GPIO_BASE_PA (0x8A000000) +#define CG_DRIVER_INTR_BASE_PA (0xFC000000) +#define CG_DRIVER_CLK_BASE_PA (0xFC802000) + + +#ifdef CGCORE_ACCESS_VIA_SPI +#define CG_DRIVER_GPIO_GPS_MRSTN (90) +#ifdef CONFIG_ARCH_SCX35LT8 +#define CG_DRIVER_GPIO_GPS_PDN (142) +#else +#define CG_DRIVER_GPIO_GPS_PDN (76) +#endif +#define CG_DRIVER_GPIO_GPS_INT (96) +#define CG_DRIVER_GPIO_GPS_SPI_CS (52) +#else +#ifdef CONFIG_OF +struct gps_2351_addr +{ + u32 gps_base; + u32 ahb_base; + u32 irq_num; + u32 lna_gpio; + #ifdef CONFIG_ARCH_SCX30G + u32 pmu_base; + #endif +}; + +extern struct gps_2351_addr gps_2351; +extern u32 gps_get_core_base(void); +extern u32 gps_get_ahb_base(void); +extern u32 gps_get_irq(void); +extern u32 gps_get_lna_gpio(void); + + +#define CG_DRIVER_CGCORE_BASE_VA gps_get_core_base() +#define CG_DRIVER_SCLK_VA gps_get_ahb_base() +#define SPRD_GPS_INT gps_get_irq() +#define SPRD_GPS_LNA_EN gps_get_lna_gpio() + +#ifdef CONFIG_ARCH_SCX30G +extern u32 gps_get_pmu_base(void); + +#define SPRD_GPS_CLK_SINEX gps_get_pmu_base() +#define SPRD_GPS_CLK_AUTO_GATING (SPRD_GPS_CLK_SINEX+0x114) +#define SPRD_GPS_CLK_SEL (SPRD_GPS_CLK_SINEX+0x134) +#endif + +#else + +/** Virtual base address for CGsnap registers */ +#define CG_DRIVER_CGCORE_BASE_VA SPRD_GPS_BASE + +#ifdef CONFIG_ARCH_SCX30G +#define SPRD_GPS_CLK_SINEX SPRD_PMU_BASE +#define SPRD_GPS_CLK_AUTO_GATING (SPRD_GPS_CLK_SINEX+0x114) +#define SPRD_GPS_CLK_SEL (SPRD_GPS_CLK_SINEX+0x134) +#endif + +/** Virtual base address for CGsnap sclk */ +#define CG_DRIVER_SCLK_VA SPRD_AHB_BASE +#define SPRD_GPS_INT IRQ_GPS_INT + +#if defined(CONFIG_DOLPHIN_CHIP_2351) +#define SPRD_GPS_LNA_EN (35) +#elif defined(CONFIG_SHARK_CHIP_2351) +#define SPRD_GPS_LNA_EN (50) +#endif +#endif +#endif + + +/** \} Memory Mapping */ + + +/** + + + \name Interrupt Codes + \{ + */ + + +/** DMA interrupt event name + + For platforms where the interrupt is handled by BSP code, this is the event + name to be used by the driver. + in all other cases, this should be defined 'NULL' + */ +#define CGX_DRIVE_DMA_INT_EVENT_NAME (NULL) + +/** DMA completion exported sync-object name + + For platforms where the DMA interrupt is handled by BSP code/driver, this is the sync-object name + exported by the operating system, that can be waited on, and that issues a signal when DMA + x-fer is complete. + in all other cases, this should not be defined +*/ + +/*modify bu paul for compile-----debug*/ +//#define gDMACompletion NULL +// struct completion gDMACompletion; +//#define CGX_DRIVE_DMA_INT_GLOBAL_SYNC_OBJECT (gDMACompletion) + + +/** GPS interrupt event name + For platforms where the interrupt is handled by BSP code, this is the event + name to be used by the driver. + in all other cases, this should be defined 'NULL' + */ +#define CGX_DRIVE_GPS_INT_EVENT_NAME (NULL) + +/** \} Interrupt codes */ + +/** + + + \name DMA Control + \{ +*/ + + +#define CG_DRIVER_DMA_CHANNEL_READ (0) /**< DMA channel to use for snap transfer */ + + + +/** \} DMA Control */ + + +/** + + + \name GPIO mapping + \{ + */ + + + + +/** GPIO assigned to RF front-end configuration data. + This line is used to configure the ACLYS-L, (send and receive data in I2C like protocol) + a.k.a. SER2 + \attention Input & Output + */ +#define CG_DRIVER_GPIO_RF_DATA (0 + 3) + +/** GPIO assigned to RF front-end configuration clock. + This line is used to configure the ACLYS-L, (clocking the I2C like protocol) + a.k.a. SER1 + \attention Output only + */ +#define CG_DRIVER_GPIO_RF_CLK (0 + 2) + + +/** GPIO assigned to RF front-end power down. + This line is used to control RF FrontEnd power mode (i.e., select between power on and power down modes) + This value is used on if CG_DRIVER_CGCORE_CONTROLS_RF_PD is FALSE + \attention Output only + */ +#define CG_DRIVER_GPIO_RF_PD (0 + 0) +#define CG_DRIVER_CG_CORE_CONTROLS_RF_PD (TRUE) +#define RF_POWER_UP_VAL (0) // ACLYS RF requires '0' for PU + +#define CGX5000_DR (0 + 18) + +#ifndef CGCORE_ACCESS_VIA_SPI +extern struct sprd_2351_interface *gps_rf_ops; +#endif + + +//#define CGX5000_INT (CG_CPU_GPIO_GROUP_D + 9) + +/** \} GPIO mapping */ + + +/** \} */ + +#endif /* PLATFORM_H */ -- cgit v1.3.1