Commit fa35c9c0 authored by Subramaniam C.A's avatar Subramaniam C.A Committed by Hari Kanigeri

OMAP4 Mailbox driver - Includes Hiroshi's changes on mailbox driver along with...

OMAP4 Mailbox driver - Includes Hiroshi's changes on mailbox driver along with API changes introducted in the 2.6.31 kernel

This patch cleans up the mailbox driver module and adds the
following changes:
	- Remove sequence bit checking (protocol logic not
		required in the driver)
	- Remove class interface (not used presently)
	- Remove disalbe_/enable_mbox_irq in isr (No irqs
		happen in the isr)
	- Remove unnecessary arg for omap_mbox_msg_send
	- Expose omap_mbox_enable()/disable_irq()

NOTE::
For OMAP4 the tx work queue does not ssem to function
properly. Hence, calling __mbox_msg_send for now.
Signed-off-by: default avatarC A Subramaniam <subramaniam.ca@ti.com>
Signed-off-by: default avatarRamesh Gupta G <grgupta@ti.com>
parent 97a7125b
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
typedef u32 mbox_msg_t; typedef u32 mbox_msg_t;
typedef void (mbox_receiver_t)(mbox_msg_t msg);
struct omap_mbox; struct omap_mbox;
typedef int __bitwise omap_mbox_irq_t; typedef int __bitwise omap_mbox_irq_t;
...@@ -29,8 +28,10 @@ struct omap_mbox_ops { ...@@ -29,8 +28,10 @@ struct omap_mbox_ops {
int (*fifo_empty)(struct omap_mbox *mbox); int (*fifo_empty)(struct omap_mbox *mbox);
int (*fifo_full)(struct omap_mbox *mbox); int (*fifo_full)(struct omap_mbox *mbox);
/* irq */ /* irq */
void (*enable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); void (*enable_irq)(struct omap_mbox *mbox,
void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); omap_mbox_irq_t irq);
void (*disable_irq)(struct omap_mbox *mbox,
omap_mbox_irq_t irq);
void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
/* ctx */ /* ctx */
...@@ -64,7 +65,7 @@ struct omap_mbox { ...@@ -64,7 +65,7 @@ struct omap_mbox {
void (*err_notify)(void); void (*err_notify)(void);
}; };
int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg, void *); int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
void omap_mbox_init_seq(struct omap_mbox *); void omap_mbox_init_seq(struct omap_mbox *);
struct omap_mbox *omap_mbox_get(const char *); struct omap_mbox *omap_mbox_get(const char *);
...@@ -93,4 +94,16 @@ static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox) ...@@ -93,4 +94,16 @@ static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
mbox->ops->restore_ctx(mbox); mbox->ops->restore_ctx(mbox);
} }
static inline void omap_mbox_enable_irq(struct omap_mbox *mbox,
omap_mbox_irq_t irq)
{
mbox->ops->enable_irq(mbox, irq);
}
static inline void omap_mbox_disable_irq(struct omap_mbox *mbox,
omap_mbox_irq_t irq)
{
mbox->ops->disable_irq(mbox, irq);
}
#endif /* MAILBOX_H */ #endif /* MAILBOX_H */
...@@ -28,54 +28,9 @@ ...@@ -28,54 +28,9 @@
#include <mach/mailbox.h> #include <mach/mailbox.h>
static int enable_seq_bit;
module_param(enable_seq_bit, bool, 0);
MODULE_PARM_DESC(enable_seq_bit, "Enable sequence bit checking.");
static struct omap_mbox *mboxes; static struct omap_mbox *mboxes;
static DEFINE_RWLOCK(mboxes_lock); static DEFINE_RWLOCK(mboxes_lock);
/*
* Mailbox sequence bit API
*/
/* seq_rcv should be initialized with any value other than
* 0 and 1 << 31, to allow either value for the first
* message. */
static inline void mbox_seq_init(struct omap_mbox *mbox)
{
if (!enable_seq_bit)
return;
/* any value other than 0 and 1 << 31 */
mbox->seq_rcv = 0xffffffff;
}
static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
{
if (!enable_seq_bit)
return;
/* add seq_snd to msg */
*msg = (*msg & 0x7fffffff) | mbox->seq_snd;
/* flip seq_snd */
mbox->seq_snd ^= 1 << 31;
}
static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
{
mbox_msg_t seq;
if (!enable_seq_bit)
return 0;
seq = msg & (1 << 31);
if (seq == mbox->seq_rcv)
return -1;
mbox->seq_rcv = seq;
return 0;
}
/* Mailbox FIFO handle functions */ /* Mailbox FIFO handle functions */
static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
{ {
...@@ -95,14 +50,6 @@ static inline int mbox_fifo_full(struct omap_mbox *mbox) ...@@ -95,14 +50,6 @@ static inline int mbox_fifo_full(struct omap_mbox *mbox)
} }
/* Mailbox IRQ handle functions */ /* Mailbox IRQ handle functions */
static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
mbox->ops->enable_irq(mbox, irq);
}
static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
mbox->ops->disable_irq(mbox, irq);
}
static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{ {
if (mbox->ops->ack_irq) if (mbox->ops->ack_irq)
...@@ -113,17 +60,10 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) ...@@ -113,17 +60,10 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
return mbox->ops->is_irq(mbox, irq); return mbox->ops->is_irq(mbox, irq);
} }
/* Mailbox Sequence Bit function */
void omap_mbox_init_seq(struct omap_mbox *mbox)
{
mbox_seq_init(mbox);
}
EXPORT_SYMBOL(omap_mbox_init_seq);
/* /*
* message sender * message sender
*/ */
static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
{ {
int ret = 0, i = 1000; int ret = 0, i = 1000;
...@@ -134,53 +74,43 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) ...@@ -134,53 +74,43 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
return -1; return -1;
udelay(1); udelay(1);
} }
if (arg && mbox->txq->callback) {
ret = mbox->txq->callback(arg);
if (ret)
goto out;
}
mbox_seq_toggle(mbox, &msg);
mbox_fifo_write(mbox, msg); mbox_fifo_write(mbox, msg);
out:
return ret; return ret;
} }
struct omap_msg_tx_data { #if 0
mbox_msg_t msg;
void *arg;
};
static void omap_msg_tx_end_io(struct request *rq, int error) static void omap_msg_tx_end_io(struct request *rq, int error)
{ {
kfree(rq->special); kfree(rq->special);
__blk_put_request(rq->q, rq); __blk_put_request(rq->q, rq);
} }
#endif
int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
{ {
struct omap_msg_tx_data *tx_data; return __mbox_msg_send(mbox, msg);
/* FIXME Work queue is not used to send mailbox messages.
Directly calling __mbox_msg_send() */
#if 0
struct request *rq; struct request *rq;
struct request_queue *q = mbox->txq->queue; struct request_queue *q = mbox->txq->queue;
int ret = 0;
tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
if (unlikely(!tx_data))
return -ENOMEM;
rq = blk_get_request(q, WRITE, GFP_ATOMIC); rq = blk_get_request(q, WRITE, GFP_ATOMIC);
if (unlikely(!rq)) { if (unlikely(!rq)) {
kfree(tx_data); ret = -ENOMEM;
return -ENOMEM; goto fail;
} }
tx_data->msg = msg;
tx_data->arg = arg;
rq->end_io = omap_msg_tx_end_io; rq->end_io = omap_msg_tx_end_io;
blk_insert_request(q, rq, 0, tx_data);
blk_insert_request(q, rq, 0, (void *)msg);
schedule_work(&mbox->txq->work); schedule_work(&mbox->txq->work);
return 0;
fail:
return ret;
#endif
} }
EXPORT_SYMBOL(omap_mbox_msg_send); EXPORT_SYMBOL(omap_mbox_msg_send);
...@@ -194,8 +124,6 @@ static void mbox_tx_work(struct work_struct *work) ...@@ -194,8 +124,6 @@ static void mbox_tx_work(struct work_struct *work)
struct request_queue *q = mbox->txq->queue; struct request_queue *q = mbox->txq->queue;
while (1) { while (1) {
struct omap_msg_tx_data *tx_data;
spin_lock(q->queue_lock); spin_lock(q->queue_lock);
rq = blk_fetch_request(q); rq = blk_fetch_request(q);
spin_unlock(q->queue_lock); spin_unlock(q->queue_lock);
...@@ -203,11 +131,9 @@ static void mbox_tx_work(struct work_struct *work) ...@@ -203,11 +131,9 @@ static void mbox_tx_work(struct work_struct *work)
if (!rq) if (!rq)
break; break;
tx_data = rq->special; ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special);
ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg);
if (ret) { if (ret) {
enable_mbox_irq(mbox, IRQ_TX); omap_mbox_enable_irq(mbox, IRQ_TX);
spin_lock(q->queue_lock); spin_lock(q->queue_lock);
blk_requeue_request(q, rq); blk_requeue_request(q, rq);
spin_unlock(q->queue_lock); spin_unlock(q->queue_lock);
...@@ -215,7 +141,7 @@ static void mbox_tx_work(struct work_struct *work) ...@@ -215,7 +141,7 @@ static void mbox_tx_work(struct work_struct *work)
} }
spin_lock(q->queue_lock); spin_lock(q->queue_lock);
__blk_end_request_all(rq, 0); blk_end_request_all(rq, 0);
spin_unlock(q->queue_lock); spin_unlock(q->queue_lock);
} }
} }
...@@ -233,11 +159,6 @@ static void mbox_rx_work(struct work_struct *work) ...@@ -233,11 +159,6 @@ static void mbox_rx_work(struct work_struct *work)
mbox_msg_t msg; mbox_msg_t msg;
unsigned long flags; unsigned long flags;
if (mbox->rxq->callback == NULL) {
sysfs_notify(&mbox->dev->kobj, NULL, "mbox");
return;
}
while (1) { while (1) {
spin_lock_irqsave(q->queue_lock, flags); spin_lock_irqsave(q->queue_lock, flags);
rq = blk_fetch_request(q); rq = blk_fetch_request(q);
...@@ -245,7 +166,8 @@ static void mbox_rx_work(struct work_struct *work) ...@@ -245,7 +166,8 @@ static void mbox_rx_work(struct work_struct *work)
if (!rq) if (!rq)
break; break;
msg = (mbox_msg_t)rq->special; msg = (mbox_msg_t) rq->special;
blk_end_request_all(rq, 0); blk_end_request_all(rq, 0);
mbox->rxq->callback((void *)msg); mbox->rxq->callback((void *)msg);
} }
...@@ -254,17 +176,17 @@ static void mbox_rx_work(struct work_struct *work) ...@@ -254,17 +176,17 @@ static void mbox_rx_work(struct work_struct *work)
/* /*
* Mailbox interrupt handler * Mailbox interrupt handler
*/ */
static void mbox_txq_fn(struct request_queue * q) static void mbox_txq_fn(struct request_queue *q)
{ {
} }
static void mbox_rxq_fn(struct request_queue * q) static void mbox_rxq_fn(struct request_queue *q)
{ {
} }
static void __mbox_tx_interrupt(struct omap_mbox *mbox) static void __mbox_tx_interrupt(struct omap_mbox *mbox)
{ {
disable_mbox_irq(mbox, IRQ_TX); omap_mbox_disable_irq(mbox, IRQ_TX);
ack_mbox_irq(mbox, IRQ_TX); ack_mbox_irq(mbox, IRQ_TX);
schedule_work(&mbox->txq->work); schedule_work(&mbox->txq->work);
} }
...@@ -275,20 +197,13 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) ...@@ -275,20 +197,13 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
mbox_msg_t msg; mbox_msg_t msg;
struct request_queue *q = mbox->rxq->queue; struct request_queue *q = mbox->rxq->queue;
disable_mbox_irq(mbox, IRQ_RX);
while (!mbox_fifo_empty(mbox)) { while (!mbox_fifo_empty(mbox)) {
rq = blk_get_request(q, WRITE, GFP_ATOMIC); rq = blk_get_request(q, WRITE, GFP_ATOMIC);
if (unlikely(!rq)) if (unlikely(!rq))
goto nomem; goto nomem;
msg = mbox_fifo_read(mbox); msg = mbox_fifo_read(mbox);
rq->special = (void *)msg;
if (unlikely(mbox_seq_test(mbox, msg))) {
pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
if (mbox->err_notify)
mbox->err_notify();
}
blk_insert_request(q, rq, 0, (void *)msg); blk_insert_request(q, rq, 0, (void *)msg);
if (mbox->ops->type == OMAP_MBOX_TYPE1) if (mbox->ops->type == OMAP_MBOX_TYPE1)
...@@ -297,7 +212,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) ...@@ -297,7 +212,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
/* no more messages in the fifo. clear IRQ source. */ /* no more messages in the fifo. clear IRQ source. */
ack_mbox_irq(mbox, IRQ_RX); ack_mbox_irq(mbox, IRQ_RX);
enable_mbox_irq(mbox, IRQ_RX);
nomem: nomem:
schedule_work(&mbox->rxq->work); schedule_work(&mbox->rxq->work);
} }
...@@ -315,75 +229,8 @@ static irqreturn_t mbox_interrupt(int irq, void *p) ...@@ -315,75 +229,8 @@ static irqreturn_t mbox_interrupt(int irq, void *p)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/*
* sysfs files
*/
static ssize_t
omap_mbox_write(struct device *dev, struct device_attribute *attr,
const char * buf, size_t count)
{
int ret;
mbox_msg_t *p = (mbox_msg_t *)buf;
struct omap_mbox *mbox = dev_get_drvdata(dev);
for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) {
ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL);
if (ret)
return -EAGAIN;
p++;
}
return (size_t)((char *)p - buf);
}
static ssize_t
omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned long flags;
struct request *rq;
mbox_msg_t *p = (mbox_msg_t *) buf;
struct omap_mbox *mbox = dev_get_drvdata(dev);
struct request_queue *q = mbox->rxq->queue;
while (1) {
spin_lock_irqsave(q->queue_lock, flags);
rq = blk_fetch_request(q);
spin_unlock_irqrestore(q->queue_lock, flags);
if (!rq)
break;
*p = (mbox_msg_t)rq->special;
blk_end_request_all(rq, 0);
if (unlikely(mbox_seq_test(mbox, *p))) {
pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
continue;
}
p++;
}
pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
return (size_t) ((char *)p - buf);
}
static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write);
static ssize_t mbox_show(struct class *class, char *buf)
{
return sprintf(buf, "mbox");
}
static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
static struct class omap_mbox_class = {
.name = "omap-mailbox",
};
static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
request_fn_proc * proc, request_fn_proc *proc,
void (*work) (struct work_struct *)) void (*work) (struct work_struct *))
{ {
struct request_queue *q; struct request_queue *q;
...@@ -415,7 +262,7 @@ static void mbox_queue_free(struct omap_mbox_queue *q) ...@@ -415,7 +262,7 @@ static void mbox_queue_free(struct omap_mbox_queue *q)
kfree(q); kfree(q);
} }
static int omap_mbox_init(struct omap_mbox *mbox) static int omap_mbox_startup(struct omap_mbox *mbox)
{ {
int ret; int ret;
struct omap_mbox_queue *mq; struct omap_mbox_queue *mq;
...@@ -498,7 +345,7 @@ struct omap_mbox *omap_mbox_get(const char *name) ...@@ -498,7 +345,7 @@ struct omap_mbox *omap_mbox_get(const char *name)
read_unlock(&mboxes_lock); read_unlock(&mboxes_lock);
ret = omap_mbox_init(mbox); ret = omap_mbox_startup(mbox);
if (ret) if (ret)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
...@@ -522,15 +369,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) ...@@ -522,15 +369,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox)
if (mbox->next) if (mbox->next)
return -EBUSY; return -EBUSY;
mbox->dev = device_create(&omap_mbox_class,
parent, 0, mbox, "%s", mbox->name);
if (IS_ERR(mbox->dev))
return PTR_ERR(mbox->dev);
ret = device_create_file(mbox->dev, &dev_attr_mbox);
if (ret)
goto err_sysfs;
write_lock(&mboxes_lock); write_lock(&mboxes_lock);
tmp = find_mboxes(mbox->name); tmp = find_mboxes(mbox->name);
if (*tmp) { if (*tmp) {
...@@ -544,9 +382,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) ...@@ -544,9 +382,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox)
return 0; return 0;
err_find: err_find:
device_remove_file(mbox->dev, &dev_attr_mbox);
err_sysfs:
device_unregister(mbox->dev);
return ret; return ret;
} }
EXPORT_SYMBOL(omap_mbox_register); EXPORT_SYMBOL(omap_mbox_register);
...@@ -562,8 +397,6 @@ int omap_mbox_unregister(struct omap_mbox *mbox) ...@@ -562,8 +397,6 @@ int omap_mbox_unregister(struct omap_mbox *mbox)
*tmp = mbox->next; *tmp = mbox->next;
mbox->next = NULL; mbox->next = NULL;
write_unlock(&mboxes_lock); write_unlock(&mboxes_lock);
device_remove_file(mbox->dev, &dev_attr_mbox);
device_unregister(mbox->dev);
return 0; return 0;
} }
tmp = &(*tmp)->next; tmp = &(*tmp)->next;
...@@ -574,23 +407,16 @@ int omap_mbox_unregister(struct omap_mbox *mbox) ...@@ -574,23 +407,16 @@ int omap_mbox_unregister(struct omap_mbox *mbox)
} }
EXPORT_SYMBOL(omap_mbox_unregister); EXPORT_SYMBOL(omap_mbox_unregister);
static int __init omap_mbox_class_init(void) static int __init omap_mbox_init(void)
{ {
int ret = class_register(&omap_mbox_class); return 0;
if (!ret)
ret = class_create_file(&omap_mbox_class, &class_attr_mbox);
return ret;
} }
module_init(omap_mbox_init);
static void __exit omap_mbox_class_exit(void) static void __exit omap_mbox_exit(void)
{ {
class_remove_file(&omap_mbox_class, &class_attr_mbox);
class_unregister(&omap_mbox_class);
} }
module_exit(omap_mbox_exit);
subsys_initcall(omap_mbox_class_init);
module_exit(omap_mbox_class_exit);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment