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