mbox-db5500.c Change initate to initiate.
[linux-2.6.git] / arch / arm / mach-ux500 / mbox-db5500.c
1 /*
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.
6  */
7
8 /*
9  * Mailbox nomenclature:
10  *
11  *       APE           MODEM
12  *           mbox pairX
13  *   ..........................
14  *   .                       .
15  *   .           peer        .
16  *   .     send  ----        .
17  *   .      -->  |  |        .
18  *   .           |  |        .
19  *   .           ----        .
20  *   .                       .
21  *   .           local       .
22  *   .     rec   ----        .
23  *   .           |  | <--    .
24  *   .           |  |        .
25  *   .           ----        .
26  *   .........................
27  */
28
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>
35 #include <linux/io.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>
42
43 #define MBOX_NAME "mbox"
44
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
51
52 #define MBOX_DISABLE_IRQ 0x4
53 #define MBOX_ENABLE_IRQ  0x0
54 #define MBOX_LATCH 1
55
56 /* Global list of all mailboxes */
57 static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
58
59 static struct mbox *get_mbox_with_id(u8 id)
60 {
61         u8 i;
62         struct list_head *pos = &mboxs;
63         for (i = 0; i <= id; i++)
64                 pos = pos->next;
65
66         return (struct mbox *) list_entry(pos, struct mbox, list);
67 }
68
69 int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
70 {
71         int res = 0;
72
73         spin_lock(&mbox->lock);
74
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,
79                 mbox->write_index);
80
81         /* Check if write buffer is full */
82         while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
83                 if (!block) {
84                         dev_dbg(&(mbox->pdev->dev),
85                         "Buffer full in non-blocking call! "
86                         "Returning -ENOMEM!\n");
87                         res = -ENOMEM;
88                         goto exit;
89                 }
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);
98         }
99
100         mbox->buffer[mbox->write_index] = mbox_msg;
101         mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
102
103         /*
104          * Indicate that we want an IRQ as soon as there is a slot
105          * in the FIFO
106          */
107         writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
108
109 exit:
110         spin_unlock(&mbox->lock);
111         return res;
112 }
113 EXPORT_SYMBOL(mbox_send);
114
115 #if defined(CONFIG_DEBUG_FS)
116 /*
117  * Expected input: <value> <nbr sends>
118  * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
119  */
120 static ssize_t mbox_write_fifo(struct device *dev,
121                                struct device_attribute *attr,
122                                const char *buf,
123                                size_t count)
124 {
125         unsigned long mbox_mess;
126         unsigned long nbr_sends;
127         unsigned long i;
128         char int_buf[16];
129         char *token;
130         char *val;
131
132         struct mbox *mbox = (struct mbox *) dev->platform_data;
133
134         strncpy((char *) &int_buf, buf, sizeof(int_buf));
135         token = (char *) &int_buf;
136
137         /* Parse message */
138         val = strsep(&token, " ");
139         if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
140                 mbox_mess = 0xDEADBEEF;
141
142         val = strsep(&token, " ");
143         if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
144                 nbr_sends = 1;
145
146         dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
147                 mbox_mess, nbr_sends, (u32) mbox);
148
149         for (i = 0; i < nbr_sends; i++)
150                 mbox_send(mbox, mbox_mess, true);
151
152         return count;
153 }
154
155 static ssize_t mbox_read_fifo(struct device *dev,
156                               struct device_attribute *attr,
157                               char *buf)
158 {
159         int mbox_value;
160         struct mbox *mbox = (struct mbox *) dev->platform_data;
161
162         if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
163                 return sprintf(buf, "Mailbox is empty\n");
164
165         mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
166         writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
167
168         return sprintf(buf, "0x%X\n", mbox_value);
169 }
170
171 static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
172
173 static int mbox_show(struct seq_file *s, void *data)
174 {
175         struct list_head *pos;
176         u8 mbox_index = 0;
177
178         list_for_each(pos, &mboxs) {
179                 struct mbox *m =
180                         (struct mbox *) list_entry(pos, struct mbox, list);
181                 if (m == NULL) {
182                         seq_printf(s,
183                                    "Unable to retrieve mailbox %d\n",
184                                    mbox_index);
185                         continue;
186                 }
187
188                 spin_lock(&m->lock);
189                 if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
190                         seq_printf(s, "MAILBOX %d not setup or corrupt\n",
191                                    mbox_index);
192                         spin_unlock(&m->lock);
193                         continue;
194                 }
195
196                 seq_printf(s,
197                 "===========================\n"
198                 " MAILBOX %d\n"
199                 " PEER MAILBOX DUMP\n"
200                 "---------------------------\n"
201                 "FIFO:                 0x%X (%d)\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"
210                 "FIFO:                 0x%.X (%d)\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"
217                 "write_index: %d\n"
218                 "read_index : %d\n"
219                 "===========================\n"
220                 "\n",
221                 mbox_index,
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);
247                 mbox_index++;
248                 spin_unlock(&m->lock);
249         }
250
251         return 0;
252 }
253
254 static int mbox_open(struct inode *inode, struct file *file)
255 {
256         return single_open(file, mbox_show, NULL);
257 }
258
259 static const struct file_operations mbox_operations = {
260         .owner = THIS_MODULE,
261         .open = mbox_open,
262         .read = seq_read,
263         .llseek = seq_lseek,
264         .release = single_release,
265 };
266 #endif
267
268 static irqreturn_t mbox_irq(int irq, void *arg)
269 {
270         u32 mbox_value;
271         int nbr_occup;
272         int nbr_free;
273         struct mbox *mbox = (struct mbox *) arg;
274
275         spin_lock(&mbox->lock);
276
277         dev_dbg(&(mbox->pdev->dev),
278                 "mbox IRQ [%d] received. ri = %d, wi = %d\n",
279                 irq, mbox->read_index, mbox->write_index);
280
281         /*
282          * Check if we have any outgoing messages, and if there is space for
283          * them in the FIFO.
284          */
285         if (mbox->read_index != mbox->write_index) {
286                 /*
287                  * Check by reading FREE for LOCAL since that indicates
288                  * OCCUP for PEER
289                  */
290                 nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
291                             >> 4) & 0x7;
292                 dev_dbg(&(mbox->pdev->dev),
293                         "Status indicates %d empty spaces in the FIFO!\n",
294                         nbr_free);
295
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));
301                         writel(MBOX_LATCH,
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));
307
308                         nbr_free--;
309                         mbox->read_index =
310                                 (mbox->read_index + 1) % MBOX_BUF_SIZE;
311                 }
312
313                 /*
314                  * Check if we still want IRQ:s when there is free
315                  * space to send
316                  */
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);
323                 } else {
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);
329                 }
330
331                 /*
332                  * Check if we can signal any blocked clients that it is OK to
333                  * start buffering again
334                  */
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;
342                 }
343         }
344
345         /* Check if we have any incoming messages */
346         nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
347         if (nbr_occup == 0)
348                 goto exit;
349
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);
353                 goto exit;
354         }
355
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));
359
360         /* Notify consumer of new mailbox message */
361         dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
362                 mbox_value);
363         mbox->cb(mbox_value, mbox->client_data);
364
365 exit:
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);
369
370         return IRQ_HANDLED;
371 }
372
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)
375 {
376         struct resource *resource;
377         int irq;
378         int res;
379         struct mbox *mbox;
380
381         mbox = get_mbox_with_id(mbox_id);
382         if (mbox == NULL) {
383                 dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
384                         mbox_id);
385                 goto exit;
386         }
387
388         /*
389          * Check if mailbox has been allocated to someone else,
390          * otherwise allocate it
391          */
392         if (mbox->allocated) {
393                 dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
394                         mbox_id);
395                 mbox = NULL;
396                 goto exit;
397         }
398         mbox->allocated = true;
399
400         dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
401                 mbox_id, (u32)mbox);
402
403         mbox->client_data = priv;
404         mbox->cb = mbox_cb;
405
406         /* Get addr for peer mailbox and ioremap it */
407         resource = platform_get_resource_byname(mbox->pdev,
408                                                 IORESOURCE_MEM,
409                                                 "mbox_peer");
410         if (resource == NULL) {
411                 dev_err(&(mbox->pdev->dev),
412                         "Unable to retrieve mbox peer resource\n");
413                 mbox = NULL;
414                 goto exit;
415         }
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 =
420                 ioremap(resource->start, resource->end - resource->start);
421         if (!mbox->virtbase_peer) {
422                 dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
423                 mbox = NULL;
424                 goto exit;
425         }
426         dev_dbg(&(mbox->pdev->dev),
427                 "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
428                 resource->start, resource->end, (u32) mbox->virtbase_peer);
429
430         /* Get addr for local mailbox and ioremap it */
431         resource = platform_get_resource_byname(mbox->pdev,
432                                                 IORESOURCE_MEM,
433                                                 "mbox_local");
434         if (resource == NULL) {
435                 dev_err(&(mbox->pdev->dev),
436                         "Unable to retrieve mbox local resource\n");
437                 mbox = NULL;
438                 goto exit;
439         }
440         dev_dbg(&(mbox->pdev->dev),
441                 "Resource name: %s start: 0x%X, end: 0x%X\n",
442                 resource->name, resource->start, resource->end);
443         mbox->virtbase_local =
444                 ioremap(resource->start, resource->end - resource->start);
445         if (!mbox->virtbase_local) {
446                 dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
447                 mbox = NULL;
448                 goto exit;
449         }
450         dev_dbg(&(mbox->pdev->dev),
451                 "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
452                 resource->start, resource->end, (u32) mbox->virtbase_peer);
453
454         init_completion(&mbox->buffer_available);
455         mbox->client_blocked = 0;
456
457         /* Get IRQ for mailbox and allocate it */
458         irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
459         if (irq < 0) {
460                 dev_err(&(mbox->pdev->dev),
461                         "Unable to retrieve mbox irq resource\n");
462                 mbox = NULL;
463                 goto exit;
464         }
465
466         dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
467         res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
468         if (res < 0) {
469                 dev_err(&(mbox->pdev->dev),
470                         "Unable to allocate mbox irq %d\n", irq);
471                 mbox = NULL;
472                 goto exit;
473         }
474
475         /* Set up mailbox to not launch IRQ on free space in mailbox */
476         writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
477
478         /*
479          * Set up mailbox to launch IRQ on new message if we have
480          * a callback set. If not, do not raise IRQ, but keep message
481          * in FIFO for manual retrieval
482          */
483         if (mbox_cb != NULL)
484                 writel(MBOX_ENABLE_IRQ,
485                        mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
486         else
487                 writel(MBOX_DISABLE_IRQ,
488                        mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
489
490 #if defined(CONFIG_DEBUG_FS)
491         res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
492         if (res != 0)
493                 dev_warn(&(mbox->pdev->dev),
494                          "Unable to create mbox sysfs entry");
495
496         (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
497                                    NULL, &mbox_operations);
498 #endif
499
500         dev_info(&(mbox->pdev->dev),
501                  "Mailbox driver with index %d initiated!\n", mbox_id);
502
503 exit:
504         return mbox;
505 }
506 EXPORT_SYMBOL(mbox_setup);
507
508
509 int __init mbox_probe(struct platform_device *pdev)
510 {
511         struct mbox local_mbox;
512         struct mbox *mbox;
513         int res = 0;
514         dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
515
516         memset(&local_mbox, 0x0, sizeof(struct mbox));
517
518         /* Associate our mbox data with the platform device */
519         res = platform_device_add_data(pdev,
520                                        (void *) &local_mbox,
521                                        sizeof(struct mbox));
522         if (res != 0) {
523                 dev_err(&(pdev->dev),
524                         "Unable to allocate driver platform data!\n");
525                 goto exit;
526         }
527
528         mbox = (struct mbox *) pdev->dev.platform_data;
529         mbox->pdev = pdev;
530         mbox->write_index = 0;
531         mbox->read_index = 0;
532
533         INIT_LIST_HEAD(&(mbox->list));
534         list_add_tail(&(mbox->list), &mboxs);
535
536         sprintf(mbox->name, "%s", MBOX_NAME);
537         spin_lock_init(&mbox->lock);
538
539         dev_info(&(pdev->dev), "Mailbox driver loaded\n");
540
541 exit:
542         return res;
543 }
544
545 static struct platform_driver mbox_driver = {
546         .driver = {
547                 .name = MBOX_NAME,
548                 .owner = THIS_MODULE,
549         },
550 };
551
552 static int __init mbox_init(void)
553 {
554         return platform_driver_probe(&mbox_driver, mbox_probe);
555 }
556
557 module_init(mbox_init);
558
559 void __exit mbox_exit(void)
560 {
561         platform_driver_unregister(&mbox_driver);
562 }
563
564 module_exit(mbox_exit);
565
566 MODULE_LICENSE("GPL");
567 MODULE_DESCRIPTION("MBOX driver");