File Index
Files and directories
Sign in
FILE

cix-mailbox.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mailbox/cix-mailbox.c C
  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
 78enum 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
 85struct cix_mbox_con_priv {
 86	enum cix_mbox_chan_type type;
 87	struct mbox_chan	*chan;
 88	int index;
 89};
 90
 91struct 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 */
107union 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
112static 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
117static 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
125static 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
133static 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 */
144static 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
152static 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
162static 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
181static 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
203static 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
223static 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
253static 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
277static 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
308static 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
355static 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
374static 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
401static 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
471failed:
472	free_irq(priv->irq, chan);
473	return ret;
474}
475
476static 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
532static 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
538static 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
559static 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
623static const struct of_device_id cix_mbox_dt_ids[] = {
624	{ .compatible = "cix,sky1-mbox" },
625	{ },
626};
627MODULE_DEVICE_TABLE(of, cix_mbox_dt_ids);
628
629static 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
637static int __init cix_mailbox_init(void)
638{
639	return platform_driver_register(&cix_mbox_driver);
640}
641arch_initcall(cix_mailbox_init);
642
643MODULE_AUTHOR("Cix Technology Group Co., Ltd.");
644MODULE_DESCRIPTION("CIX mailbox driver");
645MODULE_LICENSE("GPL");
~/ Read-only file preview.