~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-ux500/mbox-db5500.c

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.72 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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_IWUSR | 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 = ioremap(resource->start, resource_size(resource));
420         if (!mbox->virtbase_peer) {
421                 dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
422                 mbox = NULL;
423                 goto exit;
424         }
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);
428 
429         /* Get addr for local mailbox and ioremap it */
430         resource = platform_get_resource_byname(mbox->pdev,
431                                                 IORESOURCE_MEM,
432                                                 "mbox_local");
433         if (resource == NULL) {
434                 dev_err(&(mbox->pdev->dev),
435                         "Unable to retrieve mbox local resource\n");
436                 mbox = NULL;
437                 goto exit;
438         }
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");
445                 mbox = NULL;
446                 goto exit;
447         }
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);
451 
452         init_completion(&mbox->buffer_available);
453         mbox->client_blocked = 0;
454 
455         /* Get IRQ for mailbox and allocate it */
456         irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
457         if (irq < 0) {
458                 dev_err(&(mbox->pdev->dev),
459                         "Unable to retrieve mbox irq resource\n");
460                 mbox = NULL;
461                 goto exit;
462         }
463 
464         dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
465         res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
466         if (res < 0) {
467                 dev_err(&(mbox->pdev->dev),
468                         "Unable to allocate mbox irq %d\n", irq);
469                 mbox = NULL;
470                 goto exit;
471         }
472 
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);
475 
476         /*
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
480          */
481         if (mbox_cb != NULL)
482                 writel(MBOX_ENABLE_IRQ,
483                        mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
484         else
485                 writel(MBOX_DISABLE_IRQ,
486                        mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
487 
488 #if defined(CONFIG_DEBUG_FS)
489         res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
490         if (res != 0)
491                 dev_warn(&(mbox->pdev->dev),
492                          "Unable to create mbox sysfs entry");
493 
494         (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
495                                    NULL, &mbox_operations);
496 #endif
497 
498         dev_info(&(mbox->pdev->dev),
499                  "Mailbox driver with index %d initiated!\n", mbox_id);
500 
501 exit:
502         return mbox;
503 }
504 EXPORT_SYMBOL(mbox_setup);
505 
506 
507 int __init mbox_probe(struct platform_device *pdev)
508 {
509         struct mbox local_mbox;
510         struct mbox *mbox;
511         int res = 0;
512         dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
513 
514         memset(&local_mbox, 0x0, sizeof(struct mbox));
515 
516         /* Associate our mbox data with the platform device */
517         res = platform_device_add_data(pdev,
518                                        (void *) &local_mbox,
519                                        sizeof(struct mbox));
520         if (res != 0) {
521                 dev_err(&(pdev->dev),
522                         "Unable to allocate driver platform data!\n");
523                 goto exit;
524         }
525 
526         mbox = (struct mbox *) pdev->dev.platform_data;
527         mbox->pdev = pdev;
528         mbox->write_index = 0;
529         mbox->read_index = 0;
530 
531         INIT_LIST_HEAD(&(mbox->list));
532         list_add_tail(&(mbox->list), &mboxs);
533 
534         sprintf(mbox->name, "%s", MBOX_NAME);
535         spin_lock_init(&mbox->lock);
536 
537         dev_info(&(pdev->dev), "Mailbox driver loaded\n");
538 
539 exit:
540         return res;
541 }
542 
543 static struct platform_driver mbox_driver = {
544         .driver = {
545                 .name = MBOX_NAME,
546                 .owner = THIS_MODULE,
547         },
548 };
549 
550 static int __init mbox_init(void)
551 {
552         return platform_driver_probe(&mbox_driver, mbox_probe);
553 }
554 
555 module_init(mbox_init);
556 
557 void __exit mbox_exit(void)
558 {
559         platform_driver_unregister(&mbox_driver);
560 }
561 
562 module_exit(mbox_exit);
563 
564 MODULE_LICENSE("GPL");
565 MODULE_DESCRIPTION("MBOX driver");
566 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp