1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
|
/*
* Mailbox reservation modules for OMAP2
*
* Copyright (C) 2006 Nokia Corporation
* Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
* and Paul Mundt <paul.mundt@nokia.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <asm/arch/mailbox.h>
#include <asm/arch/irqs.h>
#include <asm/io.h>
#define MAILBOX_REVISION 0x00
#define MAILBOX_SYSCONFIG 0x10
#define MAILBOX_SYSSTATUS 0x14
#define MAILBOX_MESSAGE_0 0x40
#define MAILBOX_MESSAGE_1 0x44
#define MAILBOX_MESSAGE_2 0x48
#define MAILBOX_MESSAGE_3 0x4c
#define MAILBOX_MESSAGE_4 0x50
#define MAILBOX_MESSAGE_5 0x54
#define MAILBOX_FIFOSTATUS_0 0x80
#define MAILBOX_FIFOSTATUS_1 0x84
#define MAILBOX_FIFOSTATUS_2 0x88
#define MAILBOX_FIFOSTATUS_3 0x8c
#define MAILBOX_FIFOSTATUS_4 0x90
#define MAILBOX_FIFOSTATUS_5 0x94
#define MAILBOX_MSGSTATUS_0 0xc0
#define MAILBOX_MSGSTATUS_1 0xc4
#define MAILBOX_MSGSTATUS_2 0xc8
#define MAILBOX_MSGSTATUS_3 0xcc
#define MAILBOX_MSGSTATUS_4 0xd0
#define MAILBOX_MSGSTATUS_5 0xd4
#define MAILBOX_IRQSTATUS_0 0x100
#define MAILBOX_IRQENABLE_0 0x104
#define MAILBOX_IRQSTATUS_1 0x108
#define MAILBOX_IRQENABLE_1 0x10c
#define MAILBOX_IRQSTATUS_2 0x110
#define MAILBOX_IRQENABLE_2 0x114
#define MAILBOX_IRQSTATUS_3 0x118
#define MAILBOX_IRQENABLE_3 0x11c
static unsigned long mbox_base;
#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1))
#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n)))
struct omap_mbox2_fifo {
unsigned long msg;
unsigned long fifo_stat;
unsigned long msg_stat;
};
struct omap_mbox2_priv {
struct omap_mbox2_fifo tx_fifo;
struct omap_mbox2_fifo rx_fifo;
unsigned long irqenable;
unsigned long irqstatus;
u32 newmsg_bit;
u32 notfull_bit;
};
static struct clk *mbox_ick_handle;
static inline unsigned int mbox_read_reg(unsigned int reg)
{
return __raw_readl(mbox_base + reg);
}
static inline void mbox_write_reg(unsigned int val, unsigned int reg)
{
__raw_writel(val, mbox_base + reg);
}
/* Mailbox H/W preparations */
static inline int omap2_mbox_startup(struct omap_mbox *mbox)
{
unsigned int l;
mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
if (IS_ERR(mbox_ick_handle)) {
printk("Could not get mailboxes_ick\n");
return -ENODEV;
}
clk_enable(mbox_ick_handle);
/* set smart-idle & autoidle */
l = mbox_read_reg(MAILBOX_SYSCONFIG);
l |= 0x00000011;
mbox_write_reg(l, MAILBOX_SYSCONFIG);
return 0;
}
static inline void omap2_mbox_shutdown(struct omap_mbox *mbox)
{
clk_disable(mbox_ick_handle);
clk_put(mbox_ick_handle);
}
/* Mailbox FIFO handle functions */
static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
{
struct omap_mbox2_fifo *fifo =
&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
return (mbox_msg_t) mbox_read_reg(fifo->msg);
}
static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
struct omap_mbox2_fifo *fifo =
&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
mbox_write_reg(msg, fifo->msg);
}
static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
{
struct omap_mbox2_fifo *fifo =
&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
return (mbox_read_reg(fifo->msg_stat) == 0);
}
static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox)
{
struct omap_mbox2_fifo *fifo =
&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
return (mbox_read_reg(fifo->fifo_stat));
}
/* Mailbox IRQ handle functions */
static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
l = mbox_read_reg(p->irqenable);
l |= bit;
mbox_write_reg(l, p->irqenable);
}
static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
l = mbox_read_reg(p->irqenable);
l &= ~bit;
mbox_write_reg(l, p->irqenable);
}
static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
mbox_write_reg(bit, p->irqstatus);
}
static inline int omap2_mbox_is_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
u32 enable = mbox_read_reg(p->irqenable);
u32 status = mbox_read_reg(p->irqstatus);
return (enable & status & bit);
}
static struct omap_mbox_ops omap2_mbox_ops = {
.type = OMAP_MBOX_TYPE2,
.startup = omap2_mbox_startup,
.shutdown = omap2_mbox_shutdown,
.fifo_read = omap2_mbox_fifo_read,
.fifo_write = omap2_mbox_fifo_write,
.fifo_empty = omap2_mbox_fifo_empty,
.fifo_full = omap2_mbox_fifo_full,
.enable_irq = omap2_mbox_enable_irq,
.disable_irq = omap2_mbox_disable_irq,
.ack_irq = omap2_mbox_ack_irq,
.is_irq = omap2_mbox_is_irq,
};
/*
* MAILBOX 0: ARM -> DSP,
* MAILBOX 1: ARM <- DSP.
* MAILBOX 2: ARM -> IVA,
* MAILBOX 3: ARM <- IVA.
*/
/* FIXME: the following structs should be filled automatically by the user id */
/* DSP */
static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
.tx_fifo = {
.msg = MAILBOX_MESSAGE_0,
.fifo_stat = MAILBOX_FIFOSTATUS_0,
},
.rx_fifo = {
.msg = MAILBOX_MESSAGE_1,
.msg_stat = MAILBOX_MSGSTATUS_1,
},
.irqenable = MAILBOX_IRQENABLE_0,
.irqstatus = MAILBOX_IRQSTATUS_0,
.notfull_bit = MAILBOX_IRQ_NOTFULL(0),
.newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
};
struct omap_mbox mbox_dsp_info = {
.name = "dsp",
.ops = &omap2_mbox_ops,
.priv = &omap2_mbox_dsp_priv,
};
EXPORT_SYMBOL(mbox_dsp_info);
/* IVA */
static struct omap_mbox2_priv omap2_mbox_iva_priv = {
.tx_fifo = {
.msg = MAILBOX_MESSAGE_2,
.fifo_stat = MAILBOX_FIFOSTATUS_2,
},
.rx_fifo = {
.msg = MAILBOX_MESSAGE_3,
.msg_stat = MAILBOX_MSGSTATUS_3,
},
.irqenable = MAILBOX_IRQENABLE_3,
.irqstatus = MAILBOX_IRQSTATUS_3,
.notfull_bit = MAILBOX_IRQ_NOTFULL(2),
.newmsg_bit = MAILBOX_IRQ_NEWMSG(3),
};
static struct omap_mbox mbox_iva_info = {
.name = "iva",
.ops = &omap2_mbox_ops,
.priv = &omap2_mbox_iva_priv,
};
static int __init omap2_mbox_probe(struct platform_device *pdev)
{
struct resource *res;
int ret = 0;
if (pdev->num_resources != 3) {
dev_err(&pdev->dev, "invalid number of resources: %d\n",
pdev->num_resources);
return -ENODEV;
}
/* MBOX base */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid mem resource\n");
return -ENODEV;
}
mbox_base = res->start;
/* DSP IRQ */
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid irq resource\n");
return -ENODEV;
}
mbox_dsp_info.irq = res->start;
ret = omap_mbox_register(&mbox_dsp_info);
/* IVA IRQ */
res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid irq resource\n");
return -ENODEV;
}
mbox_iva_info.irq = res->start;
ret = omap_mbox_register(&mbox_iva_info);
return ret;
}
static int omap2_mbox_remove(struct platform_device *pdev)
{
omap_mbox_unregister(&mbox_dsp_info);
return 0;
}
static struct platform_driver omap2_mbox_driver = {
.probe = omap2_mbox_probe,
.remove = omap2_mbox_remove,
.driver = {
.name = "mailbox",
},
};
static int __init omap2_mbox_init(void)
{
return platform_driver_register(&omap2_mbox_driver);
}
static void __exit omap2_mbox_exit(void)
{
platform_driver_unregister(&omap2_mbox_driver);
}
module_init(omap2_mbox_init);
module_exit(omap2_mbox_exit);
MODULE_LICENSE("GPL");
|