1 // SPDX-License-Identifier: GPL-2.0
3 * Xilinx Inter Processor Interrupt(IPI) Mailbox Driver
5 * Copyright (C) 2018 Xilinx, Inc.
8 #include <linux/arm-smccc.h>
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/interrupt.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>
18 #include <linux/of_address.h>
19 #include <linux/of_device.h>
20 #include <linux/of_irq.h>
21 #include <linux/platform_device.h>
23 /* IPI agent ID any */
24 #define IPI_ID_ANY 0xFFUL
26 /* indicate if ZynqMP IPI mailbox driver uses SMC calls or HVC calls */
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
40 #define IPI_SMC_ENQUIRY_DIRQ_MASK 0x00000001UL /* Flag to indicate if
41 * notification interrupt
44 #define IPI_SMC_ACK_EIRQ_MASK 0x00000001UL /* Flag to indicate if
45 * notification interrupt
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
54 #define IPI_MB_CHNL_TX 0 /* IPI mailbox TX channel */
55 #define IPI_MB_CHNL_RX 1 /* IPI mailbox RX channel */
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
67 struct zynqmp_ipi_mchan
{
69 void __iomem
*req_buf
;
70 void __iomem
*resp_buf
;
74 unsigned int chan_type
;
78 * struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox
80 * @pdata: pointer to the IPI private data
81 * @dev: device pointer corresponding to the Xilinx ZynqMP
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
88 struct zynqmp_ipi_mbox
{
89 struct zynqmp_ipi_pdata
*pdata
;
92 struct mbox_controller mbox
;
93 struct zynqmp_ipi_mchan mchans
[2];
97 * struct zynqmp_ipi_pdata - Description of z ZynqMP IPI agent platform data.
99 * @dev: device pointer corresponding to the Xilinx ZynqMP
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
107 struct zynqmp_ipi_pdata
{
113 struct zynqmp_ipi_mbox
*ipi_mboxes
;
116 static struct device_driver zynqmp_ipi_mbox_driver
= {
117 .owner
= THIS_MODULE
,
118 .name
= "zynqmp-ipi-mbox",
121 static void zynqmp_ipi_fw_call(struct zynqmp_ipi_mbox
*ipi_mbox
,
122 unsigned long a0
, unsigned long a3
,
123 struct arm_smccc_res
*res
)
125 struct zynqmp_ipi_pdata
*pdata
= ipi_mbox
->pdata
;
126 unsigned long a1
, a2
;
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
);
133 arm_smccc_hvc(a0
, a1
, a2
, a3
, 0, 0, 0, 0, res
);
137 * zynqmp_ipi_interrupt - Interrupt handler for IPI notification
139 * @irq: Interrupt number
140 * @data: ZynqMP IPI mailbox platform data.
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.
146 static irqreturn_t
zynqmp_ipi_interrupt(int irq
, void *data
)
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
;
154 struct arm_smccc_res res
;
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
) {
169 msg
->len
= mchan
->req_buf_size
;
170 memcpy_fromio(msg
->data
, mchan
->req_buf
,
172 mbox_chan_received_data(chan
, (void *)msg
);
181 * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.
183 * @chan: Channel Pointer
185 * Return: 'true' if there is pending rx data, 'false' if there is none.
187 static bool zynqmp_ipi_peek_data(struct mbox_chan
*chan
)
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
;
194 struct arm_smccc_res res
;
196 if (WARN_ON(!ipi_mbox
)) {
197 dev_err(dev
, "no platform drv data??\n");
201 arg0
= SMC_IPI_MAILBOX_STATUS_ENQUIRY
;
202 zynqmp_ipi_fw_call(ipi_mbox
, arg0
, 0, &res
);
203 ret
= (int)(res
.a0
& 0xFFFFFFFF);
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.
209 if (ret
< 0 || ret
& IPI_MB_STATUS_SEND_PENDING
)
213 } else if (ret
> 0 && ret
& IPI_MB_STATUS_RECV_PENDING
) {
214 /* RX channel, check if there is message arrived. */
221 * zynqmp_ipi_last_tx_done - See if the last tx message is sent
223 * @chan: Channel pointer
225 * Return: 'true' is no pending tx data, 'false' if there are any.
227 static bool zynqmp_ipi_last_tx_done(struct mbox_chan
*chan
)
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
;
234 struct arm_smccc_res res
;
236 if (WARN_ON(!ipi_mbox
)) {
237 dev_err(dev
, "no platform drv data??\n");
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
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
)
253 /* Always true for the response message in RX channel */
258 * zynqmp_ipi_send_data - Send data
260 * @chan: Channel Pointer
261 * @data: Message Pointer
263 * Return: 0 if all goes good, else appropriate error messages.
265 static int zynqmp_ipi_send_data(struct mbox_chan
*chan
, void *data
)
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
;
272 struct arm_smccc_res res
;
274 if (WARN_ON(!ipi_mbox
)) {
275 dev_err(dev
, "no platform drv data??\n");
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
);
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
);
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
);
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
,
310 * zynqmp_ipi_startup - Startup the IPI channel
312 * @chan: Channel pointer
314 * Return: 0 if all goes good, else return corresponding error message
316 static int zynqmp_ipi_startup(struct mbox_chan
*chan
)
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
;
322 struct arm_smccc_res res
;
324 unsigned int nchan_type
;
326 if (mchan
->is_opened
)
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);
337 dev_err(dev
, "SMC to open the IPI channel failed.\n");
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
);
348 mchan
->is_opened
= 1;
354 * zynqmp_ipi_shutdown - Shutdown the IPI channel
356 * @chan: Channel pointer
358 static void zynqmp_ipi_shutdown(struct mbox_chan
*chan
)
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
;
364 struct arm_smccc_res res
;
365 unsigned int chan_type
;
367 if (!mchan
->is_opened
)
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
);
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
);
383 mchan
->is_opened
= 0;
386 /* ZynqMP IPI mailbox operations */
387 static 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
,
396 * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel
398 * @mbox: mailbox controller pointer
399 * @p: phandle pointer
401 * Return: Mailbox channel, else return error pointer.
403 static struct mbox_chan
*zynqmp_ipi_of_xlate(struct mbox_controller
*mbox
,
404 const struct of_phandle_args
*p
)
406 struct mbox_chan
*chan
;
407 struct device
*dev
= mbox
->dev
;
408 unsigned int chan_type
;
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",
415 return ERR_PTR(-EINVAL
);
417 chan
= &mbox
->chans
[chan_type
];
421 static const struct of_device_id zynqmp_ipi_of_match
[] = {
422 { .compatible
= "xlnx,zynqmp-ipi-mailbox" },
425 MODULE_DEVICE_TABLE(of
, zynqmp_ipi_of_match
);
428 * zynqmp_ipi_mbox_get_buf_res - Get buffer resource from the IPI dev node
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.
434 * Return: 0 for success, negative value for failure
436 static int zynqmp_ipi_mbox_get_buf_res(struct device_node
*node
,
438 struct resource
*res
)
442 index
= of_property_match_string(node
, "reg-names", name
);
444 ret
= of_address_to_resource(node
, index
, res
);
453 * zynqmp_ipi_mbox_dev_release() - release the existence of a ipi mbox dev
455 * @dev: the ipi mailbox device
457 * This is to avoid the no device release() function kernel warning.
460 static void zynqmp_ipi_mbox_dev_release(struct device
*dev
)
466 * zynqmp_ipi_mbox_probe - probe IPI mailbox resource from device node
468 * @ipi_mbox: pointer to IPI mailbox private data structure
469 * @node: IPI mailbox device node
471 * Return: 0 for success, negative value for failure
473 static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox
*ipi_mbox
,
474 struct device_node
*node
)
476 struct zynqmp_ipi_mchan
*mchan
;
477 struct mbox_chan
*chans
;
478 struct mbox_controller
*mbox
;
480 struct device
*dev
, *mdev
;
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
);
495 dev_err(dev
, "Failed to register ipi mbox dev.\n");
498 mdev
= &ipi_mbox
->dev
;
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
);
504 mchan
->req_buf_size
= resource_size(&res
);
505 mchan
->req_buf
= devm_ioremap(mdev
, res
.start
,
506 mchan
->req_buf_size
);
507 if (!mchan
->req_buf
) {
508 dev_err(mdev
, "Unable to map IPI buffer I/O memory\n");
511 } else if (ret
!= -ENODEV
) {
512 dev_err(mdev
, "Unmatched resource %s, %d.\n", name
, ret
);
516 name
= "remote_response_region";
517 ret
= zynqmp_ipi_mbox_get_buf_res(node
, name
, &res
);
519 mchan
->resp_buf_size
= resource_size(&res
);
520 mchan
->resp_buf
= devm_ioremap(mdev
, res
.start
,
521 mchan
->resp_buf_size
);
522 if (!mchan
->resp_buf
) {
523 dev_err(mdev
, "Unable to map IPI buffer I/O memory\n");
526 } else if (ret
!= -ENODEV
) {
527 dev_err(mdev
, "Unmatched resource %s.\n", name
);
530 mchan
->rx_buf
= devm_kzalloc(mdev
,
531 mchan
->resp_buf_size
+
532 sizeof(struct zynqmp_ipi_message
),
537 mchan
= &ipi_mbox
->mchans
[IPI_MB_CHNL_RX
];
538 name
= "remote_request_region";
539 ret
= zynqmp_ipi_mbox_get_buf_res(node
, name
, &res
);
541 mchan
->req_buf_size
= resource_size(&res
);
542 mchan
->req_buf
= devm_ioremap(mdev
, res
.start
,
543 mchan
->req_buf_size
);
544 if (!mchan
->req_buf
) {
545 dev_err(mdev
, "Unable to map IPI buffer I/O memory\n");
548 } else if (ret
!= -ENODEV
) {
549 dev_err(mdev
, "Unmatched resource %s.\n", name
);
553 name
= "local_response_region";
554 ret
= zynqmp_ipi_mbox_get_buf_res(node
, name
, &res
);
556 mchan
->resp_buf_size
= resource_size(&res
);
557 mchan
->resp_buf
= devm_ioremap(mdev
, res
.start
,
558 mchan
->resp_buf_size
);
559 if (!mchan
->resp_buf
) {
560 dev_err(mdev
, "Unable to map IPI buffer I/O memory\n");
563 } else if (ret
!= -ENODEV
) {
564 dev_err(mdev
, "Unmatched resource %s.\n", name
);
567 mchan
->rx_buf
= devm_kzalloc(mdev
,
568 mchan
->resp_buf_size
+
569 sizeof(struct zynqmp_ipi_message
),
574 /* Get the IPI remote agent ID */
575 ret
= of_property_read_u32(node
, "xlnx,ipi-id", &ipi_mbox
->remote_id
);
577 dev_err(dev
, "No IPI remote ID is specified.\n");
581 mbox
= &ipi_mbox
->mbox
;
583 mbox
->ops
= &zynqmp_ipi_chan_ops
;
585 mbox
->txdone_irq
= false;
586 mbox
->txdone_poll
= true;
587 mbox
->txpoll_period
= 5;
588 mbox
->of_xlate
= zynqmp_ipi_of_xlate
;
589 chans
= devm_kzalloc(mdev
, 2 * sizeof(*chans
), GFP_KERNEL
);
593 chans
[IPI_MB_CHNL_TX
].con_priv
= &ipi_mbox
->mchans
[IPI_MB_CHNL_TX
];
594 chans
[IPI_MB_CHNL_RX
].con_priv
= &ipi_mbox
->mchans
[IPI_MB_CHNL_RX
];
595 ipi_mbox
->mchans
[IPI_MB_CHNL_TX
].chan_type
= IPI_MB_CHNL_TX
;
596 ipi_mbox
->mchans
[IPI_MB_CHNL_RX
].chan_type
= IPI_MB_CHNL_RX
;
597 ret
= devm_mbox_controller_register(mdev
, mbox
);
600 "Failed to register mbox_controller(%d)\n", ret
);
603 "Registered ZynqMP IPI mbox with TX/RX channels.\n");
608 * zynqmp_ipi_free_mboxes - Free IPI mailboxes devices
610 * @pdata: IPI private data
612 static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata
*pdata
)
614 struct zynqmp_ipi_mbox
*ipi_mbox
;
617 i
= pdata
->num_mboxes
;
618 for (; i
>= 0; i
--) {
619 ipi_mbox
= &pdata
->ipi_mboxes
[i
];
620 if (ipi_mbox
->dev
.parent
) {
621 mbox_controller_unregister(&ipi_mbox
->mbox
);
622 device_unregister(&ipi_mbox
->dev
);
627 static int zynqmp_ipi_probe(struct platform_device
*pdev
)
629 struct device
*dev
= &pdev
->dev
;
630 struct device_node
*nc
, *np
= pdev
->dev
.of_node
;
631 struct zynqmp_ipi_pdata
*pdata
;
632 struct zynqmp_ipi_mbox
*mbox
;
633 int num_mboxes
, ret
= -EINVAL
;
635 num_mboxes
= of_get_child_count(np
);
636 pdata
= devm_kzalloc(dev
, sizeof(*pdata
) + (num_mboxes
* sizeof(*mbox
)),
642 /* Get the IPI local agents ID */
643 ret
= of_property_read_u32(np
, "xlnx,ipi-id", &pdata
->local_id
);
645 dev_err(dev
, "No IPI local ID is specified.\n");
649 pdata
->num_mboxes
= num_mboxes
;
650 pdata
->ipi_mboxes
= (struct zynqmp_ipi_mbox
*)
651 ((char *)pdata
+ sizeof(*pdata
));
653 mbox
= pdata
->ipi_mboxes
;
654 for_each_available_child_of_node(np
, nc
) {
656 ret
= zynqmp_ipi_mbox_probe(mbox
, nc
);
658 dev_err(dev
, "failed to probe subdev.\n");
666 ret
= platform_get_irq(pdev
, 0);
668 dev_err(dev
, "unable to find IPI IRQ.\n");
672 ret
= devm_request_irq(dev
, pdata
->irq
, zynqmp_ipi_interrupt
,
673 IRQF_SHARED
, dev_name(dev
), pdata
);
675 dev_err(dev
, "IRQ %d is not requested successfully.\n",
680 platform_set_drvdata(pdev
, pdata
);
684 zynqmp_ipi_free_mboxes(pdata
);
688 static int zynqmp_ipi_remove(struct platform_device
*pdev
)
690 struct zynqmp_ipi_pdata
*pdata
;
692 pdata
= platform_get_drvdata(pdev
);
693 zynqmp_ipi_free_mboxes(pdata
);
698 static struct platform_driver zynqmp_ipi_driver
= {
699 .probe
= zynqmp_ipi_probe
,
700 .remove
= zynqmp_ipi_remove
,
702 .name
= "zynqmp-ipi",
703 .of_match_table
= of_match_ptr(zynqmp_ipi_of_match
),
707 static int __init
zynqmp_ipi_init(void)
709 return platform_driver_register(&zynqmp_ipi_driver
);
711 subsys_initcall(zynqmp_ipi_init
);
713 static void __exit
zynqmp_ipi_exit(void)
715 platform_driver_unregister(&zynqmp_ipi_driver
);
717 module_exit(zynqmp_ipi_exit
);
719 MODULE_LICENSE("GPL v2");
720 MODULE_DESCRIPTION("Xilinx ZynqMP IPI Mailbox driver");
721 MODULE_AUTHOR("Xilinx Inc.");