diff options
Diffstat (limited to 'drivers/misc/gpsip')
29 files changed, 9391 insertions, 0 deletions
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=<tool chain prefix>
+ 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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/hardirq.h>
+#include <linux/serial.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#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;i<XVU_PAIRS * 2; i++)
+ init_waitqueue_head(&xvu_dev.endpoint[i].msr_wait);
+
+ /* allocate the tty driver with 2 minor devices per pair */
+ xvu_ttydriver = alloc_tty_driver( XVU_PAIRS * 2);
+ if (!xvu_ttydriver)
+ return -ENOMEM;
+
+ tty_port_init(&xvu_port[0]);
+ tty_port_init(&xvu_port[1]);
+
+ /* initialize the tty driver */
+ xvu_ttydriver->owner = 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;i<XVU_PAIRS * 2; i++)
+ {
+ spin_lock_init(&xvu_dev.endpoint[i].sercnt_lock);
+ __XVU_SetMSR(i);
+ }
+ up(&xvu_dev.sem);
+
+ printk(KERN_INFO MODULE_NAME ": Virtual UART Device Ready... Major DevId: %d\n", xvu_ttydriver->major );
+ 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 <pablo@ximpo.com>");
+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 <linux/module.h>
+#include <linux/kernel.h>
+#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<aCount; cnt++) {
+ z *=2;
+ }
+ return ECgOk;
+}
+
+TCgReturnCode CgCpuRFControlWriteByte(unsigned char aValue)
+{
+ printk(" CgCpuControlWriteByte.\n");
+ if(aValue == 1)
+ CgxDriverRFPowerUp();
+ else if(aValue == 0)
+ CgxDriverRFPowerDown();
+ else
+ printk(" invalid arg.\n");
+ return ECgOk;
+}
+
+#ifdef CG_STORE_ERROR_LINE
+ BOOL cgRetCode_store_error_line(const char * aFileName, long lineNumber, TCgReturnCode aRc) {
+ return TRUE;
+ }
+#endif
diff --git a/drivers/misc/gpsip/cgdriver/CgCpu.h b/drivers/misc/gpsip/cgdriver/CgCpu.h new file mode 100644 index 00000000..de064b00 --- /dev/null +++ b/drivers/misc/gpsip/cgdriver/CgCpu.h @@ -0,0 +1,1644 @@ +/****************************************************************************** + * 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 CPU API + \attention This file should not be modified. + If you think something is wrong here, please contact CellGuide + + CellGuide's API to access low-level CPU resources + + The API is used by CellGuide drivers and applications that require access to low-level CPU resources + like DMA, SPI. + + CPU depended code is divided to the following API groups: + \li \ref cg_cpu_clk + \li \ref cg_cpu_dma + \li \ref cg_cpu_gpio + \li \ref cg_cpu_spi + \li \ref cg_cpu_interrupt + \li \ref cg_cpu_rtc + \li \ref cg_cpu_miscellanies +*/ + +#ifndef CG_CPU_H +#define CG_CPU_H + +#ifdef __cplusplus + extern "C" { +#endif /*__cplusplus*/ + +// =========================================================================== + +#include "CgTypes.h" +#include "CgReturnCodes.h" +#include "CgCpuOs.h" + +// =========================================================================== + +/** helper macro to calculate minimum of 2 numbers */ +#ifndef MIN + #define MIN(__a__, __b__) ((__a__) < (__b__) ? (__a__) : (__b__)) +#endif + +/** helper macro to align memory */ +#ifndef ALLIGN + #define ALLIGN(__var__,__base__) ((__var__)%(__base__)) ? __var__ = (__base__) * ((U32)((__var__) / (__base__)) + 1) : (__var__) +#endif + +/** helper macro to find the ceiling of a number */ +#ifndef DIV_CEIL + #define DIV_CEIL(__counter__,__devider__) ( ((__counter__) + (__devider__) -1) / (__devider__) ) +#endif + +/** Undefined addresss means the address needs to be filled during porting **/ +#define CG_UNDEFINED_ADDRESS (0xFFFFFFFF) + +/** helper macro to get the 'controller' part of a channel code */ +#define CG_CONTROLLER(ch) (ch & 0xFFFF0000) + +/** helper macro to get the 'channel' part of a channel code */ +#define CG_CHANNEL(ch) (ch & 0x0000FFFF) + +/** helper macro to check NULL pointer in argument */ +#define ASSERT_NOT_NULL(p) if (p == NULL) return ECgNullPointer; + +/** helper macro to calculate register index from it's offset */ +#define REGIDX(offset) (offset/4) + + +/** Bit field definition + This structure is used to define a sub-register bit field, with arbitrary size. + */ +typedef struct { + U32 start; /**< start bit (0 based) 0 == LSB */ + U32 length; /**< length of bit field (1-32) */ + U32 defaultValue; /**< default value */ +} TCgBitField; + + +#define CG_CPU_DEVICE_SPI (1) + +#define CG_CPU_SPI_MODE_DMA (0) /**< Use DMA to handle SPI communication */ +#define CG_CPU_SPI_MODE_MANUAL (1) /**< Use polling to handle SPI communication */ + +/** \name Controllers logical codes +\{ +*/ + + +/** +DMA Controller logical unit code +\note Do not change; this value is used internally in the driver +\ingroup cg_cpu_dma +*/ +#define CG_CPU_CONTROLLER_DMA (0x00020000) + +/** +SPI Controller logical unit code +\note Do not change; this value is used internally in the driver +\ingroup cg_cpu_spi +*/ +#define CG_CPU_CONTROLLER_SPI (0x00030000) + +/** +GPIO Controller logical unit code +\note Do not change; this value is used internally in the driver +\ingroup cg_cpu_gpio +*/ +#define CG_CPU_CONTROLLER_GPIO (0x00040000) + + + +/** \} Controllers logical codes*/ + +/** Virtual GPIO groups definitions + These values are used to define CellGuide 'virtual' GPIO codes, later converted to specific + CPU GPIO register and pin. + */ + + +/** Maximum number of GPIOs in a group. + the number is artificial, and should be the largest GPIO group there is. +*/ +#define CG_CPU_GPIO_GROUP_SIZE (128) + +#define CG_CPU_GPIO_GROUP_INDEX_A (1) /**< GPIO group A index */ +#define CG_CPU_GPIO_GROUP_INDEX_B (CG_CPU_GPIO_GROUP_INDEX_A+1) /**< GPIO group B index */ +#define CG_CPU_GPIO_GROUP_INDEX_C (CG_CPU_GPIO_GROUP_INDEX_B+1) /**< GPIO group C index */ +#define CG_CPU_GPIO_GROUP_INDEX_D (CG_CPU_GPIO_GROUP_INDEX_C+1) /**< GPIO group A index */ +#define CG_CPU_GPIO_GROUP_INDEX_E (CG_CPU_GPIO_GROUP_INDEX_D+1) /**< GPIO group A index */ +#define CG_CPU_GPIO_GROUP_INDEX_F (CG_CPU_GPIO_GROUP_INDEX_E+1) /**< GPIO group A index */ +#define CG_CPU_GPIO_GROUP_INDEX_G (CG_CPU_GPIO_GROUP_INDEX_F+1) /**< GPIO group G index */ +#define CG_CPU_GPIO_GROUP_INDEX_H (CG_CPU_GPIO_GROUP_INDEX_G+1) /**< GPIO group H index */ +#define CG_CPU_GPIO_GROUP_INDEX_I (CG_CPU_GPIO_GROUP_INDEX_H+1) /**< GPIO group I index */ +#define CG_CPU_GPIO_GROUP_INDEX_J (CG_CPU_GPIO_GROUP_INDEX_I+1) /**< GPIO group J index */ +#define CG_CPU_GPIO_GROUP_INDEX_K (CG_CPU_GPIO_GROUP_INDEX_J+1) /**< GPIO group K index */ +#define CG_CPU_GPIO_GROUP_INDEX_L (CG_CPU_GPIO_GROUP_INDEX_K+1) /**< GPIO group L index */ +#define CG_CPU_GPIO_GROUP_INDEX_M (CG_CPU_GPIO_GROUP_INDEX_L+1) /**< GPIO group M index */ +#define CG_CPU_GPIO_GROUP_INDEX_N (CG_CPU_GPIO_GROUP_INDEX_M+1) /**< GPIO group N index */ +#define CG_CPU_GPIO_GROUP_INDEX_O (CG_CPU_GPIO_GROUP_INDEX_N+1) /**< GPIO group O index */ +#define CG_CPU_GPIO_GROUP_INDEX_P (CG_CPU_GPIO_GROUP_INDEX_O+1) /**< GPIO group P index */ +#define CG_CPU_GPIO_GROUP_INDEX_Q (CG_CPU_GPIO_GROUP_INDEX_P+1) /**< GPIO group Q index */ +#define CG_CPU_GPIO_GROUP_INDEX_R (CG_CPU_GPIO_GROUP_INDEX_Q+1) /**< GPIO group R index */ +#define CG_CPU_GPIO_GROUP_INDEX_S (CG_CPU_GPIO_GROUP_INDEX_R+1) /**< GPIO group S index */ +#define CG_CPU_GPIO_GROUP_INDEX_T (CG_CPU_GPIO_GROUP_INDEX_S+1) /**< GPIO group T index */ +#define CG_CPU_GPIO_GROUP_INDEX_U (CG_CPU_GPIO_GROUP_INDEX_T+1) /**< GPIO group U index */ +#define CG_CPU_GPIO_GROUP_INDEX_V (CG_CPU_GPIO_GROUP_INDEX_U+1) /**< GPIO group V index */ +#define CG_CPU_GPIO_GROUP_INDEX_W (CG_CPU_GPIO_GROUP_INDEX_V+1) /**< GPIO group W index */ +#define CG_CPU_GPIO_GROUP_INDEX_X (CG_CPU_GPIO_GROUP_INDEX_W+1) /**< GPIO group X index */ +#define CG_CPU_GPIO_GROUP_INDEX_Y (CG_CPU_GPIO_GROUP_INDEX_X+1) /**< GPIO group Y index */ +#define CG_CPU_GPIO_GROUP_INDEX_Z (CG_CPU_GPIO_GROUP_INDEX_Y+1) /**< GPIO group Z index */ +#define CG_CPU_GPIO_GROUP_INDEX___ (CG_CPU_GPIO_GROUP_INDEX_Z+1) + + +#define CG_CPU_GPIO_GROUP_A (CG_CPU_GPIO_GROUP_INDEX_A * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group A */ +#define CG_CPU_GPIO_GROUP_B (CG_CPU_GPIO_GROUP_INDEX_B * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group B */ +#define CG_CPU_GPIO_GROUP_C (CG_CPU_GPIO_GROUP_INDEX_C * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group C */ +#define CG_CPU_GPIO_GROUP_D (CG_CPU_GPIO_GROUP_INDEX_D * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group D */ +#define CG_CPU_GPIO_GROUP_E (CG_CPU_GPIO_GROUP_INDEX_E * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group E */ +#define CG_CPU_GPIO_GROUP_F (CG_CPU_GPIO_GROUP_INDEX_F * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group F */ +#define CG_CPU_GPIO_GROUP_G (CG_CPU_GPIO_GROUP_INDEX_G * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group G */ +#define CG_CPU_GPIO_GROUP_H (CG_CPU_GPIO_GROUP_INDEX_H * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group H */ +#define CG_CPU_GPIO_GROUP_I (CG_CPU_GPIO_GROUP_INDEX_I * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group I */ +#define CG_CPU_GPIO_GROUP_J (CG_CPU_GPIO_GROUP_INDEX_J * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group J */ +#define CG_CPU_GPIO_GROUP_K (CG_CPU_GPIO_GROUP_INDEX_K * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group K */ +#define CG_CPU_GPIO_GROUP_L (CG_CPU_GPIO_GROUP_INDEX_L * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group L */ +#define CG_CPU_GPIO_GROUP_M (CG_CPU_GPIO_GROUP_INDEX_M * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group M */ +#define CG_CPU_GPIO_GROUP_N (CG_CPU_GPIO_GROUP_INDEX_N * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group N */ +#define CG_CPU_GPIO_GROUP_O (CG_CPU_GPIO_GROUP_INDEX_O * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group O */ +#define CG_CPU_GPIO_GROUP_P (CG_CPU_GPIO_GROUP_INDEX_P * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group P */ +#define CG_CPU_GPIO_GROUP_Q (CG_CPU_GPIO_GROUP_INDEX_Q * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group Q */ +#define CG_CPU_GPIO_GROUP_R (CG_CPU_GPIO_GROUP_INDEX_R * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group R */ +#define CG_CPU_GPIO_GROUP_S (CG_CPU_GPIO_GROUP_INDEX_S * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group S */ +#define CG_CPU_GPIO_GROUP_T (CG_CPU_GPIO_GROUP_INDEX_T * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group T */ +#define CG_CPU_GPIO_GROUP_U (CG_CPU_GPIO_GROUP_INDEX_U * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group U */ +#define CG_CPU_GPIO_GROUP_V (CG_CPU_GPIO_GROUP_INDEX_V * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group V */ +#define CG_CPU_GPIO_GROUP_W (CG_CPU_GPIO_GROUP_INDEX_W * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group W */ +#define CG_CPU_GPIO_GROUP_X (CG_CPU_GPIO_GROUP_INDEX_X * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group X */ +#define CG_CPU_GPIO_GROUP_Y (CG_CPU_GPIO_GROUP_INDEX_Y * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group Y */ +#define CG_CPU_GPIO_GROUP_Z (CG_CPU_GPIO_GROUP_INDEX_Z * CG_CPU_GPIO_GROUP_SIZE) /**< 1st GPIO code in group Z */ + + + +#define REG32(r) *((volatile U32*)(r)) + +#define REG_GET1(aReg, aPin) \ + ((aReg >> 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 <stdarg.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/cdev.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/dma-mapping.h> +#include <linux/wait.h> + +#include <linux/sched.h> +#include <linux/time.h> + +#include <asm/io.h> +#include <asm/dma.h> +#include <asm/cacheflush.h> + +#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 <linux/delay.h> + +#include "CgxDriverCore.h" +#include "CgCpu.h" +#include "CgCpuOs.h" +#include "platform.h" +#include "CgxDriverPlatform.h" +#include "CgxDriverOs.h" +#include "CgBuildNumber.h" +#include "CgVersion.h" +#include "CgxDriverCoreCommon.h" + + +/** + Driver version structure + \note this structure is filled automatically on build time, by CellGuide build machine +*/ +const TCgVersion gCgDriverVersion = { + CG_BUILD_VERSION, /**< Software Version number (Text)*/ + CG_BUILD_ORIGINATOR, /**< Build Originator name (Text)*/ + CGX_PLATFORM_NAME, /**< Platform Name (Text), as specified in platform.h file */ + CG_BUILD_NUMBER, /**< Unique Build Number (Text) - automatically assigned by build machine*/ + CG_BUILD_DATE, /**< Build Date (Text)*/ + CG_BUILD_TIME, /**< Build Time (Text)*/ + CG_BUILD_MODE /**< Build Mode (Text) - Release/Test/Debug */ +}; + +extern void gps_chip_power_on(void); +extern void gps_chip_power_off(void); +extern void gps_gpio_request(void); + +#define CG_MATH_ALIGNMENT(__var__,__base__) __var__ = (__base__) * ((U32)(((__var__) + ((__base__)/2)) / (__base__))) + + +TCgCpuDmaTask gChunksList[MAX_DMA_TRANSFER_TASKS]; /**< DMA tasks list */ +S32 CgxDriverSnapLengthExtraBytes = 0; + +extern U32 CGCORE_BASE_ADDR; + +/** CGsnap GPO register offset */ +const U32 CGCORE_REG_OFFSET_GPO = 0x00000040; + +/** CGsnap version register offset */ +const U32 CGCORE_REG_OFFSET_VERSION = 0x00000044; + +/** CGsnap interrupt register offset (KAGPSRawInt)*/ +const U32 CGCORE_REG_RAW_INT = 0x00000080; + +/** CGsnap Soft_CMD register offset */ +const U32 CGCORE_REG_OFFSET_SOFT_CMD = 0x000000CC; +const U32 CGCORE_SOFT_CMD_POWER_DOWN = 0xFDB96420; + +/** CGsnap reset register offset */ + +const U32 CGCORE_REG_OFFSET_CORE_RESETS = 0x000000FC; + +#ifndef RF_POWER_UP_VAL + #define RF_POWER_UP_VAL (0) // ACLYS requires '0' for PU +#endif + +#ifdef CGCORE_ACCESS_VIA_SPI +extern void init_spi_block_var(void); +static unsigned int block_num; +#endif +bool flag_power_up = 0; +TCgReturnCode CgxDriverTcxoControl(u32 aEnable); + +#define CGCORE_ENABLE_CORE (0x00000000) +#define CGCORE_ENABLE_TCXO (0x00000001) +#define CGCORE_ENABLE_RTC (0x00000002) +#define CGCORE_ENABLE_BS (0x00000003) +#define CGCORE_RF_POWER_UP_POL (0x00000004) // RF Power up polarity. "Power UP" GPO[0] value is determined by this bit's value. + // (if bit is '1', during power up, the IP will output '1', and during power down, + // it will output '0'. When this bit is '0', the output is reversed) + +const U32 CGCORE_CORE_RESETS_ENABLE = ((1<<CGCORE_ENABLE_CORE) | (1<<CGCORE_ENABLE_TCXO) | ( RF_POWER_UP_VAL * (1<<CGCORE_RF_POWER_UP_POL))); + // This is the default 'enable' value, to the core_Resets register. + // It needs to be written prior to accessing CGsnap. + // ALL CGCORE_ENABLE_XXX are reset to 0, when the MasterReset pin is toggled + +#define CGCORE_ENABLE_DMA (5) +#define CGCORE_ENABLE_GPS (12) + + +#define CGCORE_ENABLE_SCLK ((1<<CGCORE_ENABLE_DMA) | (1<<CGCORE_ENABLE_GPS)) +#define CGCORE_RESET_DELAY (1000) // Used as a delay between '0' and '1', when reseting the CGsnap + +TCgReturnCode CGCoreReset(U32 aUnitToReset); + +#ifndef CGCORE_ACCESS_VIA_SPI +//bxd add for slck enable +TCgReturnCode CGCoreSclkEnable(int enable) +{ + TCgReturnCode rc = ECgOk; + + if(1 == enable) + { + sci_glb_set(CG_DRIVER_SCLK_VA,BIT_12); + } + else if(0 == enable) + { + sci_glb_clr(CG_DRIVER_SCLK_VA,BIT_12); + } + return rc; +} +#endif + + +TCgReturnCode CgxDriverDestroy(void *pDriver) +{ + DBG_FUNC_NAME("CgxDriverDestroy") + TCgReturnCode rc = ECgOk; + + rc = CgCpuDmaDestroy(CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070); + if (!OK(rc)) DBGMSG("Failed to destroy DMA"); + rc = CgCpuGpioDestroy(); + if (!OK(rc)) DBGMSG("Failed to destroy GPIO"); + rc = CgCpuIntrDestroy(); + if (!OK(rc)) DBGMSG("Failed to destroy INTR"); + rc = CgCpuClockDestroy(); + if (!OK(rc)) DBGMSG("Failed to destroy CLK"); + rc = CgxDriverTransferEndDestroy(pDriver); + return rc; +} + + + +TCgReturnCode CgxDriverConstruct(void *pDriver, TCgxDriverState *pState) +{ + //DBG_FUNC_NAME("CgxDriverConstruct") + TCgReturnCode rc = ECgOk; + rc = CgCpuAllocateVa(); + memset(gChunksList,0,sizeof(TCgCpuDmaTask)*MAX_DMA_TRANSFER_TASKS); + + gps_gpio_request(); + +#if 0 + if (OK(rc)) rc = CgCpuDmaCreate(CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070); + + // set up DMA interrupt handler + if (OK(rc)) rc = CgxDriverDmaInterruptPrepare(); +#endif + + if (OK(rc)) rc = CgxDriverDataReadyInterruptHandlerStart(pDriver); + + // set up internal synchronization mechanism + if (OK(rc)) rc = CgxDriverTransferEndCreate(pDriver); + + + // set up GPS interrupt handler + if (OK(rc)) rc = CgxDriverGpsInterruptPrepare(); + if (OK(rc)) rc = CgxDriverGpsInterruptHandlerStart(pDriver); +#if 0 + // enable IP (not-reset) + if (OK(rc)) rc = CgCpuGpioModeSet(CG_DRIVER_GPIO_GPS_MRSTN, ECG_CPU_GPIO_OUTPUT); + if (OK(rc)) rc = CgCpuIPMasterResetOn(); + if (OK(rc)) rc = CgCpuDelay(CGCORE_RESET_DELAY); + if (OK(rc)) rc = CgCpuIPMasterResetClear(); + + // set up Sclk register + if (OK(rc)) rc = CGCoreSclkEnable(1); + + DBGMSG1("CGCORE_CORE_SCLK_ENABLE = 0x%08X", CGCORE_ENABLE_SCLK); + + // set up core-resets register + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, CGCORE_CORE_RESETS_ENABLE); + + DBGMSG1("CGCORE_CORE_RESETS_ENABLE = 0x%08X", CGCORE_CORE_RESETS_ENABLE); + + // Setup GPIO for RF-Power, and power up RF chip + //if (OK(rc)) rc = CgCpuGpioModeSet(CG_DRIVER_GPIO_RF_PD, ECG_CPU_GPIO_OUTPUT); + //if (OK(rc)) rc = CgxDriverRFPowerUp(); + + if (OK(rc)) rc = CgCpuGpioModeSet(CG_DRIVER_GPIO_TCXO_EN, ECG_CPU_GPIO_OUTPUT); + if (OK(rc)) rc = CgxDriverTcxoControl(TRUE); +#endif + + pState->constructionRc = rc; // For later reference (if needed by application) + pState->flags.resume = FALSE; + #ifdef CGCORE_ACCESS_VIA_SPI + gps_chip_power_off(); + #endif + return rc; +} + + + +TCgReturnCode CgxDriverPowerUp(void) +{ + TCgReturnCode rc = ECgOk; + U32 version = 0; + + // In order to power up the CGsnap, do a dummy access + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_VERSION, &version ); + return rc; +} + +TCgReturnCode CgxDriverPowerDown(void) +{ + TCgReturnCode rc = ECgOk; + + // Write software power-down command to CGsnap + rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_SOFT_CMD, CGCORE_SOFT_CMD_POWER_DOWN ); + + return rc; +} + +#ifdef CGCORE_ACCESS_VIA_SPI +unsigned int get_block_num(void ) +{ + return block_num; +} +#endif + +#if 0 +//gaole add +void CgCoreReleaseRes(void) +{ + printk("\n gaole: run to CgCoreReleaseRes \n"); + memset(gChunksList,0,sizeof(TCgCpuDmaTask)*MAX_DMA_TRANSFER_TASKS); +#ifdef CGCORE_ACCESS_VIA_SPI + block_num = 0; +#endif +} + +void CgGpsReset(void) +{ + CGCORE_WRITE_REG( 0x00000038, 0x0); + + CGCORE_WRITE_REG( 0x0000003c, 0x0); + + CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, CGCORE_CORE_RESETS_ENABLE); +} +#endif +/* +split blocks to chunks +last chunk might be small +last chunk generate app event +start of block aligned to chunk size +*/ + +TCgReturnCode CgxDriverPrepareRecieve( + TCgxDriverState *pState, + unsigned char *apBuf, + U32 aBufPhys, + U32 aBufSize, + unsigned long aLength, + unsigned long aBlockLength, + TCgByteOrder aByteOrder) +{ + DBG_FUNC_NAME("CgxDriverPrepareRecieve") + TCgReturnCode rc = ECgOk; + U32 blockIndex = 0; + U32 chunksInBlock = 0; + U32 chunkSize = 0; + U32 length = aLength + CgxDriverSnapLengthExtraBytes; // Potential patch + U32 numOfBlocksInBuffer = 0; + + memset(gChunksList,0,sizeof(TCgCpuDmaTask)*MAX_DMA_TRANSFER_TASKS); + + DBGMSG1("buffer v-address = 0x%x", apBuf); + DBGMSG1("start address value = 0x%x", *((U32*)apBuf) ); + DBGMSG1("dest address value = 0x%x", *((U32*)apBuf + 128) ); + + pState->transfer.blockSize = ((aBlockLength == 0) || (length < aBlockLength)) ? length : aBlockLength; + /*bxd modify for not limted to 512k Bytes each block*/ + chunkSize = pState->transfer.blockSize; + //chunkSize = MIN(MAX_DMA_CHUNK_SIZE, pState->transfer.blockSize); + chunksInBlock = pState->transfer.blockSize / chunkSize; + + + DBGMSG3("Requested %d bytes, Block=(%d bytes,%d chunks)", length, pState->transfer.blockSize, chunksInBlock); + DBGMSG1("Maximum DMA chunk size is set to %d bytes", chunkSize); + + pState->flags.overrun = FALSE; + pState->transfer.cancel.request = FALSE; + pState->transfer.cancel.onByte = 0; + pState->transfer.cancel.onChunk = 0; + pState->transfer.done = 0; + pState->transfer.originalBuffer = apBuf; + pState->transfer.bufferPhys = pState->buffer.physAddr; + pState->transfer.byteOrder = aByteOrder; + + pState->transfer.bytes.required = length; + pState->transfer.bytes.received = 0; + + pState->transfer.blocks.required = (length + pState->transfer.blockSize - 1) / pState->transfer.blockSize; +#ifdef CGCORE_ACCESS_VIA_SPI + block_num = pState->transfer.blocks.required; +#endif + DBGMSG1("%d blocks required", pState->transfer.blocks.required); + pState->transfer.lastBlockSize = length - (pState->transfer.blocks.required - 1) * pState->transfer.blockSize; + DBGMSG1("last block size: %d bytes", pState->transfer.lastBlockSize); + pState->transfer.blocks.received = 0; + + pState->transfer.chunks.required = 0; + pState->transfer.chunks.received = 0; + pState->transfer.chunks.active = 0; + + // split snap to blocks + ////////////////////////////////////////////////////////////////////////// + + if (pState->transfer.blocks.required * chunksInBlock > MAX_DMA_TRANSFER_TASKS) { + DBGMSG2("ERROR! too many chunks! %d > %d", pState->transfer.blocks.required * chunksInBlock, MAX_DMA_TRANSFER_TASKS); + return ECgErrMemory; + } + + numOfBlocksInBuffer = aBufSize / pState->transfer.blockSize; + DBGMSG2("aBufSize = %d, blockSize = %d", aBufSize, pState->transfer.blockSize ); + for(blockIndex = 0; blockIndex < pState->transfer.blocks.required; blockIndex++) + { + // Init the snap's blocks' offsets + pState->transfer.bufferOffset[blockIndex] = pState->transfer.blockSize * (blockIndex % numOfBlocksInBuffer); // roll-over to start of buffer, + // if we reached end of buffer. + //DBGMSG2("buffer[%d] = 0x%08X", blockIndex, pState->transfer.bufferPhys + pState->transfer.bufferOffset[blockIndex]) + } + + // split blocks to chunks + ////////////////////////////////////////////////////////////////////////// + + for(blockIndex = 0; blockIndex < pState->transfer.blocks.required; blockIndex++) { + U32 chunkIndex = 0; + U32 more, dest; + + more = (blockIndex == (pState->transfer.blocks.required-1)) ? pState->transfer.lastBlockSize : pState->transfer.blockSize; + dest = pState->transfer.bufferPhys + pState->transfer.bufferOffset[blockIndex]; + + // DBGMSG4("Block %02d/%02d: % 6d bytes @ 0x%08X", blockIndex + 1, pState->transfer.blocks.required, + for(chunkIndex = 0; chunkIndex < chunksInBlock-1; chunkIndex++) { + U32 size = MIN(more, chunkSize); + if ((more - size) < chunkSize) + break; + gChunksList[pState->transfer.chunks.required].address = dest; + gChunksList[pState->transfer.chunks.required].length = size; + more -= size; + // DBGMSG5("chunk %02d/%02d in block: length %d bytes @ 0x%08X (%d more)", chunkIndex + 1, chunksInBlock, + dest += size; + pState->transfer.chunks.required++; + } + // last chunk + gChunksList[pState->transfer.chunks.required].address = dest; + gChunksList[pState->transfer.chunks.required].length = more; + DBGMSG3("last chunk out of %02d in block: % 6d bytes @ 0x%08X", chunksInBlock, more, dest); + pState->transfer.chunks.required++; + } + + DBGMSG1("%d chunks required", pState->transfer.chunks.required); + + if (length > pState->transfer.blockSize * pState->transfer.blocks.required) { + // there are leftovers + U32 more = length - pState->transfer.blockSize * pState->transfer.blocks.required; + U32 dest = pState->transfer.bufferPhys + pState->transfer.bufferOffset[pState->transfer.blocks.required]; + DBGMSG4("Extra Block % 2d/% 2d: % 6d bytes @ 0x%08X", pState->transfer.blocks.required, pState->transfer.blocks.required, more, dest); + for (; (more > 0) && (pState->transfer.chunks.required < MAX_DMA_TRANSFER_TASKS); pState->transfer.chunks.required++) { + U32 size = MIN(more, chunkSize); + gChunksList[pState->transfer.chunks.required].address = dest; + gChunksList[pState->transfer.chunks.required].length = size; + more -= size; + dest += size; + DBGMSG4("chunk % 4d: % 4d bytes @ 0x%08X (%d bytes left)", pState->transfer.chunks.required + 1, size, dest, more); + } + DBGMSG1("%d chunks required", pState->transfer.chunks.required); + } + + + // setup 1st DMA chunk + #ifndef CGCORE_ACCESS_VIA_SPI + rc = CgCpuDmaSetupFromGps(gChunksList, pState->transfer.chunks.required, CG_DRIVER_DMA_CHANNEL_READ, CGCORE_BASE_ADDR + 0x00000070); + rc = CgCpuDmaStart(CG_DRIVER_DMA_CHANNEL_READ); + #else + // rc =CgxCpuSpiReadData(); + #endif + + return rc; +} + + + +TCgReturnCode CgxDriverIsReadCanceled(TCgxDriverState *pState) +{ + DBG_FUNC_NAME("CgxDriverIsReadCanceled") + TCgReturnCode rc = ECgOk; + + + // Check if snap was unconditionally canceled + if (pState->transfer.cancel.request && (pState->transfer.bytes.received > pState->transfer.cancel.onByte)) + { + CGCoreReset(CGCORE_ENABLE_CORE); + CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + return ECgCanceled; + } + + // Check if we have reached the cancel point + if (pState->transfer.cancel.request) { + U32 curDmaCount = 0; + U32 requestedDmaCount = 0; + rc = CgCpuDmaRequestedCount(CG_DRIVER_DMA_CHANNEL_READ, &requestedDmaCount); // how many bursts requested to receive + DBGMSG1("requestedDmaCount = %d", requestedDmaCount); + + rc = CgCpuDmaCurCount(CG_DRIVER_DMA_CHANNEL_READ, &curDmaCount); // how many bursts left to receive + DBGMSG1("curDmaCount = %d", curDmaCount); + + DBGMSG2("%d >= %d ? ==> canceled", pState->transfer.bytes.received + (requestedDmaCount - curDmaCount) , pState->transfer.cancel.onByte); + + if (pState->transfer.bytes.received + (requestedDmaCount - curDmaCount) >= pState->transfer.cancel.onByte) + { + CGCoreReset(CGCORE_ENABLE_CORE); + CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + return ECgCanceled; + } + } + + return ECgOk; +} + +TCgReturnCode CGCoreEnable(U32 aUnitToEnable) +{ + DBG_FUNC_NAME("CGCoreEnable") + TCgReturnCode rc = ECgOk; + + U32 enableValue = 1; + U32 coreResetsReg = 0; + + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_CORE_RESETS, &coreResetsReg); +// DBGMSG1("Read coreResetsReg=0x%08X", coreResetsReg); + REG_SET1(coreResetsReg, aUnitToEnable, enableValue); + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, coreResetsReg); + DBGMSG1("Write [0x%08X]", coreResetsReg); + return rc; +} + +TCgReturnCode CGCoreDisable(U32 aUnitToDisable) +{ + DBG_FUNC_NAME("CGCoreDisable") + TCgReturnCode rc = ECgOk; + + U32 disableValue = 0; + U32 coreResetsReg = 0; + + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_CORE_RESETS,&coreResetsReg); +// DBGMSG1("Read coreResetsReg=0x%08X", coreResetsReg); + REG_SET1(coreResetsReg, aUnitToDisable, disableValue); + if (OK(rc)) rc = CGCORE_WRITE_REG(CGCORE_REG_OFFSET_CORE_RESETS,coreResetsReg); + DBGMSG1("Write [0x%08X]", coreResetsReg); + return ECgOk; +} + +TCgReturnCode CGCoreReset(U32 aUnitToReset) +{ + DBG_FUNC_NAME("CGCoreReset") + TCgReturnCode rc = ECgOk; + U32 coreResetsReg = 0; + U32 coreResetsRegOld = 0; + + ////////////////// Core Disable ////////////// + rc = CGCORE_READ_REG(CGCORE_REG_OFFSET_CORE_RESETS,&coreResetsReg); + coreResetsRegOld = coreResetsReg; + REG_SET1(coreResetsReg, aUnitToReset, 0); + if (OK(rc)) rc = CGCORE_WRITE_REG(CGCORE_REG_OFFSET_CORE_RESETS,coreResetsReg); + DBGMSG1("Write [0x%08X]", coreResetsReg); + + if (OK(rc)) rc = CgCpuDelay(CGCORE_RESET_DELAY); + + ////////////////// Core Enable ////////////// + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, coreResetsRegOld); + DBGMSG1("Write [0x%08X]", coreResetsRegOld); + + return rc; +} + + +TCgReturnCode CgxDriverExecuteSpecific( + void *pDriver, + TCgxDriverState *pState, + U32 aRequest, + TCgDriverControl *pControl, + TCgDriverStatus *pResults) +{ + DBG_FUNC_NAME("CgxDriverExecuteSpecific") + DBGMSG1("aRequest =%x",aRequest); + switch (aRequest) { + case CGX_IOCTL_INIT: + DBGMSG("CGX_IOCTL_INIT"); + // This is 1st time initialization, meaning the software is restarted, not resumed, so set the state accordingly. + DBGMSG1("pState = 0x%x", pState); + + pState->flags.resume = FALSE; + DBGMSG("after pState->flags.resume = FALSE;"); + pResults->rc = CgxDriverInit(pDriver); + break; + + case CGX_IOCTL_STOP: + pResults->rc = CgxDriverDestroy(pDriver); + break; + + case CGX_IOCTL_READ_REG: + pState->transfer.cancel.request = FALSE; + // Verify register is of the CGX_sat_ram group + pResults->readReg.value = 0; + DBGMSG1("readReg.offset %x ",pControl->readReg.offset); + if ( pControl->readReg.offset >= CGCORE_REG_OFFSET_SAT_RAM && pControl->readReg.offset <= CGCORE_REG_OFFSET_SAT_RAM_LAST ) + { + // Write read command to the APB (9 bits of the register offset, with 0x80000000, as the read command) + pResults->rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_APB_COMMAND, (0x000001FF & pControl->readReg.offset) | 0x80000000); + + // Wait 4 system clocks + CgCpuDelay(100); // TODO : what is the actual period of this wait. Is it 4 system clocks? + + // Read data from the APB + if (OK(pResults->rc)) + pResults->rc = CGCORE_READ_REG( CGCORE_REG_OFFSET_APB_DATA, &pResults->readReg.value); + } + else + { + // It is not part of the CGX_sat_ram. Read register normaly, via the APB + + pResults->rc = CGCORE_READ_REG( pControl->readReg.offset, &pResults->readReg.value); + } + break; + + case CGX_IOCTL_WRITE_REG: + pState->transfer.cancel.request = FALSE; + // Write to CGsnap register + pResults->rc = CGCORE_WRITE_REG( pControl->writeReg.offset, pControl->writeReg.value); + // DBGMSG2("CGX_IOCTL_WRITE_REG *0x%08X = 0x%08X", CGCORE_BASE_ADDR_VA + pControl->writeReg.offset, pControl->writeReg.value); + break; + + case CGX_IOCTL_PREPARE_RECEIVE: + DBGMSG("CGX_IOCTL_PREPARE_RECEIVE"); + // Prepare driver for massive data receive (snap) + pState->transfer.cancel.request = FALSE; + pResults->rc = CgxDriverPrepareRecieve(pState, pControl->read.buf, pControl->read.bufPhys, + pState->buffer.length, pControl->read.alignedLength, pControl->read.blockLength, + pControl->read.byteOrder); + break; + + case CGX_IOCTL_STATUS: + pResults->rc = pState->constructionRc; + break; + + case CGX_IOCTL_RESUME_CLEAR: + DBGMSG("CGX_IOCTL_RESUME_CLEAR!"); + pState->flags.resume = FALSE; + pState->transfer.cancel.request = FALSE; + break; + case CGX_IOCTL_RESET: + DBGMSG1("CGX_IOCTL_RESET level %d", pControl->reset.resetLevel); + pState->transfer.cancel.request = FALSE; + switch( pControl->reset.resetLevel ) + { + case 0: // Full reset + #if 0 + if (OK(pResults->rc)) pResults->rc = CgCpuIPMasterResetOn(); + if (OK(pResults->rc)) pResults->rc = CgCpuDelay(CGCORE_RESET_DELAY); + if (OK(pResults->rc)) pResults->rc = CgCpuIPMasterResetClear(); + #endif + if (OK(pResults->rc)) pResults->rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_CORE_RESETS, CGCORE_CORE_RESETS_ENABLE); + break; + case 1: // Semi reset + if (OK(pResults->rc)) pResults->rc = CGCoreReset(CGCORE_ENABLE_CORE); + #ifdef CGCORE_ACCESS_VIA_SPI + init_spi_block_var(); + #endif + break; + case 2: // CPU reset + break; + default : // Semi reset, also. + if (OK(pResults->rc)) pResults->rc = CGCoreReset(CGCORE_ENABLE_CORE); + break; + } + pResults->rc = CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + break; + + case CGX_IOCTL_COUNTER_RESET: + DBGMSG("CGX_IOCTL_COUNTER_RESET!"); + pResults->rc = CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + if (OK(pResults->rc)) pResults->rc = CGCoreReset(CGCORE_ENABLE_TCXO); + break; + + case CGX_IOCTL_POWER_DOWN: + DBGMSG("CGX_IOCTL_POWER_DOWN!"); + flag_power_up = 0; + pResults->rc = CgxDriverPowerDown(); + if (OK(pResults->rc)) pResults->rc = CgxDriverRFPowerDown(); + break; + + case CGX_IOCTL_POWER_UP: + flag_power_up = 1; + pState->transfer.cancel.request = FALSE; + pResults->rc = CgxDriverPowerUp(); + if (OK(pResults->rc)) pResults->rc = CgxDriverRFPowerUp(); + break; + + case CGX_IOCTL_POWER_OFF : + pResults->rc = CgxDriverPowerOff(); + break; + + case CGX_IOCTL_POWER_ON : + pResults->rc = CgxDriverPowerOn(); + break; + + case CGX_IOCTL_GPIO_SET: + //DBGMSG2("CGX_IOCTL_GPIO_SET 0x%08X = %d", pControl->GPIO.code, pControl->GPIO.out); + if (pControl->GPIO.out) + pResults->rc = CgCpuGpioSet(pControl->GPIO.code); + else + pResults->rc = CgCpuGpioReset(pControl->GPIO.code); + //rc = CgxDriverDebugGpio((int)pControl->GPIO.code, (int)pControl->GPIO.out); + break; + + case CGX_IOCTL_GPIO_GET: + //DBGMSG1("CGX_IOCTL_GPIO_GET 0x%08X", pControl->GPIO.code); + //pResults->GPIO.in = 0x5a5a; + //DBGMSG2("CGX_IOCTL_GPIO_GET before 0x%08X=0x%08X", pControl->GPIO.code, pResults->GPIO.in) + pResults->rc = CgCpuGpioGet(pControl->GPIO.code, (int *)&(pResults->GPIO.val)); + pResults->GPIO.code = pControl->GPIO.code; + //DBGMSG2("CGX_IOCTL_GPIO_GET after 0x%08X=0x%08X", pControl->GPIO.code, pResults->GPIO.in) + //rc = CgxDriverDebugGpioRead((int)pResults->GPIO.code, (int*)&pResults->GPIO.in); + break; + + case CGX_IOCTL_GET_VERSION: + memcpy(pResults->version.buildVersion, gCgDriverVersion.buildVersion, sizeof(pResults->version.buildVersion)); + memcpy(pResults->version.buildMode, gCgDriverVersion.buildMode, sizeof(pResults->version.buildNumber)); + memcpy(pResults->version.buildNumber, gCgDriverVersion.buildNumber, sizeof(pResults->version.buildNumber)); + memcpy(pResults->version.buildTime, gCgDriverVersion.buildTime, sizeof(pResults->version.buildTime)); + memcpy(pResults->version.buildDate, gCgDriverVersion.buildDate, sizeof(pResults->version.buildDate)); + break; + + case CGX_IOCTL_CANCEL_RECEIVE: + DBGMSG1("Request cancel on byte %d", pControl->cancel.onByteCount); + + // set up receive abort flag. + // the flag is cleared be prepare receive command + + if (pControl->cancel.onByteCount > (U32)CgxDriverSnapLengthExtraBytes) { + pState->transfer.cancel.onByte = pControl->cancel.onByteCount - CgxDriverSnapLengthExtraBytes; + CG_MATH_ALIGNMENT((pState->transfer.cancel.onByte), NUMBER_1K); + DBGMSG1("cancel on Byte: 0x%08X", pState->transfer.cancel.onByte); + } + else { + pState->transfer.cancel.onByte = 0; // Cancel snap req immediately + } + pState->transfer.cancel.request = TRUE; + DBGMSG1("cancel on Byte: 0x%08X", ((pState->transfer.cancel.onByte / 16) & 0x00FFFFF) | 0x0F000000); + CGCORE_WRITE_REG( 0x30, ((pState->transfer.cancel.onByte / 16) & 0x00FFFFF) | 0x0F000000); + CGCORE_WRITE_REG( 0x34, 0); + + // check if cancel point passed + pResults->rc = CgxDriverIsReadCanceled(pState); + if ((pControl->cancel.onByteCount == 0) || // Cancel snap req immediately + (!OK(pResults->rc) && pState->flags.wait)) {// release a waiting thread, if any + CGCoreReset(CGCORE_ENABLE_CORE); + CgCpuDmaStop(CG_DRIVER_DMA_CHANNEL_READ); + CgxDriverDataReadyInterruptHandler(pDriver, pState); + } + + break; + + case CGX_IOCTL_ALLOC_BUFF: + DBGMSG1("CGX_IOCTL_ALLOC_BUFF, pControl->alloc.length=%d", pControl->alloc.length); + + // pControl->alloc.length = 1 *1024 * 1024; // 1M + + pResults->rc = CgxDriverAllocInternalBuff(pDriver, pControl->alloc.length, + (void**)&(pResults->buffer.bufferPhysAddr), pControl->alloc.processId); + DBGMSG1("alloc p =0x%08X", pState->buffer.virtAddr); + if (OK(pResults->rc)) { + pResults->buffer.size = pControl->alloc.length; + pResults->buffer.bufferAppVirtAddr = pState->buffer.virtAddr; + } + break; + + case CGX_IOCTL_FREE_BUFF: + DBGMSG("CGX_IOCTL_FREE_BUFF"); + pResults->rc = CgxDriverFreeInternalBuff(pDriver, pControl->alloc.processId); + break; + case CGX_IOCTL_READ_MEM: + DBGMSG("CGX_IOCTL_READ_MEM"); + pState->transfer.cancel.request = FALSE; + DBGMSG1("read from 0x%08X", pControl->readReg.offset); + pResults->rc = CgxCpuReadMemory(pControl->readReg.offset, 0, &pResults->readReg.value); + break; + + case CGX_IOCTL_CPU_REVISION: + pResults->rc = CgCpuRevision(pResults->cpuRevision.revisionCode); // TODO - fix CgCpuRevision so it reads from the right address + break; + + case CGX_IOCTL_TCXO_ENABLE: + DBGMSG("CGX_IOCTL_TCXO_ENABLE"); + pResults->rc = CgxDriverTcxoControl(pControl->tcxoControl.enable); + break; + + case CGX_IOCTL_RF_WRITE_CONTROL: + DBGMSG("CGX_IOCTL_RF_WRITE_CONTROL"); + pResults->rc = CgCpuRFControlWriteByte(pControl->writeReg.value); + break; + + default: + return ECgGeneralFailure; + } + + return ECgOk; +} + +TCgReturnCode CgxDriverPowerOn(void) +{ + TCgReturnCode rc = ECgOk; + + gps_chip_power_on(); + + // Enable clock to the GPS device + msleep(1); + rc = CGCoreEnable(CGCORE_ENABLE_TCXO); + + return rc; +} + +TCgReturnCode CgxDriverPowerOff(void) +{ + TCgReturnCode rc = ECgOk; + + // Disable clock to the GPS device + rc = CGCoreDisable(CGCORE_ENABLE_TCXO); + gps_chip_power_off(); + + return rc; +} + +TCgReturnCode CgxDriverTcxoControl(u32 aEnable) +{ + TCgReturnCode rc = ECgOk; + + if(aEnable) + CGCoreEnable(CGCORE_ENABLE_TCXO); + else + CGCoreDisable(CGCORE_ENABLE_TCXO); + + return rc; +} + +TCgReturnCode CgCGCoreGpioSet(U32 aGpioPin, U32 aVal) +{ + TCgReturnCode rc = ECgOk; + U32 valToSet = 0; + + if (aGpioPin <= 0 || aGpioPin > 4) rc = ECgBadArgument; + + if (OK(rc)) rc = CGCORE_READ_REG( CGCORE_REG_OFFSET_GPO, &valToSet); + REG_SET1(valToSet,aGpioPin,aVal ? 1 : 0); + if (OK(rc)) rc = CGCORE_WRITE_REG( CGCORE_REG_OFFSET_GPO, valToSet ); + + return rc; +} + +/* + +TCgReturnCode CgxDriverRFPowerDown(void) +{ + DBG_FUNC_NAME("CgxDriverRFPowerDown") + TCgReturnCode rc = ECgOk; + + #if CG_DRIVER_CG_CORE_CONTROLS_RF_PD + // Do nothing - Core controls RF power down pin + #else + #ifdef RF_POWER_UP_VAL + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, RF_POWER_UP_VAL); + #else + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, 1); + #endif + #endif + + return rc; +} + +TCgReturnCode CgxDriverRFPowerUp(void) +{ + DBG_FUNC_NAME("CgxDriverRFPowerUp"); + TCgReturnCode rc = ECgOk; + + #if CG_DRIVER_CG_CORE_CONTROLS_RF_PD + // Do nothing - Core controls RF power down pin + #else + #ifdef RF_POWER_UP_VAL + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, !RF_POWER_UP_VAL); + #else + rc = CgCpuGpioSet(CG_DRIVER_GPIO_RF_PD, 0); + #endif + #endif + + return rc; +} + +*/ 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 <asm/io.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/cdev.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/poll.h> +#include <linux/device.h> +#include <linux/major.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/errno.h> +#include <linux/completion.h> +#include <linux/dma-mapping.h> + +#ifdef CONFIG_OF +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_gpio.h> +#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 <pablo@ximpo.com> - 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 <linux/kthread.h> +#include <linux/signal.h> +#include <soc/sprd/board.h> +#include <soc/sprd/hardware.h> +#include <soc/sprd/dma.h> +#include <linux/slab.h> + +#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 <asm/io.h> + +#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 <linux/gpio.h> +#include <soc/sprd/gpio.h> +//#include <asm/mach-types.h> +#include <asm/io.h> +#include <soc/sprd/board.h> +#include <soc/sprd/hardware.h> +#include <soc/sprd/irqs.h> +// =========================================================================== +//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 <linux/init.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/ioctl.h> +#include <linux/fs.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/spi/spi.h> +#include <linux/spi/spidev.h> +#include <asm/uaccess.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/delay.h> +#include <soc/sprd/dma.h> +#include <soc/sprd/hardware.h> +#include <soc/sprd/gpio.h> +#include <linux/proc_fs.h> +#include <linux/kthread.h> + +#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 <asm/uaccess.h>
+#include <soc/sprd/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <soc/sprd/regulator.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include "CgxDriverApi.h"
+#include "CgCpu.h"
+#include "platform.h"
+#include "CgReturnCodes.h"
+#include "CgxDriverOs.h"
+#include "CgxDriverCore.h"
+
+#ifdef CONFIG_ARCH_SCX20
+#include <linux/sprd_2351.h> +#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 <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <asm/dma.h> +#include <asm/io.h> +#include<soc/sprd/system.h> +#include <asm/uaccess.h> +#include <asm/irq.h> +#include <linux/dma-mapping.h> + +#include <soc/sprd/hardware.h> +#include <soc/sprd/sci.h> +#ifndef CGCORE_ACCESS_VIA_SPI +#include <linux/sprd_2351.h> +#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 */ |
