2 * Copyright (C) ST-Ericsson SA 2010
3 * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
4 * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
5 * License terms: GNU General Public License (GPL), version 2.
9 * Mailbox nomenclature:
13 * ..........................
26 * .........................
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/device.h>
32 #include <linux/interrupt.h>
33 #include <linux/spinlock.h>
34 #include <linux/errno.h>
36 #include <linux/irq.h>
37 #include <linux/platform_device.h>
38 #include <linux/debugfs.h>
39 #include <linux/seq_file.h>
40 #include <linux/completion.h>
41 #include <mach/mbox-db5500.h>
43 #define MBOX_NAME "mbox"
45 #define MBOX_FIFO_DATA 0x000
46 #define MBOX_FIFO_ADD 0x004
47 #define MBOX_FIFO_REMOVE 0x008
48 #define MBOX_FIFO_THRES_FREE 0x00C
49 #define MBOX_FIFO_THRES_OCCUP 0x010
50 #define MBOX_FIFO_STATUS 0x014
52 #define MBOX_DISABLE_IRQ 0x4
53 #define MBOX_ENABLE_IRQ 0x0
56 /* Global list of all mailboxes */
57 static struct list_head mboxs
= LIST_HEAD_INIT(mboxs
);
59 static struct mbox
*get_mbox_with_id(u8 id
)
62 struct list_head
*pos
= &mboxs
;
63 for (i
= 0; i
<= id
; i
++)
66 return (struct mbox
*) list_entry(pos
, struct mbox
, list
);
69 int mbox_send(struct mbox
*mbox
, u32 mbox_msg
, bool block
)
73 spin_lock(&mbox
->lock
);
75 dev_dbg(&(mbox
->pdev
->dev
),
76 "About to buffer 0x%X to mailbox 0x%X."
77 " ri = %d, wi = %d\n",
78 mbox_msg
, (u32
)mbox
, mbox
->read_index
,
81 /* Check if write buffer is full */
82 while (((mbox
->write_index
+ 1) % MBOX_BUF_SIZE
) == mbox
->read_index
) {
84 dev_dbg(&(mbox
->pdev
->dev
),
85 "Buffer full in non-blocking call! "
86 "Returning -ENOMEM!\n");
90 spin_unlock(&mbox
->lock
);
91 dev_dbg(&(mbox
->pdev
->dev
),
92 "Buffer full in blocking call! Sleeping...\n");
93 mbox
->client_blocked
= 1;
94 wait_for_completion(&mbox
->buffer_available
);
95 dev_dbg(&(mbox
->pdev
->dev
),
96 "Blocking send was woken up! Trying again...\n");
97 spin_lock(&mbox
->lock
);
100 mbox
->buffer
[mbox
->write_index
] = mbox_msg
;
101 mbox
->write_index
= (mbox
->write_index
+ 1) % MBOX_BUF_SIZE
;
104 * Indicate that we want an IRQ as soon as there is a slot
107 writel(MBOX_ENABLE_IRQ
, mbox
->virtbase_peer
+ MBOX_FIFO_THRES_FREE
);
110 spin_unlock(&mbox
->lock
);
113 EXPORT_SYMBOL(mbox_send
);
115 #if defined(CONFIG_DEBUG_FS)
117 * Expected input: <value> <nbr sends>
118 * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
120 static ssize_t
mbox_write_fifo(struct device
*dev
,
121 struct device_attribute
*attr
,
125 unsigned long mbox_mess
;
126 unsigned long nbr_sends
;
132 struct mbox
*mbox
= (struct mbox
*) dev
->platform_data
;
134 strncpy((char *) &int_buf
, buf
, sizeof(int_buf
));
135 token
= (char *) &int_buf
;
138 val
= strsep(&token
, " ");
139 if ((val
== NULL
) || (strict_strtoul(val
, 16, &mbox_mess
) != 0))
140 mbox_mess
= 0xDEADBEEF;
142 val
= strsep(&token
, " ");
143 if ((val
== NULL
) || (strict_strtoul(val
, 10, &nbr_sends
) != 0))
146 dev_dbg(dev
, "Will write 0x%lX %ld times using data struct at 0x%X\n",
147 mbox_mess
, nbr_sends
, (u32
) mbox
);
149 for (i
= 0; i
< nbr_sends
; i
++)
150 mbox_send(mbox
, mbox_mess
, true);
155 static ssize_t
mbox_read_fifo(struct device
*dev
,
156 struct device_attribute
*attr
,
160 struct mbox
*mbox
= (struct mbox
*) dev
->platform_data
;
162 if ((readl(mbox
->virtbase_local
+ MBOX_FIFO_STATUS
) & 0x7) <= 0)
163 return sprintf(buf
, "Mailbox is empty\n");
165 mbox_value
= readl(mbox
->virtbase_local
+ MBOX_FIFO_DATA
);
166 writel(MBOX_LATCH
, (mbox
->virtbase_local
+ MBOX_FIFO_REMOVE
));
168 return sprintf(buf
, "0x%X\n", mbox_value
);
171 static DEVICE_ATTR(fifo
, S_IWUGO
| S_IRUGO
, mbox_read_fifo
, mbox_write_fifo
);
173 static int mbox_show(struct seq_file
*s
, void *data
)
175 struct list_head
*pos
;
178 list_for_each(pos
, &mboxs
) {
180 (struct mbox
*) list_entry(pos
, struct mbox
, list
);
183 "Unable to retrieve mailbox %d\n",
189 if ((m
->virtbase_peer
== NULL
) || (m
->virtbase_local
== NULL
)) {
190 seq_printf(s
, "MAILBOX %d not setup or corrupt\n",
192 spin_unlock(&m
->lock
);
197 "===========================\n"
199 " PEER MAILBOX DUMP\n"
200 "---------------------------\n"
202 "Free Threshold: 0x%.2X (%d)\n"
203 "Occupied Threshold: 0x%.2X (%d)\n"
204 "Status: 0x%.2X (%d)\n"
205 " Free spaces (ot): %d (%d)\n"
206 " Occup spaces (ot): %d (%d)\n"
207 "===========================\n"
208 " LOCAL MAILBOX DUMP\n"
209 "---------------------------\n"
211 "Free Threshold: 0x%.2X (%d)\n"
212 "Occupied Threshold: 0x%.2X (%d)\n"
213 "Status: 0x%.2X (%d)\n"
214 " Free spaces (ot): %d (%d)\n"
215 " Occup spaces (ot): %d (%d)\n"
216 "===========================\n"
219 "===========================\n"
222 readl(m
->virtbase_peer
+ MBOX_FIFO_DATA
),
223 readl(m
->virtbase_peer
+ MBOX_FIFO_DATA
),
224 readl(m
->virtbase_peer
+ MBOX_FIFO_THRES_FREE
),
225 readl(m
->virtbase_peer
+ MBOX_FIFO_THRES_FREE
),
226 readl(m
->virtbase_peer
+ MBOX_FIFO_THRES_OCCUP
),
227 readl(m
->virtbase_peer
+ MBOX_FIFO_THRES_OCCUP
),
228 readl(m
->virtbase_peer
+ MBOX_FIFO_STATUS
),
229 readl(m
->virtbase_peer
+ MBOX_FIFO_STATUS
),
230 (readl(m
->virtbase_peer
+ MBOX_FIFO_STATUS
) >> 4) & 0x7,
231 (readl(m
->virtbase_peer
+ MBOX_FIFO_STATUS
) >> 7) & 0x1,
232 (readl(m
->virtbase_peer
+ MBOX_FIFO_STATUS
) >> 0) & 0x7,
233 (readl(m
->virtbase_peer
+ MBOX_FIFO_STATUS
) >> 3) & 0x1,
234 readl(m
->virtbase_local
+ MBOX_FIFO_DATA
),
235 readl(m
->virtbase_local
+ MBOX_FIFO_DATA
),
236 readl(m
->virtbase_local
+ MBOX_FIFO_THRES_FREE
),
237 readl(m
->virtbase_local
+ MBOX_FIFO_THRES_FREE
),
238 readl(m
->virtbase_local
+ MBOX_FIFO_THRES_OCCUP
),
239 readl(m
->virtbase_local
+ MBOX_FIFO_THRES_OCCUP
),
240 readl(m
->virtbase_local
+ MBOX_FIFO_STATUS
),
241 readl(m
->virtbase_local
+ MBOX_FIFO_STATUS
),
242 (readl(m
->virtbase_local
+ MBOX_FIFO_STATUS
) >> 4) & 0x7,
243 (readl(m
->virtbase_local
+ MBOX_FIFO_STATUS
) >> 7) & 0x1,
244 (readl(m
->virtbase_local
+ MBOX_FIFO_STATUS
) >> 0) & 0x7,
245 (readl(m
->virtbase_local
+ MBOX_FIFO_STATUS
) >> 3) & 0x1,
246 m
->write_index
, m
->read_index
);
248 spin_unlock(&m
->lock
);
254 static int mbox_open(struct inode
*inode
, struct file
*file
)
256 return single_open(file
, mbox_show
, NULL
);
259 static const struct file_operations mbox_operations
= {
260 .owner
= THIS_MODULE
,
264 .release
= single_release
,
268 static irqreturn_t
mbox_irq(int irq
, void *arg
)
273 struct mbox
*mbox
= (struct mbox
*) arg
;
275 spin_lock(&mbox
->lock
);
277 dev_dbg(&(mbox
->pdev
->dev
),
278 "mbox IRQ [%d] received. ri = %d, wi = %d\n",
279 irq
, mbox
->read_index
, mbox
->write_index
);
282 * Check if we have any outgoing messages, and if there is space for
285 if (mbox
->read_index
!= mbox
->write_index
) {
287 * Check by reading FREE for LOCAL since that indicates
290 nbr_free
= (readl(mbox
->virtbase_local
+ MBOX_FIFO_STATUS
)
292 dev_dbg(&(mbox
->pdev
->dev
),
293 "Status indicates %d empty spaces in the FIFO!\n",
296 while ((nbr_free
> 0) &&
297 (mbox
->read_index
!= mbox
->write_index
)) {
298 /* Write the message and latch it into the FIFO */
299 writel(mbox
->buffer
[mbox
->read_index
],
300 (mbox
->virtbase_peer
+ MBOX_FIFO_DATA
));
302 (mbox
->virtbase_peer
+ MBOX_FIFO_ADD
));
303 dev_dbg(&(mbox
->pdev
->dev
),
304 "Wrote message 0x%X to addr 0x%X\n",
305 mbox
->buffer
[mbox
->read_index
],
306 (u32
) (mbox
->virtbase_peer
+ MBOX_FIFO_DATA
));
310 (mbox
->read_index
+ 1) % MBOX_BUF_SIZE
;
314 * Check if we still want IRQ:s when there is free
317 if (mbox
->read_index
!= mbox
->write_index
) {
318 dev_dbg(&(mbox
->pdev
->dev
),
319 "Still have messages to send, but FIFO full. "
320 "Request IRQ again!\n");
321 writel(MBOX_ENABLE_IRQ
,
322 mbox
->virtbase_peer
+ MBOX_FIFO_THRES_FREE
);
324 dev_dbg(&(mbox
->pdev
->dev
),
325 "No more messages to send. "
326 "Do not request IRQ again!\n");
327 writel(MBOX_DISABLE_IRQ
,
328 mbox
->virtbase_peer
+ MBOX_FIFO_THRES_FREE
);
332 * Check if we can signal any blocked clients that it is OK to
333 * start buffering again
335 if (mbox
->client_blocked
&&
336 (((mbox
->write_index
+ 1) % MBOX_BUF_SIZE
)
337 != mbox
->read_index
)) {
338 dev_dbg(&(mbox
->pdev
->dev
),
339 "Waking up blocked client\n");
340 complete(&mbox
->buffer_available
);
341 mbox
->client_blocked
= 0;
345 /* Check if we have any incoming messages */
346 nbr_occup
= readl(mbox
->virtbase_local
+ MBOX_FIFO_STATUS
) & 0x7;
350 if (mbox
->cb
== NULL
) {
351 dev_dbg(&(mbox
->pdev
->dev
), "No receive callback registered, "
352 "leaving %d incoming messages in fifo!\n", nbr_occup
);
356 /* Read and acknowledge the message */
357 mbox_value
= readl(mbox
->virtbase_local
+ MBOX_FIFO_DATA
);
358 writel(MBOX_LATCH
, (mbox
->virtbase_local
+ MBOX_FIFO_REMOVE
));
360 /* Notify consumer of new mailbox message */
361 dev_dbg(&(mbox
->pdev
->dev
), "Calling callback for message 0x%X!\n",
363 mbox
->cb(mbox_value
, mbox
->client_data
);
366 dev_dbg(&(mbox
->pdev
->dev
), "Exit mbox IRQ. ri = %d, wi = %d\n",
367 mbox
->read_index
, mbox
->write_index
);
368 spin_unlock(&mbox
->lock
);
373 /* Setup is executed once for each mbox pair */
374 struct mbox
*mbox_setup(u8 mbox_id
, mbox_recv_cb_t
*mbox_cb
, void *priv
)
376 struct resource
*resource
;
381 mbox
= get_mbox_with_id(mbox_id
);
383 dev_err(&(mbox
->pdev
->dev
), "Incorrect mailbox id: %d!\n",
389 * Check if mailbox has been allocated to someone else,
390 * otherwise allocate it
392 if (mbox
->allocated
) {
393 dev_err(&(mbox
->pdev
->dev
), "Mailbox number %d is busy!\n",
398 mbox
->allocated
= true;
400 dev_dbg(&(mbox
->pdev
->dev
), "Initiating mailbox number %d: 0x%X...\n",
403 mbox
->client_data
= priv
;
406 /* Get addr for peer mailbox and ioremap it */
407 resource
= platform_get_resource_byname(mbox
->pdev
,
410 if (resource
== NULL
) {
411 dev_err(&(mbox
->pdev
->dev
),
412 "Unable to retrieve mbox peer resource\n");
416 dev_dbg(&(mbox
->pdev
->dev
),
417 "Resource name: %s start: 0x%X, end: 0x%X\n",
418 resource
->name
, resource
->start
, resource
->end
);
419 mbox
->virtbase_peer
= ioremap(resource
->start
, resource_size(resource
));
420 if (!mbox
->virtbase_peer
) {
421 dev_err(&(mbox
->pdev
->dev
), "Unable to ioremap peer mbox\n");
425 dev_dbg(&(mbox
->pdev
->dev
),
426 "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
427 resource
->start
, resource
->end
, (u32
) mbox
->virtbase_peer
);
429 /* Get addr for local mailbox and ioremap it */
430 resource
= platform_get_resource_byname(mbox
->pdev
,
433 if (resource
== NULL
) {
434 dev_err(&(mbox
->pdev
->dev
),
435 "Unable to retrieve mbox local resource\n");
439 dev_dbg(&(mbox
->pdev
->dev
),
440 "Resource name: %s start: 0x%X, end: 0x%X\n",
441 resource
->name
, resource
->start
, resource
->end
);
442 mbox
->virtbase_local
= ioremap(resource
->start
, resource_size(resource
));
443 if (!mbox
->virtbase_local
) {
444 dev_err(&(mbox
->pdev
->dev
), "Unable to ioremap local mbox\n");
448 dev_dbg(&(mbox
->pdev
->dev
),
449 "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
450 resource
->start
, resource
->end
, (u32
) mbox
->virtbase_peer
);
452 init_completion(&mbox
->buffer_available
);
453 mbox
->client_blocked
= 0;
455 /* Get IRQ for mailbox and allocate it */
456 irq
= platform_get_irq_byname(mbox
->pdev
, "mbox_irq");
458 dev_err(&(mbox
->pdev
->dev
),
459 "Unable to retrieve mbox irq resource\n");
464 dev_dbg(&(mbox
->pdev
->dev
), "Allocating irq %d...\n", irq
);
465 res
= request_irq(irq
, mbox_irq
, 0, mbox
->name
, (void *) mbox
);
467 dev_err(&(mbox
->pdev
->dev
),
468 "Unable to allocate mbox irq %d\n", irq
);
473 /* Set up mailbox to not launch IRQ on free space in mailbox */
474 writel(MBOX_DISABLE_IRQ
, mbox
->virtbase_peer
+ MBOX_FIFO_THRES_FREE
);
477 * Set up mailbox to launch IRQ on new message if we have
478 * a callback set. If not, do not raise IRQ, but keep message
479 * in FIFO for manual retrieval
482 writel(MBOX_ENABLE_IRQ
,
483 mbox
->virtbase_local
+ MBOX_FIFO_THRES_OCCUP
);
485 writel(MBOX_DISABLE_IRQ
,
486 mbox
->virtbase_local
+ MBOX_FIFO_THRES_OCCUP
);
488 #if defined(CONFIG_DEBUG_FS)
489 res
= device_create_file(&(mbox
->pdev
->dev
), &dev_attr_fifo
);
491 dev_warn(&(mbox
->pdev
->dev
),
492 "Unable to create mbox sysfs entry");
494 (void) debugfs_create_file("mbox", S_IFREG
| S_IRUGO
, NULL
,
495 NULL
, &mbox_operations
);
498 dev_info(&(mbox
->pdev
->dev
),
499 "Mailbox driver with index %d initiated!\n", mbox_id
);
504 EXPORT_SYMBOL(mbox_setup
);
507 int __init
mbox_probe(struct platform_device
*pdev
)
509 struct mbox local_mbox
;
512 dev_dbg(&(pdev
->dev
), "Probing mailbox (pdev = 0x%X)...\n", (u32
) pdev
);
514 memset(&local_mbox
, 0x0, sizeof(struct mbox
));
516 /* Associate our mbox data with the platform device */
517 res
= platform_device_add_data(pdev
,
518 (void *) &local_mbox
,
519 sizeof(struct mbox
));
521 dev_err(&(pdev
->dev
),
522 "Unable to allocate driver platform data!\n");
526 mbox
= (struct mbox
*) pdev
->dev
.platform_data
;
528 mbox
->write_index
= 0;
529 mbox
->read_index
= 0;
531 INIT_LIST_HEAD(&(mbox
->list
));
532 list_add_tail(&(mbox
->list
), &mboxs
);
534 sprintf(mbox
->name
, "%s", MBOX_NAME
);
535 spin_lock_init(&mbox
->lock
);
537 dev_info(&(pdev
->dev
), "Mailbox driver loaded\n");
543 static struct platform_driver mbox_driver
= {
546 .owner
= THIS_MODULE
,
550 static int __init
mbox_init(void)
552 return platform_driver_probe(&mbox_driver
, mbox_probe
);
555 module_init(mbox_init
);
557 void __exit
mbox_exit(void)
559 platform_driver_unregister(&mbox_driver
);
562 module_exit(mbox_exit
);
564 MODULE_LICENSE("GPL");
565 MODULE_DESCRIPTION("MBOX driver");