1 /* 2 * OMAP mailbox driver 3 * 4 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. 5 * Copyright (C) 2013-2014 Texas Instruments Inc. 6 * 7 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> 8 * Suman Anna <s-anna@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * version 2 as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 * 02110-1301 USA 23 * 24 */ 25 26 #include <linux/interrupt.h> 27 #include <linux/spinlock.h> 28 #include <linux/mutex.h> 29 #include <linux/slab.h> 30 #include <linux/kfifo.h> 31 #include <linux/err.h> 32 #include <linux/notifier.h> 33 #include <linux/module.h> 34 #include <linux/of_device.h> 35 #include <linux/platform_device.h> 36 #include <linux/pm_runtime.h> 37 #include <linux/platform_data/mailbox-omap.h> 38 #include <linux/omap-mailbox.h> 39 40 #define MAILBOX_REVISION 0x000 41 #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) 42 #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m)) 43 #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m)) 44 45 #define OMAP2_MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u)) 46 #define OMAP2_MAILBOX_IRQENABLE(u) (0x104 + 8 * (u)) 47 48 #define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u)) 49 #define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u)) 50 #define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u)) 51 52 #define MAILBOX_IRQSTATUS(type, u) (type ? OMAP4_MAILBOX_IRQSTATUS(u) : \ 53 OMAP2_MAILBOX_IRQSTATUS(u)) 54 #define MAILBOX_IRQENABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE(u) : \ 55 OMAP2_MAILBOX_IRQENABLE(u)) 56 #define MAILBOX_IRQDISABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \ 57 : OMAP2_MAILBOX_IRQENABLE(u)) 58 59 #define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m))) 60 #define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1)) 61 62 #define MBOX_REG_SIZE 0x120 63 64 #define OMAP4_MBOX_REG_SIZE 0x130 65 66 #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) 67 #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) 68 69 struct omap_mbox_fifo { 70 unsigned long msg; 71 unsigned long fifo_stat; 72 unsigned long msg_stat; 73 unsigned long irqenable; 74 unsigned long irqstatus; 75 unsigned long irqdisable; 76 u32 intr_bit; 77 }; 78 79 struct omap_mbox_queue { 80 spinlock_t lock; 81 struct kfifo fifo; 82 struct work_struct work; 83 struct tasklet_struct tasklet; 84 struct omap_mbox *mbox; 85 bool full; 86 }; 87 88 struct omap_mbox_device { 89 struct device *dev; 90 struct mutex cfg_lock; 91 void __iomem *mbox_base; 92 u32 num_users; 93 u32 num_fifos; 94 struct omap_mbox **mboxes; 95 struct list_head elem; 96 }; 97 98 struct omap_mbox_fifo_info { 99 int tx_id; 100 int tx_usr; 101 int tx_irq; 102 103 int rx_id; 104 int rx_usr; 105 int rx_irq; 106 107 const char *name; 108 }; 109 110 struct omap_mbox { 111 const char *name; 112 int irq; 113 struct omap_mbox_queue *txq, *rxq; 114 struct device *dev; 115 struct omap_mbox_device *parent; 116 struct omap_mbox_fifo tx_fifo; 117 struct omap_mbox_fifo rx_fifo; 118 u32 ctx[OMAP4_MBOX_NR_REGS]; 119 u32 intr_type; 120 int use_count; 121 struct blocking_notifier_head notifier; 122 }; 123 124 /* global variables for the mailbox devices */ 125 static DEFINE_MUTEX(omap_mbox_devices_lock); 126 static LIST_HEAD(omap_mbox_devices); 127 128 static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; 129 module_param(mbox_kfifo_size, uint, S_IRUGO); 130 MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); 131 132 static inline 133 unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs) 134 { 135 return __raw_readl(mdev->mbox_base + ofs); 136 } 137 138 static inline 139 void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs) 140 { 141 __raw_writel(val, mdev->mbox_base + ofs); 142 } 143 144 /* Mailbox FIFO handle functions */ 145 static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) 146 { 147 struct omap_mbox_fifo *fifo = &mbox->rx_fifo; 148 return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg); 149 } 150 151 static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 152 { 153 struct omap_mbox_fifo *fifo = &mbox->tx_fifo; 154 mbox_write_reg(mbox->parent, msg, fifo->msg); 155 } 156 157 static int mbox_fifo_empty(struct omap_mbox *mbox) 158 { 159 struct omap_mbox_fifo *fifo = &mbox->rx_fifo; 160 return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0); 161 } 162 163 static int mbox_fifo_full(struct omap_mbox *mbox) 164 { 165 struct omap_mbox_fifo *fifo = &mbox->tx_fifo; 166 return mbox_read_reg(mbox->parent, fifo->fifo_stat); 167 } 168 169 /* Mailbox IRQ handle functions */ 170 static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 171 { 172 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 173 &mbox->tx_fifo : &mbox->rx_fifo; 174 u32 bit = fifo->intr_bit; 175 u32 irqstatus = fifo->irqstatus; 176 177 mbox_write_reg(mbox->parent, bit, irqstatus); 178 179 /* Flush posted write for irq status to avoid spurious interrupts */ 180 mbox_read_reg(mbox->parent, irqstatus); 181 } 182 183 static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 184 { 185 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 186 &mbox->tx_fifo : &mbox->rx_fifo; 187 u32 bit = fifo->intr_bit; 188 u32 irqenable = fifo->irqenable; 189 u32 irqstatus = fifo->irqstatus; 190 191 u32 enable = mbox_read_reg(mbox->parent, irqenable); 192 u32 status = mbox_read_reg(mbox->parent, irqstatus); 193 194 return (int)(enable & status & bit); 195 } 196 197 /* 198 * message sender 199 */ 200 int 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 222 out: 223 spin_unlock_bh(&mq->lock); 224 return ret; 225 } 226 EXPORT_SYMBOL(omap_mbox_msg_send); 227 228 void omap_mbox_save_ctx(struct omap_mbox *mbox) 229 { 230 int i; 231 int nr_regs; 232 233 if (mbox->intr_type) 234 nr_regs = OMAP4_MBOX_NR_REGS; 235 else 236 nr_regs = MBOX_NR_REGS; 237 for (i = 0; i < nr_regs; i++) { 238 mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32)); 239 240 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 241 i, mbox->ctx[i]); 242 } 243 } 244 EXPORT_SYMBOL(omap_mbox_save_ctx); 245 246 void omap_mbox_restore_ctx(struct omap_mbox *mbox) 247 { 248 int i; 249 int nr_regs; 250 251 if (mbox->intr_type) 252 nr_regs = OMAP4_MBOX_NR_REGS; 253 else 254 nr_regs = MBOX_NR_REGS; 255 for (i = 0; i < nr_regs; i++) { 256 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32)); 257 258 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 259 i, mbox->ctx[i]); 260 } 261 } 262 EXPORT_SYMBOL(omap_mbox_restore_ctx); 263 264 void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 265 { 266 u32 l; 267 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 268 &mbox->tx_fifo : &mbox->rx_fifo; 269 u32 bit = fifo->intr_bit; 270 u32 irqenable = fifo->irqenable; 271 272 l = mbox_read_reg(mbox->parent, irqenable); 273 l |= bit; 274 mbox_write_reg(mbox->parent, l, irqenable); 275 } 276 EXPORT_SYMBOL(omap_mbox_enable_irq); 277 278 void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 279 { 280 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 281 &mbox->tx_fifo : &mbox->rx_fifo; 282 u32 bit = fifo->intr_bit; 283 u32 irqdisable = fifo->irqdisable; 284 285 /* 286 * Read and update the interrupt configuration register for pre-OMAP4. 287 * OMAP4 and later SoCs have a dedicated interrupt disabling register. 288 */ 289 if (!mbox->intr_type) 290 bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit; 291 292 mbox_write_reg(mbox->parent, bit, irqdisable); 293 } 294 EXPORT_SYMBOL(omap_mbox_disable_irq); 295 296 static void mbox_tx_tasklet(unsigned long tx_data) 297 { 298 struct omap_mbox *mbox = (struct omap_mbox *)tx_data; 299 struct omap_mbox_queue *mq = mbox->txq; 300 mbox_msg_t msg; 301 int ret; 302 303 while (kfifo_len(&mq->fifo)) { 304 if (mbox_fifo_full(mbox)) { 305 omap_mbox_enable_irq(mbox, IRQ_TX); 306 break; 307 } 308 309 ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, 310 sizeof(msg)); 311 WARN_ON(ret != sizeof(msg)); 312 313 mbox_fifo_write(mbox, msg); 314 } 315 } 316 317 /* 318 * Message receiver(workqueue) 319 */ 320 static void mbox_rx_work(struct work_struct *work) 321 { 322 struct omap_mbox_queue *mq = 323 container_of(work, struct omap_mbox_queue, work); 324 mbox_msg_t msg; 325 int len; 326 327 while (kfifo_len(&mq->fifo) >= sizeof(msg)) { 328 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); 329 WARN_ON(len != sizeof(msg)); 330 331 blocking_notifier_call_chain(&mq->mbox->notifier, len, 332 (void *)msg); 333 spin_lock_irq(&mq->lock); 334 if (mq->full) { 335 mq->full = false; 336 omap_mbox_enable_irq(mq->mbox, IRQ_RX); 337 } 338 spin_unlock_irq(&mq->lock); 339 } 340 } 341 342 /* 343 * Mailbox interrupt handler 344 */ 345 static void __mbox_tx_interrupt(struct omap_mbox *mbox) 346 { 347 omap_mbox_disable_irq(mbox, IRQ_TX); 348 ack_mbox_irq(mbox, IRQ_TX); 349 tasklet_schedule(&mbox->txq->tasklet); 350 } 351 352 static void __mbox_rx_interrupt(struct omap_mbox *mbox) 353 { 354 struct omap_mbox_queue *mq = mbox->rxq; 355 mbox_msg_t msg; 356 int len; 357 358 while (!mbox_fifo_empty(mbox)) { 359 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { 360 omap_mbox_disable_irq(mbox, IRQ_RX); 361 mq->full = true; 362 goto nomem; 363 } 364 365 msg = mbox_fifo_read(mbox); 366 367 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); 368 WARN_ON(len != sizeof(msg)); 369 } 370 371 /* no more messages in the fifo. clear IRQ source. */ 372 ack_mbox_irq(mbox, IRQ_RX); 373 nomem: 374 schedule_work(&mbox->rxq->work); 375 } 376 377 static irqreturn_t mbox_interrupt(int irq, void *p) 378 { 379 struct omap_mbox *mbox = p; 380 381 if (is_mbox_irq(mbox, IRQ_TX)) 382 __mbox_tx_interrupt(mbox); 383 384 if (is_mbox_irq(mbox, IRQ_RX)) 385 __mbox_rx_interrupt(mbox); 386 387 return IRQ_HANDLED; 388 } 389 390 static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, 391 void (*work) (struct work_struct *), 392 void (*tasklet)(unsigned long)) 393 { 394 struct omap_mbox_queue *mq; 395 396 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); 397 if (!mq) 398 return NULL; 399 400 spin_lock_init(&mq->lock); 401 402 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) 403 goto error; 404 405 if (work) 406 INIT_WORK(&mq->work, work); 407 408 if (tasklet) 409 tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox); 410 return mq; 411 error: 412 kfree(mq); 413 return NULL; 414 } 415 416 static void mbox_queue_free(struct omap_mbox_queue *q) 417 { 418 kfifo_free(&q->fifo); 419 kfree(q); 420 } 421 422 static int omap_mbox_startup(struct omap_mbox *mbox) 423 { 424 int ret = 0; 425 struct omap_mbox_queue *mq; 426 struct omap_mbox_device *mdev = mbox->parent; 427 428 mutex_lock(&mdev->cfg_lock); 429 ret = pm_runtime_get_sync(mdev->dev); 430 if (unlikely(ret < 0)) 431 goto fail_startup; 432 433 if (!mbox->use_count++) { 434 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); 435 if (!mq) { 436 ret = -ENOMEM; 437 goto fail_alloc_txq; 438 } 439 mbox->txq = mq; 440 441 mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); 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 456 omap_mbox_enable_irq(mbox, IRQ_RX); 457 } 458 mutex_unlock(&mdev->cfg_lock); 459 return 0; 460 461 fail_request_irq: 462 mbox_queue_free(mbox->rxq); 463 fail_alloc_rxq: 464 mbox_queue_free(mbox->txq); 465 fail_alloc_txq: 466 pm_runtime_put_sync(mdev->dev); 467 mbox->use_count--; 468 fail_startup: 469 mutex_unlock(&mdev->cfg_lock); 470 return ret; 471 } 472 473 static void omap_mbox_fini(struct omap_mbox *mbox) 474 { 475 struct omap_mbox_device *mdev = mbox->parent; 476 477 mutex_lock(&mdev->cfg_lock); 478 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 } 492 493 static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev, 494 const char *mbox_name) 495 { 496 struct omap_mbox *_mbox, *mbox = NULL; 497 struct omap_mbox **mboxes = mdev->mboxes; 498 int i; 499 500 if (!mboxes) 501 return NULL; 502 503 for (i = 0; (_mbox = mboxes[i]); i++) { 504 if (!strcmp(_mbox->name, mbox_name)) { 505 mbox = _mbox; 506 break; 507 } 508 } 509 return mbox; 510 } 511 512 struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) 513 { 514 struct omap_mbox *mbox = NULL; 515 struct omap_mbox_device *mdev; 516 int ret; 517 518 mutex_lock(&omap_mbox_devices_lock); 519 list_for_each_entry(mdev, &omap_mbox_devices, elem) { 520 mbox = omap_mbox_device_find(mdev, name); 521 if (mbox) 522 break; 523 } 524 mutex_unlock(&omap_mbox_devices_lock); 525 526 if (!mbox) 527 return ERR_PTR(-ENOENT); 528 529 if (nb) 530 blocking_notifier_chain_register(&mbox->notifier, nb); 531 532 ret = omap_mbox_startup(mbox); 533 if (ret) { 534 blocking_notifier_chain_unregister(&mbox->notifier, nb); 535 return ERR_PTR(-ENODEV); 536 } 537 538 return mbox; 539 } 540 EXPORT_SYMBOL(omap_mbox_get); 541 542 void 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 } 547 EXPORT_SYMBOL(omap_mbox_put); 548 549 static struct class omap_mbox_class = { .name = "mbox", }; 550 551 static int omap_mbox_register(struct omap_mbox_device *mdev) 552 { 553 int ret; 554 int i; 555 struct omap_mbox **mboxes; 556 557 if (!mdev || !mdev->mboxes) 558 return -EINVAL; 559 560 mboxes = mdev->mboxes; 561 for (i = 0; mboxes[i]; i++) { 562 struct omap_mbox *mbox = mboxes[i]; 563 mbox->dev = device_create(&omap_mbox_class, 564 mdev->dev, 0, mbox, "%s", mbox->name); 565 if (IS_ERR(mbox->dev)) { 566 ret = PTR_ERR(mbox->dev); 567 goto err_out; 568 } 569 570 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); 571 } 572 573 mutex_lock(&omap_mbox_devices_lock); 574 list_add(&mdev->elem, &omap_mbox_devices); 575 mutex_unlock(&omap_mbox_devices_lock); 576 577 return 0; 578 579 err_out: 580 while (i--) 581 device_unregister(mboxes[i]->dev); 582 return ret; 583 } 584 585 static int omap_mbox_unregister(struct omap_mbox_device *mdev) 586 { 587 int i; 588 struct omap_mbox **mboxes; 589 590 if (!mdev || !mdev->mboxes) 591 return -EINVAL; 592 593 mutex_lock(&omap_mbox_devices_lock); 594 list_del(&mdev->elem); 595 mutex_unlock(&omap_mbox_devices_lock); 596 597 mboxes = mdev->mboxes; 598 for (i = 0; mboxes[i]; i++) 599 device_unregister(mboxes[i]->dev); 600 return 0; 601 } 602 603 static const struct of_device_id omap_mailbox_of_match[] = { 604 { 605 .compatible = "ti,omap2-mailbox", 606 .data = (void *)MBOX_INTR_CFG_TYPE1, 607 }, 608 { 609 .compatible = "ti,omap3-mailbox", 610 .data = (void *)MBOX_INTR_CFG_TYPE1, 611 }, 612 { 613 .compatible = "ti,omap4-mailbox", 614 .data = (void *)MBOX_INTR_CFG_TYPE2, 615 }, 616 { 617 /* end */ 618 }, 619 }; 620 MODULE_DEVICE_TABLE(of, omap_mailbox_of_match); 621 622 static int omap_mbox_probe(struct platform_device *pdev) 623 { 624 struct resource *mem; 625 int ret; 626 struct omap_mbox **list, *mbox, *mboxblk; 627 struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 628 struct omap_mbox_dev_info *info = NULL; 629 struct omap_mbox_fifo_info *finfo, *finfoblk; 630 struct omap_mbox_device *mdev; 631 struct omap_mbox_fifo *fifo; 632 struct device_node *node = pdev->dev.of_node; 633 struct device_node *child; 634 const struct of_device_id *match; 635 u32 intr_type, info_count; 636 u32 num_users, num_fifos; 637 u32 tmp[3]; 638 u32 l; 639 int i; 640 641 if (!node && (!pdata || !pdata->info_cnt || !pdata->info)) { 642 pr_err("%s: platform not supported\n", __func__); 643 return -ENODEV; 644 } 645 646 if (node) { 647 match = of_match_device(omap_mailbox_of_match, &pdev->dev); 648 if (!match) 649 return -ENODEV; 650 intr_type = (u32)match->data; 651 652 if (of_property_read_u32(node, "ti,mbox-num-users", 653 &num_users)) 654 return -ENODEV; 655 656 if (of_property_read_u32(node, "ti,mbox-num-fifos", 657 &num_fifos)) 658 return -ENODEV; 659 660 info_count = of_get_available_child_count(node); 661 if (!info_count) { 662 dev_err(&pdev->dev, "no available mbox devices found\n"); 663 return -ENODEV; 664 } 665 } else { /* non-DT device creation */ 666 info_count = pdata->info_cnt; 667 info = pdata->info; 668 intr_type = pdata->intr_type; 669 num_users = pdata->num_users; 670 num_fifos = pdata->num_fifos; 671 } 672 673 finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk), 674 GFP_KERNEL); 675 if (!finfoblk) 676 return -ENOMEM; 677 678 finfo = finfoblk; 679 child = NULL; 680 for (i = 0; i < info_count; i++, finfo++) { 681 if (node) { 682 child = of_get_next_available_child(node, child); 683 ret = of_property_read_u32_array(child, "ti,mbox-tx", 684 tmp, ARRAY_SIZE(tmp)); 685 if (ret) 686 return ret; 687 finfo->tx_id = tmp[0]; 688 finfo->tx_irq = tmp[1]; 689 finfo->tx_usr = tmp[2]; 690 691 ret = of_property_read_u32_array(child, "ti,mbox-rx", 692 tmp, ARRAY_SIZE(tmp)); 693 if (ret) 694 return ret; 695 finfo->rx_id = tmp[0]; 696 finfo->rx_irq = tmp[1]; 697 finfo->rx_usr = tmp[2]; 698 699 finfo->name = child->name; 700 } else { 701 finfo->tx_id = info->tx_id; 702 finfo->rx_id = info->rx_id; 703 finfo->tx_usr = info->usr_id; 704 finfo->tx_irq = info->irq_id; 705 finfo->rx_usr = info->usr_id; 706 finfo->rx_irq = info->irq_id; 707 finfo->name = info->name; 708 info++; 709 } 710 if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos || 711 finfo->tx_usr >= num_users || finfo->rx_usr >= num_users) 712 return -EINVAL; 713 } 714 715 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL); 716 if (!mdev) 717 return -ENOMEM; 718 719 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 720 mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem); 721 if (IS_ERR(mdev->mbox_base)) 722 return PTR_ERR(mdev->mbox_base); 723 724 /* allocate one extra for marking end of list */ 725 list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list), 726 GFP_KERNEL); 727 if (!list) 728 return -ENOMEM; 729 730 mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox), 731 GFP_KERNEL); 732 if (!mboxblk) 733 return -ENOMEM; 734 735 mbox = mboxblk; 736 finfo = finfoblk; 737 for (i = 0; i < info_count; i++, finfo++) { 738 fifo = &mbox->tx_fifo; 739 fifo->msg = MAILBOX_MESSAGE(finfo->tx_id); 740 fifo->fifo_stat = MAILBOX_FIFOSTATUS(finfo->tx_id); 741 fifo->intr_bit = MAILBOX_IRQ_NOTFULL(finfo->tx_id); 742 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->tx_usr); 743 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->tx_usr); 744 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->tx_usr); 745 746 fifo = &mbox->rx_fifo; 747 fifo->msg = MAILBOX_MESSAGE(finfo->rx_id); 748 fifo->msg_stat = MAILBOX_MSGSTATUS(finfo->rx_id); 749 fifo->intr_bit = MAILBOX_IRQ_NEWMSG(finfo->rx_id); 750 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->rx_usr); 751 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr); 752 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr); 753 754 mbox->intr_type = intr_type; 755 756 mbox->parent = mdev; 757 mbox->name = finfo->name; 758 mbox->irq = platform_get_irq(pdev, finfo->tx_irq); 759 if (mbox->irq < 0) 760 return mbox->irq; 761 list[i] = mbox++; 762 } 763 764 mutex_init(&mdev->cfg_lock); 765 mdev->dev = &pdev->dev; 766 mdev->num_users = num_users; 767 mdev->num_fifos = num_fifos; 768 mdev->mboxes = list; 769 ret = omap_mbox_register(mdev); 770 if (ret) 771 return ret; 772 773 platform_set_drvdata(pdev, mdev); 774 pm_runtime_enable(mdev->dev); 775 776 ret = pm_runtime_get_sync(mdev->dev); 777 if (ret < 0) { 778 pm_runtime_put_noidle(mdev->dev); 779 goto unregister; 780 } 781 782 /* 783 * just print the raw revision register, the format is not 784 * uniform across all SoCs 785 */ 786 l = mbox_read_reg(mdev, MAILBOX_REVISION); 787 dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l); 788 789 ret = pm_runtime_put_sync(mdev->dev); 790 if (ret < 0) 791 goto unregister; 792 793 devm_kfree(&pdev->dev, finfoblk); 794 return 0; 795 796 unregister: 797 pm_runtime_disable(mdev->dev); 798 omap_mbox_unregister(mdev); 799 return ret; 800 } 801 802 static int omap_mbox_remove(struct platform_device *pdev) 803 { 804 struct omap_mbox_device *mdev = platform_get_drvdata(pdev); 805 806 pm_runtime_disable(mdev->dev); 807 omap_mbox_unregister(mdev); 808 809 return 0; 810 } 811 812 static struct platform_driver omap_mbox_driver = { 813 .probe = omap_mbox_probe, 814 .remove = omap_mbox_remove, 815 .driver = { 816 .name = "omap-mailbox", 817 .owner = THIS_MODULE, 818 .of_match_table = of_match_ptr(omap_mailbox_of_match), 819 }, 820 }; 821 822 static int __init omap_mbox_init(void) 823 { 824 int err; 825 826 err = class_register(&omap_mbox_class); 827 if (err) 828 return err; 829 830 /* kfifo size sanity check: alignment and minimal size */ 831 mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t)); 832 mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, 833 sizeof(mbox_msg_t)); 834 835 return platform_driver_register(&omap_mbox_driver); 836 } 837 subsys_initcall(omap_mbox_init); 838 839 static void __exit omap_mbox_exit(void) 840 { 841 platform_driver_unregister(&omap_mbox_driver); 842 class_unregister(&omap_mbox_class); 843 } 844 module_exit(omap_mbox_exit); 845 846 MODULE_LICENSE("GPL v2"); 847 MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); 848 MODULE_AUTHOR("Toshihiro Kobayashi"); 849 MODULE_AUTHOR("Hiroshi DOYU"); 850