[PATCH RFC 1/2] iop13xx: add base support for the imu

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Greg Tucker <greg.b.tucker@xxxxxxxxx>

The interprocessor messaging unit supports mailbox style communication
between the two Xscale cores on iop342.
    
Signed-off-by: Greg Tucker <greg.b.tucker@xxxxxxxxx>
Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---

 arch/arm/mach-iop13xx/Kconfig              |    2 
 arch/arm/mach-iop13xx/Makefile             |    1 
 arch/arm/mach-iop13xx/imu/Kconfig          |   19 +
 arch/arm/mach-iop13xx/imu/Makefile         |    3 
 arch/arm/mach-iop13xx/imu/common.c         |  486 ++++++++++++++++++++++++++++
 arch/arm/mach-iop13xx/imu/dev.c            |  438 +++++++++++++++++++++++++
 arch/arm/mach-iop13xx/imu/imu.c            |  151 +++++++++
 include/asm-arm/arch-iop13xx/iop13xx-imu.h |  207 ++++++++++++
 8 files changed, 1307 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-iop13xx/Kconfig b/arch/arm/mach-iop13xx/Kconfig
index 40c2d68..27c1c2c 100644
--- a/arch/arm/mach-iop13xx/Kconfig
+++ b/arch/arm/mach-iop13xx/Kconfig
@@ -16,5 +16,7 @@ config MACH_IQ81340MC
 	  Say Y here if you want to support running on the Intel IQ81340MC
 	  evaluation kit.
 
+source "arch/arm/mach-iop13xx/imu/Kconfig"
+
 endmenu
 endif
diff --git a/arch/arm/mach-iop13xx/Makefile b/arch/arm/mach-iop13xx/Makefile
index 4185e05..7937d73 100644
--- a/arch/arm/mach-iop13xx/Makefile
+++ b/arch/arm/mach-iop13xx/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_IOP13XX) += pci.o
 obj-$(CONFIG_ARCH_IOP13XX) += io.o
 obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
 obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o
+obj-$(CONFIG_IOP_IMU) += imu/
diff --git a/arch/arm/mach-iop13xx/imu/Kconfig b/arch/arm/mach-iop13xx/imu/Kconfig
new file mode 100644
index 0000000..ee49b37
--- /dev/null
+++ b/arch/arm/mach-iop13xx/imu/Kconfig
@@ -0,0 +1,19 @@
+#
+# IOP13xx IMU Support
+#
+
+menu "IOP13XX IMU Support"
+
+config IOP_IMU
+	tristate "IOP IMU support"
+	depends on EXPERIMENTAL
+	---help---
+	This includes support functions for the IMU.
+
+config IOP_IMU_DEV
+	tristate "IOP IMU char driver"
+	depends on IOP_IMU
+	---help---
+	This is a char driver that passes messages throught the IMU.
+
+endmenu
diff --git a/arch/arm/mach-iop13xx/imu/Makefile b/arch/arm/mach-iop13xx/imu/Makefile
new file mode 100644
index 0000000..f89fb53
--- /dev/null
+++ b/arch/arm/mach-iop13xx/imu/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_IOP_IMU)      += common.o imu.o
+obj-$(CONFIG_IOP_IMU_DEV)  += dev.o
+
diff --git a/arch/arm/mach-iop13xx/imu/common.c b/arch/arm/mach-iop13xx/imu/common.c
new file mode 100644
index 0000000..2d9c311
--- /dev/null
+++ b/arch/arm/mach-iop13xx/imu/common.c
@@ -0,0 +1,486 @@
+/*
+ * arch/arm/mach-iop13xx/imu/iop1340-imu-common.c
+ *
+ * Interface functions for comunication using IMU hardware on the IOP1342
+ *
+ * Copyright (C) 2005, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Greg Tucker <greg.b.tucker@xxxxxxxxx>
+ *
+ */
+
+#ifdef linux
+#  include <linux/module.h>
+#  include <linux/kernel.h>
+#  include <asm/arch/iop13xx-imu.h>
+#else
+#  include "iop1340-imu-common.h"
+#endif
+
+imu_handler *imu_irq_table[NR_IMU_DOORBELLS + NR_IMU_QUEUE_IRQS];
+struct imu_queue_params imu_queue[NR_IMU_QUEUES];
+
+/**
+ ****************************************************************************
+ * @iop_doorbell_ring
+ * @brief
+ *   Ring specified hw doorbell.
+ *
+ *   Will cause an interrupt on the other processor if enabled.
+ *
+ * @param IN: int doorbell - doorbell number
+ * @return NONE
+ *****************************************************************************/
+
+/* #define iop_doorbell_ring(doorbell)  do {*((volatile int*)IMU_DBAR) = (1<<doorbell);} while(0) */
+
+inline void iop_doorbell_ring(int doorbell)
+{
+	*((volatile int *)IMU_DBAR) = (1 << doorbell);
+}
+
+/**
+ ****************************************************************************
+ * @iop_wait_on_doorbell
+ * @brief
+ *   Spin until doorbell asserted.
+ * @param  IN: int doorbell - doorbell number
+ * @return NONE
+ *****************************************************************************/
+
+/*#define iop_wait_on_doorbell(doorbell)  do {while ( 0 == (*((volatile int*)IMU_DBCR) & (1<<doorbell)) ) ;} while (0) */
+
+inline void iop_wait_on_doorbell(int doorbell)
+{
+	while (0 == (*((volatile int *)IMU_DBCR) & (1 << doorbell))) ;
+}
+
+/**
+ ******************************************************************************
+ * @iop_doorbell_clear_status
+ * @brief
+ *   Clear doorbell status bit so future doorbells can interrupt.
+ * @param  IN: int doorbell - doorbell number
+ * @return NONE
+ *****************************************************************************/
+
+/* #define iop_doorbell_clear_status(doorbell) do {*((volatile int*)IMU_DBCR) = (1<<doorbell) & ((1<<16)-1);} while(0) */
+
+inline void iop_doorbell_clear_status(int doorbell)
+{
+	*((volatile int *)IMU_DBCR) = (1 << doorbell) & ((1 << 16) - 1);
+}
+
+/**
+ ******************************************************************************
+ * @iop_doorbell_check_status
+ * @brief
+ *   Check if doorbell is active.
+ * @param  IN: int doorbell - doorbell number
+ * @return
+ *   0: doorbell not active
+ *   other: doorbell active
+ *****************************************************************************/
+inline int iop_doorbell_check_status(int doorbell)
+{
+	return *((volatile int *)IMU_DBCR) & (1 << doorbell);
+}
+
+/**
+ ******************************************************************************
+ * @iop_doorbell_enable
+ * @brief
+ *   Enable this doorbell to interrupt processor.
+ * @param  IN: int doorbell - doorbell number
+ * @return NONE
+ *****************************************************************************/
+void iop_doorbell_enable(int doorbell)
+{
+	*((volatile int *)IMU_DBER) |= (1 << doorbell);
+}
+
+/**
+ ******************************************************************************
+ * @iop_doorbell_disable
+ * @brief
+ *   Disable particular doorbell.
+ * @param  IN: int doorbell - doorbell number
+ * @return NONE
+ *****************************************************************************/
+void iop_doorbell_disable(int doorbell)
+{
+	*((volatile int *)IMU_DBER) &= ~(1 << doorbell);
+}
+
+/**
+ ******************************************************************************
+ * @iop_doorbell_mask
+ * @brief
+ *   Mask/Disable doorbells corresponding to mask.
+ * @param  IN: int mask - vector of doorbells to disable
+ * @return NONE
+ *****************************************************************************/
+void iop_doorbell_mask(int mask)
+{
+	*((volatile int *)IMU_DBER) &= ~(mask);
+}
+
+/**
+ ******************************************************************************
+ * @iop_doorbell_unmask
+ * @brief
+ *   Unmask/Enable doorbells corresponding to mask.
+ * @param  IN: int mask - vector of doorbells to enable
+ * @return NONE
+ *****************************************************************************/
+void iop_doorbell_unmask(int mask)
+{
+	*((volatile int *)IMU_DBER) &= mask;
+}
+
+/**
+ ****************************************************************************
+ * @iop_doorbell_reg_callback
+ * @brief
+ *   Register the callback function for a particular doorbell.
+ * @param  IN: int doorbell - doorbell number
+ * @param  IN: void * callback(void) - pointer to callback function
+ * @return NONE
+ *****************************************************************************/
+int iop_doorbell_reg_callback(int doorbell, void (*callback) (int))
+{
+	if ((doorbell >= 0) && (doorbell <= IMU_DB_RQ3NE)) {
+		imu_irq_table[doorbell] = (imu_handler *) callback;
+		return 0;
+	} else
+		return 1;
+}
+
+/**
+ ******************************************************************************
+ * @iop_mutex_lock
+ * @brief
+ *   Block until mutex is granted.
+ *
+ *   Checks if current core has been granted access to the hw mutex.
+ *   Does not check if it's the current thread that has access or
+ *   another thread on the same processor.  Only binary mutex is
+ *   supported.
+ *
+ * @param  IN: mutex - mutex number
+ * @return NONE
+ *****************************************************************************/
+void iop_mutex_lock(int mutex)
+{
+	int trymutex = *IMU_TSR(mutex);
+	int corenum = (1 << CIDR_READ());
+
+	while (trymutex != 0 && trymutex != corenum) {
+		trymutex = *IMU_TSR(mutex);
+	}
+}
+
+/**
+ ****************************************************************************
+ * @iop_mutex_trylock
+ * @brief
+ *   Non-blocking attempt to get mutex.
+ *
+ *   Checks if current core has been granted access to the hw mutex.
+ *   Does not check if it's the current thread that has access or
+ *   another thread on the same processor.  Only binary mutex is
+ *   supported.
+ *
+ * @param IN: int mutex - mutex number
+ * @return
+ *   0: success
+ *   1: other core has lock
+ *****************************************************************************/
+int iop_mutex_trylock(int mutex)
+{
+	int trymutex = *IMU_TSR(mutex);
+	int coreid = CIDR_READ();
+
+	if (trymutex == 0 || (trymutex ^ (1 << coreid)) == 0)
+		return 0;
+	else
+		return 1;
+}
+
+/**
+ ****************************************************************************
+ * @iop_mutex_unlock
+ * @brief
+ *   Unlock/free the given mutex.
+ *
+ *   Does not first check if the mutex is locked.  Assumes that the
+ *   calling thread ownes the mutex.  Currently only binary mutex is
+ *   supported so does not keep a lock count.
+ *
+ * @param  IN: int mutex - mutex number
+ * @return NONE
+ *****************************************************************************/
+void iop_mutex_unlock(int mutex)
+{
+	/* assert(iop_mutex_trylock(mutex)); */
+	*IMU_TSR(mutex) = 0x0;
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_init
+ * @brief
+ *   Initialize circular queue.
+ *
+ *   Sets up a circular queue with memory for the queue buffers and
+ *   callback function for received messages.  Caller must first
+ *   allocate memory of appropriate size and type for the queue.  The
+ *   queue is of fixed size (msg_size * num_items) bytes.
+ *
+ *   @todo List restrictions on the memory type (dma-able, etc.)
+ *
+ * @param  IN: int queueid - queue identifier
+ * @param  IN: void * phys_base - physical base pointer to pre-allocated memory
+ * @param  IN: void * virt_base - virtual base pointer to pre-allocated memory
+ * @param  IN: int msg_size - size of fixed messages in bytes
+ * @param  IN: int num_items - max number of items in the queue
+ * @param  IN: void * callback(int) - pointer to callback function
+ * @param  IN: void * error_callback(int) - pointer to error function
+ * @return 0: success
+ *****************************************************************************/
+int
+iop_queue_init(int queueid, void *phys_base, void *virt_base, int msg_size,
+	       int num_items, void (*rcd_callback) (int),
+	       void (*error_callback) (int))
+{
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	if (queueid > 3 || num_items > ((1 << 16) - 1))
+		return 1;
+
+	/* init send queue pointers */
+	queue_hw->sqcr = (1 << 31)	/* reset send queue get/put pointers */
+	    |num_items;		/* set size */
+	queue_hw->rqcr = (1 << 31);	/* reset receive queue get/put pointers */
+	queue_hw->sqlbar = (int)phys_base;
+	queue_hw->squbar = 0;	/* assuming 32 bit address space */
+
+	imu_queue[queueid].txbase = virt_base;
+	imu_queue[queueid].msg_size = msg_size;
+	imu_queue[queueid].items = num_items;
+	imu_queue[queueid].alloc = queue_hw->sqpg >> 16;	/* alloc=get */
+
+	/* Register callback */
+	imu_irq_table[NR_IMU_DOORBELLS - 1 +
+		      (IMU_DB_RQ0NE - IMU_DB_QUEUE_IRQ_OFF) + (queueid * 2)] =
+	    (imu_handler *) rcd_callback;
+	/* Enable receive interrupt */
+	iop_doorbell_enable(IMU_DB_RQ0NE + (queueid * 2));
+
+	return 0;
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_allocate
+ * @brief
+ *   Return pointer to next free buffer queue.
+ * @param  IN: int queueid - queue identifier
+ * @return buffer pointer to fill with message
+ *****************************************************************************/
+void *iop_queue_allocate(int queueid)
+{
+	void *ret = NULL;
+	int alloc, get, items_m1, next_alloc;
+
+	struct imu_queue_params *queue = &imu_queue[queueid];
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	if (queueid > 3)
+		return NULL;
+
+	/* todo: put mutex around alloc update */
+	alloc = queue->alloc;
+	get = queue_hw->sqpg >> 16;
+	items_m1 = queue->items - 1;
+	next_alloc = (alloc == items_m1) ? 0 : alloc + 1;
+
+	if (next_alloc != get) {	/* not full */
+		ret = (void *)(queue->txbase + (queue->msg_size * alloc));
+		queue->alloc = next_alloc;
+	}
+	/* todo: unlock mutex on alloc */
+
+	return ret;
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_postmsg
+ * @brief
+ *   Post (send) all buffers up to message identified by message pointer.
+ * @param  IN: int queueid - queue identifier
+ * @param  IN: void * msg_adr - pointer to last message to post
+ * @return NONE
+ *****************************************************************************/
+int iop_queue_postmsg(int queueid, void *msg_adr)
+{
+	int offset, items, items_m1, put, alloc, index;
+
+	struct imu_queue_params *queue = &imu_queue[queueid];
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	offset = (int)(msg_adr - queue->txbase);
+
+	items = queue->items;
+	items_m1 = items - 1;
+
+	/* Check if it is in range for this queue */
+	if (offset < 0 || offset > (queue->msg_size * items))
+		return 1;
+
+	put = queue_hw->sqpg & 0xffff;
+	alloc = queue->alloc;
+	index = offset / queue->msg_size;
+
+	/* todo: Check if allocated? */
+	/* don't post something already posted */
+
+	if (alloc >= put) {
+		if (index < put || index >= alloc)
+			return 1;	/* already posted or not allocated */
+	} else {
+		if (index < put && index >= alloc)
+			return 1;	/* already posted or not allocated */
+	}
+
+	queue_hw->sqpg = (index == items_m1) ? 0 : index + 1;
+
+	return 0;
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_rx_not_empty
+ * @brief
+ *   Check rx queue for not empty status.
+ * @param  IN: int queueid - queue identifier
+ * @return
+ *    0: rx queue empty
+ *    other: rx queue not empty
+ *****************************************************************************/
+int iop_queue_rx_not_empty(int queueid)
+{
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	int rqpg = queue_hw->rqpg;
+	int put = rqpg & 0xffff;
+	int get = rqpg >> 16;
+	return get - put;
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_tx_not_full
+ * @brief
+ *   Check tx queue for full status
+ * @param  IN: int queueid - queue identifier
+ * @return
+ *    0: tx queue full
+ *    other: rx queue not full
+ *****************************************************************************/
+int iop_queue_tx_not_full(int queueid)
+{
+	struct imu_queue_params *queue = &imu_queue[queueid];
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	int get = queue_hw->sqpg >> 16;
+	int next_alloc = queue->alloc + 1;
+	next_alloc = (next_alloc == queue->items) ? 0 : next_alloc;
+
+	return next_alloc - get;
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_getmsg
+ * @brief
+ *   Get next available message.
+ *
+ *   Get a pointer to the next available message in the recieve queue.
+ *   Subsequent calls will return the same value until the message is freed.
+ *
+ * @param  IN: int queueid - queue identifier
+ * @return buffer pointer to next available message
+ *****************************************************************************/
+void *iop_queue_getmsg(int queueid)
+{
+
+	struct imu_queue_params *queue = &imu_queue[queueid];
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	int rqpg = queue_hw->rqpg;
+	void *base = queue->rxbase;
+	int put = rqpg & 0xffff;
+	int get = rqpg >> 16;
+
+	if (!base || put == get)
+		return 0;
+
+	return base + (get * queue->msg_size);
+}
+
+/**
+ ****************************************************************************
+ * @iop_queue_rxfree
+ * @brief
+ *   Free a buffer in the receive queue that has already been processed.
+ *
+ *   Free the buffer that includes msg_addr.  Also frees all prior
+ *  messages in the queue.
+ *
+ * @param  IN: int queueid - queue identifier
+ * @param  IN: void * msg_addr - pointer to data within message to free
+ * @return buffer pointer to next available message
+ *****************************************************************************/
+int iop_queue_rxfree(int queueid, void *msg_adr)
+{
+	int rq_items, offset, index;
+
+	struct imu_queue_params *queue = &imu_queue[queueid];
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	rq_items = queue_hw->rqcr & 0xffff;
+	offset = (int)(msg_adr - queue->rxbase);
+
+	/* Check if it is in range for this queue */
+	if (offset < 0 || offset > (queue->msg_size * rq_items)) {
+		return 1;
+	}
+
+	index = (offset / queue->msg_size) + 1;
+	index = (index == rq_items) ? 0 : index;
+	queue_hw->rqpg = index << 16;	/* update get pointer */
+
+	return 0;
+}
diff --git a/arch/arm/mach-iop13xx/imu/dev.c b/arch/arm/mach-iop13xx/imu/dev.c
new file mode 100644
index 0000000..b73af6b
--- /dev/null
+++ b/arch/arm/mach-iop13xx/imu/dev.c
@@ -0,0 +1,438 @@
+/*
+ * arch/arm/mach-iop13xx/imu/iop1340-imu-dev.c
+ *
+ * Char driver for user-space access to IMU inter-core messaging.
+ *
+ * Copyright (C) 2005, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Greg Tucker <greg.b.tucker@xxxxxxxxx>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/jiffies.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/arch/iop13xx-imu.h>
+
+#define MODULE_VERS "1.0"
+#define MODULE_NAME "IMUdev"
+//#define IMU_MAJOR       245
+#define IMU_MAJOR         0
+#define IMU_MAX_MINORS    4
+#define IMU_FIRST_MINOR   1
+
+#define Q_MSG_SIZE   64
+#define Q_MSG_ITEMS  16
+#define Q_PHYS_BASE  (128*1024*1024)
+#define Q_SIZE       (Q_MSG_ITEMS*Q_MSG_SIZE)
+#define MSG_HEADER_SIZE   4
+
+#define IMU_WRITE_TIMEOUT 1000
+
+struct imu_dev {
+	struct cdev cdev;
+	wait_queue_head_t rq;
+	wait_queue_head_t wq;
+	size_t rq_leftover;
+	char *rq_leftover_ptr;
+	atomic_t read_available;
+	atomic_t write_available;
+};
+
+static struct imu_dev imu[IMU_MAX_MINORS];
+static int imu_major = IMU_MAJOR;
+
+void queue_rq_callback(int queueid)
+{
+	struct imu_dev *imui = &imu[queueid];
+
+	pr_debug("queue_rq_callback %d\n", queueid);
+	wake_up_interruptible(&imui->rq);
+	iop_doorbell_disable(IMU_DB_RQ0NE + (queueid * 2));
+}
+
+void queue_wq_callback(int queueid)
+{
+	struct imu_dev *imui = &imu[queueid];
+
+	pr_debug("wq callback on not full q=%d\n", queueid);
+	wake_up_interruptible(&imui->wq);
+	iop_doorbell_disable(IMU_DB_SQ0NF + (queueid * 2));
+}
+
+extern struct imu_queue_params imu_queue[];
+
+/*
+ * init_callback only called on the first rx to map the base
+ */
+
+#define has_overlap(a,b,c,d) (((c<=a) && (d>a))||((c<b) && (d>=b))||((c>=a) && (d<=b)))
+
+void init_callback(int queueid)
+{
+	int i, qi_rxitems, err = 0;
+	struct imu_queue_params *qi;
+	struct imu_queue_params *queue = &imu_queue[queueid];
+	struct imu_queue *qi_hw;
+	struct imu_queue *queue_hw = (struct imu_queue *)
+	    (IMU_Q0_BASE + (queueid * sizeof(struct imu_queue)));
+
+	int phy_rxbase = queue_hw->rqlbar;
+	int rq_items = queue_hw->rqcr & 0xffff;
+
+	// check if overlap
+
+	for (i = 0; i < 4; i++) {
+		qi = &imu_queue[i];
+		qi_hw = (struct imu_queue *)
+		    (IMU_Q0_BASE + (i * sizeof(struct imu_queue)));
+		qi_rxitems = qi_hw->rqcr & 0xffff;
+
+		if (i != queueid &&	// check overlap with other registered rx
+		    qi->rxbase && qi->msg_size &&
+		    has_overlap(phy_rxbase,
+				phy_rxbase + (rq_items * qi->msg_size),
+				(int)qi->rxbase,
+				(int)qi->rxbase +
+				(qi_rxitems * qi->msg_size))) {
+			err = 1;
+		}
+
+		if (qi->txbase && qi->msg_size &&	// check overlap with tx queues
+		    has_overlap(phy_rxbase,
+				phy_rxbase + (rq_items * qi->msg_size),
+				(int)qi->txbase,
+				(int)qi->txbase + (qi->items * qi->msg_size))) {
+			err = 1;
+		}
+	}
+
+	if (err) {
+		printk(KERN_WARNING
+		       "overlap found in IMU rx queue request 0x%x\n",
+		       (int)phy_rxbase);
+	}
+
+	queue->rxbase = ioremap(phy_rxbase, rq_items * Q_MSG_SIZE);
+
+	// switch to regular callback and call
+	iop_doorbell_reg_callback(NR_IMU_DOORBELLS - 1 +
+				  (IMU_DB_RQ0NE - IMU_DB_QUEUE_IRQ_OFF) +
+				  (queueid * 2), queue_rq_callback);
+
+	printk
+	    ("init_callback registerd q=%d rxbase=0x%x rxphy=0x%x size=0x%x\n",
+	     queueid, (int)queue->rxbase, phy_rxbase, rq_items * Q_MSG_SIZE);
+	queue_rq_callback(queueid);
+}
+
+void error_callback(int queueid)
+{
+}
+
+static int imu_open(struct inode *inode, struct file *file)
+{
+	struct imu_dev *imui;
+	int queueid = iminor(file->f_dentry->d_inode);
+
+	imui = &imu[queueid];
+
+	switch (file->f_flags & O_ACCMODE) {
+	case O_RDWR:
+		if (!atomic_dec_and_test(&imui->read_available)) {
+			atomic_inc(&imui->read_available);
+			return -EBUSY;
+		}
+		if (!atomic_dec_and_test(&imui->write_available)) {
+			atomic_inc(&imui->write_available);
+			atomic_inc(&imui->read_available);
+			return -EBUSY;
+		}
+		break;
+	case O_WRONLY:
+		if (!atomic_dec_and_test(&imui->write_available)) {
+			atomic_inc(&imui->write_available);
+			return -EBUSY;
+		}
+		break;
+	case O_RDONLY:
+		if (!atomic_dec_and_test(&imui->read_available)) {
+			atomic_inc(&imui->read_available);
+			return -EBUSY;
+		}
+		break;
+
+	}
+	return 0;
+}
+
+static int imu_release(struct inode *inode, struct file *file)
+{
+	struct imu_dev *imui;
+	int queueid = iminor(file->f_dentry->d_inode);
+
+	imui = &imu[queueid];
+
+	switch (file->f_flags & O_ACCMODE) {
+	case O_RDWR:
+		atomic_inc(&imui->read_available);	// fall through
+	case O_WRONLY:
+		atomic_inc(&imui->write_available);
+		break;
+	case O_RDONLY:
+		atomic_inc(&imui->read_available);
+		break;
+	}
+	return 0;
+}
+
+static ssize_t
+imu_read(struct file *file, char __user * buf, size_t count, loff_t * f_pos)
+{
+	struct imu_dev *imui;
+	char *dat;
+	int queueid = iminor(file->f_dentry->d_inode);
+
+	imui = &imu[queueid];
+
+	pr_debug("imu_read count=%d ", count);
+
+	while (1) {
+		if (imui->rq_leftover) {
+			pr_debug("%d leftover ", imui->rq_leftover);
+			count = min(count, imui->rq_leftover);
+			if (copy_to_user(buf, imui->rq_leftover_ptr, count))
+				return -EFAULT;
+			imui->rq_leftover -= count;
+			pr_debug(" %d left \n", imui->rq_leftover);
+			if (imui->rq_leftover == 0)
+				iop_queue_rxfree(queueid,
+						 imui->rq_leftover_ptr);
+			imui->rq_leftover_ptr += count;
+			return count;
+		}
+
+		while (!iop_queue_rx_not_empty(queueid)) {
+			DECLARE_WAITQUEUE(wait, current);
+
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			pr_debug("imu_read: empty going to sleep\n");
+
+			add_wait_queue(&imui->rq, &wait);
+			set_current_state(TASK_INTERRUPTIBLE);
+			iop_doorbell_enable(IMU_DB_RQ0NE + (queueid * 2));
+			schedule_timeout(IMU_WRITE_TIMEOUT);
+
+			remove_wait_queue(&imui->rq, &wait);
+			if (signal_pending(current)) {
+				return -ERESTARTSYS;
+			}
+		}
+
+		// new message
+		dat = iop_queue_getmsg(queueid);
+
+		pr_debug("imu_read: got a new message at 0x%x\n", (int)dat);
+		if (NULL == dat)
+			return -EFAULT;
+
+#if MSG_HEADER_SIZE > 0
+		imui->rq_leftover = *((int *)dat);
+#else
+		imui->rq_leftover = 4;
+#endif
+		if (imui->rq_leftover > Q_MSG_SIZE)
+			imui->rq_leftover = 0;
+
+		imui->rq_leftover_ptr = dat + MSG_HEADER_SIZE;
+
+		pr_debug("imu_read: msg size=%d\n", imui->rq_leftover);
+		if (!imui->rq_leftover)
+			iop_queue_rxfree(queueid, imui->rq_leftover_ptr);
+	}
+
+}
+static ssize_t
+imu_write(struct file *file, const char __user * buf, size_t count,
+	  loff_t * f_pos)
+{
+	void *msg;
+	struct imu_dev *imui;
+	int queueid = iminor(file->f_dentry->d_inode);
+
+	imui = &imu[queueid];
+
+	count = min(count, (size_t) (Q_MSG_SIZE - MSG_HEADER_SIZE));
+
+	while (NULL == (msg = iop_queue_allocate(queueid))) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		pr_debug("imu_write sleeping\n");
+
+		add_wait_queue(&imui->wq, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+		iop_doorbell_enable(IMU_DB_SQ0NF + (queueid * 2));
+		schedule_timeout(IMU_WRITE_TIMEOUT);
+
+		remove_wait_queue(&imui->wq, &wait);
+		if (signal_pending(current)) {
+			return -ERESTARTSYS;
+		}
+
+	}
+
+	if (copy_from_user(msg + MSG_HEADER_SIZE, buf, count))
+		return -EFAULT;
+#if  MSG_HEADER_SIZE > 0
+	*((int *)msg) = count;
+#endif
+
+	iop_queue_postmsg(queueid, msg);
+
+	pr_debug("imu_write sent q=%d count=%d msg=0x%x\n", queueid, count,
+		 (int)msg);
+	return count;
+}
+
+static unsigned int imu_poll(struct file *file, poll_table * wait)
+{
+	struct imu_dev *imui;
+	unsigned int mask = 0;
+	int queueid = iminor(file->f_dentry->d_inode);
+
+	imui = &imu[queueid];
+	poll_wait(file, &imui->rq, wait);
+	poll_wait(file, &imui->wq, wait);
+
+	if (iop_queue_rx_not_empty(queueid))
+		mask |= POLLIN | POLLRDNORM;
+	if (iop_queue_tx_not_full(queueid))
+		mask |= POLLOUT | POLLWRNORM;
+
+	return mask;
+}
+
+static struct file_operations imu_fops = {
+	.owner = THIS_MODULE,
+	.read = imu_read,
+	.write = imu_write,
+	.poll = imu_poll,
+	.open = imu_open,
+	.release = imu_release,
+};
+
+static int __init imu_dev_init(void)
+{
+	dev_t dev;
+	// struct class_simple *imu_class;
+	int err, i;
+	char *queue_base;
+
+	if (imu_major) {
+		dev = MKDEV(imu_major, 0);
+		err = register_chrdev_region(dev, IMU_MAX_MINORS, "imu");
+	} else {
+		err = alloc_chrdev_region(&dev, IMU_FIRST_MINOR,
+					  IMU_MAX_MINORS, "imu");
+		imu_major = MAJOR(dev);
+	}
+	if (err < 0) {
+		printk(KERN_WARNING "imu: can't get major %d\n", imu_major);
+		return err;
+	}
+	//todo: update imu_class = class_simple_create(THIS_MODULE, "imu");
+
+	for (i = IMU_FIRST_MINOR; i < IMU_MAX_MINORS; i++) {
+		cdev_init(&imu[i].cdev, &imu_fops);
+		if (cdev_add(&imu[i].cdev, MKDEV(imu_major, i), 1)) {
+			printk(KERN_WARNING "Error cdev_add imu%i\n", i);
+			continue;
+		}
+
+		imu[i].rq_leftover = 0;
+		atomic_set(&imu[i].read_available, 1);
+		atomic_set(&imu[i].write_available, 1);
+		init_waitqueue_head(&imu[i].rq);
+		init_waitqueue_head(&imu[i].wq);
+		imu_queue[i].rxbase = 0;
+
+		queue_base = ioremap(Q_PHYS_BASE + (i * Q_SIZE), Q_SIZE);
+		// todo: see about changing to one of following
+		// non-shared device tex.cb = 0x010.00
+		// shared device     tex.cb = 0x001.01
+
+		err = iop_queue_init(i,
+				     (void *)Q_PHYS_BASE + (i * Q_SIZE),
+				     queue_base,
+				     Q_MSG_SIZE,
+				     Q_MSG_ITEMS,
+				     init_callback, error_callback);
+		if (err) {
+			printk(KERN_WARNING "could not init imu queue %d\n", i);
+			continue;
+		}
+		iop_doorbell_reg_callback(NR_IMU_DOORBELLS - 1 +
+					  (IMU_DB_SQ0NF -
+					   IMU_DB_QUEUE_IRQ_OFF) + (i * 2),
+					  queue_wq_callback);
+		printk(KERN_INFO
+		       "IMU Queue %d initialized major=%d minor=%d base=0x%x\n",
+		       i, imu_major, i, (int)queue_base);
+
+	}
+
+	return 0;
+}
+
+static void __exit imu_dev_cleanup(void)
+{
+	int i;
+
+	for (i = IMU_FIRST_MINOR; i < IMU_MAX_MINORS; i++) {
+		cdev_del(&imu[i].cdev);
+		iop_doorbell_disable(IMU_DB_RQ0NE + (i * 2));
+		iop_doorbell_disable(IMU_DB_SQ0NF + (i * 2));
+		iounmap(imu_queue[i].txbase);
+		if (imu_queue[i].rxbase) {
+			iounmap(imu_queue[i].rxbase);
+			imu_queue[i].rxbase = 0;
+		}
+	}
+
+	//todo: update  class_simple_device_remove(MKDEV(imu_major, 0));
+	unregister_chrdev_region(MKDEV(imu_major, 0), IMU_MAX_MINORS);
+
+	printk(KERN_INFO "%s driver ver %s removed\n",
+	       MODULE_NAME, MODULE_VERS);
+}
+
+module_init(imu_dev_init);
+module_exit(imu_dev_cleanup);
+
+MODULE_AUTHOR("Greg Tucker");
+MODULE_DESCRIPTION("IMU dev interface");
diff --git a/arch/arm/mach-iop13xx/imu/imu.c b/arch/arm/mach-iop13xx/imu/imu.c
new file mode 100644
index 0000000..6626486
--- /dev/null
+++ b/arch/arm/mach-iop13xx/imu/imu.c
@@ -0,0 +1,151 @@
+/*
+ * arch/arm/mach-iop13xx/imu/iop1340-imu.c
+ *
+ * Support for IMU communication for the Intel IOP1340 chipset
+ *
+ * Copyright (C) 2005, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Greg Tucker <greg.b.tucker@xxxxxxxxx>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#define __KERNEL_SYSCALLS__
+#include <linux/reboot.h>
+#include <linux/unistd.h>	/* for execve */
+#include <asm/arch/iop13xx-imu.h>
+
+extern imu_handler *imu_irq_table[];
+extern struct imu_queue_params imu_queue[];
+
+static irqreturn_t imu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int doorbell, queue;
+	unsigned int dbcr = *(volatile int *)IMU_DBCR;
+
+	pr_debug("got imu interrupt. IMU_DBCR=0x%x\n", dbcr);
+
+	do {
+		doorbell = dbcr >> 28;
+		queue = (dbcr >> 24) & 0xf;
+
+		if (doorbell != 0xf && imu_irq_table[doorbell]) {
+			imu_irq_table[doorbell] (doorbell);
+			*(volatile int *)IMU_DBCR = 1 << doorbell;	// clear status
+		}
+
+		if (queue != 0xf
+		    && imu_irq_table[(NR_IMU_DOORBELLS - 1) + queue])
+			imu_irq_table[(NR_IMU_DOORBELLS - 1) +
+				      queue] (queue / 2);
+
+		dbcr = *(volatile int *)IMU_DBCR;
+
+	} while ((dbcr >> 24) != 0xff);
+
+	return IRQ_HANDLED;
+}
+
+static void deferred_reset(void *dummy)
+{
+	static int in_shutdown = 0;
+	static char *envp[] = {
+		"HOME=/", "TERM=linux",
+		"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL
+	};
+	char *argv[] = {
+		"/sbin/shutdown", "-r", "now", NULL
+	};
+
+	// todo: start watchdog timer
+
+	if (!in_shutdown) {
+		in_shutdown = 1;
+		printk(KERN_CRIT "IMU reset: Shutting down the system now.\n");
+		if (0 > execve("/sbin/shutdown", argv, envp))
+			printk("IMU reset: Could not use /sbin/shutdown\n");
+		else
+			return;
+	}
+
+	printk("IMU reset: Starting hard reset\n");
+	//emergency_sync();
+	//kill_proc(1, SIGINT, 1);
+	kernel_restart(NULL);
+}
+
+void restart_callback(int irq)
+{
+	static DECLARE_WORK(reset_work, deferred_reset, NULL);
+
+	printk("\nIMU reset: Got restart doorbell\n");
+	schedule_work(&reset_work);
+	return;
+}
+
+static int __init iop_imu_init(void)
+{
+	int i, err;
+
+	for (i = 0; i < NR_IMU_DOORBELLS + NR_IMU_QUEUE_IRQS; i++)
+		imu_irq_table[i] = 0;
+
+	err = request_irq(IRQ_IOP13XX_IMU, imu_interrupt,
+			  SA_INTERRUPT, "imu interrupt", NULL);
+
+	iop_doorbell_reg_callback(IMU_RESET_DOORBELL, restart_callback);
+	iop_doorbell_enable(IMU_RESET_DOORBELL);
+
+	printk(KERN_INFO "IOP 8134x IMU driver\n");
+	return err;
+}
+
+static void __exit iop_imu_exit(void)
+{
+	free_irq(IRQ_IOP13XX_IMU, NULL);
+	return;
+}
+
+EXPORT_SYMBOL(iop_doorbell_ring);
+EXPORT_SYMBOL(iop_wait_on_doorbell);
+EXPORT_SYMBOL(iop_doorbell_clear_status);
+EXPORT_SYMBOL(iop_doorbell_check_status);
+EXPORT_SYMBOL(iop_doorbell_enable);
+EXPORT_SYMBOL(iop_doorbell_disable);
+EXPORT_SYMBOL(iop_doorbell_mask);
+EXPORT_SYMBOL(iop_doorbell_unmask);
+EXPORT_SYMBOL(iop_doorbell_reg_callback);
+EXPORT_SYMBOL(iop_mutex_lock);
+EXPORT_SYMBOL(iop_mutex_trylock);
+EXPORT_SYMBOL(iop_mutex_unlock);
+EXPORT_SYMBOL(iop_queue_init);
+EXPORT_SYMBOL(iop_queue_allocate);
+EXPORT_SYMBOL(iop_queue_postmsg);
+
+EXPORT_SYMBOL(iop_queue_getmsg);
+EXPORT_SYMBOL(iop_queue_rxfree);
+EXPORT_SYMBOL(iop_queue_rx_not_empty);
+EXPORT_SYMBOL(iop_queue_tx_not_full);
+
+EXPORT_SYMBOL(imu_queue);
+
+module_init(iop_imu_init);
+module_exit(iop_imu_exit);
+
+MODULE_AUTHOR("Greg Tucker");
+MODULE_DESCRIPTION("IMU interface");
diff --git a/include/asm-arm/arch-iop13xx/iop13xx-imu.h b/include/asm-arm/arch-iop13xx/iop13xx-imu.h
new file mode 100644
index 0000000..f7ecd6a
--- /dev/null
+++ b/include/asm-arm/arch-iop13xx/iop13xx-imu.h
@@ -0,0 +1,207 @@
+/*
+ * include/asm-arm/arch-iop13xx/iop1340-imu.h
+ *
+ * IMU hardware support on IOP342
+ *
+ * Copyright (C) 2005, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Greg Tucker <greg.b.tucker@xxxxxxxxx>
+ *
+ */
+
+#ifndef IOP34X_H
+#define IOP34X_H
+
+#ifndef NULL
+# define NULL (void *) 0
+#endif
+
+typedef int imu_handler(int);
+
+void iop_mutex_lock(int mutex);
+int iop_mutex_trylock(int mutex);
+void iop_mutex_unlock(int mutex);
+
+int iop_queue_init(int queueid, void *phys_base, void *vert_base,
+		   int msg_size, int num_items,
+		   void (*rcd_callback) (int), void (*error_callback) (int));
+void *iop_queue_allocate(int queueid);
+int iop_queue_postmsg(int queueid, void *msg_adr);
+
+int iop_doorbell_reg_callback(int doorbell, void (*callback) (int));
+void iop_doorbell_clear_status(int doorbell);
+int iop_doorbell_check_status(int doorbell);
+void iop_doorbell_enable(int doorbell);
+void iop_doorbell_disable(int doorbell);
+void iop_doorbell_mask(int doorbell);
+void iop_doorbell_unmask(int doorbell);
+void iop_doorbell_ring(int doorbell);
+inline void iop_wait_on_doorbell(int doorbell);
+
+void *iop_queue_getmsg(int queueid);
+int iop_queue_rxfree(int queueid, void *msg_adr);
+int iop_queue_rx_not_empty(int queueid);
+int iop_queue_tx_not_full(int queueid);
+
+/* Core ID - CIDR */
+
+#define CIDR_READ() \
+ ({unsigned _val_; asm volatile("mrc\tp6, 0, %0, c0, c0, 0" : "=r" (_val_)); _val_;})
+#define COREID0 0
+#define COREID1 1
+
+/* --------------------------------------------------------------------------
+ * IMU/IMM registers
+ */
+
+/* Reset cause status - RCSR */
+
+#define RCSR_READ()  \
+   ({unsigned _val_; asm volatile("mrc\tp6, 0, %0, c0, c1, 0" : "=r" (_val_));_val_;})
+#define RCSR_MU_RESET       (1<<21)
+#define RCSR_TMPI3_RESET    (1<<18)
+#define RCSR_TMPI2_RESET    (1<<15)
+#define RCSR_TMPI1_RESET    (1<<12)
+#define RCSR_TMPI0_RESET    (1<<9)
+#define RCSR_WATCHDOG_RESET (1<<5)
+#define RCSR_TARGETED_RESET (1<<4)
+#define RCSR_ID_RESET_MASK  (0xf)
+#define RCSR_SYSTEM_RESET_MASK (RCSR_MU_RESET | RCSR_TARGETED_RESET | RCSR_TMPI3_RESET | \
+				RCSR_TMPI2_RESET | RCSR_TMPI1_RESET | RCSR_TMPI0_RESET | \
+				RCSR_WATCHDOG_RESET | RCSR_TARGETED_RESET)
+
+/* #define is_sys_reset() ((RCSR_READ() & RCSR_SYSTEM_RESET_MASK) == 0)  currently  not working in simulator */
+#define is_sys_reset() 1
+
+/* Software Interrupt Generation Register - SINTGENR */
+
+#define SINTGENR_READ()  \
+   ({  unsigned _val_;asm volatile("mrc\tp6, 0, %0, c1, c1, 0" : "=r" (_val_));_val_;})
+#define SINTGENR_WRITE(val) \
+   ({ asm volatile("mcr\tp6, 0, %0, c1, c1, 0" : : "r" (val)); })
+
+/* Targeted Reset Register - TARRSTR */
+
+# define TARRSTR_WRITE(val) \
+   ({ asm volatile("mcr\tp6, 0, %0, c2, c1, 0" : : "r" (val)); })
+
+#ifdef linux
+# define IMU_BASE    IOP13XX_PMMR_VIRT_MEM_BASE
+#else
+# define IMU_BASE    0xffd80000
+#endif
+
+/* IMU doorbell registers */
+
+#define IMU_DBCR   (IMU_BASE+0xa00)
+#define IMU_DBER   (IMU_BASE+0xa04)
+#define IMU_DBAR   (IMU_BASE+0xa10)
+#define IMU_DBEOR  (IMU_BASE+0xa14)
+#define NR_IMU_DOORBELLS   14
+
+/* Conventions on doorbell use */
+
+#define IMU_RESET_DOORBELL  3
+
+/* IMU send queue */
+
+#define IMU_Q0_BASE (IMU_BASE+0xa20)
+#define IMU_Q1_BASE (IMU_BASE+0xa40)
+#define IMU_Q2_BASE (IMU_BASE+0xa60)
+#define IMU_Q3_BASE (IMU_BASE+0xa80)
+
+#define IMU_SQPG0    (IMU_Q0_BASE+0x0)
+#define IMU_SQCR0    (IMU_Q0_BASE+0x4)
+#define IMU_SQLBAR0  (IMU_Q0_BASE+0x8)
+#define IMU_SQUBAR0  (IMU_Q0_BASE+0xc)
+#define IMU_RQPG0    (IMU_Q0_BASE+0x10)
+#define IMU_RQCR0    (IMU_Q0_BASE+0x14)
+#define IMU_RQLBAR0  (IMU_Q0_BASE+0x18)
+#define IMU_RQUBAR0  (IMU_Q0_BASE+0x1c)
+
+#define IMU_SQPG1    (IMU_Q1_BASE+0x0)
+#define IMU_SQCR1    (IMU_Q1_BASE+0x4)
+#define IMU_SQLBAR1  (IMU_Q1_BASE+0x8)
+#define IMU_SQUBAR1  (IMU_Q1_BASE+0xc)
+#define IMU_RQPG1    (IMU_Q1_BASE+0x10)
+#define IMU_RQCR1    (IMU_Q1_BASE+0x14)
+#define IMU_RQLBAR1  (IMU_Q1_BASE+0x18)
+#define IMU_RQUBAR1  (IMU_Q1_BASE+0x1c)
+
+#define IMU_SQPG2    (IMU_Q2_BASE+0x0)
+#define IMU_SQCR2    (IMU_Q2_BASE+0x4)
+#define IMU_SQLBAR2  (IMU_Q2_BASE+0x8)
+#define IMU_SQUBAR2  (IMU_Q2_BASE+0xc)
+#define IMU_RQPG2    (IMU_Q2_BASE+0x10)
+#define IMU_RQCR2    (IMU_Q2_BASE+0x14)
+#define IMU_RQLBAR2  (IMU_Q2_BASE+0x18)
+#define IMU_RQUBAR2  (IMU_Q2_BASE+0x1c)
+
+#define IMU_SQPG3    (IMU_Q3_BASE+0x0)
+#define IMU_SQCR3    (IMU_Q3_BASE+0x4)
+#define IMU_SQLBAR3  (IMU_Q3_BASE+0x8)
+#define IMU_SQUBAR3  (IMU_Q3_BASE+0xc)
+#define IMU_RQPG3    (IMU_Q3_BASE+0x10)
+#define IMU_RQCR3    (IMU_Q3_BASE+0x14)
+#define IMU_RQLBAR3  (IMU_Q3_BASE+0x18)
+#define IMU_RQUBAR3  (IMU_Q3_BASE+0x1c)
+#define NR_IMU_QUEUES       3
+
+/* IMU queue interrupts */
+
+#define IMU_DB_SQ0NF 16
+#define IMU_DB_RQ0NE 17
+#define IMU_DB_SQ1NF 18
+#define IMU_DB_RQ1NE 19
+#define IMU_DB_SQ2NF 20
+#define IMU_DB_RQ2NE 21
+#define IMU_DB_SQ3NF 22
+#define IMU_DB_RQ3NE 23
+#define IMU_DB_QUEUE_IRQ_OFF 16
+#define NR_IMU_QUEUE_IRQS     8
+
+#ifndef __ASSEMBLER__
+struct imu_queue {
+	unsigned int sqpg;	/* Send queue put/get register */
+	unsigned int sqcr;	/* Send queue control register */
+	unsigned int sqlbar;	/* Send queue lower base address reg */
+	unsigned int squbar;	/* Send queue upper base address reg */
+	unsigned int rqpg;	/* Receive queue put/get register */
+	unsigned int rqcr;	/* Receive queue control register */
+	unsigned int rqlbar;	/* Receive queue lower base address reg */
+	unsigned int rqubar;	/* Receive queue upper base address reg */
+};
+
+struct imu_queue_params {
+	void *txbase;
+	void *rxbase;
+	int alloc;
+	int msg_size;
+	int items;
+};
+#endif
+
+/* Test and set semaphore registers */
+
+#define IMU_TSR_BASE (IMU_BASE+0xb00)
+#define IMU_TSR(x)   ((volatile char*)(IMU_TSR_BASE+x))
+
+/* Some conventions on the semaphores */
+
+#define HW_MUTEX_FLASH_READ_CORE0 0
+#define HW_MUTEX_FLASH_READ_CORE1 1
+
+#endif				/* IOP34X_H */
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux