Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mailbox/omap: adapt to the new mailbox framework

The OMAP mailbox driver and its existing clients (remoteproc
for OMAP4+) are adapted to use the generic mailbox framework.

The main changes for the adaptation are:
- The tasklet used for Tx is replaced with the state machine from
the generic mailbox framework. The workqueue used for processing
the received messages stays intact for minimizing the effects on
the OMAP mailbox clients.
- The existing exported client API, omap_mbox_get, omap_mbox_put and
omap_mbox_send_msg are deleted, as the framework provides equivalent
functionality. A OMAP-specific omap_mbox_request_channel is added
though to support non-DT way of requesting mailboxes.
- The OMAP mailbox driver is integrated with the mailbox framework
through the proper implementations of mbox_chan_ops, except for
.last_tx_done and .peek_data. The OMAP mailbox driver does not need
these ops, as it is completely interrupt driven.
- The OMAP mailbox driver uses a custom of_xlate controller ops that
allows phandles for the pargs specifier instead of indexing to avoid
any channel registration order dependencies.
- The new framework does not support multiple clients operating on a
single channel, so the reference counting logic is simplified.
- The remoteproc driver (current client) is adapted to use the new API.
The notifier callbacks used within this client is replaced with the
regular callbacks from the newer framework.
- The exported OMAP mailbox API are limited to omap_mbox_save_ctx,
omap_mbox_restore_ctx, omap_mbox_enable_irq & omap_mbox_disable_irq,
with the signature modified to take in the new mbox_chan handle instead
of the OMAP specific omap_mbox handle. The first 2 will be removed when
the OMAP mailbox driver is adapted to runtime_pm. The other exported
API omap_mbox_request_channel will be removed once existing legacy
users are converted to DT.

Signed-off-by: Suman Anna <s-anna@ti.com>
Cc: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>

authored by

Suman Anna and committed by
Jassi Brar
8841a66a 97b0c7bd

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