aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mailbox/Kconfig11
-rw-r--r--drivers/mailbox/Makefile2
-rw-r--r--drivers/mailbox/zynqmp-ipi-mailbox.c725
-rw-r--r--include/linux/mailbox/zynqmp-ipi-message.h20
4 files changed, 758 insertions, 0 deletions
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 3eeb12e93e98..d86e7a4ac04d 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -205,4 +205,15 @@ config MTK_CMDQ_MBOX
205 mailbox driver. The CMDQ is used to help read/write registers with 205 mailbox driver. The CMDQ is used to help read/write registers with
206 critical time limitation, such as updating display configuration 206 critical time limitation, such as updating display configuration
207 during the vblank. 207 during the vblank.
208
209config ZYNQMP_IPI_MBOX
210 bool "Xilinx ZynqMP IPI Mailbox"
211 depends on ARCH_ZYNQMP && OF
212 help
213 Say yes here to add support for Xilinx IPI mailbox driver.
214 This mailbox driver is used to send notification or short message
215 between processors with Xilinx ZynqMP IPI. It will place the
216 message to the IPI buffer and will access the IPI control
217 registers to kick the other processor or enquire status.
218
208endif 219endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index c818b5d011ae..8be3bcbcf882 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -44,3 +44,5 @@ obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
44obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o 44obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o
45 45
46obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o 46obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o
47
48obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o
diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
new file mode 100644
index 000000000000..86887c9a349a
--- /dev/null
+++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
@@ -0,0 +1,725 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Xilinx Inter Processor Interrupt(IPI) Mailbox Driver
4 *
5 * Copyright (C) 2018 Xilinx, Inc.
6 */
7
8#include <linux/arm-smccc.h>
9#include <linux/delay.h>
10#include <linux/device.h>
11#include <linux/interrupt.h>
12#include <linux/io.h>
13#include <linux/kernel.h>
14#include <linux/mailbox_controller.h>
15#include <linux/mailbox/zynqmp-ipi-message.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/of_device.h>
20#include <linux/of_irq.h>
21#include <linux/platform_device.h>
22
23/* IPI agent ID any */
24#define IPI_ID_ANY 0xFFUL
25
26/* indicate if ZynqMP IPI mailbox driver uses SMC calls or HVC calls */
27#define USE_SMC 0
28#define USE_HVC 1
29
30/* Default IPI SMC function IDs */
31#define SMC_IPI_MAILBOX_OPEN 0x82001000U
32#define SMC_IPI_MAILBOX_RELEASE 0x82001001U
33#define SMC_IPI_MAILBOX_STATUS_ENQUIRY 0x82001002U
34#define SMC_IPI_MAILBOX_NOTIFY 0x82001003U
35#define SMC_IPI_MAILBOX_ACK 0x82001004U
36#define SMC_IPI_MAILBOX_ENABLE_IRQ 0x82001005U
37#define SMC_IPI_MAILBOX_DISABLE_IRQ 0x82001006U
38
39/* IPI SMC Macros */
40#define IPI_SMC_ENQUIRY_DIRQ_MASK 0x00000001UL /* Flag to indicate if
41 * notification interrupt
42 * to be disabled.
43 */
44#define IPI_SMC_ACK_EIRQ_MASK 0x00000001UL /* Flag to indicate if
45 * notification interrupt
46 * to be enabled.
47 */
48
49/* IPI mailbox status */
50#define IPI_MB_STATUS_IDLE 0
51#define IPI_MB_STATUS_SEND_PENDING 1
52#define IPI_MB_STATUS_RECV_PENDING 2
53
54#define IPI_MB_CHNL_TX 0 /* IPI mailbox TX channel */
55#define IPI_MB_CHNL_RX 1 /* IPI mailbox RX channel */
56
57/**
58 * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel
59 * @is_opened: indicate if the IPI channel is opened
60 * @req_buf: local to remote request buffer start address
61 * @resp_buf: local to remote response buffer start address
62 * @req_buf_size: request buffer size
63 * @resp_buf_size: response buffer size
64 * @rx_buf: receive buffer to pass received message to client
65 * @chan_type: channel type
66 */
67struct zynqmp_ipi_mchan {
68 int is_opened;
69 void __iomem *req_buf;
70 void __iomem *resp_buf;
71 void *rx_buf;
72 size_t req_buf_size;
73 size_t resp_buf_size;
74 unsigned int chan_type;
75};
76
77/**
78 * struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox
79 * platform data.
80 * @pdata: pointer to the IPI private data
81 * @dev: device pointer corresponding to the Xilinx ZynqMP
82 * IPI mailbox
83 * @remote_id: remote IPI agent ID
84 * @mbox: mailbox Controller
85 * @mchans: array for channels, tx channel and rx channel.
86 * @irq: IPI agent interrupt ID
87 */
88struct zynqmp_ipi_mbox {
89 struct zynqmp_ipi_pdata *pdata;
90 struct device dev;
91 u32 remote_id;
92 struct mbox_controller mbox;
93 struct zynqmp_ipi_mchan mchans[2];
94};
95
96/**
97 * struct zynqmp_ipi_pdata - Description of z ZynqMP IPI agent platform data.
98 *
99 * @dev: device pointer corresponding to the Xilinx ZynqMP
100 * IPI agent
101 * @irq: IPI agent interrupt ID
102 * @method: IPI SMC or HVC is going to be used
103 * @local_id: local IPI agent ID
104 * @num_mboxes: number of mailboxes of this IPI agent
105 * @ipi_mboxes: IPI mailboxes of this IPI agent
106 */
107struct zynqmp_ipi_pdata {
108 struct device *dev;
109 int irq;
110 unsigned int method;
111 u32 local_id;
112 int num_mboxes;
113 struct zynqmp_ipi_mbox *ipi_mboxes;
114};
115
116static struct device_driver zynqmp_ipi_mbox_driver = {
117 .owner = THIS_MODULE,
118 .name = "zynqmp-ipi-mbox",
119};
120
121static void zynqmp_ipi_fw_call(struct zynqmp_ipi_mbox *ipi_mbox,
122 unsigned long a0, unsigned long a3,
123 struct arm_smccc_res *res)
124{
125 struct zynqmp_ipi_pdata *pdata = ipi_mbox->pdata;
126 unsigned long a1, a2;
127
128 a1 = pdata->local_id;
129 a2 = ipi_mbox->remote_id;
130 if (pdata->method == USE_SMC)
131 arm_smccc_smc(a0, a1, a2, a3, 0, 0, 0, 0, res);
132 else
133 arm_smccc_hvc(a0, a1, a2, a3, 0, 0, 0, 0, res);
134}
135
136/**
137 * zynqmp_ipi_interrupt - Interrupt handler for IPI notification
138 *
139 * @irq: Interrupt number
140 * @data: ZynqMP IPI mailbox platform data.
141 *
142 * Return: -EINVAL if there is no instance
143 * IRQ_NONE if the interrupt is not ours.
144 * IRQ_HANDLED if the rx interrupt was successfully handled.
145 */
146static irqreturn_t zynqmp_ipi_interrupt(int irq, void *data)
147{
148 struct zynqmp_ipi_pdata *pdata = data;
149 struct mbox_chan *chan;
150 struct zynqmp_ipi_mbox *ipi_mbox;
151 struct zynqmp_ipi_mchan *mchan;
152 struct zynqmp_ipi_message *msg;
153 u64 arg0, arg3;
154 struct arm_smccc_res res;
155 int ret, i;
156
157 (void)irq;
158 arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
159 arg3 = IPI_SMC_ENQUIRY_DIRQ_MASK;
160 for (i = 0; i < pdata->num_mboxes; i++) {
161 ipi_mbox = &pdata->ipi_mboxes[i];
162 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
163 chan = &ipi_mbox->mbox.chans[IPI_MB_CHNL_RX];
164 zynqmp_ipi_fw_call(ipi_mbox, arg0, arg3, &res);
165 ret = (int)(res.a0 & 0xFFFFFFFF);
166 if (ret > 0 && ret & IPI_MB_STATUS_RECV_PENDING) {
167 if (mchan->is_opened) {
168 msg = mchan->rx_buf;
169 msg->len = mchan->req_buf_size;
170 memcpy_fromio(msg->data, mchan->req_buf,
171 msg->len);
172 mbox_chan_received_data(chan, (void *)msg);
173 return IRQ_HANDLED;
174 }
175 }
176 }
177 return IRQ_NONE;
178}
179
180/**
181 * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.
182 *
183 * @chan: Channel Pointer
184 *
185 * Return: 'true' if there is pending rx data, 'false' if there is none.
186 */
187static bool zynqmp_ipi_peek_data(struct mbox_chan *chan)
188{
189 struct device *dev = chan->mbox->dev;
190 struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);
191 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
192 int ret;
193 u64 arg0;
194 struct arm_smccc_res res;
195
196 if (WARN_ON(!ipi_mbox)) {
197 dev_err(dev, "no platform drv data??\n");
198 return false;
199 }
200
201 arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
202 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
203 ret = (int)(res.a0 & 0xFFFFFFFF);
204
205 if (mchan->chan_type == IPI_MB_CHNL_TX) {
206 /* TX channel, check if the message has been acked
207 * by the remote, if yes, response is available.
208 */
209 if (ret < 0 || ret & IPI_MB_STATUS_SEND_PENDING)
210 return false;
211 else
212 return true;
213 } else if (ret > 0 && ret & IPI_MB_STATUS_RECV_PENDING) {
214 /* RX channel, check if there is message arrived. */
215 return true;
216 }
217 return false;
218}
219
220/**
221 * zynqmp_ipi_last_tx_done - See if the last tx message is sent
222 *
223 * @chan: Channel pointer
224 *
225 * Return: 'true' is no pending tx data, 'false' if there are any.
226 */
227static bool zynqmp_ipi_last_tx_done(struct mbox_chan *chan)
228{
229 struct device *dev = chan->mbox->dev;
230 struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);
231 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
232 int ret;
233 u64 arg0;
234 struct arm_smccc_res res;
235
236 if (WARN_ON(!ipi_mbox)) {
237 dev_err(dev, "no platform drv data??\n");
238 return false;
239 }
240
241 if (mchan->chan_type == IPI_MB_CHNL_TX) {
242 /* We only need to check if the message been taken
243 * by the remote in the TX channel
244 */
245 arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
246 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
247 /* Check the SMC call status, a0 of the result */
248 ret = (int)(res.a0 & 0xFFFFFFFF);
249 if (ret < 0 || ret & IPI_MB_STATUS_SEND_PENDING)
250 return false;
251 return true;
252 }
253 /* Always true for the response message in RX channel */
254 return true;
255}
256
257/**
258 * zynqmp_ipi_send_data - Send data
259 *
260 * @chan: Channel Pointer
261 * @data: Message Pointer
262 *
263 * Return: 0 if all goes good, else appropriate error messages.
264 */
265static int zynqmp_ipi_send_data(struct mbox_chan *chan, void *data)
266{
267 struct device *dev = chan->mbox->dev;
268 struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);
269 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
270 struct zynqmp_ipi_message *msg = data;
271 u64 arg0;
272 struct arm_smccc_res res;
273
274 if (WARN_ON(!ipi_mbox)) {
275 dev_err(dev, "no platform drv data??\n");
276 return -EINVAL;
277 }
278
279 if (mchan->chan_type == IPI_MB_CHNL_TX) {
280 /* Send request message */
281 if (msg && msg->len > mchan->req_buf_size) {
282 dev_err(dev, "channel %d message length %u > max %lu\n",
283 mchan->chan_type, (unsigned int)msg->len,
284 mchan->req_buf_size);
285 return -EINVAL;
286 }
287 if (msg && msg->len)
288 memcpy_toio(mchan->req_buf, msg->data, msg->len);
289 /* Kick IPI mailbox to send message */
290 arg0 = SMC_IPI_MAILBOX_NOTIFY;
291 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
292 } else {
293 /* Send response message */
294 if (msg && msg->len > mchan->resp_buf_size) {
295 dev_err(dev, "channel %d message length %u > max %lu\n",
296 mchan->chan_type, (unsigned int)msg->len,
297 mchan->resp_buf_size);
298 return -EINVAL;
299 }
300 if (msg && msg->len)
301 memcpy_toio(mchan->resp_buf, msg->data, msg->len);
302 arg0 = SMC_IPI_MAILBOX_ACK;
303 zynqmp_ipi_fw_call(ipi_mbox, arg0, IPI_SMC_ACK_EIRQ_MASK,
304 &res);
305 }
306 return 0;
307}
308
309/**
310 * zynqmp_ipi_startup - Startup the IPI channel
311 *
312 * @chan: Channel pointer
313 *
314 * Return: 0 if all goes good, else return corresponding error message
315 */
316static int zynqmp_ipi_startup(struct mbox_chan *chan)
317{
318 struct device *dev = chan->mbox->dev;
319 struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);
320 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
321 u64 arg0;
322 struct arm_smccc_res res;
323 int ret = 0;
324 unsigned int nchan_type;
325
326 if (mchan->is_opened)
327 return 0;
328
329 /* If no channel has been opened, open the IPI mailbox */
330 nchan_type = (mchan->chan_type + 1) % 2;
331 if (!ipi_mbox->mchans[nchan_type].is_opened) {
332 arg0 = SMC_IPI_MAILBOX_OPEN;
333 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
334 /* Check the SMC call status, a0 of the result */
335 ret = (int)(res.a0 & 0xFFFFFFFF);
336 if (ret < 0) {
337 dev_err(dev, "SMC to open the IPI channel failed.\n");
338 return ret;
339 }
340 ret = 0;
341 }
342
343 /* If it is RX channel, enable the IPI notification interrupt */
344 if (mchan->chan_type == IPI_MB_CHNL_RX) {
345 arg0 = SMC_IPI_MAILBOX_ENABLE_IRQ;
346 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
347 }
348 mchan->is_opened = 1;
349
350 return ret;
351}
352
353/**
354 * zynqmp_ipi_shutdown - Shutdown the IPI channel
355 *
356 * @chan: Channel pointer
357 */
358static void zynqmp_ipi_shutdown(struct mbox_chan *chan)
359{
360 struct device *dev = chan->mbox->dev;
361 struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);
362 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
363 u64 arg0;
364 struct arm_smccc_res res;
365 unsigned int chan_type;
366
367 if (!mchan->is_opened)
368 return;
369
370 /* If it is RX channel, disable notification interrupt */
371 chan_type = mchan->chan_type;
372 if (chan_type == IPI_MB_CHNL_RX) {
373 arg0 = SMC_IPI_MAILBOX_DISABLE_IRQ;
374 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
375 }
376 /* Release IPI mailbox if no other channel is opened */
377 chan_type = (chan_type + 1) % 2;
378 if (!ipi_mbox->mchans[chan_type].is_opened) {
379 arg0 = SMC_IPI_MAILBOX_RELEASE;
380 zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
381 }
382
383 mchan->is_opened = 0;
384}
385
386/* ZynqMP IPI mailbox operations */
387static const struct mbox_chan_ops zynqmp_ipi_chan_ops = {
388 .startup = zynqmp_ipi_startup,
389 .shutdown = zynqmp_ipi_shutdown,
390 .peek_data = zynqmp_ipi_peek_data,
391 .last_tx_done = zynqmp_ipi_last_tx_done,
392 .send_data = zynqmp_ipi_send_data,
393};
394
395/**
396 * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel
397 *
398 * @mbox: mailbox controller pointer
399 * @p: phandle pointer
400 *
401 * Return: Mailbox channel, else return error pointer.
402 */
403static struct mbox_chan *zynqmp_ipi_of_xlate(struct mbox_controller *mbox,
404 const struct of_phandle_args *p)
405{
406 struct mbox_chan *chan;
407 struct device *dev = mbox->dev;
408 unsigned int chan_type;
409
410 /* Only supports TX and RX channels */
411 chan_type = p->args[0];
412 if (chan_type != IPI_MB_CHNL_TX && chan_type != IPI_MB_CHNL_RX) {
413 dev_err(dev, "req chnl failure: invalid chnl type %u.\n",
414 chan_type);
415 return ERR_PTR(-EINVAL);
416 }
417 chan = &mbox->chans[chan_type];
418 return chan;
419}
420
421static const struct of_device_id zynqmp_ipi_of_match[] = {
422 { .compatible = "xlnx,zynqmp-ipi-mailbox" },
423 {},
424};
425MODULE_DEVICE_TABLE(of, zynqmp_ipi_of_match);
426
427/**
428 * zynqmp_ipi_mbox_get_buf_res - Get buffer resource from the IPI dev node
429 *
430 * @node: IPI mbox device child node
431 * @name: name of the IPI buffer
432 * @res: pointer to where the resource information will be stored.
433 *
434 * Return: 0 for success, negative value for failure
435 */
436static int zynqmp_ipi_mbox_get_buf_res(struct device_node *node,
437 const char *name,
438 struct resource *res)
439{
440 int ret, index;
441
442 index = of_property_match_string(node, "reg-names", name);
443 if (index >= 0) {
444 ret = of_address_to_resource(node, index, res);
445 if (ret < 0)
446 return -EINVAL;
447 return 0;
448 }
449 return -ENODEV;
450}
451
452/**
453 * zynqmp_ipi_mbox_dev_release() - release the existence of a ipi mbox dev
454 *
455 * @dev: the ipi mailbox device
456 *
457 * This is to avoid the no device release() function kernel warning.
458 *
459 */
460static void zynqmp_ipi_mbox_dev_release(struct device *dev)
461{
462 (void)dev;
463}
464
465/**
466 * zynqmp_ipi_mbox_probe - probe IPI mailbox resource from device node
467 *
468 * @ipi_mbox: pointer to IPI mailbox private data structure
469 * @node: IPI mailbox device node
470 *
471 * Return: 0 for success, negative value for failure
472 */
473static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,
474 struct device_node *node)
475{
476 struct zynqmp_ipi_mchan *mchan;
477 struct mbox_chan *chans;
478 struct mbox_controller *mbox;
479 struct resource res;
480 struct device *dev, *mdev;
481 const char *name;
482 int ret;
483
484 dev = ipi_mbox->pdata->dev;
485 /* Initialize dev for IPI mailbox */
486 ipi_mbox->dev.parent = dev;
487 ipi_mbox->dev.release = NULL;
488 ipi_mbox->dev.of_node = node;
489 dev_set_name(&ipi_mbox->dev, "%s", of_node_full_name(node));
490 dev_set_drvdata(&ipi_mbox->dev, ipi_mbox);
491 ipi_mbox->dev.release = zynqmp_ipi_mbox_dev_release;
492 ipi_mbox->dev.driver = &zynqmp_ipi_mbox_driver;
493 ret = device_register(&ipi_mbox->dev);
494 if (ret) {
495 dev_err(dev, "Failed to register ipi mbox dev.\n");
496 return ret;
497 }
498 mdev = &ipi_mbox->dev;
499
500 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
501 name = "local_request_region";
502 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
503 if (!ret) {
504 mchan->req_buf_size = resource_size(&res);
505 mchan->req_buf = devm_ioremap(mdev, res.start,
506 mchan->req_buf_size);
507 if (IS_ERR(mchan->req_buf)) {
508 dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
509 ret = PTR_ERR(mchan->req_buf);
510 return ret;
511 }
512 } else if (ret != -ENODEV) {
513 dev_err(mdev, "Unmatched resource %s, %d.\n", name, ret);
514 return ret;
515 }
516
517 name = "remote_response_region";
518 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
519 if (!ret) {
520 mchan->resp_buf_size = resource_size(&res);
521 mchan->resp_buf = devm_ioremap(mdev, res.start,
522 mchan->resp_buf_size);
523 if (IS_ERR(mchan->resp_buf)) {
524 dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
525 ret = PTR_ERR(mchan->resp_buf);
526 return ret;
527 }
528 } else if (ret != -ENODEV) {
529 dev_err(mdev, "Unmatched resource %s.\n", name);
530 return ret;
531 }
532 mchan->rx_buf = devm_kzalloc(mdev,
533 mchan->resp_buf_size +
534 sizeof(struct zynqmp_ipi_message),
535 GFP_KERNEL);
536 if (!mchan->rx_buf)
537 return -ENOMEM;
538
539 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
540 name = "remote_request_region";
541 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
542 if (!ret) {
543 mchan->req_buf_size = resource_size(&res);
544 mchan->req_buf = devm_ioremap(mdev, res.start,
545 mchan->req_buf_size);
546 if (IS_ERR(mchan->req_buf)) {
547 dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
548 ret = PTR_ERR(mchan->req_buf);
549 return ret;
550 }
551 } else if (ret != -ENODEV) {
552 dev_err(mdev, "Unmatched resource %s.\n", name);
553 return ret;
554 }
555
556 name = "local_response_region";
557 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
558 if (!ret) {
559 mchan->resp_buf_size = resource_size(&res);
560 mchan->resp_buf = devm_ioremap(mdev, res.start,
561 mchan->resp_buf_size);
562 if (IS_ERR(mchan->resp_buf)) {
563 dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
564 ret = PTR_ERR(mchan->resp_buf);
565 return ret;
566 }
567 } else if (ret != -ENODEV) {
568 dev_err(mdev, "Unmatched resource %s.\n", name);
569 return ret;
570 }
571 mchan->rx_buf = devm_kzalloc(mdev,
572 mchan->resp_buf_size +
573 sizeof(struct zynqmp_ipi_message),
574 GFP_KERNEL);
575 if (!mchan->rx_buf)
576 return -ENOMEM;
577
578 /* Get the IPI remote agent ID */
579 ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id);
580 if (ret < 0) {
581 dev_err(dev, "No IPI remote ID is specified.\n");
582 return ret;
583 }
584
585 mbox = &ipi_mbox->mbox;
586 mbox->dev = mdev;
587 mbox->ops = &zynqmp_ipi_chan_ops;
588 mbox->num_chans = 2;
589 mbox->txdone_irq = false;
590 mbox->txdone_poll = true;
591 mbox->txpoll_period = 5;
592 mbox->of_xlate = zynqmp_ipi_of_xlate;
593 chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL);
594 if (!chans)
595 return -ENOMEM;
596 mbox->chans = chans;
597 chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
598 chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
599 ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;
600 ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;
601 ret = devm_mbox_controller_register(mdev, mbox);
602 if (ret)
603 dev_err(mdev,
604 "Failed to register mbox_controller(%d)\n", ret);
605 else
606 dev_info(mdev,
607 "Registered ZynqMP IPI mbox with TX/RX channels.\n");
608 return ret;
609}
610
611/**
612 * zynqmp_ipi_free_mboxes - Free IPI mailboxes devices
613 *
614 * @pdata: IPI private data
615 */
616static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata)
617{
618 struct zynqmp_ipi_mbox *ipi_mbox;
619 int i;
620
621 i = pdata->num_mboxes;
622 for (; i >= 0; i--) {
623 ipi_mbox = &pdata->ipi_mboxes[i];
624 if (ipi_mbox->dev.parent) {
625 mbox_controller_unregister(&ipi_mbox->mbox);
626 device_unregister(&ipi_mbox->dev);
627 }
628 }
629}
630
631static int zynqmp_ipi_probe(struct platform_device *pdev)
632{
633 struct device *dev = &pdev->dev;
634 struct device_node *nc, *np = pdev->dev.of_node;
635 struct zynqmp_ipi_pdata *pdata;
636 struct zynqmp_ipi_mbox *mbox;
637 int num_mboxes, ret = -EINVAL;
638
639 num_mboxes = of_get_child_count(np);
640 pdata = devm_kzalloc(dev, sizeof(*pdata) + (num_mboxes * sizeof(*mbox)),
641 GFP_KERNEL);
642 if (!pdata)
643 return -ENOMEM;
644 pdata->dev = dev;
645
646 /* Get the IPI local agents ID */
647 ret = of_property_read_u32(np, "xlnx,ipi-id", &pdata->local_id);
648 if (ret < 0) {
649 dev_err(dev, "No IPI local ID is specified.\n");
650 return ret;
651 }
652
653 pdata->num_mboxes = num_mboxes;
654 pdata->ipi_mboxes = (struct zynqmp_ipi_mbox *)
655 ((char *)pdata + sizeof(*pdata));
656
657 mbox = pdata->ipi_mboxes;
658 for_each_available_child_of_node(np, nc) {
659 mbox->pdata = pdata;
660 ret = zynqmp_ipi_mbox_probe(mbox, nc);
661 if (ret) {
662 dev_err(dev, "failed to probe subdev.\n");
663 ret = -EINVAL;
664 goto free_mbox_dev;
665 }
666 mbox++;
667 }
668
669 /* IPI IRQ */
670 ret = platform_get_irq(pdev, 0);
671 if (ret < 0) {
672 dev_err(dev, "unable to find IPI IRQ.\n");
673 goto free_mbox_dev;
674 }
675 pdata->irq = ret;
676 ret = devm_request_irq(dev, pdata->irq, zynqmp_ipi_interrupt,
677 IRQF_SHARED, dev_name(dev), pdata);
678 if (ret) {
679 dev_err(dev, "IRQ %d is not requested successfully.\n",
680 pdata->irq);
681 goto free_mbox_dev;
682 }
683
684 platform_set_drvdata(pdev, pdata);
685 return ret;
686
687free_mbox_dev:
688 zynqmp_ipi_free_mboxes(pdata);
689 return ret;
690}
691
692static int zynqmp_ipi_remove(struct platform_device *pdev)
693{
694 struct zynqmp_ipi_pdata *pdata;
695
696 pdata = platform_get_drvdata(pdev);
697 zynqmp_ipi_free_mboxes(pdata);
698
699 return 0;
700}
701
702static struct platform_driver zynqmp_ipi_driver = {
703 .probe = zynqmp_ipi_probe,
704 .remove = zynqmp_ipi_remove,
705 .driver = {
706 .name = "zynqmp-ipi",
707 .of_match_table = of_match_ptr(zynqmp_ipi_of_match),
708 },
709};
710
711static int __init zynqmp_ipi_init(void)
712{
713 return platform_driver_register(&zynqmp_ipi_driver);
714}
715subsys_initcall(zynqmp_ipi_init);
716
717static void __exit zynqmp_ipi_exit(void)
718{
719 platform_driver_unregister(&zynqmp_ipi_driver);
720}
721module_exit(zynqmp_ipi_exit);
722
723MODULE_LICENSE("GPL v2");
724MODULE_DESCRIPTION("Xilinx ZynqMP IPI Mailbox driver");
725MODULE_AUTHOR("Xilinx Inc.");
diff --git a/include/linux/mailbox/zynqmp-ipi-message.h b/include/linux/mailbox/zynqmp-ipi-message.h
new file mode 100644
index 000000000000..9542b41eacfd
--- /dev/null
+++ b/include/linux/mailbox/zynqmp-ipi-message.h
@@ -0,0 +1,20 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef _LINUX_ZYNQMP_IPI_MESSAGE_H_
4#define _LINUX_ZYNQMP_IPI_MESSAGE_H_
5
6/**
7 * struct zynqmp_ipi_message - ZynqMP IPI message structure
8 * @len: Length of message
9 * @data: message payload
10 *
11 * This is the structure for data used in mbox_send_message
12 * the maximum length of data buffer is fixed to 12 bytes.
13 * Client is supposed to be aware of this.
14 */
15struct zynqmp_ipi_message {
16 size_t len;
17 u8 data[0];
18};
19
20#endif /* _LINUX_ZYNQMP_IPI_MESSAGE_H_ */