Root/
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.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 initated!\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"); |
568 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9