aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mailbox/omap-mailbox.c346
-rw-r--r--drivers/remoteproc/omap_remoteproc.c51
2 files changed, 225 insertions, 172 deletions
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index bcc7ee129276..66b83ca94dcf 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -29,13 +29,14 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/kfifo.h> 30#include <linux/kfifo.h>
31#include <linux/err.h> 31#include <linux/err.h>
32#include <linux/notifier.h>
33#include <linux/module.h> 32#include <linux/module.h>
34#include <linux/of_device.h> 33#include <linux/of_device.h>
35#include <linux/platform_device.h> 34#include <linux/platform_device.h>
36#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
37#include <linux/platform_data/mailbox-omap.h> 36#include <linux/platform_data/mailbox-omap.h>
38#include <linux/omap-mailbox.h> 37#include <linux/omap-mailbox.h>
38#include <linux/mailbox_controller.h>
39#include <linux/mailbox_client.h>
39 40
40#define MAILBOX_REVISION 0x000 41#define MAILBOX_REVISION 0x000
41#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) 42#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
@@ -80,7 +81,6 @@ struct omap_mbox_queue {
80 spinlock_t lock; 81 spinlock_t lock;
81 struct kfifo fifo; 82 struct kfifo fifo;
82 struct work_struct work; 83 struct work_struct work;
83 struct tasklet_struct tasklet;
84 struct omap_mbox *mbox; 84 struct omap_mbox *mbox;
85 bool full; 85 bool full;
86}; 86};
@@ -92,6 +92,7 @@ struct omap_mbox_device {
92 u32 num_users; 92 u32 num_users;
93 u32 num_fifos; 93 u32 num_fifos;
94 struct omap_mbox **mboxes; 94 struct omap_mbox **mboxes;
95 struct mbox_controller controller;
95 struct list_head elem; 96 struct list_head elem;
96}; 97};
97 98
@@ -110,15 +111,14 @@ struct omap_mbox_fifo_info {
110struct omap_mbox { 111struct omap_mbox {
111 const char *name; 112 const char *name;
112 int irq; 113 int irq;
113 struct omap_mbox_queue *txq, *rxq; 114 struct omap_mbox_queue *rxq;
114 struct device *dev; 115 struct device *dev;
115 struct omap_mbox_device *parent; 116 struct omap_mbox_device *parent;
116 struct omap_mbox_fifo tx_fifo; 117 struct omap_mbox_fifo tx_fifo;
117 struct omap_mbox_fifo rx_fifo; 118 struct omap_mbox_fifo rx_fifo;
118 u32 ctx[OMAP4_MBOX_NR_REGS]; 119 u32 ctx[OMAP4_MBOX_NR_REGS];
119 u32 intr_type; 120 u32 intr_type;
120 int use_count; 121 struct mbox_chan *chan;
121 struct blocking_notifier_head notifier;
122}; 122};
123 123
124/* global variables for the mailbox devices */ 124/* global variables for the mailbox devices */
@@ -129,6 +129,14 @@ static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
129module_param(mbox_kfifo_size, uint, S_IRUGO); 129module_param(mbox_kfifo_size, uint, S_IRUGO);
130MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); 130MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
131 131
132static struct omap_mbox *mbox_chan_to_omap_mbox(struct mbox_chan *chan)
133{
134 if (!chan || !chan->con_priv)
135 return NULL;
136
137 return (struct omap_mbox *)chan->con_priv;
138}
139
132static inline 140static inline
133unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs) 141unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
134{ 142{
@@ -194,41 +202,14 @@ static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
194 return (int)(enable & status & bit); 202 return (int)(enable & status & bit);
195} 203}
196 204
197/* 205void omap_mbox_save_ctx(struct mbox_chan *chan)
198 * message sender
199 */
200int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
201{
202 struct omap_mbox_queue *mq = mbox->txq;
203 int ret = 0, len;
204
205 spin_lock_bh(&mq->lock);
206
207 if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
208 ret = -ENOMEM;
209 goto out;
210 }
211
212 if (kfifo_is_empty(&mq->fifo) && !mbox_fifo_full(mbox)) {
213 mbox_fifo_write(mbox, msg);
214 goto out;
215 }
216
217 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
218 WARN_ON(len != sizeof(msg));
219
220 tasklet_schedule(&mbox->txq->tasklet);
221
222out:
223 spin_unlock_bh(&mq->lock);
224 return ret;
225}
226EXPORT_SYMBOL(omap_mbox_msg_send);
227
228void omap_mbox_save_ctx(struct omap_mbox *mbox)
229{ 206{
230 int i; 207 int i;
231 int nr_regs; 208 int nr_regs;
209 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
210
211 if (WARN_ON(!mbox))
212 return;
232 213
233 if (mbox->intr_type) 214 if (mbox->intr_type)
234 nr_regs = OMAP4_MBOX_NR_REGS; 215 nr_regs = OMAP4_MBOX_NR_REGS;
@@ -243,10 +224,14 @@ void omap_mbox_save_ctx(struct omap_mbox *mbox)
243} 224}
244EXPORT_SYMBOL(omap_mbox_save_ctx); 225EXPORT_SYMBOL(omap_mbox_save_ctx);
245 226
246void omap_mbox_restore_ctx(struct omap_mbox *mbox) 227void omap_mbox_restore_ctx(struct mbox_chan *chan)
247{ 228{
248 int i; 229 int i;
249 int nr_regs; 230 int nr_regs;
231 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
232
233 if (WARN_ON(!mbox))
234 return;
250 235
251 if (mbox->intr_type) 236 if (mbox->intr_type)
252 nr_regs = OMAP4_MBOX_NR_REGS; 237 nr_regs = OMAP4_MBOX_NR_REGS;
@@ -254,14 +239,13 @@ void omap_mbox_restore_ctx(struct omap_mbox *mbox)
254 nr_regs = MBOX_NR_REGS; 239 nr_regs = MBOX_NR_REGS;
255 for (i = 0; i < nr_regs; i++) { 240 for (i = 0; i < nr_regs; i++) {
256 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32)); 241 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
257
258 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 242 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
259 i, mbox->ctx[i]); 243 i, mbox->ctx[i]);
260 } 244 }
261} 245}
262EXPORT_SYMBOL(omap_mbox_restore_ctx); 246EXPORT_SYMBOL(omap_mbox_restore_ctx);
263 247
264void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 248static void _omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
265{ 249{
266 u32 l; 250 u32 l;
267 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 251 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
@@ -273,9 +257,8 @@ void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
273 l |= bit; 257 l |= bit;
274 mbox_write_reg(mbox->parent, l, irqenable); 258 mbox_write_reg(mbox->parent, l, irqenable);
275} 259}
276EXPORT_SYMBOL(omap_mbox_enable_irq);
277 260
278void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 261static void _omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
279{ 262{
280 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 263 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
281 &mbox->tx_fifo : &mbox->rx_fifo; 264 &mbox->tx_fifo : &mbox->rx_fifo;
@@ -291,28 +274,28 @@ void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
291 274
292 mbox_write_reg(mbox->parent, bit, irqdisable); 275 mbox_write_reg(mbox->parent, bit, irqdisable);
293} 276}
294EXPORT_SYMBOL(omap_mbox_disable_irq);
295 277
296static void mbox_tx_tasklet(unsigned long tx_data) 278void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq)
297{ 279{
298 struct omap_mbox *mbox = (struct omap_mbox *)tx_data; 280 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
299 struct omap_mbox_queue *mq = mbox->txq;
300 mbox_msg_t msg;
301 int ret;
302 281
303 while (kfifo_len(&mq->fifo)) { 282 if (WARN_ON(!mbox))
304 if (mbox_fifo_full(mbox)) { 283 return;
305 omap_mbox_enable_irq(mbox, IRQ_TX);
306 break;
307 }
308 284
309 ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, 285 _omap_mbox_enable_irq(mbox, irq);
310 sizeof(msg)); 286}
311 WARN_ON(ret != sizeof(msg)); 287EXPORT_SYMBOL(omap_mbox_enable_irq);
312 288
313 mbox_fifo_write(mbox, msg); 289void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq)
314 } 290{
291 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
292
293 if (WARN_ON(!mbox))
294 return;
295
296 _omap_mbox_disable_irq(mbox, irq);
315} 297}
298EXPORT_SYMBOL(omap_mbox_disable_irq);
316 299
317/* 300/*
318 * Message receiver(workqueue) 301 * Message receiver(workqueue)
@@ -328,12 +311,11 @@ static void mbox_rx_work(struct work_struct *work)
328 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); 311 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
329 WARN_ON(len != sizeof(msg)); 312 WARN_ON(len != sizeof(msg));
330 313
331 blocking_notifier_call_chain(&mq->mbox->notifier, len, 314 mbox_chan_received_data(mq->mbox->chan, (void *)msg);
332 (void *)msg);
333 spin_lock_irq(&mq->lock); 315 spin_lock_irq(&mq->lock);
334 if (mq->full) { 316 if (mq->full) {
335 mq->full = false; 317 mq->full = false;
336 omap_mbox_enable_irq(mq->mbox, IRQ_RX); 318 _omap_mbox_enable_irq(mq->mbox, IRQ_RX);
337 } 319 }
338 spin_unlock_irq(&mq->lock); 320 spin_unlock_irq(&mq->lock);
339 } 321 }
@@ -344,9 +326,9 @@ static void mbox_rx_work(struct work_struct *work)
344 */ 326 */
345static void __mbox_tx_interrupt(struct omap_mbox *mbox) 327static void __mbox_tx_interrupt(struct omap_mbox *mbox)
346{ 328{
347 omap_mbox_disable_irq(mbox, IRQ_TX); 329 _omap_mbox_disable_irq(mbox, IRQ_TX);
348 ack_mbox_irq(mbox, IRQ_TX); 330 ack_mbox_irq(mbox, IRQ_TX);
349 tasklet_schedule(&mbox->txq->tasklet); 331 mbox_chan_txdone(mbox->chan, 0);
350} 332}
351 333
352static void __mbox_rx_interrupt(struct omap_mbox *mbox) 334static void __mbox_rx_interrupt(struct omap_mbox *mbox)
@@ -357,7 +339,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
357 339
358 while (!mbox_fifo_empty(mbox)) { 340 while (!mbox_fifo_empty(mbox)) {
359 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { 341 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
360 omap_mbox_disable_irq(mbox, IRQ_RX); 342 _omap_mbox_disable_irq(mbox, IRQ_RX);
361 mq->full = true; 343 mq->full = true;
362 goto nomem; 344 goto nomem;
363 } 345 }
@@ -388,11 +370,13 @@ static irqreturn_t mbox_interrupt(int irq, void *p)
388} 370}
389 371
390static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, 372static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
391 void (*work) (struct work_struct *), 373 void (*work)(struct work_struct *))
392 void (*tasklet)(unsigned long))
393{ 374{
394 struct omap_mbox_queue *mq; 375 struct omap_mbox_queue *mq;
395 376
377 if (!work)
378 return NULL;
379
396 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); 380 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
397 if (!mq) 381 if (!mq)
398 return NULL; 382 return NULL;
@@ -402,12 +386,9 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
402 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) 386 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
403 goto error; 387 goto error;
404 388
405 if (work) 389 INIT_WORK(&mq->work, work);
406 INIT_WORK(&mq->work, work);
407
408 if (tasklet)
409 tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
410 return mq; 390 return mq;
391
411error: 392error:
412 kfree(mq); 393 kfree(mq);
413 return NULL; 394 return NULL;
@@ -423,71 +404,35 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
423{ 404{
424 int ret = 0; 405 int ret = 0;
425 struct omap_mbox_queue *mq; 406 struct omap_mbox_queue *mq;
426 struct omap_mbox_device *mdev = mbox->parent;
427 407
428 mutex_lock(&mdev->cfg_lock); 408 mq = mbox_queue_alloc(mbox, mbox_rx_work);
429 ret = pm_runtime_get_sync(mdev->dev); 409 if (!mq)
430 if (unlikely(ret < 0)) 410 return -ENOMEM;
431 goto fail_startup; 411 mbox->rxq = mq;
432 412 mq->mbox = mbox;
433 if (!mbox->use_count++) { 413
434 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); 414 ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
435 if (!mq) { 415 mbox->name, mbox);
436 ret = -ENOMEM; 416 if (unlikely(ret)) {
437 goto fail_alloc_txq; 417 pr_err("failed to register mailbox interrupt:%d\n", ret);
438 } 418 goto fail_request_irq;
439 mbox->txq = mq; 419 }
440 420
441 mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); 421 _omap_mbox_enable_irq(mbox, IRQ_RX);
442 if (!mq) {
443 ret = -ENOMEM;
444 goto fail_alloc_rxq;
445 }
446 mbox->rxq = mq;
447 mq->mbox = mbox;
448 ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
449 mbox->name, mbox);
450 if (unlikely(ret)) {
451 pr_err("failed to register mailbox interrupt:%d\n",
452 ret);
453 goto fail_request_irq;
454 }
455 422
456 omap_mbox_enable_irq(mbox, IRQ_RX);
457 }
458 mutex_unlock(&mdev->cfg_lock);
459 return 0; 423 return 0;
460 424
461fail_request_irq: 425fail_request_irq:
462 mbox_queue_free(mbox->rxq); 426 mbox_queue_free(mbox->rxq);
463fail_alloc_rxq:
464 mbox_queue_free(mbox->txq);
465fail_alloc_txq:
466 pm_runtime_put_sync(mdev->dev);
467 mbox->use_count--;
468fail_startup:
469 mutex_unlock(&mdev->cfg_lock);
470 return ret; 427 return ret;
471} 428}
472 429
473static void omap_mbox_fini(struct omap_mbox *mbox) 430static void omap_mbox_fini(struct omap_mbox *mbox)
474{ 431{
475 struct omap_mbox_device *mdev = mbox->parent; 432 _omap_mbox_disable_irq(mbox, IRQ_RX);
476 433 free_irq(mbox->irq, mbox);
477 mutex_lock(&mdev->cfg_lock); 434 flush_work(&mbox->rxq->work);
478 435 mbox_queue_free(mbox->rxq);
479 if (!--mbox->use_count) {
480 omap_mbox_disable_irq(mbox, IRQ_RX);
481 free_irq(mbox->irq, mbox);
482 tasklet_kill(&mbox->txq->tasklet);
483 flush_work(&mbox->rxq->work);
484 mbox_queue_free(mbox->txq);
485 mbox_queue_free(mbox->rxq);
486 }
487
488 pm_runtime_put_sync(mdev->dev);
489
490 mutex_unlock(&mdev->cfg_lock);
491} 436}
492 437
493static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev, 438static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
@@ -509,42 +454,55 @@ static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
509 return mbox; 454 return mbox;
510} 455}
511 456
512struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) 457struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
458 const char *chan_name)
513{ 459{
460 struct device *dev = cl->dev;
514 struct omap_mbox *mbox = NULL; 461 struct omap_mbox *mbox = NULL;
515 struct omap_mbox_device *mdev; 462 struct omap_mbox_device *mdev;
463 struct mbox_chan *chan;
464 unsigned long flags;
516 int ret; 465 int ret;
517 466
467 if (!dev)
468 return ERR_PTR(-ENODEV);
469
470 if (dev->of_node) {
471 pr_err("%s: please use mbox_request_channel(), this API is supported only for OMAP non-DT usage\n",
472 __func__);
473 return ERR_PTR(-ENODEV);
474 }
475
518 mutex_lock(&omap_mbox_devices_lock); 476 mutex_lock(&omap_mbox_devices_lock);
519 list_for_each_entry(mdev, &omap_mbox_devices, elem) { 477 list_for_each_entry(mdev, &omap_mbox_devices, elem) {
520 mbox = omap_mbox_device_find(mdev, name); 478 mbox = omap_mbox_device_find(mdev, chan_name);
521 if (mbox) 479 if (mbox)
522 break; 480 break;
523 } 481 }
524 mutex_unlock(&omap_mbox_devices_lock); 482 mutex_unlock(&omap_mbox_devices_lock);
525 483
526 if (!mbox) 484 if (!mbox || !mbox->chan)
527 return ERR_PTR(-ENOENT); 485 return ERR_PTR(-ENOENT);
528 486
529 if (nb) 487 chan = mbox->chan;
530 blocking_notifier_chain_register(&mbox->notifier, nb); 488 spin_lock_irqsave(&chan->lock, flags);
489 chan->msg_free = 0;
490 chan->msg_count = 0;
491 chan->active_req = NULL;
492 chan->cl = cl;
493 init_completion(&chan->tx_complete);
494 spin_unlock_irqrestore(&chan->lock, flags);
531 495
532 ret = omap_mbox_startup(mbox); 496 ret = chan->mbox->ops->startup(chan);
533 if (ret) { 497 if (ret) {
534 blocking_notifier_chain_unregister(&mbox->notifier, nb); 498 pr_err("Unable to startup the chan (%d)\n", ret);
535 return ERR_PTR(-ENODEV); 499 mbox_free_channel(chan);
500 chan = ERR_PTR(ret);
536 } 501 }
537 502
538 return mbox; 503 return chan;
539}
540EXPORT_SYMBOL(omap_mbox_get);
541
542void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
543{
544 blocking_notifier_chain_unregister(&mbox->notifier, nb);
545 omap_mbox_fini(mbox);
546} 504}
547EXPORT_SYMBOL(omap_mbox_put); 505EXPORT_SYMBOL(omap_mbox_request_channel);
548 506
549static struct class omap_mbox_class = { .name = "mbox", }; 507static struct class omap_mbox_class = { .name = "mbox", };
550 508
@@ -560,25 +518,25 @@ static int omap_mbox_register(struct omap_mbox_device *mdev)
560 mboxes = mdev->mboxes; 518 mboxes = mdev->mboxes;
561 for (i = 0; mboxes[i]; i++) { 519 for (i = 0; mboxes[i]; i++) {
562 struct omap_mbox *mbox = mboxes[i]; 520 struct omap_mbox *mbox = mboxes[i];
563 mbox->dev = device_create(&omap_mbox_class, 521 mbox->dev = device_create(&omap_mbox_class, mdev->dev,
564 mdev->dev, 0, mbox, "%s", mbox->name); 522 0, mbox, "%s", mbox->name);
565 if (IS_ERR(mbox->dev)) { 523 if (IS_ERR(mbox->dev)) {
566 ret = PTR_ERR(mbox->dev); 524 ret = PTR_ERR(mbox->dev);
567 goto err_out; 525 goto err_out;
568 } 526 }
569
570 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
571 } 527 }
572 528
573 mutex_lock(&omap_mbox_devices_lock); 529 mutex_lock(&omap_mbox_devices_lock);
574 list_add(&mdev->elem, &omap_mbox_devices); 530 list_add(&mdev->elem, &omap_mbox_devices);
575 mutex_unlock(&omap_mbox_devices_lock); 531 mutex_unlock(&omap_mbox_devices_lock);
576 532
577 return 0; 533 ret = mbox_controller_register(&mdev->controller);
578 534
579err_out: 535err_out:
580 while (i--) 536 if (ret) {
581 device_unregister(mboxes[i]->dev); 537 while (i--)
538 device_unregister(mboxes[i]->dev);
539 }
582 return ret; 540 return ret;
583} 541}
584 542
@@ -594,12 +552,64 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev)
594 list_del(&mdev->elem); 552 list_del(&mdev->elem);
595 mutex_unlock(&omap_mbox_devices_lock); 553 mutex_unlock(&omap_mbox_devices_lock);
596 554
555 mbox_controller_unregister(&mdev->controller);
556
597 mboxes = mdev->mboxes; 557 mboxes = mdev->mboxes;
598 for (i = 0; mboxes[i]; i++) 558 for (i = 0; mboxes[i]; i++)
599 device_unregister(mboxes[i]->dev); 559 device_unregister(mboxes[i]->dev);
600 return 0; 560 return 0;
601} 561}
602 562
563static int omap_mbox_chan_startup(struct mbox_chan *chan)
564{
565 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
566 struct omap_mbox_device *mdev = mbox->parent;
567 int ret = 0;
568
569 mutex_lock(&mdev->cfg_lock);
570 pm_runtime_get_sync(mdev->dev);
571 ret = omap_mbox_startup(mbox);
572 if (ret)
573 pm_runtime_put_sync(mdev->dev);
574 mutex_unlock(&mdev->cfg_lock);
575 return ret;
576}
577
578static void omap_mbox_chan_shutdown(struct mbox_chan *chan)
579{
580 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
581 struct omap_mbox_device *mdev = mbox->parent;
582
583 mutex_lock(&mdev->cfg_lock);
584 omap_mbox_fini(mbox);
585 pm_runtime_put_sync(mdev->dev);
586 mutex_unlock(&mdev->cfg_lock);
587}
588
589static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
590{
591 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
592 int ret = -EBUSY;
593
594 if (!mbox)
595 return -EINVAL;
596
597 if (!mbox_fifo_full(mbox)) {
598 mbox_fifo_write(mbox, (mbox_msg_t)data);
599 ret = 0;
600 }
601
602 /* always enable the interrupt */
603 _omap_mbox_enable_irq(mbox, IRQ_TX);
604 return ret;
605}
606
607static struct mbox_chan_ops omap_mbox_chan_ops = {
608 .startup = omap_mbox_chan_startup,
609 .send_data = omap_mbox_chan_send_data,
610 .shutdown = omap_mbox_chan_shutdown,
611};
612
603static const struct of_device_id omap_mailbox_of_match[] = { 613static const struct of_device_id omap_mailbox_of_match[] = {
604 { 614 {
605 .compatible = "ti,omap2-mailbox", 615 .compatible = "ti,omap2-mailbox",
@@ -619,10 +629,35 @@ static const struct of_device_id omap_mailbox_of_match[] = {
619}; 629};
620MODULE_DEVICE_TABLE(of, omap_mailbox_of_match); 630MODULE_DEVICE_TABLE(of, omap_mailbox_of_match);
621 631
632static struct mbox_chan *omap_mbox_of_xlate(struct mbox_controller *controller,
633 const struct of_phandle_args *sp)
634{
635 phandle phandle = sp->args[0];
636 struct device_node *node;
637 struct omap_mbox_device *mdev;
638 struct omap_mbox *mbox;
639
640 mdev = container_of(controller, struct omap_mbox_device, controller);
641 if (WARN_ON(!mdev))
642 return NULL;
643
644 node = of_find_node_by_phandle(phandle);
645 if (!node) {
646 pr_err("%s: could not find node phandle 0x%x\n",
647 __func__, phandle);
648 return NULL;
649 }
650
651 mbox = omap_mbox_device_find(mdev, node->name);
652 of_node_put(node);
653 return mbox ? mbox->chan : NULL;
654}
655
622static int omap_mbox_probe(struct platform_device *pdev) 656static int omap_mbox_probe(struct platform_device *pdev)
623{ 657{
624 struct resource *mem; 658 struct resource *mem;
625 int ret; 659 int ret;
660 struct mbox_chan *chnls;
626 struct omap_mbox **list, *mbox, *mboxblk; 661 struct omap_mbox **list, *mbox, *mboxblk;
627 struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 662 struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
628 struct omap_mbox_dev_info *info = NULL; 663 struct omap_mbox_dev_info *info = NULL;
@@ -727,6 +762,11 @@ static int omap_mbox_probe(struct platform_device *pdev)
727 if (!list) 762 if (!list)
728 return -ENOMEM; 763 return -ENOMEM;
729 764
765 chnls = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*chnls),
766 GFP_KERNEL);
767 if (!chnls)
768 return -ENOMEM;
769
730 mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox), 770 mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox),
731 GFP_KERNEL); 771 GFP_KERNEL);
732 if (!mboxblk) 772 if (!mboxblk)
@@ -758,6 +798,8 @@ static int omap_mbox_probe(struct platform_device *pdev)
758 mbox->irq = platform_get_irq(pdev, finfo->tx_irq); 798 mbox->irq = platform_get_irq(pdev, finfo->tx_irq);
759 if (mbox->irq < 0) 799 if (mbox->irq < 0)
760 return mbox->irq; 800 return mbox->irq;
801 mbox->chan = &chnls[i];
802 chnls[i].con_priv = mbox;
761 list[i] = mbox++; 803 list[i] = mbox++;
762 } 804 }
763 805
@@ -766,6 +808,14 @@ static int omap_mbox_probe(struct platform_device *pdev)
766 mdev->num_users = num_users; 808 mdev->num_users = num_users;
767 mdev->num_fifos = num_fifos; 809 mdev->num_fifos = num_fifos;
768 mdev->mboxes = list; 810 mdev->mboxes = list;
811
812 /* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
813 mdev->controller.txdone_irq = true;
814 mdev->controller.dev = mdev->dev;
815 mdev->controller.ops = &omap_mbox_chan_ops;
816 mdev->controller.chans = chnls;
817 mdev->controller.num_chans = info_count;
818 mdev->controller.of_xlate = omap_mbox_of_xlate;
769 ret = omap_mbox_register(mdev); 819 ret = omap_mbox_register(mdev);
770 if (ret) 820 if (ret)
771 return ret; 821 return ret;
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index 51689721ea7a..cf92f6e7c5dc 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -27,6 +27,7 @@
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/remoteproc.h> 29#include <linux/remoteproc.h>
30#include <linux/mailbox_client.h>
30#include <linux/omap-mailbox.h> 31#include <linux/omap-mailbox.h>
31 32
32#include <linux/platform_data/remoteproc-omap.h> 33#include <linux/platform_data/remoteproc-omap.h>
@@ -36,20 +37,19 @@
36 37
37/** 38/**
38 * struct omap_rproc - omap remote processor state 39 * struct omap_rproc - omap remote processor state
39 * @mbox: omap mailbox handle 40 * @mbox: mailbox channel handle
40 * @nb: notifier block that will be invoked on inbound mailbox messages 41 * @client: mailbox client to request the mailbox channel
41 * @rproc: rproc handle 42 * @rproc: rproc handle
42 */ 43 */
43struct omap_rproc { 44struct omap_rproc {
44 struct omap_mbox *mbox; 45 struct mbox_chan *mbox;
45 struct notifier_block nb; 46 struct mbox_client client;
46 struct rproc *rproc; 47 struct rproc *rproc;
47}; 48};
48 49
49/** 50/**
50 * omap_rproc_mbox_callback() - inbound mailbox message handler 51 * omap_rproc_mbox_callback() - inbound mailbox message handler
51 * @this: notifier block 52 * @client: mailbox client pointer used for requesting the mailbox channel
52 * @index: unused
53 * @data: mailbox payload 53 * @data: mailbox payload
54 * 54 *
55 * This handler is invoked by omap's mailbox driver whenever a mailbox 55 * This handler is invoked by omap's mailbox driver whenever a mailbox
@@ -61,13 +61,13 @@ struct omap_rproc {
61 * that indicates different events. Those values are deliberately very 61 * that indicates different events. Those values are deliberately very
62 * big so they don't coincide with virtqueue indices. 62 * big so they don't coincide with virtqueue indices.
63 */ 63 */
64static int omap_rproc_mbox_callback(struct notifier_block *this, 64static void omap_rproc_mbox_callback(struct mbox_client *client, void *data)
65 unsigned long index, void *data)
66{ 65{
67 mbox_msg_t msg = (mbox_msg_t) data; 66 struct omap_rproc *oproc = container_of(client, struct omap_rproc,
68 struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); 67 client);
69 struct device *dev = oproc->rproc->dev.parent; 68 struct device *dev = oproc->rproc->dev.parent;
70 const char *name = oproc->rproc->name; 69 const char *name = oproc->rproc->name;
70 u32 msg = (u32)data;
71 71
72 dev_dbg(dev, "mbox msg: 0x%x\n", msg); 72 dev_dbg(dev, "mbox msg: 0x%x\n", msg);
73 73
@@ -84,8 +84,6 @@ static int omap_rproc_mbox_callback(struct notifier_block *this,
84 if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) 84 if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
85 dev_dbg(dev, "no message was found in vqid %d\n", msg); 85 dev_dbg(dev, "no message was found in vqid %d\n", msg);
86 } 86 }
87
88 return NOTIFY_DONE;
89} 87}
90 88
91/* kick a virtqueue */ 89/* kick a virtqueue */
@@ -96,8 +94,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid)
96 int ret; 94 int ret;
97 95
98 /* send the index of the triggered virtqueue in the mailbox payload */ 96 /* send the index of the triggered virtqueue in the mailbox payload */
99 ret = omap_mbox_msg_send(oproc->mbox, vqid); 97 ret = mbox_send_message(oproc->mbox, (void *)vqid);
100 if (ret) 98 if (ret < 0)
101 dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret); 99 dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
102} 100}
103 101
@@ -115,17 +113,22 @@ static int omap_rproc_start(struct rproc *rproc)
115 struct platform_device *pdev = to_platform_device(dev); 113 struct platform_device *pdev = to_platform_device(dev);
116 struct omap_rproc_pdata *pdata = pdev->dev.platform_data; 114 struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
117 int ret; 115 int ret;
116 struct mbox_client *client = &oproc->client;
118 117
119 if (pdata->set_bootaddr) 118 if (pdata->set_bootaddr)
120 pdata->set_bootaddr(rproc->bootaddr); 119 pdata->set_bootaddr(rproc->bootaddr);
121 120
122 oproc->nb.notifier_call = omap_rproc_mbox_callback; 121 client->dev = dev;
122 client->tx_done = NULL;
123 client->rx_callback = omap_rproc_mbox_callback;
124 client->tx_block = false;
125 client->knows_txdone = false;
123 126
124 /* every omap rproc is assigned a mailbox instance for messaging */ 127 oproc->mbox = omap_mbox_request_channel(client, pdata->mbox_name);
125 oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
126 if (IS_ERR(oproc->mbox)) { 128 if (IS_ERR(oproc->mbox)) {
127 ret = PTR_ERR(oproc->mbox); 129 ret = -EBUSY;
128 dev_err(dev, "omap_mbox_get failed: %d\n", ret); 130 dev_err(dev, "mbox_request_channel failed: %ld\n",
131 PTR_ERR(oproc->mbox));
129 return ret; 132 return ret;
130 } 133 }
131 134
@@ -136,9 +139,9 @@ static int omap_rproc_start(struct rproc *rproc)
136 * Note that the reply will _not_ arrive immediately: this message 139 * Note that the reply will _not_ arrive immediately: this message
137 * will wait in the mailbox fifo until the remote processor is booted. 140 * will wait in the mailbox fifo until the remote processor is booted.
138 */ 141 */
139 ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); 142 ret = mbox_send_message(oproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
140 if (ret) { 143 if (ret < 0) {
141 dev_err(dev, "omap_mbox_get failed: %d\n", ret); 144 dev_err(dev, "mbox_send_message failed: %d\n", ret);
142 goto put_mbox; 145 goto put_mbox;
143 } 146 }
144 147
@@ -151,7 +154,7 @@ static int omap_rproc_start(struct rproc *rproc)
151 return 0; 154 return 0;
152 155
153put_mbox: 156put_mbox:
154 omap_mbox_put(oproc->mbox, &oproc->nb); 157 mbox_free_channel(oproc->mbox);
155 return ret; 158 return ret;
156} 159}
157 160
@@ -168,7 +171,7 @@ static int omap_rproc_stop(struct rproc *rproc)
168 if (ret) 171 if (ret)
169 return ret; 172 return ret;
170 173
171 omap_mbox_put(oproc->mbox, &oproc->nb); 174 mbox_free_channel(oproc->mbox);
172 175
173 return 0; 176 return 0;
174} 177}