xref: /linux/drivers/mailbox/sprd-mailbox.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Spreadtrum mailbox driver
4  *
5  * Copyright (c) 2020 Spreadtrum Communications Inc.
6  */
7 
8 #include <linux/delay.h>
9 #include <linux/err.h>
10 #include <linux/interrupt.h>
11 #include <linux/io.h>
12 #include <linux/mailbox_controller.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/platform_device.h>
16 #include <linux/clk.h>
17 
18 #define SPRD_MBOX_ID		0x0
19 #define SPRD_MBOX_MSG_LOW	0x4
20 #define SPRD_MBOX_MSG_HIGH	0x8
21 #define SPRD_MBOX_TRIGGER	0xc
22 #define SPRD_MBOX_FIFO_RST	0x10
23 #define SPRD_MBOX_FIFO_STS	0x14
24 #define SPRD_MBOX_IRQ_STS	0x18
25 #define SPRD_MBOX_IRQ_MSK	0x1c
26 #define SPRD_MBOX_LOCK		0x20
27 #define SPRD_MBOX_FIFO_DEPTH	0x24 /* outbox only */
28 #define SPRD_MBOX_IN_FIFO_STS2	0x24 /* inbox only, revision 2 */
29 
30 /* Bit and mask definition for inbox's SPRD_MBOX_FIFO_STS register */
31 #define SPRD_INBOX_FIFO_DELIVER_MASK		GENMASK(23, 16)
32 #define SPRD_INBOX_FIFO_OVERLOW_MASK		GENMASK(15, 8)
33 #define SPRD_INBOX_FIFO_DELIVER_SHIFT		16
34 #define SPRD_INBOX_FIFO_BUSY_MASK		GENMASK(7, 0)
35 
36 /* Bit and mask definition for R2 inbox's SPRD_MBOX_FIFO_RST register */
37 #define SPRD_INBOX_R2_FIFO_OVERFLOW_DELIVER_RST	GENMASK(31, 0)
38 
39 /* Bit and mask definition for R2 inbox's SPRD_MBOX_FIFO_STS register */
40 #define SPRD_INBOX_R2_FIFO_DELIVER_MASK		GENMASK(15, 0)
41 
42 /* Bit and mask definition for SPRD_MBOX_IN_FIFO_STS2 register */
43 #define SPRD_INBOX_R2_FIFO_OVERFLOW_MASK	GENMASK(31, 16)
44 #define SPRD_INBOX_R2_FIFO_BUSY_MASK		GENMASK(15, 0)
45 
46 /* Bit and mask definition for SPRD_MBOX_IRQ_STS register */
47 #define SPRD_MBOX_IRQ_CLR			GENMASK(31, 0)
48 
49 /* Bit and mask definition for outbox's SPRD_MBOX_FIFO_STS register */
50 #define SPRD_OUTBOX_FIFO_FULL			BIT(2)
51 #define SPRD_OUTBOX_FIFO_WR_SHIFT		16
52 #define SPRD_OUTBOX_FIFO_RD_SHIFT		24
53 #define SPRD_OUTBOX_FIFO_POS_MASK		GENMASK(7, 0)
54 
55 /* Bit and mask definition for inbox's SPRD_MBOX_IRQ_MSK register */
56 #define SPRD_INBOX_FIFO_BLOCK_IRQ		BIT(0)
57 #define SPRD_INBOX_FIFO_OVERFLOW_IRQ		BIT(1)
58 #define SPRD_INBOX_FIFO_DELIVER_IRQ		BIT(2)
59 #define SPRD_INBOX_FIFO_IRQ_MASK		GENMASK(2, 0)
60 
61 /* Bit and mask definition for outbox's SPRD_MBOX_IRQ_MSK register */
62 #define SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ		BIT(0)
63 #define SPRD_OUTBOX_FIFO_IRQ_MASK		GENMASK(4, 0)
64 
65 #define SPRD_OUTBOX_BASE_SPAN			0x1000
66 #define SPRD_MBOX_R1_CHAN_MAX			8
67 #define SPRD_MBOX_R2_CHAN_MAX			16
68 
69 enum sprd_mbox_version {
70 	SPRD_MBOX_R1,
71 	SPRD_MBOX_R2,
72 };
73 
74 struct sprd_mbox_info {
75 	enum sprd_mbox_version version;
76 	unsigned long supp_id;
77 };
78 
79 struct sprd_mbox_priv {
80 	struct mbox_controller	mbox;
81 	struct device		*dev;
82 	void __iomem		*inbox_base;
83 	void __iomem		*outbox_base;
84 	/*  Base register address for supplementary outbox */
85 	void __iomem		*supp_base;
86 	u32			outbox_fifo_depth;
87 
88 	const struct sprd_mbox_info *info;
89 
90 	struct mutex		lock;
91 	u32			refcnt;
92 	struct mbox_chan	chan[SPRD_MBOX_R2_CHAN_MAX];
93 };
94 
95 static struct sprd_mbox_priv *to_sprd_mbox_priv(struct mbox_controller *mbox)
96 {
97 	return container_of(mbox, struct sprd_mbox_priv, mbox);
98 }
99 
100 static u32 sprd_mbox_get_fifo_len(struct sprd_mbox_priv *priv, u32 fifo_sts)
101 {
102 	u32 wr_pos = (fifo_sts >> SPRD_OUTBOX_FIFO_WR_SHIFT) &
103 		SPRD_OUTBOX_FIFO_POS_MASK;
104 	u32 rd_pos = (fifo_sts >> SPRD_OUTBOX_FIFO_RD_SHIFT) &
105 		SPRD_OUTBOX_FIFO_POS_MASK;
106 	u32 fifo_len;
107 
108 	/*
109 	 * If the read pointer is equal with write pointer, which means the fifo
110 	 * is full or empty.
111 	 */
112 	if (wr_pos == rd_pos) {
113 		if (fifo_sts & SPRD_OUTBOX_FIFO_FULL)
114 			fifo_len = priv->outbox_fifo_depth;
115 		else
116 			fifo_len = 0;
117 	} else if (wr_pos > rd_pos) {
118 		fifo_len = wr_pos - rd_pos;
119 	} else {
120 		fifo_len = priv->outbox_fifo_depth - rd_pos + wr_pos;
121 	}
122 
123 	return fifo_len;
124 }
125 
126 static irqreturn_t do_outbox_isr(void __iomem *base, struct sprd_mbox_priv *priv)
127 {
128 	struct mbox_chan *chan;
129 	u32 fifo_sts, fifo_len, msg[2];
130 	int i, id;
131 
132 	fifo_sts = readl(base + SPRD_MBOX_FIFO_STS);
133 
134 	fifo_len = sprd_mbox_get_fifo_len(priv, fifo_sts);
135 	if (!fifo_len) {
136 		dev_warn_ratelimited(priv->dev, "spurious outbox interrupt\n");
137 		return IRQ_NONE;
138 	}
139 
140 	for (i = 0; i < fifo_len; i++) {
141 		msg[0] = readl(base + SPRD_MBOX_MSG_LOW);
142 		msg[1] = readl(base + SPRD_MBOX_MSG_HIGH);
143 		id = readl(base + SPRD_MBOX_ID);
144 
145 		chan = &priv->chan[id];
146 		if (chan->cl)
147 			mbox_chan_received_data(chan, (void *)msg);
148 		else
149 			dev_warn_ratelimited(priv->dev,
150 				    "message's been dropped at ch[%d]\n", id);
151 
152 		/* Trigger to update outbox FIFO pointer */
153 		writel(0x1, base + SPRD_MBOX_TRIGGER);
154 	}
155 
156 	/* Clear irq status after reading all message. */
157 	writel(SPRD_MBOX_IRQ_CLR, base + SPRD_MBOX_IRQ_STS);
158 
159 	return IRQ_HANDLED;
160 }
161 
162 static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data)
163 {
164 	struct sprd_mbox_priv *priv = data;
165 
166 	return do_outbox_isr(priv->outbox_base, priv);
167 }
168 
169 static irqreturn_t sprd_mbox_supp_isr(int irq, void *data)
170 {
171 	struct sprd_mbox_priv *priv = data;
172 
173 	return do_outbox_isr(priv->supp_base, priv);
174 }
175 
176 static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
177 {
178 	struct sprd_mbox_priv *priv = data;
179 	struct mbox_chan *chan;
180 	u32 fifo_sts, fifo_sts2, send_sts, busy, id;
181 
182 	fifo_sts = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS);
183 
184 	if (priv->info->version == SPRD_MBOX_R2)
185 		fifo_sts2 = readl(priv->inbox_base + SPRD_MBOX_IN_FIFO_STS2);
186 
187 	/* Get the inbox data delivery status */
188 	if (priv->info->version == SPRD_MBOX_R2) {
189 		send_sts = fifo_sts & SPRD_INBOX_R2_FIFO_DELIVER_MASK;
190 	} else {
191 		send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >>
192 			SPRD_INBOX_FIFO_DELIVER_SHIFT;
193 	}
194 
195 	if (!send_sts) {
196 		dev_warn_ratelimited(priv->dev, "spurious inbox interrupt\n");
197 		return IRQ_NONE;
198 	}
199 
200 	/* Clear FIFO delivery and overflow status first */
201 	if (priv->info->version == SPRD_MBOX_R2) {
202 		writel(SPRD_INBOX_R2_FIFO_OVERFLOW_DELIVER_RST,
203 		       priv->inbox_base + SPRD_MBOX_FIFO_RST);
204 	} else {
205 		writel(fifo_sts & (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK),
206 		       priv->inbox_base + SPRD_MBOX_FIFO_RST);
207 	}
208 
209 	while (send_sts) {
210 		id = __ffs(send_sts);
211 		send_sts &= (send_sts - 1);
212 
213 		chan = &priv->chan[id];
214 
215 		/*
216 		 * Check if the message was fetched by remote target, if yes,
217 		 * that means the transmission has been completed.
218 		 */
219 		if (priv->info->version == SPRD_MBOX_R2)
220 			busy = fifo_sts2 & SPRD_INBOX_R2_FIFO_BUSY_MASK;
221 		else
222 			busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
223 
224 		if (!(busy & BIT(id)))
225 			mbox_chan_txdone(chan, 0);
226 	}
227 
228 	/* Clear irq status */
229 	writel(SPRD_MBOX_IRQ_CLR, priv->inbox_base + SPRD_MBOX_IRQ_STS);
230 
231 	return IRQ_HANDLED;
232 }
233 
234 static int sprd_mbox_send_data(struct mbox_chan *chan, void *msg)
235 {
236 	struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
237 	unsigned long id = (unsigned long)chan->con_priv;
238 	u32 *data = msg;
239 
240 	/* Write data into inbox FIFO, and only support 8 bytes every time */
241 	writel(data[0], priv->inbox_base + SPRD_MBOX_MSG_LOW);
242 	writel(data[1], priv->inbox_base + SPRD_MBOX_MSG_HIGH);
243 
244 	/* Set target core id */
245 	writel(id, priv->inbox_base + SPRD_MBOX_ID);
246 
247 	/* Trigger remote request */
248 	writel(0x1, priv->inbox_base + SPRD_MBOX_TRIGGER);
249 
250 	return 0;
251 }
252 
253 static int sprd_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
254 {
255 	struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
256 	unsigned long id = (unsigned long)chan->con_priv;
257 	u32 busy;
258 
259 	timeout = jiffies + msecs_to_jiffies(timeout);
260 
261 	while (time_before(jiffies, timeout)) {
262 		busy = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS) &
263 			SPRD_INBOX_FIFO_BUSY_MASK;
264 		if (!(busy & BIT(id))) {
265 			mbox_chan_txdone(chan, 0);
266 			return 0;
267 		}
268 
269 		udelay(1);
270 	}
271 
272 	return -ETIME;
273 }
274 
275 static int sprd_mbox_startup(struct mbox_chan *chan)
276 {
277 	struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
278 	u32 val;
279 
280 	mutex_lock(&priv->lock);
281 	if (priv->refcnt++ == 0) {
282 		/* Select outbox FIFO mode and reset the outbox FIFO status */
283 		writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST);
284 
285 		/* Enable inbox FIFO delivery interrupt */
286 		val = SPRD_INBOX_FIFO_IRQ_MASK;
287 		val &= ~SPRD_INBOX_FIFO_DELIVER_IRQ;
288 		writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
289 
290 		/* Enable outbox FIFO not empty interrupt */
291 		val = SPRD_OUTBOX_FIFO_IRQ_MASK;
292 		val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
293 		writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
294 
295 		/* Enable supplementary outbox as the fundamental one */
296 		if (priv->supp_base) {
297 			writel(0x0, priv->supp_base + SPRD_MBOX_FIFO_RST);
298 			writel(val, priv->supp_base + SPRD_MBOX_IRQ_MSK);
299 		}
300 	}
301 	mutex_unlock(&priv->lock);
302 
303 	return 0;
304 }
305 
306 static void sprd_mbox_shutdown(struct mbox_chan *chan)
307 {
308 	struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
309 
310 	mutex_lock(&priv->lock);
311 	if (--priv->refcnt == 0) {
312 		/* Disable inbox & outbox interrupt */
313 		writel(SPRD_INBOX_FIFO_IRQ_MASK, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
314 		writel(SPRD_OUTBOX_FIFO_IRQ_MASK, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
315 
316 		if (priv->supp_base)
317 			writel(SPRD_OUTBOX_FIFO_IRQ_MASK,
318 			       priv->supp_base + SPRD_MBOX_IRQ_MSK);
319 	}
320 	mutex_unlock(&priv->lock);
321 }
322 
323 static const struct mbox_chan_ops sprd_mbox_ops = {
324 	.send_data	= sprd_mbox_send_data,
325 	.flush		= sprd_mbox_flush,
326 	.startup	= sprd_mbox_startup,
327 	.shutdown	= sprd_mbox_shutdown,
328 };
329 
330 static int sprd_mbox_probe(struct platform_device *pdev)
331 {
332 	struct device *dev = &pdev->dev;
333 	struct sprd_mbox_priv *priv;
334 	int ret, inbox_irq, outbox_irq, supp_irq;
335 	unsigned long id;
336 	struct clk *clk;
337 
338 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
339 	if (!priv)
340 		return -ENOMEM;
341 
342 	priv->dev = dev;
343 	mutex_init(&priv->lock);
344 
345 	priv->info = of_device_get_match_data(dev);
346 	if (!priv->info)
347 		return -EINVAL;
348 
349 	/*
350 	 * Unisoc mailbox uses an inbox to send messages to the target
351 	 * core, and uses (an) outbox(es) to receive messages from other
352 	 * cores.
353 	 *
354 	 * Thus in general the mailbox controller supplies 2 different
355 	 * register addresses and IRQ numbers for inbox and outbox.
356 	 *
357 	 * If necessary, a supplementary inbox could be enabled optionally
358 	 * with an independent FIFO and an extra interrupt.
359 	 */
360 	priv->inbox_base = devm_platform_ioremap_resource(pdev, 0);
361 	if (IS_ERR(priv->inbox_base))
362 		return PTR_ERR(priv->inbox_base);
363 
364 	priv->outbox_base = devm_platform_ioremap_resource(pdev, 1);
365 	if (IS_ERR(priv->outbox_base))
366 		return PTR_ERR(priv->outbox_base);
367 
368 	clk = devm_clk_get_enabled(dev, "enable");
369 	if (IS_ERR(clk)) {
370 		dev_err(dev, "failed to get mailbox clock\n");
371 		return PTR_ERR(clk);
372 	}
373 
374 	inbox_irq = platform_get_irq_byname(pdev, "inbox");
375 	if (inbox_irq < 0)
376 		return inbox_irq;
377 
378 	ret = devm_request_irq(dev, inbox_irq, sprd_mbox_inbox_isr,
379 			       IRQF_NO_SUSPEND, dev_name(dev), priv);
380 	if (ret) {
381 		dev_err(dev, "failed to request inbox IRQ: %d\n", ret);
382 		return ret;
383 	}
384 
385 	outbox_irq = platform_get_irq_byname(pdev, "outbox");
386 	if (outbox_irq < 0)
387 		return outbox_irq;
388 
389 	ret = devm_request_irq(dev, outbox_irq, sprd_mbox_outbox_isr,
390 			       IRQF_NO_SUSPEND, dev_name(dev), priv);
391 	if (ret) {
392 		dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
393 		return ret;
394 	}
395 
396 	/* Supplementary outbox IRQ is optional */
397 	supp_irq = platform_get_irq_byname(pdev, "supp-outbox");
398 	if (supp_irq > 0) {
399 		ret = devm_request_irq(dev, supp_irq, sprd_mbox_supp_isr,
400 				       IRQF_NO_SUSPEND, dev_name(dev), priv);
401 		if (ret) {
402 			dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
403 			return ret;
404 		}
405 
406 		if (!priv->info->supp_id) {
407 			dev_err(dev, "no supplementary outbox specified\n");
408 			return -ENODEV;
409 		}
410 		priv->supp_base = priv->outbox_base +
411 			(SPRD_OUTBOX_BASE_SPAN * priv->info->supp_id);
412 	}
413 
414 	/* Get the default outbox FIFO depth */
415 	priv->outbox_fifo_depth =
416 		readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1;
417 	priv->mbox.dev = dev;
418 	priv->mbox.chans = &priv->chan[0];
419 	priv->mbox.ops = &sprd_mbox_ops;
420 	priv->mbox.txdone_irq = true;
421 
422 	if (priv->info->version == SPRD_MBOX_R2)
423 		priv->mbox.num_chans = SPRD_MBOX_R2_CHAN_MAX;
424 	else
425 		priv->mbox.num_chans = SPRD_MBOX_R1_CHAN_MAX;
426 
427 	for (id = 0; id < priv->mbox.num_chans; id++)
428 		priv->chan[id].con_priv = (void *)id;
429 
430 	ret = devm_mbox_controller_register(dev, &priv->mbox);
431 	if (ret) {
432 		dev_err(dev, "failed to register mailbox: %d\n", ret);
433 		return ret;
434 	}
435 
436 	return 0;
437 }
438 
439 static const struct sprd_mbox_info sc9860_mbox_info = {
440 	.version = SPRD_MBOX_R1,
441 };
442 
443 static const struct sprd_mbox_info sc9863a_mbox_info = {
444 	.version = SPRD_MBOX_R1,
445 	.supp_id = 7,
446 };
447 
448 static const struct sprd_mbox_info ums9230_mbox_info = {
449 	.version = SPRD_MBOX_R2,
450 	.supp_id = 6,
451 };
452 
453 static const struct of_device_id sprd_mbox_of_match[] = {
454 	{ .compatible = "sprd,sc9860-mailbox", .data = &sc9860_mbox_info },
455 	{ .compatible = "sprd,sc9863a-mailbox", .data = &sc9863a_mbox_info },
456 	{ .compatible = "sprd,ums9230-mailbox", .data = &ums9230_mbox_info },
457 	{ },
458 };
459 MODULE_DEVICE_TABLE(of, sprd_mbox_of_match);
460 
461 static struct platform_driver sprd_mbox_driver = {
462 	.driver = {
463 		.name = "sprd-mailbox",
464 		.of_match_table = sprd_mbox_of_match,
465 	},
466 	.probe	= sprd_mbox_probe,
467 };
468 module_platform_driver(sprd_mbox_driver);
469 
470 MODULE_AUTHOR("Baolin Wang <baolin.wang@unisoc.com>");
471 MODULE_DESCRIPTION("Spreadtrum mailbox driver");
472 MODULE_LICENSE("GPL v2");
473