1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Broadcom BCM74110 Mailbox Driver 4 * 5 * Copyright (c) 2025 Broadcom 6 */ 7 #include <linux/list.h> 8 #include <linux/types.h> 9 #include <linux/workqueue.h> 10 #include <linux/io-64-nonatomic-hi-lo.h> 11 #include <linux/interrupt.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/of.h> 15 #include <linux/delay.h> 16 #include <linux/mailbox_controller.h> 17 #include <linux/bitfield.h> 18 #include <linux/slab.h> 19 20 #define BCM_MBOX_BASE(sel) ((sel) * 0x40) 21 #define BCM_MBOX_IRQ_BASE(sel) (((sel) * 0x20) + 0x800) 22 23 #define BCM_MBOX_CFGA 0x0 24 #define BCM_MBOX_CFGB 0x4 25 #define BCM_MBOX_CFGC 0x8 26 #define BCM_MBOX_CFGD 0xc 27 #define BCM_MBOX_CTRL 0x10 28 #define BCM_MBOX_CTRL_EN BIT(0) 29 #define BCM_MBOX_CTRL_CLR BIT(1) 30 #define BCM_MBOX_STATUS0 0x14 31 #define BCM_MBOX_STATUS0_NOT_EMPTY BIT(28) 32 #define BCM_MBOX_STATUS0_FULL BIT(29) 33 #define BCM_MBOX_STATUS1 0x18 34 #define BCM_MBOX_STATUS2 0x1c 35 #define BCM_MBOX_WDATA 0x20 36 #define BCM_MBOX_RDATA 0x28 37 38 #define BCM_MBOX_IRQ_STATUS 0x0 39 #define BCM_MBOX_IRQ_SET 0x4 40 #define BCM_MBOX_IRQ_CLEAR 0x8 41 #define BCM_MBOX_IRQ_MASK_STATUS 0xc 42 #define BCM_MBOX_IRQ_MASK_SET 0x10 43 #define BCM_MBOX_IRQ_MASK_CLEAR 0x14 44 #define BCM_MBOX_IRQ_TIMEOUT BIT(0) 45 #define BCM_MBOX_IRQ_NOT_EMPTY BIT(1) 46 #define BCM_MBOX_IRQ_FULL BIT(2) 47 #define BCM_MBOX_IRQ_LOW_WM BIT(3) 48 #define BCM_MBOX_IRQ_HIGH_WM BIT(4) 49 50 #define BCM_LINK_CODE0 0xbe0 51 #define BCM_LINK_CODE1 0xbe1 52 #define BCM_LINK_CODE2 0xbe2 53 54 enum { 55 BCM_MSG_FUNC_LINK_START = 0, 56 BCM_MSG_FUNC_LINK_STOP, 57 BCM_MSG_FUNC_SHMEM_TX, 58 BCM_MSG_FUNC_SHMEM_RX, 59 BCM_MSG_FUNC_SHMEM_STOP, 60 BCM_MSG_FUNC_MAX, 61 }; 62 63 enum { 64 BCM_MSG_SVC_INIT = 0, 65 BCM_MSG_SVC_PMC, 66 BCM_MSG_SVC_SCMI, 67 BCM_MSG_SVC_DPFE, 68 BCM_MSG_SVC_MAX, 69 }; 70 71 struct bcm74110_mbox_msg { 72 struct list_head list_entry; 73 #define BCM_MSG_VERSION_MASK GENMASK(31, 29) 74 #define BCM_MSG_VERSION 0x1 75 #define BCM_MSG_REQ_MASK BIT(28) 76 #define BCM_MSG_RPLY_MASK BIT(27) 77 #define BCM_MSG_SVC_MASK GENMASK(26, 24) 78 #define BCM_MSG_FUNC_MASK GENMASK(23, 16) 79 #define BCM_MSG_LENGTH_MASK GENMASK(15, 4) 80 #define BCM_MSG_SLOT_MASK GENMASK(3, 0) 81 82 #define BCM_MSG_SET_FIELD(hdr, field, val) \ 83 do { \ 84 hdr &= ~BCM_MSG_##field##_MASK; \ 85 hdr |= FIELD_PREP(BCM_MSG_##field##_MASK, val); \ 86 } while (0) 87 88 #define BCM_MSG_GET_FIELD(hdr, field) \ 89 FIELD_GET(BCM_MSG_##field##_MASK, hdr) 90 u32 msg; 91 }; 92 93 struct bcm74110_mbox_chan { 94 struct bcm74110_mbox *mbox; 95 bool en; 96 int slot; 97 int type; 98 }; 99 100 struct bcm74110_mbox { 101 struct platform_device *pdev; 102 void __iomem *base; 103 104 int tx_chan; 105 int rx_chan; 106 int rx_irq; 107 struct list_head rx_svc_init_list; 108 spinlock_t rx_svc_list_lock; 109 110 struct mbox_controller controller; 111 struct bcm74110_mbox_chan *mbox_chan; 112 }; 113 114 #define BCM74110_OFFSET_IO_WRITEL_MACRO(name, offset_base) \ 115 static void bcm74110_##name##_writel(struct bcm74110_mbox *mbox,\ 116 u32 val, u32 off) \ 117 { \ 118 writel_relaxed(val, mbox->base + offset_base + off); \ 119 } 120 BCM74110_OFFSET_IO_WRITEL_MACRO(tx, BCM_MBOX_BASE(mbox->tx_chan)); 121 BCM74110_OFFSET_IO_WRITEL_MACRO(irq, BCM_MBOX_IRQ_BASE(mbox->rx_chan)); 122 123 #define BCM74110_OFFSET_IO_READL_MACRO(name, offset_base) \ 124 static u32 bcm74110_##name##_readl(struct bcm74110_mbox *mbox, \ 125 u32 off) \ 126 { \ 127 return readl_relaxed(mbox->base + offset_base + off); \ 128 } 129 BCM74110_OFFSET_IO_READL_MACRO(tx, BCM_MBOX_BASE(mbox->tx_chan)); 130 BCM74110_OFFSET_IO_READL_MACRO(rx, BCM_MBOX_BASE(mbox->rx_chan)); 131 BCM74110_OFFSET_IO_READL_MACRO(irq, BCM_MBOX_IRQ_BASE(mbox->rx_chan)); 132 133 static inline struct bcm74110_mbox *bcm74110_mbox_from_cntrl( 134 struct mbox_controller *cntrl) 135 { 136 return container_of(cntrl, struct bcm74110_mbox, controller); 137 } 138 139 static void bcm74110_rx_push_init_msg(struct bcm74110_mbox *mbox, u32 val) 140 { 141 struct bcm74110_mbox_msg *msg; 142 143 msg = kzalloc(sizeof(*msg), GFP_ATOMIC); 144 if (!msg) 145 return; 146 147 INIT_LIST_HEAD(&msg->list_entry); 148 msg->msg = val; 149 150 spin_lock(&mbox->rx_svc_list_lock); 151 list_add_tail(&msg->list_entry, &mbox->rx_svc_init_list); 152 spin_unlock(&mbox->rx_svc_list_lock); 153 } 154 155 static void bcm74110_rx_process_msg(struct bcm74110_mbox *mbox) 156 { 157 struct device *dev = &mbox->pdev->dev; 158 struct bcm74110_mbox_chan *chan_priv; 159 struct mbox_chan *chan; 160 u32 msg, status; 161 int type; 162 163 do { 164 msg = bcm74110_rx_readl(mbox, BCM_MBOX_RDATA); 165 status = bcm74110_rx_readl(mbox, BCM_MBOX_STATUS0); 166 167 dev_dbg(dev, "rx: [{req=%lu|rply=%lu|srv=%lu|fn=%lu|length=%lu|slot=%lu]\n", 168 BCM_MSG_GET_FIELD(msg, REQ), BCM_MSG_GET_FIELD(msg, RPLY), 169 BCM_MSG_GET_FIELD(msg, SVC), BCM_MSG_GET_FIELD(msg, FUNC), 170 BCM_MSG_GET_FIELD(msg, LENGTH), BCM_MSG_GET_FIELD(msg, SLOT)); 171 172 type = BCM_MSG_GET_FIELD(msg, SVC); 173 switch (type) { 174 case BCM_MSG_SVC_INIT: 175 bcm74110_rx_push_init_msg(mbox, msg); 176 break; 177 case BCM_MSG_SVC_PMC: 178 case BCM_MSG_SVC_SCMI: 179 case BCM_MSG_SVC_DPFE: 180 chan = &mbox->controller.chans[type]; 181 chan_priv = chan->con_priv; 182 if (chan_priv->en) 183 mbox_chan_received_data(chan, NULL); 184 else 185 dev_warn(dev, "Channel not enabled\n"); 186 break; 187 default: 188 dev_warn(dev, "Unsupported msg received\n"); 189 } 190 } while (status & BCM_MBOX_STATUS0_NOT_EMPTY); 191 } 192 193 static irqreturn_t bcm74110_mbox_isr(int irq, void *data) 194 { 195 struct bcm74110_mbox *mbox = data; 196 u32 status; 197 198 status = bcm74110_irq_readl(mbox, BCM_MBOX_IRQ_STATUS); 199 200 bcm74110_irq_writel(mbox, 0xffffffff, BCM_MBOX_IRQ_CLEAR); 201 202 if (status & BCM_MBOX_IRQ_NOT_EMPTY) 203 bcm74110_rx_process_msg(mbox); 204 else 205 dev_warn(&mbox->pdev->dev, "Spurious interrupt\n"); 206 207 return IRQ_HANDLED; 208 } 209 210 static void bcm74110_mbox_mask_and_clear(struct bcm74110_mbox *mbox) 211 { 212 bcm74110_irq_writel(mbox, 0xffffffff, BCM_MBOX_IRQ_MASK_SET); 213 bcm74110_irq_writel(mbox, 0xffffffff, BCM_MBOX_IRQ_CLEAR); 214 } 215 216 static int bcm74110_rx_pop_init_msg(struct bcm74110_mbox *mbox, u32 func_type, 217 u32 *val) 218 { 219 struct bcm74110_mbox_msg *msg, *msg_tmp; 220 unsigned long flags; 221 bool found = false; 222 223 spin_lock_irqsave(&mbox->rx_svc_list_lock, flags); 224 list_for_each_entry_safe(msg, msg_tmp, &mbox->rx_svc_init_list, 225 list_entry) { 226 if (BCM_MSG_GET_FIELD(msg->msg, FUNC) == func_type) { 227 list_del(&msg->list_entry); 228 found = true; 229 break; 230 } 231 } 232 spin_unlock_irqrestore(&mbox->rx_svc_list_lock, flags); 233 234 if (!found) 235 return -EINVAL; 236 237 *val = msg->msg; 238 kfree(msg); 239 240 return 0; 241 } 242 243 static void bcm74110_rx_flush_msg(struct bcm74110_mbox *mbox) 244 { 245 struct bcm74110_mbox_msg *msg, *msg_tmp; 246 LIST_HEAD(list_temp); 247 unsigned long flags; 248 249 spin_lock_irqsave(&mbox->rx_svc_list_lock, flags); 250 list_splice_init(&mbox->rx_svc_init_list, &list_temp); 251 spin_unlock_irqrestore(&mbox->rx_svc_list_lock, flags); 252 253 list_for_each_entry_safe(msg, msg_tmp, &list_temp, list_entry) { 254 list_del(&msg->list_entry); 255 kfree(msg); 256 } 257 } 258 259 #define BCM_DEQUEUE_TIMEOUT_MS 30 260 static int bcm74110_rx_pop_init_msg_block(struct bcm74110_mbox *mbox, u32 func_type, 261 u32 *val) 262 { 263 int ret, timeout = 0; 264 265 do { 266 ret = bcm74110_rx_pop_init_msg(mbox, func_type, val); 267 268 if (!ret) 269 return 0; 270 271 /* TODO: Figure out what is a good sleep here. */ 272 usleep_range(1000, 2000); 273 timeout++; 274 } while (timeout < BCM_DEQUEUE_TIMEOUT_MS); 275 276 dev_warn(&mbox->pdev->dev, "Timeout waiting for service init response\n"); 277 return -ETIMEDOUT; 278 } 279 280 static int bcm74110_mbox_create_msg(int req, int rply, int svc, int func, 281 int length, int slot) 282 { 283 u32 msg = 0; 284 285 BCM_MSG_SET_FIELD(msg, REQ, req); 286 BCM_MSG_SET_FIELD(msg, RPLY, rply); 287 BCM_MSG_SET_FIELD(msg, SVC, svc); 288 BCM_MSG_SET_FIELD(msg, FUNC, func); 289 BCM_MSG_SET_FIELD(msg, LENGTH, length); 290 BCM_MSG_SET_FIELD(msg, SLOT, slot); 291 292 return msg; 293 } 294 295 static int bcm74110_mbox_tx_msg(struct bcm74110_mbox *mbox, u32 msg) 296 { 297 int val; 298 299 /* We can potentially poll with timeout here instead */ 300 val = bcm74110_tx_readl(mbox, BCM_MBOX_STATUS0); 301 if (val & BCM_MBOX_STATUS0_FULL) { 302 dev_err(&mbox->pdev->dev, "Mailbox full\n"); 303 return -EINVAL; 304 } 305 306 dev_dbg(&mbox->pdev->dev, "tx: [{req=%lu|rply=%lu|srv=%lu|fn=%lu|length=%lu|slot=%lu]\n", 307 BCM_MSG_GET_FIELD(msg, REQ), BCM_MSG_GET_FIELD(msg, RPLY), 308 BCM_MSG_GET_FIELD(msg, SVC), BCM_MSG_GET_FIELD(msg, FUNC), 309 BCM_MSG_GET_FIELD(msg, LENGTH), BCM_MSG_GET_FIELD(msg, SLOT)); 310 311 bcm74110_tx_writel(mbox, msg, BCM_MBOX_WDATA); 312 313 return 0; 314 } 315 316 #define BCM_MBOX_LINK_TRAINING_RETRIES 5 317 static int bcm74110_mbox_link_training(struct bcm74110_mbox *mbox) 318 { 319 int ret, retries = 0; 320 u32 msg = 0, orig_len = 0, len = BCM_LINK_CODE0; 321 322 do { 323 switch (len) { 324 case 0: 325 retries++; 326 dev_warn(&mbox->pdev->dev, 327 "Link train failed, trying again... %d\n", 328 retries); 329 if (retries > BCM_MBOX_LINK_TRAINING_RETRIES) 330 return -EINVAL; 331 len = BCM_LINK_CODE0; 332 fallthrough; 333 case BCM_LINK_CODE0: 334 case BCM_LINK_CODE1: 335 case BCM_LINK_CODE2: 336 msg = bcm74110_mbox_create_msg(1, 0, BCM_MSG_SVC_INIT, 337 BCM_MSG_FUNC_LINK_START, 338 len, BCM_MSG_SVC_INIT); 339 break; 340 default: 341 break; 342 } 343 344 bcm74110_mbox_tx_msg(mbox, msg); 345 346 /* No response expected for LINK_CODE2 */ 347 if (len == BCM_LINK_CODE2) 348 return 0; 349 350 orig_len = len; 351 352 ret = bcm74110_rx_pop_init_msg_block(mbox, 353 BCM_MSG_GET_FIELD(msg, FUNC), 354 &msg); 355 if (ret) { 356 len = 0; 357 continue; 358 } 359 360 if ((BCM_MSG_GET_FIELD(msg, SVC) != BCM_MSG_SVC_INIT) || 361 (BCM_MSG_GET_FIELD(msg, FUNC) != BCM_MSG_FUNC_LINK_START) || 362 (BCM_MSG_GET_FIELD(msg, SLOT) != 0) || 363 (BCM_MSG_GET_FIELD(msg, RPLY) != 1) || 364 (BCM_MSG_GET_FIELD(msg, REQ) != 0)) { 365 len = 0; 366 continue; 367 } 368 369 len = BCM_MSG_GET_FIELD(msg, LENGTH); 370 371 /* Make sure sequence is good */ 372 if (len != (orig_len + 1)) { 373 len = 0; 374 continue; 375 } 376 } while (1); 377 378 return -EINVAL; 379 } 380 381 static int bcm74110_mbox_tx_msg_and_wait_ack(struct bcm74110_mbox *mbox, u32 msg) 382 { 383 int ret; 384 u32 recv_msg; 385 386 ret = bcm74110_mbox_tx_msg(mbox, msg); 387 if (ret) 388 return ret; 389 390 ret = bcm74110_rx_pop_init_msg_block(mbox, BCM_MSG_GET_FIELD(msg, FUNC), 391 &recv_msg); 392 if (ret) 393 return ret; 394 395 /* 396 * Modify tx message to verify rx ack. 397 * Flip RPLY/REQ for synchronous messages 398 */ 399 if (BCM_MSG_GET_FIELD(msg, REQ) == 1) { 400 BCM_MSG_SET_FIELD(msg, RPLY, 1); 401 BCM_MSG_SET_FIELD(msg, REQ, 0); 402 } 403 404 if (msg != recv_msg) { 405 dev_err(&mbox->pdev->dev, "Found ack, but ack is invalid\n"); 406 return -EINVAL; 407 } 408 409 return 0; 410 } 411 412 /* Each index points to 0x100 of HAB MEM. IDX size counts from 0 */ 413 #define BCM_MBOX_HAB_MEM_IDX_START 0x30 414 #define BCM_MBOX_HAB_MEM_IDX_SIZE 0x0 415 static int bcm74110_mbox_shmem_init(struct bcm74110_mbox *mbox) 416 { 417 u32 msg = 0; 418 int ret; 419 420 msg = bcm74110_mbox_create_msg(1, 0, BCM_MSG_SVC_INIT, 421 BCM_MSG_FUNC_SHMEM_STOP, 422 0, BCM_MSG_SVC_INIT); 423 ret = bcm74110_mbox_tx_msg_and_wait_ack(mbox, msg); 424 if (ret) 425 return -EINVAL; 426 427 msg = bcm74110_mbox_create_msg(1, 0, BCM_MSG_SVC_INIT, 428 BCM_MSG_FUNC_SHMEM_TX, 429 BCM_MBOX_HAB_MEM_IDX_START, 430 BCM_MBOX_HAB_MEM_IDX_SIZE); 431 ret = bcm74110_mbox_tx_msg_and_wait_ack(mbox, msg); 432 if (ret) 433 return -EINVAL; 434 435 msg = bcm74110_mbox_create_msg(1, 0, BCM_MSG_SVC_INIT, 436 BCM_MSG_FUNC_SHMEM_RX, 437 BCM_MBOX_HAB_MEM_IDX_START, 438 BCM_MBOX_HAB_MEM_IDX_SIZE); 439 ret = bcm74110_mbox_tx_msg_and_wait_ack(mbox, msg); 440 if (ret) 441 return -EINVAL; 442 443 return 0; 444 } 445 446 static int bcm74110_mbox_init(struct bcm74110_mbox *mbox) 447 { 448 int ret = 0; 449 450 /* Disable queues tx/rx */ 451 bcm74110_tx_writel(mbox, 0x0, BCM_MBOX_CTRL); 452 453 /* Clear status & restart tx/rx*/ 454 bcm74110_tx_writel(mbox, BCM_MBOX_CTRL_EN | BCM_MBOX_CTRL_CLR, 455 BCM_MBOX_CTRL); 456 457 /* Unmask irq */ 458 bcm74110_irq_writel(mbox, BCM_MBOX_IRQ_NOT_EMPTY, BCM_MBOX_IRQ_MASK_CLEAR); 459 460 ret = bcm74110_mbox_link_training(mbox); 461 if (ret) { 462 dev_err(&mbox->pdev->dev, "Training failed\n"); 463 return ret; 464 } 465 466 return bcm74110_mbox_shmem_init(mbox); 467 } 468 469 static int bcm74110_mbox_send_data(struct mbox_chan *chan, void *data) 470 { 471 struct bcm74110_mbox_chan *chan_priv = chan->con_priv; 472 u32 msg; 473 474 switch (chan_priv->type) { 475 case BCM_MSG_SVC_PMC: 476 case BCM_MSG_SVC_SCMI: 477 case BCM_MSG_SVC_DPFE: 478 msg = bcm74110_mbox_create_msg(1, 0, chan_priv->type, 0, 479 128 + 28, chan_priv->slot); 480 break; 481 default: 482 return -EINVAL; 483 } 484 485 return bcm74110_mbox_tx_msg(chan_priv->mbox, msg); 486 } 487 488 static int bcm74110_mbox_chan_startup(struct mbox_chan *chan) 489 { 490 struct bcm74110_mbox_chan *chan_priv = chan->con_priv; 491 492 chan_priv->en = true; 493 494 return 0; 495 } 496 497 static void bcm74110_mbox_chan_shutdown(struct mbox_chan *chan) 498 { 499 struct bcm74110_mbox_chan *chan_priv = chan->con_priv; 500 501 chan_priv->en = false; 502 } 503 504 static const struct mbox_chan_ops bcm74110_mbox_chan_ops = { 505 .send_data = bcm74110_mbox_send_data, 506 .startup = bcm74110_mbox_chan_startup, 507 .shutdown = bcm74110_mbox_chan_shutdown, 508 }; 509 510 static void bcm74110_mbox_shutdown(struct platform_device *pdev) 511 { 512 struct bcm74110_mbox *mbox = dev_get_drvdata(&pdev->dev); 513 u32 msg; 514 515 msg = bcm74110_mbox_create_msg(1, 0, BCM_MSG_SVC_INIT, 516 BCM_MSG_FUNC_LINK_STOP, 517 0, 0); 518 519 bcm74110_mbox_tx_msg_and_wait_ack(mbox, msg); 520 521 /* Even if we don't receive ACK, lets shut it down */ 522 523 bcm74110_mbox_mask_and_clear(mbox); 524 525 /* Disable queues tx/rx */ 526 bcm74110_tx_writel(mbox, 0x0, BCM_MBOX_CTRL); 527 528 /* Flush queues */ 529 bcm74110_rx_flush_msg(mbox); 530 } 531 532 static struct mbox_chan *bcm74110_mbox_of_xlate(struct mbox_controller *cntrl, 533 const struct of_phandle_args *p) 534 { 535 struct bcm74110_mbox *mbox = bcm74110_mbox_from_cntrl(cntrl); 536 struct device *dev = &mbox->pdev->dev; 537 struct bcm74110_mbox_chan *chan_priv; 538 int slot, type; 539 540 if (p->args_count != 2) { 541 dev_err(dev, "Invalid arguments\n"); 542 return ERR_PTR(-EINVAL); 543 } 544 545 type = p->args[0]; 546 slot = p->args[1]; 547 548 switch (type) { 549 case BCM_MSG_SVC_PMC: 550 case BCM_MSG_SVC_SCMI: 551 case BCM_MSG_SVC_DPFE: 552 if (slot > BCM_MBOX_HAB_MEM_IDX_SIZE) { 553 dev_err(dev, "Not enough shared memory\n"); 554 return ERR_PTR(-EINVAL); 555 } 556 chan_priv = cntrl->chans[type].con_priv; 557 chan_priv->slot = slot; 558 chan_priv->type = type; 559 break; 560 default: 561 dev_err(dev, "Invalid channel type: %d\n", type); 562 return ERR_PTR(-EINVAL); 563 } 564 565 return &cntrl->chans[type]; 566 } 567 568 static int bcm74110_mbox_probe(struct platform_device *pdev) 569 { 570 struct device *dev = &pdev->dev; 571 struct bcm74110_mbox *mbox; 572 int i, ret; 573 574 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); 575 if (!mbox) 576 return -ENOMEM; 577 578 mbox->pdev = pdev; 579 platform_set_drvdata(pdev, mbox); 580 581 mbox->base = devm_platform_ioremap_resource(pdev, 0); 582 if (IS_ERR(mbox->base)) 583 return dev_err_probe(dev, PTR_ERR(mbox->base), "Failed to iomap\n"); 584 585 ret = of_property_read_u32(dev->of_node, "brcm,tx", &mbox->tx_chan); 586 if (ret) 587 return dev_err_probe(dev, ret, "Failed to find tx channel\n"); 588 589 ret = of_property_read_u32(dev->of_node, "brcm,rx", &mbox->rx_chan); 590 if (ret) 591 return dev_err_probe(dev, ret, "Failed to find rx channel\n"); 592 593 mbox->rx_irq = platform_get_irq(pdev, 0); 594 if (mbox->rx_irq < 0) 595 return mbox->rx_irq; 596 597 INIT_LIST_HEAD(&mbox->rx_svc_init_list); 598 spin_lock_init(&mbox->rx_svc_list_lock); 599 bcm74110_mbox_mask_and_clear(mbox); 600 601 ret = devm_request_irq(dev, mbox->rx_irq, bcm74110_mbox_isr, 602 IRQF_NO_SUSPEND, pdev->name, mbox); 603 if (ret) 604 return dev_err_probe(dev, ret, "Failed to request irq\n"); 605 606 mbox->controller.ops = &bcm74110_mbox_chan_ops; 607 mbox->controller.dev = dev; 608 mbox->controller.num_chans = BCM_MSG_SVC_MAX; 609 mbox->controller.of_xlate = &bcm74110_mbox_of_xlate; 610 mbox->controller.chans = devm_kcalloc(dev, BCM_MSG_SVC_MAX, 611 sizeof(*mbox->controller.chans), 612 GFP_KERNEL); 613 if (!mbox->controller.chans) 614 return -ENOMEM; 615 616 mbox->mbox_chan = devm_kcalloc(dev, BCM_MSG_SVC_MAX, 617 sizeof(*mbox->mbox_chan), 618 GFP_KERNEL); 619 if (!mbox->mbox_chan) 620 return -ENOMEM; 621 622 for (i = 0; i < BCM_MSG_SVC_MAX; i++) { 623 mbox->mbox_chan[i].mbox = mbox; 624 mbox->controller.chans[i].con_priv = &mbox->mbox_chan[i]; 625 } 626 627 ret = devm_mbox_controller_register(dev, &mbox->controller); 628 if (ret) 629 return ret; 630 631 ret = bcm74110_mbox_init(mbox); 632 if (ret) 633 return ret; 634 635 return 0; 636 } 637 638 static const struct of_device_id bcm74110_mbox_of_match[] = { 639 { .compatible = "brcm,bcm74110-mbox", }, 640 { /* sentinel */ }, 641 }; 642 MODULE_DEVICE_TABLE(of, bcm74110_mbox_of_match); 643 644 static struct platform_driver bcm74110_mbox_driver = { 645 .driver = { 646 .name = "bcm74110-mbox", 647 .of_match_table = bcm74110_mbox_of_match, 648 }, 649 .probe = bcm74110_mbox_probe, 650 .shutdown = bcm74110_mbox_shutdown, 651 }; 652 module_platform_driver(bcm74110_mbox_driver); 653 654 MODULE_AUTHOR("Justin Chen <justin.chen@broadcom.com>"); 655 MODULE_DESCRIPTION("BCM74110 mailbox driver"); 656 MODULE_LICENSE("GPL"); 657