diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap1/mailbox.c | 55 | ||||
-rw-r--r-- | arch/arm/mach-omap2/devices.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mailbox.c | 182 | ||||
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 9 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/mailbox.h | 20 | ||||
-rw-r--r-- | arch/arm/plat-omap/mailbox.c | 248 |
6 files changed, 241 insertions, 279 deletions
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c index 4f5b3da3d559..1a85a421007f 100644 --- a/arch/arm/mach-omap1/mailbox.c +++ b/arch/arm/mach-omap1/mailbox.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Mailbox reservation modules for DSP | 2 | * Mailbox reservation modules for OMAP1 |
3 | * | 3 | * |
4 | * Copyright (C) 2006-2009 Nokia Corporation | 4 | * Copyright (C) 2006-2009 Nokia Corporation |
5 | * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | 5 | * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> |
@@ -9,13 +9,10 @@ | |||
9 | * for more details. | 9 | * for more details. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/resource.h> | ||
14 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
15 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
16 | #include <linux/io.h> | 14 | #include <linux/io.h> |
17 | #include <plat/mailbox.h> | 15 | #include <plat/mailbox.h> |
18 | #include <mach/irqs.h> | ||
19 | 16 | ||
20 | #define MAILBOX_ARM2DSP1 0x00 | 17 | #define MAILBOX_ARM2DSP1 0x00 |
21 | #define MAILBOX_ARM2DSP1b 0x04 | 18 | #define MAILBOX_ARM2DSP1b 0x04 |
@@ -83,7 +80,7 @@ static int omap1_mbox_fifo_full(struct omap_mbox *mbox) | |||
83 | struct omap_mbox1_fifo *fifo = | 80 | struct omap_mbox1_fifo *fifo = |
84 | &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; | 81 | &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; |
85 | 82 | ||
86 | return (mbox_read_reg(fifo->flag)); | 83 | return mbox_read_reg(fifo->flag); |
87 | } | 84 | } |
88 | 85 | ||
89 | /* irq */ | 86 | /* irq */ |
@@ -141,47 +138,37 @@ struct omap_mbox mbox_dsp_info = { | |||
141 | .ops = &omap1_mbox_ops, | 138 | .ops = &omap1_mbox_ops, |
142 | .priv = &omap1_mbox_dsp_priv, | 139 | .priv = &omap1_mbox_dsp_priv, |
143 | }; | 140 | }; |
144 | EXPORT_SYMBOL(mbox_dsp_info); | 141 | |
142 | struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL }; | ||
145 | 143 | ||
146 | static int __devinit omap1_mbox_probe(struct platform_device *pdev) | 144 | static int __devinit omap1_mbox_probe(struct platform_device *pdev) |
147 | { | 145 | { |
148 | struct resource *res; | 146 | struct resource *mem; |
147 | int ret; | ||
148 | int i; | ||
149 | struct omap_mbox **list; | ||
149 | 150 | ||
150 | if (pdev->num_resources != 2) { | 151 | list = omap1_mboxes; |
151 | dev_err(&pdev->dev, "invalid number of resources: %d\n", | 152 | list[0]->irq = platform_get_irq_byname(pdev, "dsp"); |
152 | pdev->num_resources); | ||
153 | return -ENODEV; | ||
154 | } | ||
155 | 153 | ||
156 | /* MBOX base */ | 154 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
157 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 155 | mbox_base = ioremap(mem->start, resource_size(mem)); |
158 | if (unlikely(!res)) { | 156 | if (!mbox_base) |
159 | dev_err(&pdev->dev, "invalid mem resource\n"); | 157 | return -ENOMEM; |
160 | return -ENODEV; | ||
161 | } | ||
162 | 158 | ||
163 | mbox_base = ioremap(res->start, resource_size(res)); | 159 | ret = omap_mbox_register(&pdev->dev, list); |
164 | if (!mbox_base) { | 160 | if (ret) { |
165 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | |||
169 | /* DSP IRQ */ | ||
170 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
171 | if (unlikely(!res)) { | ||
172 | dev_err(&pdev->dev, "invalid irq resource\n"); | ||
173 | iounmap(mbox_base); | 161 | iounmap(mbox_base); |
174 | return -ENODEV; | 162 | return ret; |
175 | } | 163 | } |
176 | mbox_dsp_info.irq = res->start; | ||
177 | 164 | ||
178 | return omap_mbox_register(&pdev->dev, &mbox_dsp_info); | 165 | return 0; |
179 | } | 166 | } |
180 | 167 | ||
181 | static int __devexit omap1_mbox_remove(struct platform_device *pdev) | 168 | static int __devexit omap1_mbox_remove(struct platform_device *pdev) |
182 | { | 169 | { |
183 | omap_mbox_unregister(&mbox_dsp_info); | 170 | omap_mbox_unregister(); |
184 | 171 | iounmap(mbox_base); | |
185 | return 0; | 172 | return 0; |
186 | } | 173 | } |
187 | 174 | ||
@@ -189,7 +176,7 @@ static struct platform_driver omap1_mbox_driver = { | |||
189 | .probe = omap1_mbox_probe, | 176 | .probe = omap1_mbox_probe, |
190 | .remove = __devexit_p(omap1_mbox_remove), | 177 | .remove = __devexit_p(omap1_mbox_remove), |
191 | .driver = { | 178 | .driver = { |
192 | .name = "omap1-mailbox", | 179 | .name = "omap-mailbox", |
193 | }, | 180 | }, |
194 | }; | 181 | }; |
195 | 182 | ||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 162a9be3cbb1..2dbb265bedd4 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -152,10 +152,12 @@ static struct resource omap2_mbox_resources[] = { | |||
152 | { | 152 | { |
153 | .start = INT_24XX_MAIL_U0_MPU, | 153 | .start = INT_24XX_MAIL_U0_MPU, |
154 | .flags = IORESOURCE_IRQ, | 154 | .flags = IORESOURCE_IRQ, |
155 | .name = "dsp", | ||
155 | }, | 156 | }, |
156 | { | 157 | { |
157 | .start = INT_24XX_MAIL_U3_MPU, | 158 | .start = INT_24XX_MAIL_U3_MPU, |
158 | .flags = IORESOURCE_IRQ, | 159 | .flags = IORESOURCE_IRQ, |
160 | .name = "iva", | ||
159 | }, | 161 | }, |
160 | }; | 162 | }; |
161 | static int omap2_mbox_resources_sz = ARRAY_SIZE(omap2_mbox_resources); | 163 | static int omap2_mbox_resources_sz = ARRAY_SIZE(omap2_mbox_resources); |
@@ -174,6 +176,7 @@ static struct resource omap3_mbox_resources[] = { | |||
174 | { | 176 | { |
175 | .start = INT_24XX_MAIL_U0_MPU, | 177 | .start = INT_24XX_MAIL_U0_MPU, |
176 | .flags = IORESOURCE_IRQ, | 178 | .flags = IORESOURCE_IRQ, |
179 | .name = "dsp", | ||
177 | }, | 180 | }, |
178 | }; | 181 | }; |
179 | static int omap3_mbox_resources_sz = ARRAY_SIZE(omap3_mbox_resources); | 182 | static int omap3_mbox_resources_sz = ARRAY_SIZE(omap3_mbox_resources); |
@@ -195,6 +198,7 @@ static struct resource omap4_mbox_resources[] = { | |||
195 | { | 198 | { |
196 | .start = OMAP44XX_IRQ_MAIL_U0, | 199 | .start = OMAP44XX_IRQ_MAIL_U0, |
197 | .flags = IORESOURCE_IRQ, | 200 | .flags = IORESOURCE_IRQ, |
201 | .name = "mbox", | ||
198 | }, | 202 | }, |
199 | }; | 203 | }; |
200 | static int omap4_mbox_resources_sz = ARRAY_SIZE(omap4_mbox_resources); | 204 | static int omap4_mbox_resources_sz = ARRAY_SIZE(omap4_mbox_resources); |
@@ -204,7 +208,7 @@ static int omap4_mbox_resources_sz = ARRAY_SIZE(omap4_mbox_resources); | |||
204 | #endif | 208 | #endif |
205 | 209 | ||
206 | static struct platform_device mbox_device = { | 210 | static struct platform_device mbox_device = { |
207 | .name = "omap2-mailbox", | 211 | .name = "omap-mailbox", |
208 | .id = -1, | 212 | .id = -1, |
209 | }; | 213 | }; |
210 | 214 | ||
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 318f3638653c..42dbfa46e656 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * for more details. | 10 | * for more details. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
15 | #include <linux/err.h> | 14 | #include <linux/err.h> |
16 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
@@ -18,8 +17,6 @@ | |||
18 | #include <plat/mailbox.h> | 17 | #include <plat/mailbox.h> |
19 | #include <mach/irqs.h> | 18 | #include <mach/irqs.h> |
20 | 19 | ||
21 | #define DRV_NAME "omap2-mailbox" | ||
22 | |||
23 | #define MAILBOX_REVISION 0x000 | 20 | #define MAILBOX_REVISION 0x000 |
24 | #define MAILBOX_SYSCONFIG 0x010 | 21 | #define MAILBOX_SYSCONFIG 0x010 |
25 | #define MAILBOX_SYSSTATUS 0x014 | 22 | #define MAILBOX_SYSSTATUS 0x014 |
@@ -131,7 +128,7 @@ static int omap2_mbox_startup(struct omap_mbox *mbox) | |||
131 | } | 128 | } |
132 | 129 | ||
133 | l = mbox_read_reg(MAILBOX_REVISION); | 130 | l = mbox_read_reg(MAILBOX_REVISION); |
134 | pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); | 131 | pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); |
135 | 132 | ||
136 | if (cpu_is_omap44xx()) | 133 | if (cpu_is_omap44xx()) |
137 | l = OMAP4_SMARTIDLE; | 134 | l = OMAP4_SMARTIDLE; |
@@ -283,6 +280,8 @@ static struct omap_mbox_ops omap2_mbox_ops = { | |||
283 | */ | 280 | */ |
284 | 281 | ||
285 | /* FIXME: the following structs should be filled automatically by the user id */ | 282 | /* FIXME: the following structs should be filled automatically by the user id */ |
283 | |||
284 | #if defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_ARCH_OMAP2420) | ||
286 | /* DSP */ | 285 | /* DSP */ |
287 | static struct omap_mbox2_priv omap2_mbox_dsp_priv = { | 286 | static struct omap_mbox2_priv omap2_mbox_dsp_priv = { |
288 | .tx_fifo = { | 287 | .tx_fifo = { |
@@ -300,10 +299,46 @@ static struct omap_mbox2_priv omap2_mbox_dsp_priv = { | |||
300 | .irqdisable = MAILBOX_IRQENABLE(0), | 299 | .irqdisable = MAILBOX_IRQENABLE(0), |
301 | }; | 300 | }; |
302 | 301 | ||
302 | struct omap_mbox mbox_dsp_info = { | ||
303 | .name = "dsp", | ||
304 | .ops = &omap2_mbox_ops, | ||
305 | .priv = &omap2_mbox_dsp_priv, | ||
306 | }; | ||
307 | #endif | ||
308 | |||
309 | #if defined(CONFIG_ARCH_OMAP3430) | ||
310 | struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL }; | ||
311 | #endif | ||
312 | |||
313 | #if defined(CONFIG_ARCH_OMAP2420) | ||
314 | /* IVA */ | ||
315 | static struct omap_mbox2_priv omap2_mbox_iva_priv = { | ||
316 | .tx_fifo = { | ||
317 | .msg = MAILBOX_MESSAGE(2), | ||
318 | .fifo_stat = MAILBOX_FIFOSTATUS(2), | ||
319 | }, | ||
320 | .rx_fifo = { | ||
321 | .msg = MAILBOX_MESSAGE(3), | ||
322 | .msg_stat = MAILBOX_MSGSTATUS(3), | ||
323 | }, | ||
324 | .irqenable = MAILBOX_IRQENABLE(3), | ||
325 | .irqstatus = MAILBOX_IRQSTATUS(3), | ||
326 | .notfull_bit = MAILBOX_IRQ_NOTFULL(2), | ||
327 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), | ||
328 | .irqdisable = MAILBOX_IRQENABLE(3), | ||
329 | }; | ||
330 | |||
331 | static struct omap_mbox mbox_iva_info = { | ||
332 | .name = "iva", | ||
333 | .ops = &omap2_mbox_ops, | ||
334 | .priv = &omap2_mbox_iva_priv, | ||
335 | }; | ||
303 | 336 | ||
337 | struct omap_mbox *omap2_mboxes[] = { &mbox_iva_info, &mbox_dsp_info, NULL }; | ||
338 | #endif | ||
304 | 339 | ||
305 | /* OMAP4 specific data structure. Use the cpu_is_omap4xxx() | 340 | #if defined(CONFIG_ARCH_OMAP4) |
306 | to use this*/ | 341 | /* OMAP4 */ |
307 | static struct omap_mbox2_priv omap2_mbox_1_priv = { | 342 | static struct omap_mbox2_priv omap2_mbox_1_priv = { |
308 | .tx_fifo = { | 343 | .tx_fifo = { |
309 | .msg = MAILBOX_MESSAGE(0), | 344 | .msg = MAILBOX_MESSAGE(0), |
@@ -325,14 +360,6 @@ struct omap_mbox mbox_1_info = { | |||
325 | .ops = &omap2_mbox_ops, | 360 | .ops = &omap2_mbox_ops, |
326 | .priv = &omap2_mbox_1_priv, | 361 | .priv = &omap2_mbox_1_priv, |
327 | }; | 362 | }; |
328 | EXPORT_SYMBOL(mbox_1_info); | ||
329 | |||
330 | struct omap_mbox mbox_dsp_info = { | ||
331 | .name = "dsp", | ||
332 | .ops = &omap2_mbox_ops, | ||
333 | .priv = &omap2_mbox_dsp_priv, | ||
334 | }; | ||
335 | EXPORT_SYMBOL(mbox_dsp_info); | ||
336 | 363 | ||
337 | static struct omap_mbox2_priv omap2_mbox_2_priv = { | 364 | static struct omap_mbox2_priv omap2_mbox_2_priv = { |
338 | .tx_fifo = { | 365 | .tx_fifo = { |
@@ -355,110 +382,64 @@ struct omap_mbox mbox_2_info = { | |||
355 | .ops = &omap2_mbox_ops, | 382 | .ops = &omap2_mbox_ops, |
356 | .priv = &omap2_mbox_2_priv, | 383 | .priv = &omap2_mbox_2_priv, |
357 | }; | 384 | }; |
358 | EXPORT_SYMBOL(mbox_2_info); | ||
359 | |||
360 | |||
361 | #if defined(CONFIG_ARCH_OMAP2420) /* IVA */ | ||
362 | static struct omap_mbox2_priv omap2_mbox_iva_priv = { | ||
363 | .tx_fifo = { | ||
364 | .msg = MAILBOX_MESSAGE(2), | ||
365 | .fifo_stat = MAILBOX_FIFOSTATUS(2), | ||
366 | }, | ||
367 | .rx_fifo = { | ||
368 | .msg = MAILBOX_MESSAGE(3), | ||
369 | .msg_stat = MAILBOX_MSGSTATUS(3), | ||
370 | }, | ||
371 | .irqenable = MAILBOX_IRQENABLE(3), | ||
372 | .irqstatus = MAILBOX_IRQSTATUS(3), | ||
373 | .notfull_bit = MAILBOX_IRQ_NOTFULL(2), | ||
374 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), | ||
375 | .irqdisable = MAILBOX_IRQENABLE(3), | ||
376 | }; | ||
377 | 385 | ||
378 | static struct omap_mbox mbox_iva_info = { | 386 | struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL }; |
379 | .name = "iva", | ||
380 | .ops = &omap2_mbox_ops, | ||
381 | .priv = &omap2_mbox_iva_priv, | ||
382 | }; | ||
383 | #endif | 387 | #endif |
384 | 388 | ||
385 | static int __devinit omap2_mbox_probe(struct platform_device *pdev) | 389 | static int __devinit omap2_mbox_probe(struct platform_device *pdev) |
386 | { | 390 | { |
387 | struct resource *res; | 391 | struct resource *mem; |
388 | int ret; | 392 | int ret; |
393 | struct omap_mbox **list; | ||
389 | 394 | ||
390 | /* MBOX base */ | 395 | if (false) |
391 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 396 | ; |
392 | if (unlikely(!res)) { | 397 | #if defined(CONFIG_ARCH_OMAP3430) |
393 | dev_err(&pdev->dev, "invalid mem resource\n"); | 398 | else if (cpu_is_omap3430()) { |
394 | return -ENODEV; | 399 | list = omap3_mboxes; |
400 | |||
401 | list[0]->irq = platform_get_irq_byname(pdev, "dsp"); | ||
395 | } | 402 | } |
396 | mbox_base = ioremap(res->start, resource_size(res)); | 403 | #endif |
397 | if (!mbox_base) | 404 | #if defined(CONFIG_ARCH_OMAP2420) |
398 | return -ENOMEM; | 405 | else if (cpu_is_omap2420()) { |
406 | list = omap2_mboxes; | ||
399 | 407 | ||
400 | /* DSP or IVA2 IRQ */ | 408 | list[0]->irq = platform_get_irq_byname(pdev, "dsp"); |
401 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 409 | list[1]->irq = platform_get_irq_byname(pdev, "iva"); |
410 | } | ||
411 | #endif | ||
412 | #if defined(CONFIG_ARCH_OMAP4) | ||
413 | else if (cpu_is_omap44xx()) { | ||
414 | list = omap4_mboxes; | ||
402 | 415 | ||
403 | if (unlikely(!res)) { | 416 | list[0]->irq = list[1]->irq = |
404 | dev_err(&pdev->dev, "invalid irq resource\n"); | 417 | platform_get_irq_byname(pdev, "mbox"); |
405 | ret = -ENODEV; | ||
406 | goto err_dsp; | ||
407 | } | 418 | } |
408 | if (cpu_is_omap44xx()) { | 419 | #endif |
409 | mbox_1_info.irq = res->start; | 420 | else { |
410 | ret = omap_mbox_register(&pdev->dev, &mbox_1_info); | 421 | pr_err("%s: platform not supported\n", __func__); |
411 | } else { | 422 | return -ENODEV; |
412 | mbox_dsp_info.irq = res->start; | ||
413 | ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info); | ||
414 | } | 423 | } |
415 | if (ret) | ||
416 | goto err_dsp; | ||
417 | 424 | ||
418 | if (cpu_is_omap44xx()) { | 425 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
419 | mbox_2_info.irq = res->start; | 426 | mbox_base = ioremap(mem->start, resource_size(mem)); |
420 | ret = omap_mbox_register(&pdev->dev, &mbox_2_info); | 427 | if (!mbox_base) |
421 | if (ret) { | 428 | return -ENOMEM; |
422 | omap_mbox_unregister(&mbox_1_info); | 429 | |
423 | goto err_dsp; | 430 | ret = omap_mbox_register(&pdev->dev, list); |
424 | } | 431 | if (ret) { |
425 | } | 432 | iounmap(mbox_base); |
426 | #if defined(CONFIG_ARCH_OMAP2420) /* IVA */ | 433 | return ret; |
427 | if (cpu_is_omap2420()) { | ||
428 | /* IVA IRQ */ | ||
429 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
430 | if (unlikely(!res)) { | ||
431 | dev_err(&pdev->dev, "invalid irq resource\n"); | ||
432 | ret = -ENODEV; | ||
433 | omap_mbox_unregister(&mbox_dsp_info); | ||
434 | goto err_dsp; | ||
435 | } | ||
436 | mbox_iva_info.irq = res->start; | ||
437 | ret = omap_mbox_register(&pdev->dev, &mbox_iva_info); | ||
438 | if (ret) { | ||
439 | omap_mbox_unregister(&mbox_dsp_info); | ||
440 | goto err_dsp; | ||
441 | } | ||
442 | } | 434 | } |
443 | #endif | ||
444 | return 0; | 435 | return 0; |
445 | 436 | ||
446 | err_dsp: | ||
447 | iounmap(mbox_base); | ||
448 | return ret; | 437 | return ret; |
449 | } | 438 | } |
450 | 439 | ||
451 | static int __devexit omap2_mbox_remove(struct platform_device *pdev) | 440 | static int __devexit omap2_mbox_remove(struct platform_device *pdev) |
452 | { | 441 | { |
453 | #if defined(CONFIG_ARCH_OMAP2420) | 442 | omap_mbox_unregister(); |
454 | omap_mbox_unregister(&mbox_iva_info); | ||
455 | #endif | ||
456 | |||
457 | if (cpu_is_omap44xx()) { | ||
458 | omap_mbox_unregister(&mbox_2_info); | ||
459 | omap_mbox_unregister(&mbox_1_info); | ||
460 | } else | ||
461 | omap_mbox_unregister(&mbox_dsp_info); | ||
462 | iounmap(mbox_base); | 443 | iounmap(mbox_base); |
463 | return 0; | 444 | return 0; |
464 | } | 445 | } |
@@ -467,7 +448,7 @@ static struct platform_driver omap2_mbox_driver = { | |||
467 | .probe = omap2_mbox_probe, | 448 | .probe = omap2_mbox_probe, |
468 | .remove = __devexit_p(omap2_mbox_remove), | 449 | .remove = __devexit_p(omap2_mbox_remove), |
469 | .driver = { | 450 | .driver = { |
470 | .name = DRV_NAME, | 451 | .name = "omap-mailbox", |
471 | }, | 452 | }, |
472 | }; | 453 | }; |
473 | 454 | ||
@@ -486,5 +467,6 @@ module_exit(omap2_mbox_exit); | |||
486 | 467 | ||
487 | MODULE_LICENSE("GPL v2"); | 468 | MODULE_LICENSE("GPL v2"); |
488 | MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions"); | 469 | MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions"); |
489 | MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt"); | 470 | MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>"); |
490 | MODULE_ALIAS("platform:"DRV_NAME); | 471 | MODULE_AUTHOR("Paul Mundt"); |
472 | MODULE_ALIAS("platform:omap2-mailbox"); | ||
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index e2ed952df23d..e39a417a368d 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -88,6 +88,15 @@ config OMAP_MBOX_FWK | |||
88 | Say Y here if you want to use OMAP Mailbox framework support for | 88 | Say Y here if you want to use OMAP Mailbox framework support for |
89 | DSP, IVA1.0 and IVA2 in OMAP1/2/3. | 89 | DSP, IVA1.0 and IVA2 in OMAP1/2/3. |
90 | 90 | ||
91 | config OMAP_MBOX_KFIFO_SIZE | ||
92 | int "Mailbox kfifo default buffer size (bytes)" | ||
93 | depends on OMAP_MBOX_FWK | ||
94 | default 256 | ||
95 | help | ||
96 | Specify the default size of mailbox's kfifo buffers (bytes). | ||
97 | This can also be changed at runtime (via the mbox_kfifo_size | ||
98 | module parameter). | ||
99 | |||
91 | config OMAP_IOMMU | 100 | config OMAP_IOMMU |
92 | tristate | 101 | tristate |
93 | 102 | ||
diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h index 729166b76a7c..997656552109 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/arch/arm/plat-omap/include/plat/mailbox.h | |||
@@ -3,10 +3,11 @@ | |||
3 | #ifndef MAILBOX_H | 3 | #ifndef MAILBOX_H |
4 | #define MAILBOX_H | 4 | #define MAILBOX_H |
5 | 5 | ||
6 | #include <linux/wait.h> | 6 | #include <linux/spinlock.h> |
7 | #include <linux/workqueue.h> | 7 | #include <linux/workqueue.h> |
8 | #include <linux/blkdev.h> | ||
9 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
9 | #include <linux/device.h> | ||
10 | #include <linux/kfifo.h> | ||
10 | 11 | ||
11 | typedef u32 mbox_msg_t; | 12 | typedef u32 mbox_msg_t; |
12 | struct omap_mbox; | 13 | struct omap_mbox; |
@@ -42,7 +43,7 @@ struct omap_mbox_ops { | |||
42 | 43 | ||
43 | struct omap_mbox_queue { | 44 | struct omap_mbox_queue { |
44 | spinlock_t lock; | 45 | spinlock_t lock; |
45 | struct request_queue *queue; | 46 | struct kfifo fifo; |
46 | struct work_struct work; | 47 | struct work_struct work; |
47 | struct tasklet_struct tasklet; | 48 | struct tasklet_struct tasklet; |
48 | int (*callback)(void *); | 49 | int (*callback)(void *); |
@@ -52,19 +53,10 @@ struct omap_mbox_queue { | |||
52 | struct omap_mbox { | 53 | struct omap_mbox { |
53 | char *name; | 54 | char *name; |
54 | unsigned int irq; | 55 | unsigned int irq; |
55 | |||
56 | struct omap_mbox_queue *txq, *rxq; | 56 | struct omap_mbox_queue *txq, *rxq; |
57 | |||
58 | struct omap_mbox_ops *ops; | 57 | struct omap_mbox_ops *ops; |
59 | |||
60 | mbox_msg_t seq_snd, seq_rcv; | ||
61 | |||
62 | struct device *dev; | 58 | struct device *dev; |
63 | |||
64 | struct omap_mbox *next; | ||
65 | void *priv; | 59 | void *priv; |
66 | |||
67 | void (*err_notify)(void); | ||
68 | }; | 60 | }; |
69 | 61 | ||
70 | int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); | 62 | int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); |
@@ -73,8 +65,8 @@ void omap_mbox_init_seq(struct omap_mbox *); | |||
73 | struct omap_mbox *omap_mbox_get(const char *); | 65 | struct omap_mbox *omap_mbox_get(const char *); |
74 | void omap_mbox_put(struct omap_mbox *); | 66 | void omap_mbox_put(struct omap_mbox *); |
75 | 67 | ||
76 | int omap_mbox_register(struct device *parent, struct omap_mbox *); | 68 | int omap_mbox_register(struct device *parent, struct omap_mbox **); |
77 | int omap_mbox_unregister(struct omap_mbox *); | 69 | int omap_mbox_unregister(void); |
78 | 70 | ||
79 | static inline void omap_mbox_save_ctx(struct omap_mbox *mbox) | 71 | static inline void omap_mbox_save_ctx(struct omap_mbox *mbox) |
80 | { | 72 | { |
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 08a2df766289..d2fafb892f7f 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c | |||
@@ -21,19 +21,26 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
26 | #include <linux/device.h> | 25 | #include <linux/spinlock.h> |
26 | #include <linux/mutex.h> | ||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/kfifo.h> | ||
30 | #include <linux/err.h> | ||
29 | 31 | ||
30 | #include <plat/mailbox.h> | 32 | #include <plat/mailbox.h> |
31 | 33 | ||
32 | static struct workqueue_struct *mboxd; | 34 | static struct workqueue_struct *mboxd; |
33 | static struct omap_mbox *mboxes; | 35 | static struct omap_mbox **mboxes; |
34 | static DEFINE_RWLOCK(mboxes_lock); | 36 | static bool rq_full; |
35 | 37 | ||
36 | static int mbox_configured; | 38 | static int mbox_configured; |
39 | static DEFINE_MUTEX(mbox_configured_lock); | ||
40 | |||
41 | static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; | ||
42 | module_param(mbox_kfifo_size, uint, S_IRUGO); | ||
43 | MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); | ||
37 | 44 | ||
38 | /* Mailbox FIFO handle functions */ | 45 | /* Mailbox FIFO handle functions */ |
39 | static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) | 46 | static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) |
@@ -67,7 +74,7 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | |||
67 | /* | 74 | /* |
68 | * message sender | 75 | * message sender |
69 | */ | 76 | */ |
70 | static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) | 77 | static int __mbox_poll_for_space(struct omap_mbox *mbox) |
71 | { | 78 | { |
72 | int ret = 0, i = 1000; | 79 | int ret = 0, i = 1000; |
73 | 80 | ||
@@ -78,49 +85,50 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) | |||
78 | return -1; | 85 | return -1; |
79 | udelay(1); | 86 | udelay(1); |
80 | } | 87 | } |
81 | mbox_fifo_write(mbox, msg); | ||
82 | return ret; | 88 | return ret; |
83 | } | 89 | } |
84 | 90 | ||
85 | |||
86 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) | 91 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) |
87 | { | 92 | { |
93 | struct omap_mbox_queue *mq = mbox->txq; | ||
94 | int ret = 0, len; | ||
88 | 95 | ||
89 | struct request *rq; | 96 | spin_lock(&mq->lock); |
90 | struct request_queue *q = mbox->txq->queue; | ||
91 | 97 | ||
92 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | 98 | if (kfifo_avail(&mq->fifo) < sizeof(msg)) { |
93 | if (unlikely(!rq)) | 99 | ret = -ENOMEM; |
94 | return -ENOMEM; | 100 | goto out; |
101 | } | ||
102 | |||
103 | len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); | ||
104 | WARN_ON(len != sizeof(msg)); | ||
95 | 105 | ||
96 | blk_insert_request(q, rq, 0, (void *) msg); | ||
97 | tasklet_schedule(&mbox->txq->tasklet); | 106 | tasklet_schedule(&mbox->txq->tasklet); |
98 | 107 | ||
99 | return 0; | 108 | out: |
109 | spin_unlock(&mq->lock); | ||
110 | return ret; | ||
100 | } | 111 | } |
101 | EXPORT_SYMBOL(omap_mbox_msg_send); | 112 | EXPORT_SYMBOL(omap_mbox_msg_send); |
102 | 113 | ||
103 | static void mbox_tx_tasklet(unsigned long tx_data) | 114 | static void mbox_tx_tasklet(unsigned long tx_data) |
104 | { | 115 | { |
105 | int ret; | ||
106 | struct request *rq; | ||
107 | struct omap_mbox *mbox = (struct omap_mbox *)tx_data; | 116 | struct omap_mbox *mbox = (struct omap_mbox *)tx_data; |
108 | struct request_queue *q = mbox->txq->queue; | 117 | struct omap_mbox_queue *mq = mbox->txq; |
109 | 118 | mbox_msg_t msg; | |
110 | while (1) { | 119 | int ret; |
111 | |||
112 | rq = blk_fetch_request(q); | ||
113 | |||
114 | if (!rq) | ||
115 | break; | ||
116 | 120 | ||
117 | ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special); | 121 | while (kfifo_len(&mq->fifo)) { |
118 | if (ret) { | 122 | if (__mbox_poll_for_space(mbox)) { |
119 | omap_mbox_enable_irq(mbox, IRQ_TX); | 123 | omap_mbox_enable_irq(mbox, IRQ_TX); |
120 | blk_requeue_request(q, rq); | 124 | break; |
121 | return; | ||
122 | } | 125 | } |
123 | blk_end_request_all(rq, 0); | 126 | |
127 | ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, | ||
128 | sizeof(msg)); | ||
129 | WARN_ON(ret != sizeof(msg)); | ||
130 | |||
131 | mbox_fifo_write(mbox, msg); | ||
124 | } | 132 | } |
125 | } | 133 | } |
126 | 134 | ||
@@ -131,36 +139,21 @@ static void mbox_rx_work(struct work_struct *work) | |||
131 | { | 139 | { |
132 | struct omap_mbox_queue *mq = | 140 | struct omap_mbox_queue *mq = |
133 | container_of(work, struct omap_mbox_queue, work); | 141 | container_of(work, struct omap_mbox_queue, work); |
134 | struct omap_mbox *mbox = mq->queue->queuedata; | ||
135 | struct request_queue *q = mbox->rxq->queue; | ||
136 | struct request *rq; | ||
137 | mbox_msg_t msg; | 142 | mbox_msg_t msg; |
138 | unsigned long flags; | 143 | int len; |
139 | 144 | ||
140 | while (1) { | 145 | while (kfifo_len(&mq->fifo) >= sizeof(msg)) { |
141 | spin_lock_irqsave(q->queue_lock, flags); | 146 | len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); |
142 | rq = blk_fetch_request(q); | 147 | WARN_ON(len != sizeof(msg)); |
143 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
144 | if (!rq) | ||
145 | break; | ||
146 | 148 | ||
147 | msg = (mbox_msg_t)rq->special; | 149 | if (mq->callback) |
148 | blk_end_request_all(rq, 0); | 150 | mq->callback((void *)msg); |
149 | mbox->rxq->callback((void *)msg); | ||
150 | } | 151 | } |
151 | } | 152 | } |
152 | 153 | ||
153 | /* | 154 | /* |
154 | * Mailbox interrupt handler | 155 | * Mailbox interrupt handler |
155 | */ | 156 | */ |
156 | static void mbox_txq_fn(struct request_queue *q) | ||
157 | { | ||
158 | } | ||
159 | |||
160 | static void mbox_rxq_fn(struct request_queue *q) | ||
161 | { | ||
162 | } | ||
163 | |||
164 | static void __mbox_tx_interrupt(struct omap_mbox *mbox) | 157 | static void __mbox_tx_interrupt(struct omap_mbox *mbox) |
165 | { | 158 | { |
166 | omap_mbox_disable_irq(mbox, IRQ_TX); | 159 | omap_mbox_disable_irq(mbox, IRQ_TX); |
@@ -170,19 +163,22 @@ static void __mbox_tx_interrupt(struct omap_mbox *mbox) | |||
170 | 163 | ||
171 | static void __mbox_rx_interrupt(struct omap_mbox *mbox) | 164 | static void __mbox_rx_interrupt(struct omap_mbox *mbox) |
172 | { | 165 | { |
173 | struct request *rq; | 166 | struct omap_mbox_queue *mq = mbox->rxq; |
174 | mbox_msg_t msg; | 167 | mbox_msg_t msg; |
175 | struct request_queue *q = mbox->rxq->queue; | 168 | int len; |
176 | 169 | ||
177 | while (!mbox_fifo_empty(mbox)) { | 170 | while (!mbox_fifo_empty(mbox)) { |
178 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | 171 | if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { |
179 | if (unlikely(!rq)) | 172 | omap_mbox_disable_irq(mbox, IRQ_RX); |
173 | rq_full = true; | ||
180 | goto nomem; | 174 | goto nomem; |
175 | } | ||
181 | 176 | ||
182 | msg = mbox_fifo_read(mbox); | 177 | msg = mbox_fifo_read(mbox); |
183 | 178 | ||
179 | len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); | ||
180 | WARN_ON(len != sizeof(msg)); | ||
184 | 181 | ||
185 | blk_insert_request(q, rq, 0, (void *)msg); | ||
186 | if (mbox->ops->type == OMAP_MBOX_TYPE1) | 182 | if (mbox->ops->type == OMAP_MBOX_TYPE1) |
187 | break; | 183 | break; |
188 | } | 184 | } |
@@ -207,11 +203,9 @@ static irqreturn_t mbox_interrupt(int irq, void *p) | |||
207 | } | 203 | } |
208 | 204 | ||
209 | static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, | 205 | static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, |
210 | request_fn_proc *proc, | ||
211 | void (*work) (struct work_struct *), | 206 | void (*work) (struct work_struct *), |
212 | void (*tasklet)(unsigned long)) | 207 | void (*tasklet)(unsigned long)) |
213 | { | 208 | { |
214 | struct request_queue *q; | ||
215 | struct omap_mbox_queue *mq; | 209 | struct omap_mbox_queue *mq; |
216 | 210 | ||
217 | mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); | 211 | mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); |
@@ -220,11 +214,8 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, | |||
220 | 214 | ||
221 | spin_lock_init(&mq->lock); | 215 | spin_lock_init(&mq->lock); |
222 | 216 | ||
223 | q = blk_init_queue(proc, &mq->lock); | 217 | if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) |
224 | if (!q) | ||
225 | goto error; | 218 | goto error; |
226 | q->queuedata = mbox; | ||
227 | mq->queue = q; | ||
228 | 219 | ||
229 | if (work) | 220 | if (work) |
230 | INIT_WORK(&mq->work, work); | 221 | INIT_WORK(&mq->work, work); |
@@ -239,7 +230,7 @@ error: | |||
239 | 230 | ||
240 | static void mbox_queue_free(struct omap_mbox_queue *q) | 231 | static void mbox_queue_free(struct omap_mbox_queue *q) |
241 | { | 232 | { |
242 | blk_cleanup_queue(q->queue); | 233 | kfifo_free(&q->fifo); |
243 | kfree(q); | 234 | kfree(q); |
244 | } | 235 | } |
245 | 236 | ||
@@ -248,35 +239,35 @@ static int omap_mbox_startup(struct omap_mbox *mbox) | |||
248 | int ret = 0; | 239 | int ret = 0; |
249 | struct omap_mbox_queue *mq; | 240 | struct omap_mbox_queue *mq; |
250 | 241 | ||
251 | if (likely(mbox->ops->startup)) { | 242 | if (mbox->ops->startup) { |
252 | write_lock(&mboxes_lock); | 243 | mutex_lock(&mbox_configured_lock); |
253 | if (!mbox_configured) | 244 | if (!mbox_configured) |
254 | ret = mbox->ops->startup(mbox); | 245 | ret = mbox->ops->startup(mbox); |
255 | 246 | ||
256 | if (unlikely(ret)) { | 247 | if (ret) { |
257 | write_unlock(&mboxes_lock); | 248 | mutex_unlock(&mbox_configured_lock); |
258 | return ret; | 249 | return ret; |
259 | } | 250 | } |
260 | mbox_configured++; | 251 | mbox_configured++; |
261 | write_unlock(&mboxes_lock); | 252 | mutex_unlock(&mbox_configured_lock); |
262 | } | 253 | } |
263 | 254 | ||
264 | ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, | 255 | ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, |
265 | mbox->name, mbox); | 256 | mbox->name, mbox); |
266 | if (unlikely(ret)) { | 257 | if (ret) { |
267 | printk(KERN_ERR | 258 | printk(KERN_ERR |
268 | "failed to register mailbox interrupt:%d\n", ret); | 259 | "failed to register mailbox interrupt:%d\n", ret); |
269 | goto fail_request_irq; | 260 | goto fail_request_irq; |
270 | } | 261 | } |
271 | 262 | ||
272 | mq = mbox_queue_alloc(mbox, mbox_txq_fn, NULL, mbox_tx_tasklet); | 263 | mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); |
273 | if (!mq) { | 264 | if (!mq) { |
274 | ret = -ENOMEM; | 265 | ret = -ENOMEM; |
275 | goto fail_alloc_txq; | 266 | goto fail_alloc_txq; |
276 | } | 267 | } |
277 | mbox->txq = mq; | 268 | mbox->txq = mq; |
278 | 269 | ||
279 | mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work, NULL); | 270 | mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); |
280 | if (!mq) { | 271 | if (!mq) { |
281 | ret = -ENOMEM; | 272 | ret = -ENOMEM; |
282 | goto fail_alloc_rxq; | 273 | goto fail_alloc_rxq; |
@@ -290,7 +281,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox) | |||
290 | fail_alloc_txq: | 281 | fail_alloc_txq: |
291 | free_irq(mbox->irq, mbox); | 282 | free_irq(mbox->irq, mbox); |
292 | fail_request_irq: | 283 | fail_request_irq: |
293 | if (unlikely(mbox->ops->shutdown)) | 284 | if (mbox->ops->shutdown) |
294 | mbox->ops->shutdown(mbox); | 285 | mbox->ops->shutdown(mbox); |
295 | 286 | ||
296 | return ret; | 287 | return ret; |
@@ -298,31 +289,20 @@ static int omap_mbox_startup(struct omap_mbox *mbox) | |||
298 | 289 | ||
299 | static void omap_mbox_fini(struct omap_mbox *mbox) | 290 | static void omap_mbox_fini(struct omap_mbox *mbox) |
300 | { | 291 | { |
292 | free_irq(mbox->irq, mbox); | ||
293 | tasklet_kill(&mbox->txq->tasklet); | ||
294 | flush_work(&mbox->rxq->work); | ||
301 | mbox_queue_free(mbox->txq); | 295 | mbox_queue_free(mbox->txq); |
302 | mbox_queue_free(mbox->rxq); | 296 | mbox_queue_free(mbox->rxq); |
303 | 297 | ||
304 | free_irq(mbox->irq, mbox); | 298 | if (mbox->ops->shutdown) { |
305 | 299 | mutex_lock(&mbox_configured_lock); | |
306 | if (unlikely(mbox->ops->shutdown)) { | ||
307 | write_lock(&mboxes_lock); | ||
308 | if (mbox_configured > 0) | 300 | if (mbox_configured > 0) |
309 | mbox_configured--; | 301 | mbox_configured--; |
310 | if (!mbox_configured) | 302 | if (!mbox_configured) |
311 | mbox->ops->shutdown(mbox); | 303 | mbox->ops->shutdown(mbox); |
312 | write_unlock(&mboxes_lock); | 304 | mutex_unlock(&mbox_configured_lock); |
313 | } | ||
314 | } | ||
315 | |||
316 | static struct omap_mbox **find_mboxes(const char *name) | ||
317 | { | ||
318 | struct omap_mbox **p; | ||
319 | |||
320 | for (p = &mboxes; *p; p = &(*p)->next) { | ||
321 | if (strcmp((*p)->name, name) == 0) | ||
322 | break; | ||
323 | } | 305 | } |
324 | |||
325 | return p; | ||
326 | } | 306 | } |
327 | 307 | ||
328 | struct omap_mbox *omap_mbox_get(const char *name) | 308 | struct omap_mbox *omap_mbox_get(const char *name) |
@@ -330,14 +310,15 @@ struct omap_mbox *omap_mbox_get(const char *name) | |||
330 | struct omap_mbox *mbox; | 310 | struct omap_mbox *mbox; |
331 | int ret; | 311 | int ret; |
332 | 312 | ||
333 | read_lock(&mboxes_lock); | 313 | if (!mboxes) |
334 | mbox = *(find_mboxes(name)); | 314 | return ERR_PTR(-EINVAL); |
335 | if (mbox == NULL) { | ||
336 | read_unlock(&mboxes_lock); | ||
337 | return ERR_PTR(-ENOENT); | ||
338 | } | ||
339 | 315 | ||
340 | read_unlock(&mboxes_lock); | 316 | for (mbox = *mboxes; mbox; mbox++) |
317 | if (!strcmp(mbox->name, name)) | ||
318 | break; | ||
319 | |||
320 | if (!mbox) | ||
321 | return ERR_PTR(-ENOENT); | ||
341 | 322 | ||
342 | ret = omap_mbox_startup(mbox); | 323 | ret = omap_mbox_startup(mbox); |
343 | if (ret) | 324 | if (ret) |
@@ -353,70 +334,77 @@ void omap_mbox_put(struct omap_mbox *mbox) | |||
353 | } | 334 | } |
354 | EXPORT_SYMBOL(omap_mbox_put); | 335 | EXPORT_SYMBOL(omap_mbox_put); |
355 | 336 | ||
356 | int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) | 337 | static struct class omap_mbox_class = { .name = "mbox", }; |
338 | |||
339 | int omap_mbox_register(struct device *parent, struct omap_mbox **list) | ||
357 | { | 340 | { |
358 | int ret = 0; | 341 | int ret; |
359 | struct omap_mbox **tmp; | 342 | int i; |
360 | 343 | ||
361 | if (!mbox) | 344 | mboxes = list; |
345 | if (!mboxes) | ||
362 | return -EINVAL; | 346 | return -EINVAL; |
363 | if (mbox->next) | ||
364 | return -EBUSY; | ||
365 | |||
366 | write_lock(&mboxes_lock); | ||
367 | tmp = find_mboxes(mbox->name); | ||
368 | if (*tmp) { | ||
369 | ret = -EBUSY; | ||
370 | write_unlock(&mboxes_lock); | ||
371 | goto err_find; | ||
372 | } | ||
373 | *tmp = mbox; | ||
374 | write_unlock(&mboxes_lock); | ||
375 | 347 | ||
348 | for (i = 0; mboxes[i]; i++) { | ||
349 | struct omap_mbox *mbox = mboxes[i]; | ||
350 | mbox->dev = device_create(&omap_mbox_class, | ||
351 | parent, 0, mbox, "%s", mbox->name); | ||
352 | if (IS_ERR(mbox->dev)) { | ||
353 | ret = PTR_ERR(mbox->dev); | ||
354 | goto err_out; | ||
355 | } | ||
356 | } | ||
376 | return 0; | 357 | return 0; |
377 | 358 | ||
378 | err_find: | 359 | err_out: |
360 | while (i--) | ||
361 | device_unregister(mboxes[i]->dev); | ||
379 | return ret; | 362 | return ret; |
380 | } | 363 | } |
381 | EXPORT_SYMBOL(omap_mbox_register); | 364 | EXPORT_SYMBOL(omap_mbox_register); |
382 | 365 | ||
383 | int omap_mbox_unregister(struct omap_mbox *mbox) | 366 | int omap_mbox_unregister(void) |
384 | { | 367 | { |
385 | struct omap_mbox **tmp; | 368 | int i; |
386 | 369 | ||
387 | write_lock(&mboxes_lock); | 370 | if (!mboxes) |
388 | tmp = &mboxes; | 371 | return -EINVAL; |
389 | while (*tmp) { | ||
390 | if (mbox == *tmp) { | ||
391 | *tmp = mbox->next; | ||
392 | mbox->next = NULL; | ||
393 | write_unlock(&mboxes_lock); | ||
394 | return 0; | ||
395 | } | ||
396 | tmp = &(*tmp)->next; | ||
397 | } | ||
398 | write_unlock(&mboxes_lock); | ||
399 | 372 | ||
400 | return -EINVAL; | 373 | for (i = 0; mboxes[i]; i++) |
374 | device_unregister(mboxes[i]->dev); | ||
375 | mboxes = NULL; | ||
376 | return 0; | ||
401 | } | 377 | } |
402 | EXPORT_SYMBOL(omap_mbox_unregister); | 378 | EXPORT_SYMBOL(omap_mbox_unregister); |
403 | 379 | ||
404 | static int __init omap_mbox_init(void) | 380 | static int __init omap_mbox_init(void) |
405 | { | 381 | { |
382 | int err; | ||
383 | |||
384 | err = class_register(&omap_mbox_class); | ||
385 | if (err) | ||
386 | return err; | ||
387 | |||
406 | mboxd = create_workqueue("mboxd"); | 388 | mboxd = create_workqueue("mboxd"); |
407 | if (!mboxd) | 389 | if (!mboxd) |
408 | return -ENOMEM; | 390 | return -ENOMEM; |
409 | 391 | ||
392 | /* kfifo size sanity check: alignment and minimal size */ | ||
393 | mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t)); | ||
394 | mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t)); | ||
395 | |||
410 | return 0; | 396 | return 0; |
411 | } | 397 | } |
412 | module_init(omap_mbox_init); | 398 | subsys_initcall(omap_mbox_init); |
413 | 399 | ||
414 | static void __exit omap_mbox_exit(void) | 400 | static void __exit omap_mbox_exit(void) |
415 | { | 401 | { |
416 | destroy_workqueue(mboxd); | 402 | destroy_workqueue(mboxd); |
403 | class_unregister(&omap_mbox_class); | ||
417 | } | 404 | } |
418 | module_exit(omap_mbox_exit); | 405 | module_exit(omap_mbox_exit); |
419 | 406 | ||
420 | MODULE_LICENSE("GPL v2"); | 407 | MODULE_LICENSE("GPL v2"); |
421 | MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); | 408 | MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); |
422 | MODULE_AUTHOR("Toshihiro Kobayashi and Hiroshi DOYU"); | 409 | MODULE_AUTHOR("Toshihiro Kobayashi"); |
410 | MODULE_AUTHOR("Hiroshi DOYU"); | ||