Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2025 Cix Technology Group Co., Ltd.
4 */
5
6#include <linux/device.h>
7#include <linux/err.h>
8#include <linux/io.h>
9#include <linux/interrupt.h>
10#include <linux/kernel.h>
11#include <linux/mailbox_controller.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14
15/*
16 * The maximum transmission size is 32 words or 128 bytes.
17 */
18#define CIX_MBOX_MSG_WORDS 32 /* Max length = 32 words */
19#define CIX_MBOX_MSG_LEN_MASK 0x7fL /* Max length = 128 bytes */
20
21/* [0~7] Fast channel
22 * [8] doorbell base channel
23 * [9]fifo base channel
24 * [10] register base channel
25 */
26#define CIX_MBOX_FAST_IDX 7
27#define CIX_MBOX_DB_IDX 8
28#define CIX_MBOX_FIFO_IDX 9
29#define CIX_MBOX_REG_IDX 10
30#define CIX_MBOX_CHANS 11
31
32/* Register define */
33#define CIX_REG_MSG(n) (0x0 + 0x4*(n)) /* 0x0~0x7c */
34#define CIX_REG_DB_ACK CIX_REG_MSG(CIX_MBOX_MSG_WORDS) /* 0x80 */
35#define CIX_ERR_COMP (CIX_REG_DB_ACK + 0x4) /* 0x84 */
36#define CIX_ERR_COMP_CLR (CIX_REG_DB_ACK + 0x8) /* 0x88 */
37#define CIX_REG_F_INT(IDX) (CIX_ERR_COMP_CLR + 0x4*(IDX+1)) /* 0x8c~0xa8 */
38#define CIX_FIFO_WR (CIX_REG_F_INT(CIX_MBOX_FAST_IDX+1)) /* 0xac */
39#define CIX_FIFO_RD (CIX_FIFO_WR + 0x4) /* 0xb0 */
40#define CIX_FIFO_STAS (CIX_FIFO_WR + 0x8) /* 0xb4 */
41#define CIX_FIFO_WM (CIX_FIFO_WR + 0xc) /* 0xb8 */
42#define CIX_INT_ENABLE (CIX_FIFO_WR + 0x10) /* 0xbc */
43#define CIX_INT_ENABLE_SIDE_B (CIX_FIFO_WR + 0x14) /* 0xc0 */
44#define CIX_INT_CLEAR (CIX_FIFO_WR + 0x18) /* 0xc4 */
45#define CIX_INT_STATUS (CIX_FIFO_WR + 0x1c) /* 0xc8 */
46#define CIX_FIFO_RST (CIX_FIFO_WR + 0x20) /* 0xcc */
47
48#define CIX_MBOX_TX 0
49#define CIX_MBOX_RX 1
50
51#define CIX_DB_INT_BIT BIT(0)
52#define CIX_DB_ACK_INT_BIT BIT(1)
53
54#define CIX_FIFO_WM_DEFAULT CIX_MBOX_MSG_WORDS
55#define CIX_FIFO_STAS_WMK BIT(0)
56#define CIX_FIFO_STAS_FULL BIT(1)
57#define CIX_FIFO_STAS_EMPTY BIT(2)
58#define CIX_FIFO_STAS_UFLOW BIT(3)
59#define CIX_FIFO_STAS_OFLOW BIT(4)
60
61#define CIX_FIFO_RST_BIT BIT(0)
62
63#define CIX_DB_INT BIT(0)
64#define CIX_ACK_INT BIT(1)
65#define CIX_FIFO_FULL_INT BIT(2)
66#define CIX_FIFO_EMPTY_INT BIT(3)
67#define CIX_FIFO_WM01_INT BIT(4)
68#define CIX_FIFO_WM10_INT BIT(5)
69#define CIX_FIFO_OFLOW_INT BIT(6)
70#define CIX_FIFO_UFLOW_INT BIT(7)
71#define CIX_FIFO_N_EMPTY_INT BIT(8)
72#define CIX_FAST_CH_INT(IDX) BIT((IDX)+9)
73
74#define CIX_SHMEM_OFFSET 0x80
75
76enum cix_mbox_chan_type {
77 CIX_MBOX_TYPE_DB,
78 CIX_MBOX_TYPE_REG,
79 CIX_MBOX_TYPE_FIFO,
80 CIX_MBOX_TYPE_FAST,
81};
82
83struct cix_mbox_con_priv {
84 enum cix_mbox_chan_type type;
85 struct mbox_chan *chan;
86 int index;
87};
88
89struct cix_mbox_priv {
90 struct device *dev;
91 int irq;
92 int dir;
93 void __iomem *base; /* region for mailbox */
94 struct cix_mbox_con_priv con_priv[CIX_MBOX_CHANS];
95 struct mbox_chan mbox_chans[CIX_MBOX_CHANS];
96 struct mbox_controller mbox;
97 bool use_shmem;
98};
99
100/*
101 * The CIX mailbox supports four types of transfers:
102 * CIX_MBOX_TYPE_DB, CIX_MBOX_TYPE_FAST, CIX_MBOX_TYPE_REG, and CIX_MBOX_TYPE_FIFO.
103 * For the REG and FIFO types of transfers, the message format is as follows:
104 */
105union cix_mbox_msg_reg_fifo {
106 u32 length; /* unit is byte */
107 u32 buf[CIX_MBOX_MSG_WORDS]; /* buf[0] must be the byte length of this array */
108};
109
110static struct cix_mbox_priv *to_cix_mbox_priv(struct mbox_controller *mbox)
111{
112 return container_of(mbox, struct cix_mbox_priv, mbox);
113}
114
115static void cix_mbox_write(struct cix_mbox_priv *priv, u32 val, u32 offset)
116{
117 if (priv->use_shmem)
118 iowrite32(val, priv->base + offset - CIX_SHMEM_OFFSET);
119 else
120 iowrite32(val, priv->base + offset);
121}
122
123static u32 cix_mbox_read(struct cix_mbox_priv *priv, u32 offset)
124{
125 if (priv->use_shmem)
126 return ioread32(priv->base + offset - CIX_SHMEM_OFFSET);
127 else
128 return ioread32(priv->base + offset);
129}
130
131static bool mbox_fifo_empty(struct mbox_chan *chan)
132{
133 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
134
135 return ((cix_mbox_read(priv, CIX_FIFO_STAS) & CIX_FIFO_STAS_EMPTY) ? true : false);
136}
137
138/*
139 *The transmission unit of the CIX mailbox is word.
140 *The byte length should be converted into the word length.
141 */
142static inline u32 mbox_get_msg_size(void *msg)
143{
144 u32 len;
145
146 len = ((u32 *)msg)[0] & CIX_MBOX_MSG_LEN_MASK;
147 return DIV_ROUND_UP(len, 4);
148}
149
150static int cix_mbox_send_data_db(struct mbox_chan *chan, void *data)
151{
152 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
153
154 /* trigger doorbell irq */
155 cix_mbox_write(priv, CIX_DB_INT_BIT, CIX_REG_DB_ACK);
156
157 return 0;
158}
159
160static int cix_mbox_send_data_reg(struct mbox_chan *chan, void *data)
161{
162 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
163 union cix_mbox_msg_reg_fifo *msg = data;
164 u32 len, i;
165
166 if (!data)
167 return -EINVAL;
168
169 len = mbox_get_msg_size(data);
170 for (i = 0; i < len; i++)
171 cix_mbox_write(priv, msg->buf[i], CIX_REG_MSG(i));
172
173 /* trigger doorbell irq */
174 cix_mbox_write(priv, CIX_DB_INT_BIT, CIX_REG_DB_ACK);
175
176 return 0;
177}
178
179static int cix_mbox_send_data_fifo(struct mbox_chan *chan, void *data)
180{
181 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
182 union cix_mbox_msg_reg_fifo *msg = data;
183 u32 len, val, i;
184
185 if (!data)
186 return -EINVAL;
187
188 len = mbox_get_msg_size(data);
189 cix_mbox_write(priv, len, CIX_FIFO_WM);
190 for (i = 0; i < len; i++)
191 cix_mbox_write(priv, msg->buf[i], CIX_FIFO_WR);
192
193 /* Enable fifo empty interrupt */
194 val = cix_mbox_read(priv, CIX_INT_ENABLE);
195 val |= CIX_FIFO_EMPTY_INT;
196 cix_mbox_write(priv, val, CIX_INT_ENABLE);
197
198 return 0;
199}
200
201static int cix_mbox_send_data_fast(struct mbox_chan *chan, void *data)
202{
203 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
204 struct cix_mbox_con_priv *cp = chan->con_priv;
205 u32 *arg = (u32 *)data;
206 int index = cp->index;
207
208 if (!data)
209 return -EINVAL;
210
211 if (index < 0 || index > CIX_MBOX_FAST_IDX) {
212 dev_err(priv->dev, "Invalid Mbox index %d\n", index);
213 return -EINVAL;
214 }
215
216 cix_mbox_write(priv, arg[0], CIX_REG_F_INT(index));
217
218 return 0;
219}
220
221static int cix_mbox_send_data(struct mbox_chan *chan, void *data)
222{
223 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
224 struct cix_mbox_con_priv *cp = chan->con_priv;
225
226 if (priv->dir != CIX_MBOX_TX) {
227 dev_err(priv->dev, "Invalid Mbox dir %d\n", priv->dir);
228 return -EINVAL;
229 }
230
231 switch (cp->type) {
232 case CIX_MBOX_TYPE_DB:
233 cix_mbox_send_data_db(chan, data);
234 break;
235 case CIX_MBOX_TYPE_REG:
236 cix_mbox_send_data_reg(chan, data);
237 break;
238 case CIX_MBOX_TYPE_FIFO:
239 cix_mbox_send_data_fifo(chan, data);
240 break;
241 case CIX_MBOX_TYPE_FAST:
242 cix_mbox_send_data_fast(chan, data);
243 break;
244 default:
245 dev_err(priv->dev, "Invalid channel type: %d\n", cp->type);
246 return -EINVAL;
247 }
248 return 0;
249}
250
251static void cix_mbox_isr_db(struct mbox_chan *chan)
252{
253 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
254 u32 int_status;
255
256 int_status = cix_mbox_read(priv, CIX_INT_STATUS);
257
258 if (priv->dir == CIX_MBOX_RX) {
259 /* rx interrupt is triggered */
260 if (int_status & CIX_DB_INT) {
261 cix_mbox_write(priv, CIX_DB_INT, CIX_INT_CLEAR);
262 mbox_chan_received_data(chan, NULL);
263 /* trigger ack interrupt */
264 cix_mbox_write(priv, CIX_DB_ACK_INT_BIT, CIX_REG_DB_ACK);
265 }
266 } else {
267 /* tx ack interrupt is triggered */
268 if (int_status & CIX_ACK_INT) {
269 cix_mbox_write(priv, CIX_ACK_INT, CIX_INT_CLEAR);
270 mbox_chan_received_data(chan, NULL);
271 }
272 }
273}
274
275static void cix_mbox_isr_reg(struct mbox_chan *chan)
276{
277 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
278 u32 int_status;
279
280 int_status = cix_mbox_read(priv, CIX_INT_STATUS);
281
282 if (priv->dir == CIX_MBOX_RX) {
283 /* rx interrupt is triggered */
284 if (int_status & CIX_DB_INT) {
285 u32 data[CIX_MBOX_MSG_WORDS], len, i;
286
287 cix_mbox_write(priv, CIX_DB_INT, CIX_INT_CLEAR);
288 data[0] = cix_mbox_read(priv, CIX_REG_MSG(0));
289 len = mbox_get_msg_size(data);
290 for (i = 1; i < len; i++)
291 data[i] = cix_mbox_read(priv, CIX_REG_MSG(i));
292
293 /* trigger ack interrupt */
294 cix_mbox_write(priv, CIX_DB_ACK_INT_BIT, CIX_REG_DB_ACK);
295 mbox_chan_received_data(chan, data);
296 }
297 } else {
298 /* tx ack interrupt is triggered */
299 if (int_status & CIX_ACK_INT) {
300 cix_mbox_write(priv, CIX_ACK_INT, CIX_INT_CLEAR);
301 mbox_chan_txdone(chan, 0);
302 }
303 }
304}
305
306static void cix_mbox_isr_fifo(struct mbox_chan *chan)
307{
308 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
309 u32 int_status, status;
310
311 int_status = cix_mbox_read(priv, CIX_INT_STATUS);
312
313 if (priv->dir == CIX_MBOX_RX) {
314 /* FIFO waterMark interrupt is generated */
315 if (int_status & (CIX_FIFO_FULL_INT | CIX_FIFO_WM01_INT)) {
316 u32 data[CIX_MBOX_MSG_WORDS] = { 0 }, i = 0;
317
318 cix_mbox_write(priv, (CIX_FIFO_FULL_INT | CIX_FIFO_WM01_INT),
319 CIX_INT_CLEAR);
320 do {
321 data[i++] = cix_mbox_read(priv, CIX_FIFO_RD);
322 } while (!mbox_fifo_empty(chan) && i < CIX_MBOX_MSG_WORDS);
323
324 mbox_chan_received_data(chan, data);
325 }
326 /* FIFO underflow is generated */
327 if (int_status & CIX_FIFO_UFLOW_INT) {
328 status = cix_mbox_read(priv, CIX_FIFO_STAS);
329 dev_err(priv->dev, "fifo underflow: int_stats %d\n", status);
330 cix_mbox_write(priv, CIX_FIFO_UFLOW_INT, CIX_INT_CLEAR);
331 }
332 } else {
333 /* FIFO empty interrupt is generated */
334 if (int_status & CIX_FIFO_EMPTY_INT) {
335 u32 val;
336
337 cix_mbox_write(priv, CIX_FIFO_EMPTY_INT, CIX_INT_CLEAR);
338 /* Disable empty irq*/
339 val = cix_mbox_read(priv, CIX_INT_ENABLE);
340 val &= ~CIX_FIFO_EMPTY_INT;
341 cix_mbox_write(priv, val, CIX_INT_ENABLE);
342 mbox_chan_txdone(chan, 0);
343 }
344 /* FIFO overflow is generated */
345 if (int_status & CIX_FIFO_OFLOW_INT) {
346 status = cix_mbox_read(priv, CIX_FIFO_STAS);
347 dev_err(priv->dev, "fifo overflow: int_stats %d\n", status);
348 cix_mbox_write(priv, CIX_FIFO_OFLOW_INT, CIX_INT_CLEAR);
349 }
350 }
351}
352
353static void cix_mbox_isr_fast(struct mbox_chan *chan)
354{
355 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
356 struct cix_mbox_con_priv *cp = chan->con_priv;
357 u32 int_status, data;
358
359 /* no irq will be trigger for TX dir mbox */
360 if (priv->dir != CIX_MBOX_RX)
361 return;
362
363 int_status = cix_mbox_read(priv, CIX_INT_STATUS);
364
365 if (int_status & CIX_FAST_CH_INT(cp->index)) {
366 cix_mbox_write(priv, CIX_FAST_CH_INT(cp->index), CIX_INT_CLEAR);
367 data = cix_mbox_read(priv, CIX_REG_F_INT(cp->index));
368 mbox_chan_received_data(chan, &data);
369 }
370}
371
372static irqreturn_t cix_mbox_isr(int irq, void *arg)
373{
374 struct mbox_chan *chan = arg;
375 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
376 struct cix_mbox_con_priv *cp = chan->con_priv;
377
378 switch (cp->type) {
379 case CIX_MBOX_TYPE_DB:
380 cix_mbox_isr_db(chan);
381 break;
382 case CIX_MBOX_TYPE_REG:
383 cix_mbox_isr_reg(chan);
384 break;
385 case CIX_MBOX_TYPE_FIFO:
386 cix_mbox_isr_fifo(chan);
387 break;
388 case CIX_MBOX_TYPE_FAST:
389 cix_mbox_isr_fast(chan);
390 break;
391 default:
392 dev_err(priv->dev, "Invalid channel type: %d\n", cp->type);
393 return IRQ_NONE;
394 }
395
396 return IRQ_HANDLED;
397}
398
399static int cix_mbox_startup(struct mbox_chan *chan)
400{
401 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
402 struct cix_mbox_con_priv *cp = chan->con_priv;
403 int index = cp->index, ret;
404 u32 val;
405
406 ret = request_irq(priv->irq, cix_mbox_isr, IRQF_NO_SUSPEND,
407 dev_name(priv->dev), chan);
408 if (ret) {
409 dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq);
410 return ret;
411 }
412
413 switch (cp->type) {
414 case CIX_MBOX_TYPE_DB:
415 /* Overwrite txdone_method for DB channel */
416 chan->txdone_method = MBOX_TXDONE_BY_ACK;
417 fallthrough;
418 case CIX_MBOX_TYPE_REG:
419 if (priv->dir == CIX_MBOX_TX) {
420 /* Enable ACK interrupt */
421 val = cix_mbox_read(priv, CIX_INT_ENABLE);
422 val |= CIX_ACK_INT;
423 cix_mbox_write(priv, val, CIX_INT_ENABLE);
424 } else {
425 /* Enable Doorbell interrupt */
426 val = cix_mbox_read(priv, CIX_INT_ENABLE_SIDE_B);
427 val |= CIX_DB_INT;
428 cix_mbox_write(priv, val, CIX_INT_ENABLE_SIDE_B);
429 }
430 break;
431 case CIX_MBOX_TYPE_FIFO:
432 /* reset fifo */
433 cix_mbox_write(priv, CIX_FIFO_RST_BIT, CIX_FIFO_RST);
434 /* set default watermark */
435 cix_mbox_write(priv, CIX_FIFO_WM_DEFAULT, CIX_FIFO_WM);
436 if (priv->dir == CIX_MBOX_TX) {
437 /* Enable fifo overflow interrupt */
438 val = cix_mbox_read(priv, CIX_INT_ENABLE);
439 val |= CIX_FIFO_OFLOW_INT;
440 cix_mbox_write(priv, val, CIX_INT_ENABLE);
441 } else {
442 /* Enable fifo full/underflow interrupt */
443 val = cix_mbox_read(priv, CIX_INT_ENABLE_SIDE_B);
444 val |= CIX_FIFO_UFLOW_INT|CIX_FIFO_WM01_INT;
445 cix_mbox_write(priv, val, CIX_INT_ENABLE_SIDE_B);
446 }
447 break;
448 case CIX_MBOX_TYPE_FAST:
449 /* Only RX channel has intterupt */
450 if (priv->dir == CIX_MBOX_RX) {
451 if (index < 0 || index > CIX_MBOX_FAST_IDX) {
452 dev_err(priv->dev, "Invalid index %d\n", index);
453 ret = -EINVAL;
454 goto failed;
455 }
456 /* enable fast channel interrupt */
457 val = cix_mbox_read(priv, CIX_INT_ENABLE_SIDE_B);
458 val |= CIX_FAST_CH_INT(index);
459 cix_mbox_write(priv, val, CIX_INT_ENABLE_SIDE_B);
460 }
461 break;
462 default:
463 dev_err(priv->dev, "Invalid channel type: %d\n", cp->type);
464 ret = -EINVAL;
465 goto failed;
466 }
467 return 0;
468
469failed:
470 free_irq(priv->irq, chan);
471 return ret;
472}
473
474static void cix_mbox_shutdown(struct mbox_chan *chan)
475{
476 struct cix_mbox_priv *priv = to_cix_mbox_priv(chan->mbox);
477 struct cix_mbox_con_priv *cp = chan->con_priv;
478 int index = cp->index;
479 u32 val;
480
481 switch (cp->type) {
482 case CIX_MBOX_TYPE_DB:
483 case CIX_MBOX_TYPE_REG:
484 if (priv->dir == CIX_MBOX_TX) {
485 /* Disable ACK interrupt */
486 val = cix_mbox_read(priv, CIX_INT_ENABLE);
487 val &= ~CIX_ACK_INT;
488 cix_mbox_write(priv, val, CIX_INT_ENABLE);
489 } else if (priv->dir == CIX_MBOX_RX) {
490 /* Disable Doorbell interrupt */
491 val = cix_mbox_read(priv, CIX_INT_ENABLE_SIDE_B);
492 val &= ~CIX_DB_INT;
493 cix_mbox_write(priv, val, CIX_INT_ENABLE_SIDE_B);
494 }
495 break;
496 case CIX_MBOX_TYPE_FIFO:
497 if (priv->dir == CIX_MBOX_TX) {
498 /* Disable empty/fifo overflow irq*/
499 val = cix_mbox_read(priv, CIX_INT_ENABLE);
500 val &= ~(CIX_FIFO_EMPTY_INT | CIX_FIFO_OFLOW_INT);
501 cix_mbox_write(priv, val, CIX_INT_ENABLE);
502 } else if (priv->dir == CIX_MBOX_RX) {
503 /* Disable fifo WM01/underflow interrupt */
504 val = cix_mbox_read(priv, CIX_INT_ENABLE_SIDE_B);
505 val &= ~(CIX_FIFO_UFLOW_INT | CIX_FIFO_WM01_INT);
506 cix_mbox_write(priv, val, CIX_INT_ENABLE_SIDE_B);
507 }
508 break;
509 case CIX_MBOX_TYPE_FAST:
510 if (priv->dir == CIX_MBOX_RX) {
511 if (index < 0 || index > CIX_MBOX_FAST_IDX) {
512 dev_err(priv->dev, "Invalid index %d\n", index);
513 break;
514 }
515 /* Disable fast channel interrupt */
516 val = cix_mbox_read(priv, CIX_INT_ENABLE_SIDE_B);
517 val &= ~CIX_FAST_CH_INT(index);
518 cix_mbox_write(priv, val, CIX_INT_ENABLE_SIDE_B);
519 }
520 break;
521
522 default:
523 dev_err(priv->dev, "Invalid channel type: %d\n", cp->type);
524 break;
525 }
526
527 free_irq(priv->irq, chan);
528}
529
530static const struct mbox_chan_ops cix_mbox_chan_ops = {
531 .send_data = cix_mbox_send_data,
532 .startup = cix_mbox_startup,
533 .shutdown = cix_mbox_shutdown,
534};
535
536static void cix_mbox_init(struct cix_mbox_priv *priv)
537{
538 struct cix_mbox_con_priv *cp;
539 int i;
540
541 for (i = 0; i < CIX_MBOX_CHANS; i++) {
542 cp = &priv->con_priv[i];
543 cp->index = i;
544 cp->chan = &priv->mbox_chans[i];
545 priv->mbox_chans[i].con_priv = cp;
546 if (cp->index <= CIX_MBOX_FAST_IDX)
547 cp->type = CIX_MBOX_TYPE_FAST;
548 if (cp->index == CIX_MBOX_DB_IDX)
549 cp->type = CIX_MBOX_TYPE_DB;
550 if (cp->index == CIX_MBOX_FIFO_IDX)
551 cp->type = CIX_MBOX_TYPE_FIFO;
552 if (cp->index == CIX_MBOX_REG_IDX)
553 cp->type = CIX_MBOX_TYPE_REG;
554 }
555}
556
557static int cix_mbox_probe(struct platform_device *pdev)
558{
559 struct device *dev = &pdev->dev;
560 struct cix_mbox_priv *priv;
561 struct resource *res;
562 const char *dir_str;
563 int ret;
564
565 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
566 if (!priv)
567 return -ENOMEM;
568
569 priv->dev = dev;
570 priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
571 if (IS_ERR(priv->base))
572 return PTR_ERR(priv->base);
573
574 /*
575 * The first 0x80 bytes of the register space of the cix mailbox controller
576 * can be used as shared memory for clients. When this shared memory is in
577 * use, the base address of the mailbox is offset by 0x80. Therefore, when
578 * performing subsequent read/write operations, it is necessary to subtract
579 * the offset CIX_SHMEM_OFFSET.
580 *
581 * When the base address of the mailbox is offset by 0x80, it indicates
582 * that shmem is in use.
583 */
584 priv->use_shmem = !!(res->start & CIX_SHMEM_OFFSET);
585
586 priv->irq = platform_get_irq(pdev, 0);
587 if (priv->irq < 0)
588 return priv->irq;
589
590 if (device_property_read_string(dev, "cix,mbox-dir", &dir_str)) {
591 dev_err(priv->dev, "cix,mbox_dir property not found\n");
592 return -EINVAL;
593 }
594
595 if (!strcmp(dir_str, "tx"))
596 priv->dir = 0;
597 else if (!strcmp(dir_str, "rx"))
598 priv->dir = 1;
599 else {
600 dev_err(priv->dev, "cix,mbox_dir=%s is not expected\n", dir_str);
601 return -EINVAL;
602 }
603
604 cix_mbox_init(priv);
605
606 priv->mbox.dev = dev;
607 priv->mbox.ops = &cix_mbox_chan_ops;
608 priv->mbox.chans = priv->mbox_chans;
609 priv->mbox.txdone_irq = true;
610 priv->mbox.num_chans = CIX_MBOX_CHANS;
611 priv->mbox.of_xlate = NULL;
612
613 platform_set_drvdata(pdev, priv);
614 ret = devm_mbox_controller_register(dev, &priv->mbox);
615 if (ret)
616 dev_err(dev, "Failed to register mailbox %d\n", ret);
617
618 return ret;
619}
620
621static const struct of_device_id cix_mbox_dt_ids[] = {
622 { .compatible = "cix,sky1-mbox" },
623 { },
624};
625MODULE_DEVICE_TABLE(of, cix_mbox_dt_ids);
626
627static struct platform_driver cix_mbox_driver = {
628 .probe = cix_mbox_probe,
629 .driver = {
630 .name = "cix_mbox",
631 .of_match_table = cix_mbox_dt_ids,
632 },
633};
634
635static int __init cix_mailbox_init(void)
636{
637 return platform_driver_register(&cix_mbox_driver);
638}
639arch_initcall(cix_mailbox_init);
640
641MODULE_AUTHOR("Cix Technology Group Co., Ltd.");
642MODULE_DESCRIPTION("CIX mailbox driver");
643MODULE_LICENSE("GPL");