xref: /linux/drivers/mailbox/cix-mailbox.c (revision 4df9c0a2465a523e399e46a8d3b5866c769b381b)
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