88#include <linux/dma-mapping.h>
99#include <linux/firmware/xlnx-zynqmp.h>
1010#include <linux/kernel.h>
11+ #include <linux/mailbox_client.h>
12+ #include <linux/mailbox/zynqmp-ipi-message.h>
1113#include <linux/module.h>
1214#include <linux/of_address.h>
1315#include <linux/of_platform.h>
1416#include <linux/of_reserved_mem.h>
1517#include <linux/platform_device.h>
1618#include <linux/remoteproc.h>
17- #include <linux/slab.h>
1819
1920#include "remoteproc_internal.h"
2021
22+ /* IPI buffer MAX length */
23+ #define IPI_BUF_LEN_MAX 32U
24+
25+ /* RX mailbox client buffer max length */
26+ #define MBOX_CLIENT_BUF_MAX (IPI_BUF_LEN_MAX + \
27+ sizeof(struct zynqmp_ipi_message))
2128/*
2229 * settings for RPU cluster mode which
2330 * reflects possible values of xlnx,cluster-mode dt-property
@@ -43,6 +50,27 @@ struct mem_bank_data {
4350 char * bank_name ;
4451};
4552
53+ /**
54+ * struct mbox_info
55+ *
56+ * @rx_mc_buf: to copy data from mailbox rx channel
57+ * @tx_mc_buf: to copy data to mailbox tx channel
58+ * @r5_core: this mailbox's corresponding r5_core pointer
59+ * @mbox_work: schedule work after receiving data from mailbox
60+ * @mbox_cl: mailbox client
61+ * @tx_chan: mailbox tx channel
62+ * @rx_chan: mailbox rx channel
63+ */
64+ struct mbox_info {
65+ unsigned char rx_mc_buf [MBOX_CLIENT_BUF_MAX ];
66+ unsigned char tx_mc_buf [MBOX_CLIENT_BUF_MAX ];
67+ struct zynqmp_r5_core * r5_core ;
68+ struct work_struct mbox_work ;
69+ struct mbox_client mbox_cl ;
70+ struct mbox_chan * tx_chan ;
71+ struct mbox_chan * rx_chan ;
72+ };
73+
4674/*
4775 * Hardcoded TCM bank values. This will be removed once TCM bindings are
4876 * accepted for system-dt specifications and upstreamed in linux kernel
@@ -63,6 +91,7 @@ static const struct mem_bank_data zynqmp_tcm_banks[] = {
6391 * @tcm_banks: array of each TCM bank data
6492 * @rproc: rproc handle
6593 * @pm_domain_id: RPU CPU power domain id
94+ * @ipi: pointer to mailbox information
6695 */
6796struct zynqmp_r5_core {
6897 struct device * dev ;
@@ -71,6 +100,7 @@ struct zynqmp_r5_core {
71100 struct mem_bank_data * * tcm_banks ;
72101 struct rproc * rproc ;
73102 u32 pm_domain_id ;
103+ struct mbox_info * ipi ;
74104};
75105
76106/**
@@ -88,6 +118,178 @@ struct zynqmp_r5_cluster {
88118 struct zynqmp_r5_core * * r5_cores ;
89119};
90120
121+ /**
122+ * event_notified_idr_cb() - callback for vq_interrupt per notifyid
123+ * @id: rproc->notify id
124+ * @ptr: pointer to idr private data
125+ * @data: data passed to idr_for_each callback
126+ *
127+ * Pass notification to remoteproc virtio
128+ *
129+ * Return: 0. having return is to satisfy the idr_for_each() function
130+ * pointer input argument requirement.
131+ **/
132+ static int event_notified_idr_cb (int id , void * ptr , void * data )
133+ {
134+ struct rproc * rproc = data ;
135+
136+ if (rproc_vq_interrupt (rproc , id ) == IRQ_NONE )
137+ dev_dbg (& rproc -> dev , "data not found for vqid=%d\n" , id );
138+
139+ return 0 ;
140+ }
141+
142+ /**
143+ * handle_event_notified() - remoteproc notification work function
144+ * @work: pointer to the work structure
145+ *
146+ * It checks each registered remoteproc notify IDs.
147+ */
148+ static void handle_event_notified (struct work_struct * work )
149+ {
150+ struct mbox_info * ipi ;
151+ struct rproc * rproc ;
152+
153+ ipi = container_of (work , struct mbox_info , mbox_work );
154+ rproc = ipi -> r5_core -> rproc ;
155+
156+ /*
157+ * We only use IPI for interrupt. The RPU firmware side may or may
158+ * not write the notifyid when it trigger IPI.
159+ * And thus, we scan through all the registered notifyids and
160+ * find which one is valid to get the message.
161+ * Even if message from firmware is NULL, we attempt to get vqid
162+ */
163+ idr_for_each (& rproc -> notifyids , event_notified_idr_cb , rproc );
164+ }
165+
166+ /**
167+ * zynqmp_r5_mb_rx_cb() - receive channel mailbox callback
168+ * @cl: mailbox client
169+ * @msg: message pointer
170+ *
171+ * Receive data from ipi buffer, ack interrupt and then
172+ * it will schedule the R5 notification work.
173+ */
174+ static void zynqmp_r5_mb_rx_cb (struct mbox_client * cl , void * msg )
175+ {
176+ struct zynqmp_ipi_message * ipi_msg , * buf_msg ;
177+ struct mbox_info * ipi ;
178+ size_t len ;
179+
180+ ipi = container_of (cl , struct mbox_info , mbox_cl );
181+
182+ /* copy data from ipi buffer to r5_core */
183+ ipi_msg = (struct zynqmp_ipi_message * )msg ;
184+ buf_msg = (struct zynqmp_ipi_message * )ipi -> rx_mc_buf ;
185+ len = ipi_msg -> len ;
186+ if (len > IPI_BUF_LEN_MAX ) {
187+ dev_warn (cl -> dev , "msg size exceeded than %d\n" ,
188+ IPI_BUF_LEN_MAX );
189+ len = IPI_BUF_LEN_MAX ;
190+ }
191+ buf_msg -> len = len ;
192+ memcpy (buf_msg -> data , ipi_msg -> data , len );
193+
194+ /* received and processed interrupt ack */
195+ if (mbox_send_message (ipi -> rx_chan , NULL ) < 0 )
196+ dev_err (cl -> dev , "ack failed to mbox rx_chan\n" );
197+
198+ schedule_work (& ipi -> mbox_work );
199+ }
200+
201+ /**
202+ * zynqmp_r5_setup_mbox() - Setup mailboxes related properties
203+ * this is used for each individual R5 core
204+ *
205+ * @cdev: child node device
206+ *
207+ * Function to setup mailboxes related properties
208+ * return : NULL if failed else pointer to mbox_info
209+ */
210+ static struct mbox_info * zynqmp_r5_setup_mbox (struct device * cdev )
211+ {
212+ struct mbox_client * mbox_cl ;
213+ struct mbox_info * ipi ;
214+
215+ ipi = kzalloc (sizeof (* ipi ), GFP_KERNEL );
216+ if (!ipi )
217+ return NULL ;
218+
219+ mbox_cl = & ipi -> mbox_cl ;
220+ mbox_cl -> rx_callback = zynqmp_r5_mb_rx_cb ;
221+ mbox_cl -> tx_block = false;
222+ mbox_cl -> knows_txdone = false;
223+ mbox_cl -> tx_done = NULL ;
224+ mbox_cl -> dev = cdev ;
225+
226+ /* Request TX and RX channels */
227+ ipi -> tx_chan = mbox_request_channel_byname (mbox_cl , "tx" );
228+ if (IS_ERR (ipi -> tx_chan )) {
229+ ipi -> tx_chan = NULL ;
230+ kfree (ipi );
231+ dev_warn (cdev , "mbox tx channel request failed\n" );
232+ return NULL ;
233+ }
234+
235+ ipi -> rx_chan = mbox_request_channel_byname (mbox_cl , "rx" );
236+ if (IS_ERR (ipi -> rx_chan )) {
237+ mbox_free_channel (ipi -> tx_chan );
238+ ipi -> rx_chan = NULL ;
239+ ipi -> tx_chan = NULL ;
240+ kfree (ipi );
241+ dev_warn (cdev , "mbox rx channel request failed\n" );
242+ return NULL ;
243+ }
244+
245+ INIT_WORK (& ipi -> mbox_work , handle_event_notified );
246+
247+ return ipi ;
248+ }
249+
250+ static void zynqmp_r5_free_mbox (struct mbox_info * ipi )
251+ {
252+ if (!ipi )
253+ return ;
254+
255+ if (ipi -> tx_chan ) {
256+ mbox_free_channel (ipi -> tx_chan );
257+ ipi -> tx_chan = NULL ;
258+ }
259+
260+ if (ipi -> rx_chan ) {
261+ mbox_free_channel (ipi -> rx_chan );
262+ ipi -> rx_chan = NULL ;
263+ }
264+
265+ kfree (ipi );
266+ }
267+
268+ /*
269+ * zynqmp_r5_core_kick() - kick a firmware if mbox is provided
270+ * @rproc: r5 core's corresponding rproc structure
271+ * @vqid: virtqueue ID
272+ */
273+ static void zynqmp_r5_rproc_kick (struct rproc * rproc , int vqid )
274+ {
275+ struct zynqmp_r5_core * r5_core = rproc -> priv ;
276+ struct device * dev = r5_core -> dev ;
277+ struct zynqmp_ipi_message * mb_msg ;
278+ struct mbox_info * ipi ;
279+ int ret ;
280+
281+ ipi = r5_core -> ipi ;
282+ if (!ipi )
283+ return ;
284+
285+ mb_msg = (struct zynqmp_ipi_message * )ipi -> tx_mc_buf ;
286+ memcpy (mb_msg -> data , & vqid , sizeof (vqid ));
287+ mb_msg -> len = sizeof (vqid );
288+ ret = mbox_send_message (ipi -> tx_chan , mb_msg );
289+ if (ret < 0 )
290+ dev_warn (dev , "failed to send message\n" );
291+ }
292+
91293/*
92294 * zynqmp_r5_set_mode()
93295 *
@@ -624,6 +826,7 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = {
624826 .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table ,
625827 .sanity_check = rproc_elf_sanity_check ,
626828 .get_boot_addr = rproc_elf_get_boot_addr ,
829+ .kick = zynqmp_r5_rproc_kick ,
627830};
628831
629832/**
@@ -799,6 +1002,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
7991002 struct device_node * child ;
8001003 enum rpu_tcm_comb tcm_mode ;
8011004 int core_count , ret , i ;
1005+ struct mbox_info * ipi ;
8021006
8031007 ret = of_property_read_u32 (dev_node , "xlnx,cluster-mode" , & cluster_mode );
8041008
@@ -878,6 +1082,16 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
8781082 goto release_r5_cores ;
8791083 }
8801084
1085+ /*
1086+ * If mailbox nodes are disabled using "status" property then
1087+ * setting up mailbox channels will fail.
1088+ */
1089+ ipi = zynqmp_r5_setup_mbox (& child_pdev -> dev );
1090+ if (ipi ) {
1091+ r5_cores [i ]-> ipi = ipi ;
1092+ ipi -> r5_core = r5_cores [i ];
1093+ }
1094+
8811095 /*
8821096 * If two child nodes are available in dts in lockstep mode,
8831097 * then ignore second child node.
@@ -915,6 +1129,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
9151129 while (i >= 0 ) {
9161130 put_device (child_devs [i ]);
9171131 if (r5_cores [i ]) {
1132+ zynqmp_r5_free_mbox (r5_cores [i ]-> ipi );
9181133 of_reserved_mem_device_release (r5_cores [i ]-> dev );
9191134 rproc_del (r5_cores [i ]-> rproc );
9201135 rproc_free (r5_cores [i ]-> rproc );
@@ -939,6 +1154,7 @@ static void zynqmp_r5_cluster_exit(void *data)
9391154
9401155 for (i = 0 ; i < cluster -> core_count ; i ++ ) {
9411156 r5_core = cluster -> r5_cores [i ];
1157+ zynqmp_r5_free_mbox (r5_core -> ipi );
9421158 of_reserved_mem_device_release (r5_core -> dev );
9431159 put_device (r5_core -> dev );
9441160 rproc_del (r5_core -> rproc );
0 commit comments