diff options
Diffstat (limited to 'arch/arm/mach-omap2/mailbox.c')
-rw-r--r-- | arch/arm/mach-omap2/mailbox.c | 195 |
1 files changed, 113 insertions, 82 deletions
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 32b7af3c610b..fd5b8a5925cc 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Mailbox reservation modules for OMAP2 | 2 | * Mailbox reservation modules for OMAP2/3 |
3 | * | 3 | * |
4 | * Copyright (C) 2006 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> |
6 | * and Paul Mundt <paul.mundt@nokia.com> | 6 | * and Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -18,40 +18,22 @@ | |||
18 | #include <mach/mailbox.h> | 18 | #include <mach/mailbox.h> |
19 | #include <mach/irqs.h> | 19 | #include <mach/irqs.h> |
20 | 20 | ||
21 | #define MAILBOX_REVISION 0x00 | 21 | #define MAILBOX_REVISION 0x000 |
22 | #define MAILBOX_SYSCONFIG 0x10 | 22 | #define MAILBOX_SYSCONFIG 0x010 |
23 | #define MAILBOX_SYSSTATUS 0x14 | 23 | #define MAILBOX_SYSSTATUS 0x014 |
24 | #define MAILBOX_MESSAGE_0 0x40 | 24 | #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) |
25 | #define MAILBOX_MESSAGE_1 0x44 | 25 | #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m)) |
26 | #define MAILBOX_MESSAGE_2 0x48 | 26 | #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m)) |
27 | #define MAILBOX_MESSAGE_3 0x4c | 27 | #define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u)) |
28 | #define MAILBOX_MESSAGE_4 0x50 | 28 | #define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u)) |
29 | #define MAILBOX_MESSAGE_5 0x54 | 29 | |
30 | #define MAILBOX_FIFOSTATUS_0 0x80 | 30 | #define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u))) |
31 | #define MAILBOX_FIFOSTATUS_1 0x84 | 31 | #define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1)) |
32 | #define MAILBOX_FIFOSTATUS_2 0x88 | 32 | |
33 | #define MAILBOX_FIFOSTATUS_3 0x8c | 33 | #define MBOX_REG_SIZE 0x120 |
34 | #define MAILBOX_FIFOSTATUS_4 0x90 | 34 | #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) |
35 | #define MAILBOX_FIFOSTATUS_5 0x94 | 35 | |
36 | #define MAILBOX_MSGSTATUS_0 0xc0 | 36 | static void __iomem *mbox_base; |
37 | #define MAILBOX_MSGSTATUS_1 0xc4 | ||
38 | #define MAILBOX_MSGSTATUS_2 0xc8 | ||
39 | #define MAILBOX_MSGSTATUS_3 0xcc | ||
40 | #define MAILBOX_MSGSTATUS_4 0xd0 | ||
41 | #define MAILBOX_MSGSTATUS_5 0xd4 | ||
42 | #define MAILBOX_IRQSTATUS_0 0x100 | ||
43 | #define MAILBOX_IRQENABLE_0 0x104 | ||
44 | #define MAILBOX_IRQSTATUS_1 0x108 | ||
45 | #define MAILBOX_IRQENABLE_1 0x10c | ||
46 | #define MAILBOX_IRQSTATUS_2 0x110 | ||
47 | #define MAILBOX_IRQENABLE_2 0x114 | ||
48 | #define MAILBOX_IRQSTATUS_3 0x118 | ||
49 | #define MAILBOX_IRQENABLE_3 0x11c | ||
50 | |||
51 | static unsigned long mbox_base; | ||
52 | |||
53 | #define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1)) | ||
54 | #define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n))) | ||
55 | 37 | ||
56 | struct omap_mbox2_fifo { | 38 | struct omap_mbox2_fifo { |
57 | unsigned long msg; | 39 | unsigned long msg; |
@@ -66,6 +48,7 @@ struct omap_mbox2_priv { | |||
66 | unsigned long irqstatus; | 48 | unsigned long irqstatus; |
67 | u32 newmsg_bit; | 49 | u32 newmsg_bit; |
68 | u32 notfull_bit; | 50 | u32 notfull_bit; |
51 | u32 ctx[MBOX_NR_REGS]; | ||
69 | }; | 52 | }; |
70 | 53 | ||
71 | static struct clk *mbox_ick_handle; | 54 | static struct clk *mbox_ick_handle; |
@@ -73,14 +56,14 @@ static struct clk *mbox_ick_handle; | |||
73 | static void omap2_mbox_enable_irq(struct omap_mbox *mbox, | 56 | static void omap2_mbox_enable_irq(struct omap_mbox *mbox, |
74 | omap_mbox_type_t irq); | 57 | omap_mbox_type_t irq); |
75 | 58 | ||
76 | static inline unsigned int mbox_read_reg(unsigned int reg) | 59 | static inline unsigned int mbox_read_reg(size_t ofs) |
77 | { | 60 | { |
78 | return __raw_readl(mbox_base + reg); | 61 | return __raw_readl(mbox_base + ofs); |
79 | } | 62 | } |
80 | 63 | ||
81 | static inline void mbox_write_reg(unsigned int val, unsigned int reg) | 64 | static inline void mbox_write_reg(u32 val, size_t ofs) |
82 | { | 65 | { |
83 | __raw_writel(val, mbox_base + reg); | 66 | __raw_writel(val, mbox_base + ofs); |
84 | } | 67 | } |
85 | 68 | ||
86 | /* Mailbox H/W preparations */ | 69 | /* Mailbox H/W preparations */ |
@@ -95,6 +78,9 @@ static int omap2_mbox_startup(struct omap_mbox *mbox) | |||
95 | } | 78 | } |
96 | clk_enable(mbox_ick_handle); | 79 | clk_enable(mbox_ick_handle); |
97 | 80 | ||
81 | l = mbox_read_reg(MAILBOX_REVISION); | ||
82 | pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); | ||
83 | |||
98 | /* set smart-idle & autoidle */ | 84 | /* set smart-idle & autoidle */ |
99 | l = mbox_read_reg(MAILBOX_SYSCONFIG); | 85 | l = mbox_read_reg(MAILBOX_SYSCONFIG); |
100 | l |= 0x00000011; | 86 | l |= 0x00000011; |
@@ -183,6 +169,32 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox, | |||
183 | return (enable & status & bit); | 169 | return (enable & status & bit); |
184 | } | 170 | } |
185 | 171 | ||
172 | static void omap2_mbox_save_ctx(struct omap_mbox *mbox) | ||
173 | { | ||
174 | int i; | ||
175 | struct omap_mbox2_priv *p = mbox->priv; | ||
176 | |||
177 | for (i = 0; i < MBOX_NR_REGS; i++) { | ||
178 | p->ctx[i] = mbox_read_reg(i * sizeof(u32)); | ||
179 | |||
180 | dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, | ||
181 | i, p->ctx[i]); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static void omap2_mbox_restore_ctx(struct omap_mbox *mbox) | ||
186 | { | ||
187 | int i; | ||
188 | struct omap_mbox2_priv *p = mbox->priv; | ||
189 | |||
190 | for (i = 0; i < MBOX_NR_REGS; i++) { | ||
191 | mbox_write_reg(p->ctx[i], i * sizeof(u32)); | ||
192 | |||
193 | dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, | ||
194 | i, p->ctx[i]); | ||
195 | } | ||
196 | } | ||
197 | |||
186 | static struct omap_mbox_ops omap2_mbox_ops = { | 198 | static struct omap_mbox_ops omap2_mbox_ops = { |
187 | .type = OMAP_MBOX_TYPE2, | 199 | .type = OMAP_MBOX_TYPE2, |
188 | .startup = omap2_mbox_startup, | 200 | .startup = omap2_mbox_startup, |
@@ -195,6 +207,8 @@ static struct omap_mbox_ops omap2_mbox_ops = { | |||
195 | .disable_irq = omap2_mbox_disable_irq, | 207 | .disable_irq = omap2_mbox_disable_irq, |
196 | .ack_irq = omap2_mbox_ack_irq, | 208 | .ack_irq = omap2_mbox_ack_irq, |
197 | .is_irq = omap2_mbox_is_irq, | 209 | .is_irq = omap2_mbox_is_irq, |
210 | .save_ctx = omap2_mbox_save_ctx, | ||
211 | .restore_ctx = omap2_mbox_restore_ctx, | ||
198 | }; | 212 | }; |
199 | 213 | ||
200 | /* | 214 | /* |
@@ -209,15 +223,15 @@ static struct omap_mbox_ops omap2_mbox_ops = { | |||
209 | /* DSP */ | 223 | /* DSP */ |
210 | static struct omap_mbox2_priv omap2_mbox_dsp_priv = { | 224 | static struct omap_mbox2_priv omap2_mbox_dsp_priv = { |
211 | .tx_fifo = { | 225 | .tx_fifo = { |
212 | .msg = MAILBOX_MESSAGE_0, | 226 | .msg = MAILBOX_MESSAGE(0), |
213 | .fifo_stat = MAILBOX_FIFOSTATUS_0, | 227 | .fifo_stat = MAILBOX_FIFOSTATUS(0), |
214 | }, | 228 | }, |
215 | .rx_fifo = { | 229 | .rx_fifo = { |
216 | .msg = MAILBOX_MESSAGE_1, | 230 | .msg = MAILBOX_MESSAGE(1), |
217 | .msg_stat = MAILBOX_MSGSTATUS_1, | 231 | .msg_stat = MAILBOX_MSGSTATUS(1), |
218 | }, | 232 | }, |
219 | .irqenable = MAILBOX_IRQENABLE_0, | 233 | .irqenable = MAILBOX_IRQENABLE(0), |
220 | .irqstatus = MAILBOX_IRQSTATUS_0, | 234 | .irqstatus = MAILBOX_IRQSTATUS(0), |
221 | .notfull_bit = MAILBOX_IRQ_NOTFULL(0), | 235 | .notfull_bit = MAILBOX_IRQ_NOTFULL(0), |
222 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), | 236 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), |
223 | }; | 237 | }; |
@@ -229,18 +243,18 @@ struct omap_mbox mbox_dsp_info = { | |||
229 | }; | 243 | }; |
230 | EXPORT_SYMBOL(mbox_dsp_info); | 244 | EXPORT_SYMBOL(mbox_dsp_info); |
231 | 245 | ||
232 | /* IVA */ | 246 | #if defined(CONFIG_ARCH_OMAP2420) /* IVA */ |
233 | static struct omap_mbox2_priv omap2_mbox_iva_priv = { | 247 | static struct omap_mbox2_priv omap2_mbox_iva_priv = { |
234 | .tx_fifo = { | 248 | .tx_fifo = { |
235 | .msg = MAILBOX_MESSAGE_2, | 249 | .msg = MAILBOX_MESSAGE(2), |
236 | .fifo_stat = MAILBOX_FIFOSTATUS_2, | 250 | .fifo_stat = MAILBOX_FIFOSTATUS(2), |
237 | }, | 251 | }, |
238 | .rx_fifo = { | 252 | .rx_fifo = { |
239 | .msg = MAILBOX_MESSAGE_3, | 253 | .msg = MAILBOX_MESSAGE(3), |
240 | .msg_stat = MAILBOX_MSGSTATUS_3, | 254 | .msg_stat = MAILBOX_MSGSTATUS(3), |
241 | }, | 255 | }, |
242 | .irqenable = MAILBOX_IRQENABLE_3, | 256 | .irqenable = MAILBOX_IRQENABLE(3), |
243 | .irqstatus = MAILBOX_IRQSTATUS_3, | 257 | .irqstatus = MAILBOX_IRQSTATUS(3), |
244 | .notfull_bit = MAILBOX_IRQ_NOTFULL(2), | 258 | .notfull_bit = MAILBOX_IRQ_NOTFULL(2), |
245 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), | 259 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), |
246 | }; | 260 | }; |
@@ -250,17 +264,12 @@ static struct omap_mbox mbox_iva_info = { | |||
250 | .ops = &omap2_mbox_ops, | 264 | .ops = &omap2_mbox_ops, |
251 | .priv = &omap2_mbox_iva_priv, | 265 | .priv = &omap2_mbox_iva_priv, |
252 | }; | 266 | }; |
267 | #endif | ||
253 | 268 | ||
254 | static int __init omap2_mbox_probe(struct platform_device *pdev) | 269 | static int __devinit omap2_mbox_probe(struct platform_device *pdev) |
255 | { | 270 | { |
256 | struct resource *res; | 271 | struct resource *res; |
257 | int ret = 0; | 272 | int ret; |
258 | |||
259 | if (pdev->num_resources != 3) { | ||
260 | dev_err(&pdev->dev, "invalid number of resources: %d\n", | ||
261 | pdev->num_resources); | ||
262 | return -ENODEV; | ||
263 | } | ||
264 | 273 | ||
265 | /* MBOX base */ | 274 | /* MBOX base */ |
266 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 275 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -268,42 +277,61 @@ static int __init omap2_mbox_probe(struct platform_device *pdev) | |||
268 | dev_err(&pdev->dev, "invalid mem resource\n"); | 277 | dev_err(&pdev->dev, "invalid mem resource\n"); |
269 | return -ENODEV; | 278 | return -ENODEV; |
270 | } | 279 | } |
271 | mbox_base = res->start; | 280 | mbox_base = ioremap(res->start, res->end - res->start); |
281 | if (!mbox_base) | ||
282 | return -ENOMEM; | ||
272 | 283 | ||
273 | /* DSP IRQ */ | 284 | /* DSP or IVA2 IRQ */ |
274 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 285 | mbox_dsp_info.irq = platform_get_irq(pdev, 0); |
275 | if (unlikely(!res)) { | 286 | if (mbox_dsp_info.irq < 0) { |
276 | dev_err(&pdev->dev, "invalid irq resource\n"); | 287 | dev_err(&pdev->dev, "invalid irq resource\n"); |
277 | return -ENODEV; | 288 | ret = -ENODEV; |
289 | goto err_dsp; | ||
278 | } | 290 | } |
279 | mbox_dsp_info.irq = res->start; | ||
280 | 291 | ||
281 | ret = omap_mbox_register(&mbox_dsp_info); | 292 | ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info); |
282 | 293 | if (ret) | |
283 | /* IVA IRQ */ | 294 | goto err_dsp; |
284 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | 295 | |
285 | if (unlikely(!res)) { | 296 | #if defined(CONFIG_ARCH_OMAP2420) /* IVA */ |
286 | dev_err(&pdev->dev, "invalid irq resource\n"); | 297 | if (cpu_is_omap2420()) { |
287 | return -ENODEV; | 298 | /* IVA IRQ */ |
299 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
300 | if (unlikely(!res)) { | ||
301 | dev_err(&pdev->dev, "invalid irq resource\n"); | ||
302 | ret = -ENODEV; | ||
303 | goto err_iva1; | ||
304 | } | ||
305 | mbox_iva_info.irq = res->start; | ||
306 | ret = omap_mbox_register(&pdev->dev, &mbox_iva_info); | ||
307 | if (ret) | ||
308 | goto err_iva1; | ||
288 | } | 309 | } |
289 | mbox_iva_info.irq = res->start; | 310 | #endif |
290 | 311 | return 0; | |
291 | ret = omap_mbox_register(&mbox_iva_info); | ||
292 | 312 | ||
313 | err_iva1: | ||
314 | omap_mbox_unregister(&mbox_dsp_info); | ||
315 | err_dsp: | ||
316 | iounmap(mbox_base); | ||
293 | return ret; | 317 | return ret; |
294 | } | 318 | } |
295 | 319 | ||
296 | static int omap2_mbox_remove(struct platform_device *pdev) | 320 | static int __devexit omap2_mbox_remove(struct platform_device *pdev) |
297 | { | 321 | { |
322 | #if defined(CONFIG_ARCH_OMAP2420) | ||
323 | omap_mbox_unregister(&mbox_iva_info); | ||
324 | #endif | ||
298 | omap_mbox_unregister(&mbox_dsp_info); | 325 | omap_mbox_unregister(&mbox_dsp_info); |
326 | iounmap(mbox_base); | ||
299 | return 0; | 327 | return 0; |
300 | } | 328 | } |
301 | 329 | ||
302 | static struct platform_driver omap2_mbox_driver = { | 330 | static struct platform_driver omap2_mbox_driver = { |
303 | .probe = omap2_mbox_probe, | 331 | .probe = omap2_mbox_probe, |
304 | .remove = omap2_mbox_remove, | 332 | .remove = __devexit_p(omap2_mbox_remove), |
305 | .driver = { | 333 | .driver = { |
306 | .name = "mailbox", | 334 | .name = "omap2-mailbox", |
307 | }, | 335 | }, |
308 | }; | 336 | }; |
309 | 337 | ||
@@ -320,4 +348,7 @@ static void __exit omap2_mbox_exit(void) | |||
320 | module_init(omap2_mbox_init); | 348 | module_init(omap2_mbox_init); |
321 | module_exit(omap2_mbox_exit); | 349 | module_exit(omap2_mbox_exit); |
322 | 350 | ||
323 | MODULE_LICENSE("GPL"); | 351 | MODULE_LICENSE("GPL v2"); |
352 | MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions"); | ||
353 | MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt"); | ||
354 | MODULE_ALIAS("platform:omap2-mailbox"); | ||