xref: /linux/drivers/mailbox/cix-mailbox.c (revision a7cc308da5f78eee8d94bf666c026671a180d7e5)
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 
76 enum 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 
83 struct cix_mbox_con_priv {
84 	enum cix_mbox_chan_type type;
85 	struct mbox_chan	*chan;
86 	int index;
87 };
88 
89 struct 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  */
105 union 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 
to_cix_mbox_priv(struct mbox_controller * mbox)110 static 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 
cix_mbox_write(struct cix_mbox_priv * priv,u32 val,u32 offset)115 static 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 
cix_mbox_read(struct cix_mbox_priv * priv,u32 offset)123 static 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 
mbox_fifo_empty(struct mbox_chan * chan)131 static 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  */
mbox_get_msg_size(void * msg)142 static 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 
cix_mbox_send_data_db(struct mbox_chan * chan,void * data)150 static 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 
cix_mbox_send_data_reg(struct mbox_chan * chan,void * data)160 static 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 
cix_mbox_send_data_fifo(struct mbox_chan * chan,void * data)179 static 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 
cix_mbox_send_data_fast(struct mbox_chan * chan,void * data)201 static 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 
cix_mbox_send_data(struct mbox_chan * chan,void * data)221 static 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 
cix_mbox_isr_db(struct mbox_chan * chan)251 static 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 
cix_mbox_isr_reg(struct mbox_chan * chan)275 static 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 
cix_mbox_isr_fifo(struct mbox_chan * chan)306 static 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 
cix_mbox_isr_fast(struct mbox_chan * chan)353 static 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 
cix_mbox_isr(int irq,void * arg)372 static 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 
cix_mbox_startup(struct mbox_chan * chan)399 static 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 
469 failed:
470 	free_irq(priv->irq, chan);
471 	return ret;
472 }
473 
cix_mbox_shutdown(struct mbox_chan * chan)474 static 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 
530 static 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 
cix_mbox_init(struct cix_mbox_priv * priv)536 static 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 
cix_mbox_probe(struct platform_device * pdev)557 static 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 
621 static const struct of_device_id cix_mbox_dt_ids[] = {
622 	{ .compatible = "cix,sky1-mbox" },
623 	{ },
624 };
625 MODULE_DEVICE_TABLE(of, cix_mbox_dt_ids);
626 
627 static 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 
cix_mailbox_init(void)635 static int __init cix_mailbox_init(void)
636 {
637 	return platform_driver_register(&cix_mbox_driver);
638 }
639 arch_initcall(cix_mailbox_init);
640 
641 MODULE_AUTHOR("Cix Technology Group Co., Ltd.");
642 MODULE_DESCRIPTION("CIX mailbox driver");
643 MODULE_LICENSE("GPL");
644