• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mailbox reservation modules for OMAP2/3
3  *
4  * Copyright (C) 2006-2009 Nokia Corporation
5  * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
6  *        and  Paul Mundt
7  *
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
10  * for more details.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/clk.h>
15 #include <linux/err.h>
16 #include <linux/platform_device.h>
17 #include <linux/io.h>
18 #include <linux/pm_runtime.h>
19 
20 #include <plat/mailbox.h>
21 
22 #include "soc.h"
23 
24 #define MAILBOX_REVISION		0x000
25 #define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
26 #define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
27 #define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
28 #define MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
29 #define MAILBOX_IRQENABLE(u)		(0x104 + 8 * (u))
30 
31 #define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
32 #define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
33 #define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
34 
35 #define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
36 #define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
37 
38 #define MBOX_REG_SIZE			0x120
39 
40 #define OMAP4_MBOX_REG_SIZE		0x130
41 
42 #define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
43 #define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
44 
45 static void __iomem *mbox_base;
46 
47 struct omap_mbox2_fifo {
48 	unsigned long msg;
49 	unsigned long fifo_stat;
50 	unsigned long msg_stat;
51 };
52 
53 struct omap_mbox2_priv {
54 	struct omap_mbox2_fifo tx_fifo;
55 	struct omap_mbox2_fifo rx_fifo;
56 	unsigned long irqenable;
57 	unsigned long irqstatus;
58 	u32 newmsg_bit;
59 	u32 notfull_bit;
60 	u32 ctx[OMAP4_MBOX_NR_REGS];
61 	unsigned long irqdisable;
62 };
63 
64 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
65 				  omap_mbox_type_t irq);
66 
mbox_read_reg(size_t ofs)67 static inline unsigned int mbox_read_reg(size_t ofs)
68 {
69 	return __raw_readl(mbox_base + ofs);
70 }
71 
mbox_write_reg(u32 val,size_t ofs)72 static inline void mbox_write_reg(u32 val, size_t ofs)
73 {
74 	__raw_writel(val, mbox_base + ofs);
75 }
76 
77 /* Mailbox H/W preparations */
omap2_mbox_startup(struct omap_mbox * mbox)78 static int omap2_mbox_startup(struct omap_mbox *mbox)
79 {
80 	u32 l;
81 
82 	pm_runtime_enable(mbox->dev->parent);
83 	pm_runtime_get_sync(mbox->dev->parent);
84 
85 	l = mbox_read_reg(MAILBOX_REVISION);
86 	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
87 
88 	return 0;
89 }
90 
omap2_mbox_shutdown(struct omap_mbox * mbox)91 static void omap2_mbox_shutdown(struct omap_mbox *mbox)
92 {
93 	pm_runtime_put_sync(mbox->dev->parent);
94 	pm_runtime_disable(mbox->dev->parent);
95 }
96 
97 /* Mailbox FIFO handle functions */
omap2_mbox_fifo_read(struct omap_mbox * mbox)98 static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
99 {
100 	struct omap_mbox2_fifo *fifo =
101 		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
102 	return (mbox_msg_t) mbox_read_reg(fifo->msg);
103 }
104 
omap2_mbox_fifo_write(struct omap_mbox * mbox,mbox_msg_t msg)105 static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
106 {
107 	struct omap_mbox2_fifo *fifo =
108 		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
109 	mbox_write_reg(msg, fifo->msg);
110 }
111 
omap2_mbox_fifo_empty(struct omap_mbox * mbox)112 static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
113 {
114 	struct omap_mbox2_fifo *fifo =
115 		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
116 	return (mbox_read_reg(fifo->msg_stat) == 0);
117 }
118 
omap2_mbox_fifo_full(struct omap_mbox * mbox)119 static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
120 {
121 	struct omap_mbox2_fifo *fifo =
122 		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
123 	return mbox_read_reg(fifo->fifo_stat);
124 }
125 
126 /* Mailbox IRQ handle functions */
omap2_mbox_enable_irq(struct omap_mbox * mbox,omap_mbox_type_t irq)127 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
128 		omap_mbox_type_t irq)
129 {
130 	struct omap_mbox2_priv *p = mbox->priv;
131 	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
132 
133 	l = mbox_read_reg(p->irqenable);
134 	l |= bit;
135 	mbox_write_reg(l, p->irqenable);
136 }
137 
omap2_mbox_disable_irq(struct omap_mbox * mbox,omap_mbox_type_t irq)138 static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
139 		omap_mbox_type_t irq)
140 {
141 	struct omap_mbox2_priv *p = mbox->priv;
142 	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
143 
144 	if (!cpu_is_omap44xx())
145 		bit = mbox_read_reg(p->irqdisable) & ~bit;
146 
147 	mbox_write_reg(bit, p->irqdisable);
148 }
149 
omap2_mbox_ack_irq(struct omap_mbox * mbox,omap_mbox_type_t irq)150 static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
151 		omap_mbox_type_t irq)
152 {
153 	struct omap_mbox2_priv *p = mbox->priv;
154 	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
155 
156 	mbox_write_reg(bit, p->irqstatus);
157 
158 	/* Flush posted write for irq status to avoid spurious interrupts */
159 	mbox_read_reg(p->irqstatus);
160 }
161 
omap2_mbox_is_irq(struct omap_mbox * mbox,omap_mbox_type_t irq)162 static int omap2_mbox_is_irq(struct omap_mbox *mbox,
163 		omap_mbox_type_t irq)
164 {
165 	struct omap_mbox2_priv *p = mbox->priv;
166 	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
167 	u32 enable = mbox_read_reg(p->irqenable);
168 	u32 status = mbox_read_reg(p->irqstatus);
169 
170 	return (int)(enable & status & bit);
171 }
172 
omap2_mbox_save_ctx(struct omap_mbox * mbox)173 static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
174 {
175 	int i;
176 	struct omap_mbox2_priv *p = mbox->priv;
177 	int nr_regs;
178 	if (cpu_is_omap44xx())
179 		nr_regs = OMAP4_MBOX_NR_REGS;
180 	else
181 		nr_regs = MBOX_NR_REGS;
182 	for (i = 0; i < nr_regs; i++) {
183 		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
184 
185 		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
186 			i, p->ctx[i]);
187 	}
188 }
189 
omap2_mbox_restore_ctx(struct omap_mbox * mbox)190 static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
191 {
192 	int i;
193 	struct omap_mbox2_priv *p = mbox->priv;
194 	int nr_regs;
195 	if (cpu_is_omap44xx())
196 		nr_regs = OMAP4_MBOX_NR_REGS;
197 	else
198 		nr_regs = MBOX_NR_REGS;
199 	for (i = 0; i < nr_regs; i++) {
200 		mbox_write_reg(p->ctx[i], i * sizeof(u32));
201 
202 		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
203 			i, p->ctx[i]);
204 	}
205 }
206 
207 static struct omap_mbox_ops omap2_mbox_ops = {
208 	.type		= OMAP_MBOX_TYPE2,
209 	.startup	= omap2_mbox_startup,
210 	.shutdown	= omap2_mbox_shutdown,
211 	.fifo_read	= omap2_mbox_fifo_read,
212 	.fifo_write	= omap2_mbox_fifo_write,
213 	.fifo_empty	= omap2_mbox_fifo_empty,
214 	.fifo_full	= omap2_mbox_fifo_full,
215 	.enable_irq	= omap2_mbox_enable_irq,
216 	.disable_irq	= omap2_mbox_disable_irq,
217 	.ack_irq	= omap2_mbox_ack_irq,
218 	.is_irq		= omap2_mbox_is_irq,
219 	.save_ctx	= omap2_mbox_save_ctx,
220 	.restore_ctx	= omap2_mbox_restore_ctx,
221 };
222 
223 /*
224  * MAILBOX 0: ARM -> DSP,
225  * MAILBOX 1: ARM <- DSP.
226  * MAILBOX 2: ARM -> IVA,
227  * MAILBOX 3: ARM <- IVA.
228  */
229 
230 /* FIXME: the following structs should be filled automatically by the user id */
231 
232 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2)
233 /* DSP */
234 static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
235 	.tx_fifo = {
236 		.msg		= MAILBOX_MESSAGE(0),
237 		.fifo_stat	= MAILBOX_FIFOSTATUS(0),
238 	},
239 	.rx_fifo = {
240 		.msg		= MAILBOX_MESSAGE(1),
241 		.msg_stat	= MAILBOX_MSGSTATUS(1),
242 	},
243 	.irqenable	= MAILBOX_IRQENABLE(0),
244 	.irqstatus	= MAILBOX_IRQSTATUS(0),
245 	.notfull_bit	= MAILBOX_IRQ_NOTFULL(0),
246 	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(1),
247 	.irqdisable	= MAILBOX_IRQENABLE(0),
248 };
249 
250 struct omap_mbox mbox_dsp_info = {
251 	.name	= "dsp",
252 	.ops	= &omap2_mbox_ops,
253 	.priv	= &omap2_mbox_dsp_priv,
254 };
255 #endif
256 
257 #if defined(CONFIG_ARCH_OMAP3)
258 struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
259 #endif
260 
261 #if defined(CONFIG_SOC_OMAP2420)
262 /* IVA */
263 static struct omap_mbox2_priv omap2_mbox_iva_priv = {
264 	.tx_fifo = {
265 		.msg		= MAILBOX_MESSAGE(2),
266 		.fifo_stat	= MAILBOX_FIFOSTATUS(2),
267 	},
268 	.rx_fifo = {
269 		.msg		= MAILBOX_MESSAGE(3),
270 		.msg_stat	= MAILBOX_MSGSTATUS(3),
271 	},
272 	.irqenable	= MAILBOX_IRQENABLE(3),
273 	.irqstatus	= MAILBOX_IRQSTATUS(3),
274 	.notfull_bit	= MAILBOX_IRQ_NOTFULL(2),
275 	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(3),
276 	.irqdisable	= MAILBOX_IRQENABLE(3),
277 };
278 
279 static struct omap_mbox mbox_iva_info = {
280 	.name	= "iva",
281 	.ops	= &omap2_mbox_ops,
282 	.priv	= &omap2_mbox_iva_priv,
283 };
284 #endif
285 
286 #ifdef CONFIG_ARCH_OMAP2
287 struct omap_mbox *omap2_mboxes[] = {
288 	&mbox_dsp_info,
289 #ifdef CONFIG_SOC_OMAP2420
290 	&mbox_iva_info,
291 #endif
292 	NULL
293 };
294 #endif
295 
296 #if defined(CONFIG_ARCH_OMAP4)
297 /* OMAP4 */
298 static struct omap_mbox2_priv omap2_mbox_1_priv = {
299 	.tx_fifo = {
300 		.msg		= MAILBOX_MESSAGE(0),
301 		.fifo_stat	= MAILBOX_FIFOSTATUS(0),
302 	},
303 	.rx_fifo = {
304 		.msg		= MAILBOX_MESSAGE(1),
305 		.msg_stat	= MAILBOX_MSGSTATUS(1),
306 	},
307 	.irqenable	= OMAP4_MAILBOX_IRQENABLE(0),
308 	.irqstatus	= OMAP4_MAILBOX_IRQSTATUS(0),
309 	.notfull_bit	= MAILBOX_IRQ_NOTFULL(0),
310 	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(1),
311 	.irqdisable	= OMAP4_MAILBOX_IRQENABLE_CLR(0),
312 };
313 
314 struct omap_mbox mbox_1_info = {
315 	.name	= "mailbox-1",
316 	.ops	= &omap2_mbox_ops,
317 	.priv	= &omap2_mbox_1_priv,
318 };
319 
320 static struct omap_mbox2_priv omap2_mbox_2_priv = {
321 	.tx_fifo = {
322 		.msg		= MAILBOX_MESSAGE(3),
323 		.fifo_stat	= MAILBOX_FIFOSTATUS(3),
324 	},
325 	.rx_fifo = {
326 		.msg		= MAILBOX_MESSAGE(2),
327 		.msg_stat	= MAILBOX_MSGSTATUS(2),
328 	},
329 	.irqenable	= OMAP4_MAILBOX_IRQENABLE(0),
330 	.irqstatus	= OMAP4_MAILBOX_IRQSTATUS(0),
331 	.notfull_bit	= MAILBOX_IRQ_NOTFULL(3),
332 	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(2),
333 	.irqdisable     = OMAP4_MAILBOX_IRQENABLE_CLR(0),
334 };
335 
336 struct omap_mbox mbox_2_info = {
337 	.name	= "mailbox-2",
338 	.ops	= &omap2_mbox_ops,
339 	.priv	= &omap2_mbox_2_priv,
340 };
341 
342 struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL };
343 #endif
344 
omap2_mbox_probe(struct platform_device * pdev)345 static int omap2_mbox_probe(struct platform_device *pdev)
346 {
347 	struct resource *mem;
348 	int ret;
349 	struct omap_mbox **list;
350 
351 	if (false)
352 		;
353 #if defined(CONFIG_ARCH_OMAP3)
354 	else if (cpu_is_omap34xx()) {
355 		list = omap3_mboxes;
356 
357 		list[0]->irq = platform_get_irq(pdev, 0);
358 	}
359 #endif
360 #if defined(CONFIG_ARCH_OMAP2)
361 	else if (cpu_is_omap2430()) {
362 		list = omap2_mboxes;
363 
364 		list[0]->irq = platform_get_irq(pdev, 0);
365 	} else if (cpu_is_omap2420()) {
366 		list = omap2_mboxes;
367 
368 		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
369 		list[1]->irq = platform_get_irq_byname(pdev, "iva");
370 	}
371 #endif
372 #if defined(CONFIG_ARCH_OMAP4)
373 	else if (cpu_is_omap44xx()) {
374 		list = omap4_mboxes;
375 
376 		list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0);
377 	}
378 #endif
379 	else {
380 		pr_err("%s: platform not supported\n", __func__);
381 		return -ENODEV;
382 	}
383 
384 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
385 	mbox_base = ioremap(mem->start, resource_size(mem));
386 	if (!mbox_base)
387 		return -ENOMEM;
388 
389 	ret = omap_mbox_register(&pdev->dev, list);
390 	if (ret) {
391 		iounmap(mbox_base);
392 		return ret;
393 	}
394 
395 	return 0;
396 }
397 
omap2_mbox_remove(struct platform_device * pdev)398 static int omap2_mbox_remove(struct platform_device *pdev)
399 {
400 	omap_mbox_unregister();
401 	iounmap(mbox_base);
402 	return 0;
403 }
404 
405 static struct platform_driver omap2_mbox_driver = {
406 	.probe = omap2_mbox_probe,
407 	.remove = omap2_mbox_remove,
408 	.driver = {
409 		.name = "omap-mailbox",
410 	},
411 };
412 
omap2_mbox_init(void)413 static int __init omap2_mbox_init(void)
414 {
415 	return platform_driver_register(&omap2_mbox_driver);
416 }
417 
omap2_mbox_exit(void)418 static void __exit omap2_mbox_exit(void)
419 {
420 	platform_driver_unregister(&omap2_mbox_driver);
421 }
422 
423 module_init(omap2_mbox_init);
424 module_exit(omap2_mbox_exit);
425 
426 MODULE_LICENSE("GPL v2");
427 MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
428 MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
429 MODULE_AUTHOR("Paul Mundt");
430 MODULE_ALIAS("platform:omap2-mailbox");
431