1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2021-2026 Axiado Corporation (or its affiliates).
4 */
5
6 #include <linux/atomic.h>
7 #include <linux/interrupt.h>
8 #include <linux/io.h>
9 #include <linux/bitfield.h>
10 #include <linux/debugfs.h>
11 #include <linux/iopoll.h>
12 #include <linux/mailbox_controller.h>
13 #include <linux/math.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/property.h>
18 #include <linux/slab.h>
19 #include <linux/unaligned.h>
20
21 #define AXIADO_MBOX_TX_CHANS 8 /* 0-7 */
22 #define AXIADO_MBOX_RX_CHANS 8 /* 8-15 */
23 #define AXIADO_MBOX_CHAN_STRIDE 0x4
24 #define AXIADO_MBOX_TX_REG_STRIDE 0x40
25 #define AXIADO_MBOX_RX_REG_STRIDE 0x30
26 #define AXIADO_MBOX_RX_POLL_US 10
27 #define AXIADO_MBOX_RX_TIMEOUT_US 1000
28
29 /* Mailbox CSR bit definitions */
30 #define AXIADO_MBOX_CSR_EMPTY BIT(0) /* 1 = FIFO empty; 0 = data available */
31 #define AXIADO_MBOX_CSR_OVERFLOW BIT(2) /* write 1 to clear (W1C) */
32 #define AXIADO_MBOX_CSR_UNDERFLOW BIT(3) /* write 1 to clear (W1C) */
33 #define AXIADO_MBOX_CSR_FLUSH BIT(4) /* W1TRG flush; startup/shutdown */
34 #define AXIADO_MBOX_CSR_LEVEL GENMASK(11, 5)
35
36 #define AXIADO_MBOX_CSR_ERRORS (AXIADO_MBOX_CSR_OVERFLOW | \
37 AXIADO_MBOX_CSR_UNDERFLOW)
38
39 struct axiado_mbox_data {
40 u8 num_chans;
41 u16 msg_size;
42 };
43
44 struct axiado_channel_data {
45 void __iomem *mbox_reg;
46 void __iomem *csr_reg;
47 void *rx_buffer;
48 u8 channel_num;
49 int irq;
50 struct mbox_chan *chan;
51 bool active;
52 atomic_t fifo_errors;
53 };
54
55 /* mailbox side */
56 struct axiado_mbox {
57 struct mbox_controller mbox;
58 const struct axiado_mbox_data *drv_data;
59 void __iomem *tx_base;
60 void __iomem *rx_base;
61 struct dentry *debugfs_dir;
62 };
63
64 /*
65 * Checks OVERFLOW/UNDERFLOW, logs and W1C-clears them if set. Shared by the
66 * TX and RX paths; RX additionally flushes the FIFO afterwards to resync
67 * framing, which TX must not do since it could discard data the peer has
68 * not read yet.
69 */
axiado_mbox_clear_fifo_errors(struct axiado_channel_data * priv)70 static bool axiado_mbox_clear_fifo_errors(struct axiado_channel_data *priv)
71 {
72 struct device *dev = priv->chan->mbox->dev;
73 u32 errors;
74
75 errors = readl(priv->csr_reg) & AXIADO_MBOX_CSR_ERRORS;
76 if (!errors)
77 return false;
78
79 writel(errors, priv->csr_reg);
80 atomic_inc(&priv->fifo_errors);
81
82 dev_warn_ratelimited(dev, "Channel %u FIFO error: %#x\n",
83 priv->channel_num, errors);
84
85 return true;
86 }
87
axiado_mbox_send_data(struct mbox_chan * chan,void * data)88 static int axiado_mbox_send_data(struct mbox_chan *chan, void *data)
89 {
90 struct axiado_mbox *mb = dev_get_drvdata(chan->mbox->dev);
91 struct axiado_channel_data *priv = chan->con_priv;
92 unsigned int idx = priv->channel_num;
93 u8 tail[sizeof(u32)] = { 0 };
94 const u8 *buf = data;
95 unsigned int tail_len;
96 unsigned int offset;
97 u32 msg_len;
98
99 if (!data)
100 return -EINVAL;
101
102 /*
103 * The Axiado mailbox message ABI stores the total message length,
104 * including this length word, as a little-endian byte count in the
105 * first word of every message.
106 */
107 msg_len = get_unaligned_le32(data);
108 if (msg_len < sizeof(u32) || msg_len > mb->drv_data->msg_size)
109 return -EINVAL;
110
111 /* Only touch the hardware after validating the message. */
112 axiado_mbox_clear_fifo_errors(priv);
113
114 if (!(readl(priv->csr_reg) & AXIADO_MBOX_CSR_EMPTY)) {
115 dev_warn_ratelimited(mb->mbox.dev, "Channel %u is busy\n", idx);
116 return -EBUSY;
117 }
118
119 for (offset = 0; offset + sizeof(u32) <= msg_len;
120 offset += sizeof(u32))
121 writel(get_unaligned_le32(buf + offset), priv->mbox_reg);
122
123 tail_len = msg_len - offset;
124 if (tail_len) {
125 memcpy(tail, buf + offset, tail_len);
126 writel(get_unaligned_le32(tail), priv->mbox_reg);
127 }
128
129 dev_dbg(mb->mbox.dev, "%s: Ch-%u sent\n", __func__, idx);
130
131 return 0;
132 }
133
axiado_rx_thread(int irq,void * dev_id)134 static irqreturn_t axiado_rx_thread(int irq, void *dev_id)
135 {
136 struct axiado_channel_data *priv = dev_id;
137 struct mbox_chan *chan = priv->chan;
138 struct axiado_mbox *mb = dev_get_drvdata(chan->mbox->dev);
139 u8 *buf = priv->rx_buffer;
140 unsigned int num_words;
141 unsigned int remaining;
142 unsigned int i;
143 u32 msg_len;
144 u32 word;
145 u32 csr;
146 int ret;
147
148 /*
149 * Clear and log/count any pending errors, but don't discard data
150 * on their account alone: a rejected overflow write doesn't
151 * corrupt what was already safely queued ahead of it, so let the
152 * length-based read below decide whether what's here is usable.
153 */
154 axiado_mbox_clear_fifo_errors(priv);
155
156 csr = readl(priv->csr_reg);
157 if (csr & AXIADO_MBOX_CSR_EMPTY)
158 return IRQ_NONE;
159
160 /*
161 * The first word contains the total message length in bytes,
162 * including the length word itself.
163 */
164 word = readl(priv->mbox_reg);
165 msg_len = word;
166 put_unaligned_le32(word, buf);
167
168 if (msg_len < sizeof(u32) || msg_len > mb->drv_data->msg_size)
169 goto invalid_message;
170
171 num_words = DIV_ROUND_UP(msg_len, sizeof(u32));
172 remaining = num_words - 1;
173
174 /*
175 * The not-empty interrupt may occur as soon as the first DW enters
176 * the FIFO. Wait until all remaining DWs of this message arrive.
177 */
178 if (remaining) {
179 ret = readl_poll_timeout(priv->csr_reg, csr,
180 (csr & AXIADO_MBOX_CSR_ERRORS) ||
181 FIELD_GET(AXIADO_MBOX_CSR_LEVEL, csr) >=
182 remaining,
183 AXIADO_MBOX_RX_POLL_US,
184 AXIADO_MBOX_RX_TIMEOUT_US);
185 if (ret)
186 goto incomplete_message;
187
188 axiado_mbox_clear_fifo_errors(priv);
189 }
190
191 for (i = 1; i < num_words; i++) {
192 word = readl(priv->mbox_reg);
193 put_unaligned_le32(word, buf + i * sizeof(u32));
194 }
195
196 axiado_mbox_clear_fifo_errors(priv);
197
198 if (READ_ONCE(priv->active))
199 mbox_chan_received_data(chan, priv->rx_buffer);
200
201 return IRQ_HANDLED;
202
203 incomplete_message:
204 dev_warn_ratelimited(chan->mbox->dev,
205 "Channel %u received an incomplete message\n",
206 priv->channel_num);
207
208 invalid_message:
209 writel(AXIADO_MBOX_CSR_FLUSH, priv->csr_reg);
210
211 return IRQ_HANDLED;
212 }
213
axiado_mbox_startup(struct mbox_chan * chan)214 static int axiado_mbox_startup(struct mbox_chan *chan)
215 {
216 struct axiado_channel_data *priv = chan->con_priv;
217
218 /*
219 * Only flush on a genuine error. A blind flush here would discard
220 * a message the peer legitimately sent before this side started
221 * up (e.g. during normal boot sequencing), which is not corrupt
222 * and does not need resyncing.
223 */
224 if (axiado_mbox_clear_fifo_errors(priv))
225 writel(AXIADO_MBOX_CSR_FLUSH, priv->csr_reg);
226
227 WRITE_ONCE(priv->active, true);
228
229 if (priv->channel_num >= AXIADO_MBOX_TX_CHANS)
230 enable_irq(priv->irq);
231
232 return 0;
233 }
234
axiado_mbox_shutdown(struct mbox_chan * chan)235 static void axiado_mbox_shutdown(struct mbox_chan *chan)
236 {
237 struct axiado_channel_data *priv = chan->con_priv;
238
239 WRITE_ONCE(priv->active, false);
240
241 if (priv->channel_num >= AXIADO_MBOX_TX_CHANS)
242 disable_irq(priv->irq);
243
244 if (axiado_mbox_clear_fifo_errors(priv))
245 writel(AXIADO_MBOX_CSR_FLUSH, priv->csr_reg);
246 }
247
axiado_mbox_last_tx_done(struct mbox_chan * chan)248 static bool axiado_mbox_last_tx_done(struct mbox_chan *chan)
249 {
250 struct axiado_channel_data *priv = chan->con_priv;
251
252 return !!(readl(priv->csr_reg) & AXIADO_MBOX_CSR_EMPTY);
253 }
254
255 static const struct mbox_chan_ops axiado_mbox_chan_ops = {
256 .send_data = axiado_mbox_send_data,
257 .startup = axiado_mbox_startup,
258 .shutdown = axiado_mbox_shutdown,
259 .last_tx_done = axiado_mbox_last_tx_done,
260 };
261
axiado_mbox_debugfs_remove(void * dentry)262 static void axiado_mbox_debugfs_remove(void *dentry)
263 {
264 debugfs_remove_recursive(dentry);
265 }
266
axiado_mbox_probe(struct platform_device * pdev)267 static int axiado_mbox_probe(struct platform_device *pdev)
268 {
269 const struct axiado_mbox_data *drv_data;
270 struct axiado_channel_data *ch_data;
271 struct device *dev = &pdev->dev;
272 struct axiado_mbox *mb;
273 unsigned int irq_idx = 0;
274 unsigned int rx_chan;
275 unsigned int i;
276 int ret;
277
278 drv_data = device_get_match_data(dev);
279 if (!drv_data)
280 return -ENODEV;
281
282 mb = devm_kzalloc(dev, sizeof(*mb), GFP_KERNEL);
283 if (!mb)
284 return -ENOMEM;
285
286 mb->mbox.dev = dev;
287 mb->mbox.num_chans = drv_data->num_chans;
288
289 mb->mbox.chans = devm_kcalloc(&pdev->dev,
290 drv_data->num_chans,
291 sizeof(*mb->mbox.chans),
292 GFP_KERNEL);
293 if (!mb->mbox.chans)
294 return -ENOMEM;
295
296 mb->tx_base = devm_platform_ioremap_resource_byname(pdev, "tx");
297 if (IS_ERR(mb->tx_base))
298 return PTR_ERR(mb->tx_base);
299
300 mb->rx_base = devm_platform_ioremap_resource_byname(pdev, "rx");
301 if (IS_ERR(mb->rx_base))
302 return PTR_ERR(mb->rx_base);
303
304 ch_data = devm_kcalloc(&pdev->dev,
305 drv_data->num_chans,
306 sizeof(*ch_data),
307 GFP_KERNEL);
308 if (!ch_data)
309 return -ENOMEM;
310
311 mb->debugfs_dir = debugfs_create_dir(dev_name(dev), NULL);
312 ret = devm_add_action_or_reset(dev, axiado_mbox_debugfs_remove,
313 mb->debugfs_dir);
314 if (ret)
315 return ret;
316
317 for (i = 0; i < drv_data->num_chans; i++) {
318 char name[16];
319
320 ch_data[i].channel_num = i;
321 ch_data[i].chan = &mb->mbox.chans[i];
322
323 mb->mbox.chans[i].con_priv = &ch_data[i];
324
325 snprintf(name, sizeof(name), "chan%u-errors", i);
326 debugfs_create_atomic_t(name, 0444, mb->debugfs_dir,
327 &ch_data[i].fifo_errors);
328
329 if (i < AXIADO_MBOX_TX_CHANS) {
330 ch_data[i].mbox_reg = mb->tx_base + (i * AXIADO_MBOX_CHAN_STRIDE);
331 ch_data[i].csr_reg = mb->tx_base + AXIADO_MBOX_TX_REG_STRIDE +
332 (i * AXIADO_MBOX_CHAN_STRIDE);
333 ch_data[i].irq = -1;
334 continue;
335 }
336
337 ch_data[i].rx_buffer = devm_kzalloc(dev, drv_data->msg_size,
338 GFP_KERNEL);
339 if (!ch_data[i].rx_buffer)
340 return -ENOMEM;
341
342 rx_chan = i - AXIADO_MBOX_TX_CHANS;
343 ch_data[i].mbox_reg = mb->rx_base +
344 (rx_chan * AXIADO_MBOX_CHAN_STRIDE);
345 ch_data[i].csr_reg = mb->rx_base + AXIADO_MBOX_RX_REG_STRIDE +
346 (rx_chan * AXIADO_MBOX_CHAN_STRIDE);
347 ch_data[i].irq = platform_get_irq(pdev, irq_idx++);
348 if (ch_data[i].irq < 0)
349 return dev_err_probe(dev, ch_data[i].irq,
350 "Failed to get IRQ for channel %u\n", i);
351
352 ret = devm_request_threaded_irq(dev, ch_data[i].irq, NULL,
353 axiado_rx_thread,
354 IRQF_ONESHOT | IRQF_NO_AUTOEN,
355 dev_name(dev), &ch_data[i]);
356 if (ret)
357 return dev_err_probe(dev, ret,
358 "Failed to request IRQ for channel %u\n", i);
359
360 dev_dbg(dev, "RX chan %u -> irq %d\n", i, ch_data[i].irq);
361 }
362
363 platform_set_drvdata(pdev, mb);
364 mb->drv_data = drv_data;
365 mb->mbox.ops = &axiado_mbox_chan_ops;
366 mb->mbox.txdone_irq = false;
367 mb->mbox.txdone_poll = true;
368 mb->mbox.txpoll_period = 5;
369
370 return devm_mbox_controller_register(dev, &mb->mbox);
371 }
372
373 static const struct axiado_mbox_data axiado_drv_data = {
374 .num_chans = AXIADO_MBOX_TX_CHANS + AXIADO_MBOX_RX_CHANS,
375 .msg_size = 256,
376 };
377
378 static const struct of_device_id axiado_mbox_of_match[] = {
379 { .compatible = "axiado,ax3005-mailbox", .data = &axiado_drv_data },
380 { }
381 };
382 MODULE_DEVICE_TABLE(of, axiado_mbox_of_match);
383
384 static struct platform_driver axiado_mbox_driver = {
385 .driver = {
386 .name = "axiado-mailbox",
387 .of_match_table = axiado_mbox_of_match,
388 },
389 .probe = axiado_mbox_probe,
390 };
391 module_platform_driver(axiado_mbox_driver);
392
393 MODULE_AUTHOR("Axiado Corporation");
394 MODULE_DESCRIPTION("Axiado Mailbox driver");
395 MODULE_LICENSE("GPL");
396