omap-mailbox.c 21.6 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2 3 4
/*
 * OMAP mailbox driver
 *
5
 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
6
 * Copyright (C) 2013-2016 Texas Instruments Incorporated - http://www.ti.com
7
 *
8
 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
9
 *          Suman Anna <s-anna@ti.com>
10 11 12
 */

#include <linux/interrupt.h>
13 14
#include <linux/spinlock.h>
#include <linux/mutex.h>
15
#include <linux/slab.h>
16 17
#include <linux/kfifo.h>
#include <linux/err.h>
18
#include <linux/module.h>
19
#include <linux/of_device.h>
20 21 22
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/omap-mailbox.h>
23 24
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h>
25

26 27
#include "mailbox.h"

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#define MAILBOX_REVISION		0x000
#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))

#define OMAP2_MAILBOX_IRQSTATUS(u)	(0x100 + 8 * (u))
#define OMAP2_MAILBOX_IRQENABLE(u)	(0x104 + 8 * (u))

#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))

#define MAILBOX_IRQSTATUS(type, u)	(type ? OMAP4_MAILBOX_IRQSTATUS(u) : \
						OMAP2_MAILBOX_IRQSTATUS(u))
#define MAILBOX_IRQENABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE(u) : \
						OMAP2_MAILBOX_IRQENABLE(u))
#define MAILBOX_IRQDISABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \
						: OMAP2_MAILBOX_IRQENABLE(u))

#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))

50 51 52 53
/* Interrupt register configuration types */
#define MBOX_INTR_CFG_TYPE1		0
#define MBOX_INTR_CFG_TYPE2		1

54 55 56 57 58 59 60
struct omap_mbox_fifo {
	unsigned long msg;
	unsigned long fifo_stat;
	unsigned long msg_stat;
	unsigned long irqenable;
	unsigned long irqstatus;
	unsigned long irqdisable;
61
	u32 intr_bit;
62 63 64 65 66 67 68 69 70 71
};

struct omap_mbox_queue {
	spinlock_t		lock;
	struct kfifo		fifo;
	struct work_struct	work;
	struct omap_mbox	*mbox;
	bool full;
};

72 73 74 75
struct omap_mbox_match_data {
	u32 intr_type;
};

76 77 78 79
struct omap_mbox_device {
	struct device *dev;
	struct mutex cfg_lock;
	void __iomem *mbox_base;
80
	u32 *irq_ctx;
81 82
	u32 num_users;
	u32 num_fifos;
83
	u32 intr_type;
84
	struct omap_mbox **mboxes;
85
	struct mbox_controller controller;
86 87 88
	struct list_head elem;
};

89 90 91 92 93 94 95 96 97 98
struct omap_mbox_fifo_info {
	int tx_id;
	int tx_usr;
	int tx_irq;

	int rx_id;
	int rx_usr;
	int rx_irq;

	const char *name;
99
	bool send_no_irq;
100 101
};

102 103 104
struct omap_mbox {
	const char		*name;
	int			irq;
105
	struct omap_mbox_queue	*rxq;
106
	struct device		*dev;
107
	struct omap_mbox_device *parent;
108 109 110
	struct omap_mbox_fifo	tx_fifo;
	struct omap_mbox_fifo	rx_fifo;
	u32			intr_type;
111
	struct mbox_chan	*chan;
112
	bool			send_no_irq;
113 114
};

115 116 117
/* global variables for the mailbox devices */
static DEFINE_MUTEX(omap_mbox_devices_lock);
static LIST_HEAD(omap_mbox_devices);
118

119 120 121 122
static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
module_param(mbox_kfifo_size, uint, S_IRUGO);
MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");

123 124 125 126 127 128 129 130
static struct omap_mbox *mbox_chan_to_omap_mbox(struct mbox_chan *chan)
{
	if (!chan || !chan->con_priv)
		return NULL;

	return (struct omap_mbox *)chan->con_priv;
}

131 132
static inline
unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
133
{
134
	return __raw_readl(mdev->mbox_base + ofs);
135 136
}

137 138
static inline
void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
139
{
140
	__raw_writel(val, mdev->mbox_base + ofs);
141 142
}

143
/* Mailbox FIFO handle functions */
144
static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
145
{
146
	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
147 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

155
	mbox_write_reg(mbox->parent, msg, fifo->msg);
156
}
157 158

static int mbox_fifo_empty(struct omap_mbox *mbox)
159
{
160
	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
161

162
	return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
163
}
164 165

static int mbox_fifo_full(struct omap_mbox *mbox)
166
{
167
	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
168

169
	return mbox_read_reg(mbox->parent, fifo->fifo_stat);
170 171 172
}

/* Mailbox IRQ handle functions */
173
static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
174
{
175 176 177 178
	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
				&mbox->tx_fifo : &mbox->rx_fifo;
	u32 bit = fifo->intr_bit;
	u32 irqstatus = fifo->irqstatus;
179

180
	mbox_write_reg(mbox->parent, bit, irqstatus);
181 182

	/* Flush posted write for irq status to avoid spurious interrupts */
183
	mbox_read_reg(mbox->parent, irqstatus);
184
}
185 186

static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
187
{
188 189 190 191 192 193
	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
				&mbox->tx_fifo : &mbox->rx_fifo;
	u32 bit = fifo->intr_bit;
	u32 irqenable = fifo->irqenable;
	u32 irqstatus = fifo->irqstatus;

194 195
	u32 enable = mbox_read_reg(mbox->parent, irqenable);
	u32 status = mbox_read_reg(mbox->parent, irqstatus);
196 197

	return (int)(enable & status & bit);
198 199
}

200
static void _omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
201
{
202 203 204 205 206
	u32 l;
	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
				&mbox->tx_fifo : &mbox->rx_fifo;
	u32 bit = fifo->intr_bit;
	u32 irqenable = fifo->irqenable;
207

208
	l = mbox_read_reg(mbox->parent, irqenable);
209
	l |= bit;
210
	mbox_write_reg(mbox->parent, l, irqenable);
211 212
}

213
static void _omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
214
{
215 216 217 218
	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
				&mbox->tx_fifo : &mbox->rx_fifo;
	u32 bit = fifo->intr_bit;
	u32 irqdisable = fifo->irqdisable;
219 220 221 222 223

	/*
	 * Read and update the interrupt configuration register for pre-OMAP4.
	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
	 */
224
	if (!mbox->intr_type)
225
		bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit;
226

227
	mbox_write_reg(mbox->parent, bit, irqdisable);
228 229
}

230
void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq)
231
{
232
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
233

234 235
	if (WARN_ON(!mbox))
		return;
236

237 238 239
	_omap_mbox_enable_irq(mbox, irq);
}
EXPORT_SYMBOL(omap_mbox_enable_irq);
240

241 242 243 244 245 246 247 248
void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq)
{
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);

	if (WARN_ON(!mbox))
		return;

	_omap_mbox_disable_irq(mbox, irq);
249
}
250
EXPORT_SYMBOL(omap_mbox_disable_irq);
251 252 253 254 255 256 257 258 259

/*
 * Message receiver(workqueue)
 */
static void mbox_rx_work(struct work_struct *work)
{
	struct omap_mbox_queue *mq =
			container_of(work, struct omap_mbox_queue, work);
	mbox_msg_t msg;
260 261 262 263 264
	int len;

	while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
		len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
		WARN_ON(len != sizeof(msg));
265

266
		mbox_chan_received_data(mq->mbox->chan, (void *)msg);
267 268 269
		spin_lock_irq(&mq->lock);
		if (mq->full) {
			mq->full = false;
270
			_omap_mbox_enable_irq(mq->mbox, IRQ_RX);
271 272
		}
		spin_unlock_irq(&mq->lock);
273 274 275 276 277 278 279 280
	}
}

/*
 * Mailbox interrupt handler
 */
static void __mbox_tx_interrupt(struct omap_mbox *mbox)
{
281
	_omap_mbox_disable_irq(mbox, IRQ_TX);
282
	ack_mbox_irq(mbox, IRQ_TX);
283
	mbox_chan_txdone(mbox->chan, 0);
284 285 286 287
}

static void __mbox_rx_interrupt(struct omap_mbox *mbox)
{
288
	struct omap_mbox_queue *mq = mbox->rxq;
289
	mbox_msg_t msg;
290
	int len;
291 292

	while (!mbox_fifo_empty(mbox)) {
293
		if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
294
			_omap_mbox_disable_irq(mbox, IRQ_RX);
295
			mq->full = true;
296
			goto nomem;
297
		}
298 299 300

		msg = mbox_fifo_read(mbox);

301 302
		len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
		WARN_ON(len != sizeof(msg));
303 304 305 306
	}

	/* no more messages in the fifo. clear IRQ source. */
	ack_mbox_irq(mbox, IRQ_RX);
307
nomem:
T
Tejun Heo 已提交
308
	schedule_work(&mbox->rxq->work);
309 310 311 312
}

static irqreturn_t mbox_interrupt(int irq, void *p)
{
313
	struct omap_mbox *mbox = p;
314 315 316 317 318 319 320 321 322 323 324

	if (is_mbox_irq(mbox, IRQ_TX))
		__mbox_tx_interrupt(mbox);

	if (is_mbox_irq(mbox, IRQ_RX))
		__mbox_rx_interrupt(mbox);

	return IRQ_HANDLED;
}

static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
325
					void (*work)(struct work_struct *))
326 327 328
{
	struct omap_mbox_queue *mq;

329 330 331
	if (!work)
		return NULL;

332
	mq = kzalloc(sizeof(*mq), GFP_KERNEL);
333 334 335 336 337
	if (!mq)
		return NULL;

	spin_lock_init(&mq->lock);

338
	if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
339 340
		goto error;

341
	INIT_WORK(&mq->work, work);
342
	return mq;
343

344 345 346 347 348 349 350
error:
	kfree(mq);
	return NULL;
}

static void mbox_queue_free(struct omap_mbox_queue *q)
{
351
	kfifo_free(&q->fifo);
352 353 354
	kfree(q);
}

355
static int omap_mbox_startup(struct omap_mbox *mbox)
356
{
357
	int ret = 0;
358 359
	struct omap_mbox_queue *mq;

360 361 362 363 364 365 366 367 368 369 370 371
	mq = mbox_queue_alloc(mbox, mbox_rx_work);
	if (!mq)
		return -ENOMEM;
	mbox->rxq = mq;
	mq->mbox = mbox;

	ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
			  mbox->name, mbox);
	if (unlikely(ret)) {
		pr_err("failed to register mailbox interrupt:%d\n", ret);
		goto fail_request_irq;
	}
372

373 374 375
	if (mbox->send_no_irq)
		mbox->chan->txdone_method = TXDONE_BY_ACK;

376
	_omap_mbox_enable_irq(mbox, IRQ_RX);
377

378 379
	return 0;

380 381
fail_request_irq:
	mbox_queue_free(mbox->rxq);
382 383 384 385 386
	return ret;
}

static void omap_mbox_fini(struct omap_mbox *mbox)
{
387 388 389 390
	_omap_mbox_disable_irq(mbox, IRQ_RX);
	free_irq(mbox->irq, mbox);
	flush_work(&mbox->rxq->work);
	mbox_queue_free(mbox->rxq);
391 392
}

393 394
static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
					       const char *mbox_name)
395
{
396
	struct omap_mbox *_mbox, *mbox = NULL;
397 398
	struct omap_mbox **mboxes = mdev->mboxes;
	int i;
399

400
	if (!mboxes)
401
		return NULL;
402

403
	for (i = 0; (_mbox = mboxes[i]); i++) {
404
		if (!strcmp(_mbox->name, mbox_name)) {
405
			mbox = _mbox;
406
			break;
407 408
		}
	}
409 410 411
	return mbox;
}

412 413
struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
					    const char *chan_name)
414
{
415
	struct device *dev = cl->dev;
416 417
	struct omap_mbox *mbox = NULL;
	struct omap_mbox_device *mdev;
418 419
	struct mbox_chan *chan;
	unsigned long flags;
420 421
	int ret;

422 423 424 425 426 427 428 429 430
	if (!dev)
		return ERR_PTR(-ENODEV);

	if (dev->of_node) {
		pr_err("%s: please use mbox_request_channel(), this API is supported only for OMAP non-DT usage\n",
		       __func__);
		return ERR_PTR(-ENODEV);
	}

431 432
	mutex_lock(&omap_mbox_devices_lock);
	list_for_each_entry(mdev, &omap_mbox_devices, elem) {
433
		mbox = omap_mbox_device_find(mdev, chan_name);
434 435 436 437
		if (mbox)
			break;
	}
	mutex_unlock(&omap_mbox_devices_lock);
438

439
	if (!mbox || !mbox->chan)
440
		return ERR_PTR(-ENOENT);
441

442 443 444 445 446 447 448 449
	chan = mbox->chan;
	spin_lock_irqsave(&chan->lock, flags);
	chan->msg_free = 0;
	chan->msg_count = 0;
	chan->active_req = NULL;
	chan->cl = cl;
	init_completion(&chan->tx_complete);
	spin_unlock_irqrestore(&chan->lock, flags);
450

451
	ret = chan->mbox->ops->startup(chan);
452
	if (ret) {
453 454 455
		pr_err("Unable to startup the chan (%d)\n", ret);
		mbox_free_channel(chan);
		chan = ERR_PTR(ret);
456 457
	}

458
	return chan;
459
}
460
EXPORT_SYMBOL(omap_mbox_request_channel);
461

462 463
static struct class omap_mbox_class = { .name = "mbox", };

464
static int omap_mbox_register(struct omap_mbox_device *mdev)
465
{
466 467
	int ret;
	int i;
468
	struct omap_mbox **mboxes;
469

470
	if (!mdev || !mdev->mboxes)
471 472
		return -EINVAL;

473
	mboxes = mdev->mboxes;
474 475
	for (i = 0; mboxes[i]; i++) {
		struct omap_mbox *mbox = mboxes[i];
476

477 478
		mbox->dev = device_create(&omap_mbox_class, mdev->dev,
					0, mbox, "%s", mbox->name);
479 480 481 482 483
		if (IS_ERR(mbox->dev)) {
			ret = PTR_ERR(mbox->dev);
			goto err_out;
		}
	}
484 485 486 487 488

	mutex_lock(&omap_mbox_devices_lock);
	list_add(&mdev->elem, &omap_mbox_devices);
	mutex_unlock(&omap_mbox_devices_lock);

489
	ret = mbox_controller_register(&mdev->controller);
490

491
err_out:
492 493 494 495
	if (ret) {
		while (i--)
			device_unregister(mboxes[i]->dev);
	}
496 497 498
	return ret;
}

499
static int omap_mbox_unregister(struct omap_mbox_device *mdev)
500
{
501
	int i;
502
	struct omap_mbox **mboxes;
503

504
	if (!mdev || !mdev->mboxes)
505 506
		return -EINVAL;

507 508 509 510
	mutex_lock(&omap_mbox_devices_lock);
	list_del(&mdev->elem);
	mutex_unlock(&omap_mbox_devices_lock);

511 512
	mbox_controller_unregister(&mdev->controller);

513
	mboxes = mdev->mboxes;
514 515 516
	for (i = 0; mboxes[i]; i++)
		device_unregister(mboxes[i]->dev);
	return 0;
517
}
518

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
static int omap_mbox_chan_startup(struct mbox_chan *chan)
{
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
	struct omap_mbox_device *mdev = mbox->parent;
	int ret = 0;

	mutex_lock(&mdev->cfg_lock);
	pm_runtime_get_sync(mdev->dev);
	ret = omap_mbox_startup(mbox);
	if (ret)
		pm_runtime_put_sync(mdev->dev);
	mutex_unlock(&mdev->cfg_lock);
	return ret;
}

static void omap_mbox_chan_shutdown(struct mbox_chan *chan)
{
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
	struct omap_mbox_device *mdev = mbox->parent;

	mutex_lock(&mdev->cfg_lock);
	omap_mbox_fini(mbox);
	pm_runtime_put_sync(mdev->dev);
	mutex_unlock(&mdev->cfg_lock);
}

545
static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data)
546 547 548
{
	int ret = -EBUSY;

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
	if (!mbox_fifo_full(mbox)) {
		_omap_mbox_enable_irq(mbox, IRQ_RX);
		mbox_fifo_write(mbox, (mbox_msg_t)data);
		ret = 0;
		_omap_mbox_disable_irq(mbox, IRQ_RX);

		/* we must read and ack the interrupt directly from here */
		mbox_fifo_read(mbox);
		ack_mbox_irq(mbox, IRQ_RX);
	}

	return ret;
}

static int omap_mbox_chan_send(struct omap_mbox *mbox, void *data)
{
	int ret = -EBUSY;
566 567 568 569 570 571 572 573 574 575 576

	if (!mbox_fifo_full(mbox)) {
		mbox_fifo_write(mbox, (mbox_msg_t)data);
		ret = 0;
	}

	/* always enable the interrupt */
	_omap_mbox_enable_irq(mbox, IRQ_TX);
	return ret;
}

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
{
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
	int ret;

	if (!mbox)
		return -EINVAL;

	if (mbox->send_no_irq)
		ret = omap_mbox_chan_send_noirq(mbox, data);
	else
		ret = omap_mbox_chan_send(mbox, data);

	return ret;
}

593
static const struct mbox_chan_ops omap_mbox_chan_ops = {
594 595 596 597 598
	.startup        = omap_mbox_chan_startup,
	.send_data      = omap_mbox_chan_send_data,
	.shutdown       = omap_mbox_chan_shutdown,
};

599 600 601 602
#ifdef CONFIG_PM_SLEEP
static int omap_mbox_suspend(struct device *dev)
{
	struct omap_mbox_device *mdev = dev_get_drvdata(dev);
603
	u32 usr, fifo, reg;
604 605 606 607

	if (pm_runtime_status_suspended(dev))
		return 0;

608 609 610 611 612 613 614 615
	for (fifo = 0; fifo < mdev->num_fifos; fifo++) {
		if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) {
			dev_err(mdev->dev, "fifo %d has unexpected unread messages\n",
				fifo);
			return -EBUSY;
		}
	}

616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
	for (usr = 0; usr < mdev->num_users; usr++) {
		reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
		mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg);
	}

	return 0;
}

static int omap_mbox_resume(struct device *dev)
{
	struct omap_mbox_device *mdev = dev_get_drvdata(dev);
	u32 usr, reg;

	if (pm_runtime_status_suspended(dev))
		return 0;

	for (usr = 0; usr < mdev->num_users; usr++) {
		reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
		mbox_write_reg(mdev, mdev->irq_ctx[usr], reg);
	}

	return 0;
}
#endif

static const struct dev_pm_ops omap_mbox_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume)
};

645 646 647
static const struct omap_mbox_match_data omap2_data = { MBOX_INTR_CFG_TYPE1 };
static const struct omap_mbox_match_data omap4_data = { MBOX_INTR_CFG_TYPE2 };

648 649 650
static const struct of_device_id omap_mailbox_of_match[] = {
	{
		.compatible	= "ti,omap2-mailbox",
651
		.data		= &omap2_data,
652 653 654
	},
	{
		.compatible	= "ti,omap3-mailbox",
655
		.data		= &omap2_data,
656 657 658
	},
	{
		.compatible	= "ti,omap4-mailbox",
659
		.data		= &omap4_data,
660 661 662 663 664 665 666
	},
	{
		/* end */
	},
};
MODULE_DEVICE_TABLE(of, omap_mailbox_of_match);

667 668 669 670 671 672 673 674 675 676
static struct mbox_chan *omap_mbox_of_xlate(struct mbox_controller *controller,
					    const struct of_phandle_args *sp)
{
	phandle phandle = sp->args[0];
	struct device_node *node;
	struct omap_mbox_device *mdev;
	struct omap_mbox *mbox;

	mdev = container_of(controller, struct omap_mbox_device, controller);
	if (WARN_ON(!mdev))
677
		return ERR_PTR(-EINVAL);
678 679 680 681 682

	node = of_find_node_by_phandle(phandle);
	if (!node) {
		pr_err("%s: could not find node phandle 0x%x\n",
		       __func__, phandle);
683
		return ERR_PTR(-ENODEV);
684 685 686 687
	}

	mbox = omap_mbox_device_find(mdev, node->name);
	of_node_put(node);
688
	return mbox ? mbox->chan : ERR_PTR(-ENOENT);
689 690
}

691 692 693 694
static int omap_mbox_probe(struct platform_device *pdev)
{
	struct resource *mem;
	int ret;
695
	struct mbox_chan *chnls;
696
	struct omap_mbox **list, *mbox, *mboxblk;
697
	struct omap_mbox_fifo_info *finfo, *finfoblk;
698
	struct omap_mbox_device *mdev;
699
	struct omap_mbox_fifo *fifo;
700 701
	struct device_node *node = pdev->dev.of_node;
	struct device_node *child;
702
	const struct omap_mbox_match_data *match_data;
703 704 705
	u32 intr_type, info_count;
	u32 num_users, num_fifos;
	u32 tmp[3];
706 707 708
	u32 l;
	int i;

709 710
	if (!node) {
		pr_err("%s: only DT-based devices are supported\n", __func__);
711 712 713
		return -ENODEV;
	}

714 715
	match_data = of_device_get_match_data(&pdev->dev);
	if (!match_data)
716
		return -ENODEV;
717
	intr_type = match_data->intr_type;
718

719 720
	if (of_property_read_u32(node, "ti,mbox-num-users", &num_users))
		return -ENODEV;
721

722 723
	if (of_property_read_u32(node, "ti,mbox-num-fifos", &num_fifos))
		return -ENODEV;
724

725 726 727 728
	info_count = of_get_available_child_count(node);
	if (!info_count) {
		dev_err(&pdev->dev, "no available mbox devices found\n");
		return -ENODEV;
729 730
	}

731
	finfoblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*finfoblk),
732 733 734 735 736 737 738
				GFP_KERNEL);
	if (!finfoblk)
		return -ENOMEM;

	finfo = finfoblk;
	child = NULL;
	for (i = 0; i < info_count; i++, finfo++) {
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
		child = of_get_next_available_child(node, child);
		ret = of_property_read_u32_array(child, "ti,mbox-tx", tmp,
						 ARRAY_SIZE(tmp));
		if (ret)
			return ret;
		finfo->tx_id = tmp[0];
		finfo->tx_irq = tmp[1];
		finfo->tx_usr = tmp[2];

		ret = of_property_read_u32_array(child, "ti,mbox-rx", tmp,
						 ARRAY_SIZE(tmp));
		if (ret)
			return ret;
		finfo->rx_id = tmp[0];
		finfo->rx_irq = tmp[1];
		finfo->rx_usr = tmp[2];

		finfo->name = child->name;

		if (of_find_property(child, "ti,mbox-send-noirq", NULL))
			finfo->send_no_irq = true;

761 762 763 764 765
		if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos ||
		    finfo->tx_usr >= num_users || finfo->rx_usr >= num_users)
			return -EINVAL;
	}

766 767 768 769 770 771 772 773 774
	mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
	if (!mdev)
		return -ENOMEM;

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem);
	if (IS_ERR(mdev->mbox_base))
		return PTR_ERR(mdev->mbox_base);

775
	mdev->irq_ctx = devm_kcalloc(&pdev->dev, num_users, sizeof(u32),
776 777 778 779
				     GFP_KERNEL);
	if (!mdev->irq_ctx)
		return -ENOMEM;

780
	/* allocate one extra for marking end of list */
781
	list = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*list),
782 783 784 785
			    GFP_KERNEL);
	if (!list)
		return -ENOMEM;

786
	chnls = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*chnls),
787 788 789 790
			     GFP_KERNEL);
	if (!chnls)
		return -ENOMEM;

791
	mboxblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*mbox),
792 793 794 795 796
			       GFP_KERNEL);
	if (!mboxblk)
		return -ENOMEM;

	mbox = mboxblk;
797 798
	finfo = finfoblk;
	for (i = 0; i < info_count; i++, finfo++) {
799
		fifo = &mbox->tx_fifo;
800 801 802 803 804 805
		fifo->msg = MAILBOX_MESSAGE(finfo->tx_id);
		fifo->fifo_stat = MAILBOX_FIFOSTATUS(finfo->tx_id);
		fifo->intr_bit = MAILBOX_IRQ_NOTFULL(finfo->tx_id);
		fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->tx_usr);
		fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->tx_usr);
		fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->tx_usr);
806 807

		fifo = &mbox->rx_fifo;
808 809 810 811 812 813
		fifo->msg = MAILBOX_MESSAGE(finfo->rx_id);
		fifo->msg_stat =  MAILBOX_MSGSTATUS(finfo->rx_id);
		fifo->intr_bit = MAILBOX_IRQ_NEWMSG(finfo->rx_id);
		fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->rx_usr);
		fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr);
		fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr);
814

815
		mbox->send_no_irq = finfo->send_no_irq;
816 817
		mbox->intr_type = intr_type;

818
		mbox->parent = mdev;
819 820
		mbox->name = finfo->name;
		mbox->irq = platform_get_irq(pdev, finfo->tx_irq);
821 822
		if (mbox->irq < 0)
			return mbox->irq;
823 824
		mbox->chan = &chnls[i];
		chnls[i].con_priv = mbox;
825 826 827
		list[i] = mbox++;
	}

828 829
	mutex_init(&mdev->cfg_lock);
	mdev->dev = &pdev->dev;
830 831
	mdev->num_users = num_users;
	mdev->num_fifos = num_fifos;
832
	mdev->intr_type = intr_type;
833
	mdev->mboxes = list;
834 835 836 837 838 839 840 841

	/* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
	mdev->controller.txdone_irq = true;
	mdev->controller.dev = mdev->dev;
	mdev->controller.ops = &omap_mbox_chan_ops;
	mdev->controller.chans = chnls;
	mdev->controller.num_chans = info_count;
	mdev->controller.of_xlate = omap_mbox_of_xlate;
842
	ret = omap_mbox_register(mdev);
843 844 845
	if (ret)
		return ret;

846 847
	platform_set_drvdata(pdev, mdev);
	pm_runtime_enable(mdev->dev);
848

849
	ret = pm_runtime_get_sync(mdev->dev);
850
	if (ret < 0) {
851
		pm_runtime_put_noidle(mdev->dev);
852 853 854 855 856 857 858
		goto unregister;
	}

	/*
	 * just print the raw revision register, the format is not
	 * uniform across all SoCs
	 */
859 860
	l = mbox_read_reg(mdev, MAILBOX_REVISION);
	dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l);
861

862
	ret = pm_runtime_put_sync(mdev->dev);
863 864 865
	if (ret < 0)
		goto unregister;

866
	devm_kfree(&pdev->dev, finfoblk);
867 868 869
	return 0;

unregister:
870 871
	pm_runtime_disable(mdev->dev);
	omap_mbox_unregister(mdev);
872 873 874 875 876
	return ret;
}

static int omap_mbox_remove(struct platform_device *pdev)
{
877 878 879 880
	struct omap_mbox_device *mdev = platform_get_drvdata(pdev);

	pm_runtime_disable(mdev->dev);
	omap_mbox_unregister(mdev);
881 882 883 884 885 886 887 888 889

	return 0;
}

static struct platform_driver omap_mbox_driver = {
	.probe	= omap_mbox_probe,
	.remove	= omap_mbox_remove,
	.driver	= {
		.name = "omap-mailbox",
890
		.pm = &omap_mbox_pm_ops,
891
		.of_match_table = of_match_ptr(omap_mailbox_of_match),
892 893
	},
};
894

895
static int __init omap_mbox_init(void)
896
{
897 898 899 900 901 902
	int err;

	err = class_register(&omap_mbox_class);
	if (err)
		return err;

903 904
	/* kfifo size sanity check: alignment and minimal size */
	mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
905 906
	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
							sizeof(mbox_msg_t));
907

A
Arvind Yadav 已提交
908 909 910 911 912
	err = platform_driver_register(&omap_mbox_driver);
	if (err)
		class_unregister(&omap_mbox_class);

	return err;
913
}
914
subsys_initcall(omap_mbox_init);
915

916
static void __exit omap_mbox_exit(void)
917
{
918
	platform_driver_unregister(&omap_mbox_driver);
919
	class_unregister(&omap_mbox_class);
920
}
921
module_exit(omap_mbox_exit);
922

923 924
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
925 926
MODULE_AUTHOR("Toshihiro Kobayashi");
MODULE_AUTHOR("Hiroshi DOYU");