Lines Matching +full:inter +full:- +full:data

1 // SPDX-License-Identifier: GPL-2.0
3 * Microchip Inter-Processor communication (IPC) driver
5 * Copyright (c) 2021 - 2024 Microchip Technology Inc. All rights reserved.
19 #include <linux/dma-mapping.h>
21 #include <linux/mailbox/mchp-ipc.h>
44 * struct mchp_ipc_mbox_info - IPC probe message format
58 * struct mchp_ipc_init - IPC channel init message format
70 * struct mchp_ipc_status - IPC status message format
85 * struct mchp_ipc_sbi_msg - IPC SBI payload message
87 * @buf_addr: physical address where the received data should be copied to
150 struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv; in mchp_ipc_prepare_receive_req()
153 request.buf_addr = chan_info->msg_buf_rx_addr; in mchp_ipc_prepare_receive_req()
154 request.size = chan_info->max_msg_size; in mchp_ipc_prepare_receive_req()
155 memcpy(chan_info->buf_base_rx, &request, sizeof(struct mchp_ipc_sbi_msg)); in mchp_ipc_prepare_receive_req()
161 struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv; in mchp_ipc_process_received_data()
164 memcpy(&sbi_msg, chan_info->buf_base_rx, sizeof(struct mchp_ipc_sbi_msg)); in mchp_ipc_process_received_data()
165 ipc_msg->buf = (u32 *)chan_info->msg_buf_rx; in mchp_ipc_process_received_data()
166 ipc_msg->size = sbi_msg.size; in mchp_ipc_process_received_data()
169 static irqreturn_t mchp_ipc_cluster_aggr_isr(int irq, void *data) in mchp_ipc_cluster_aggr_isr() argument
173 struct mchp_ipc_sbi_mbox *ipc = (struct mchp_ipc_sbi_mbox *)data; in mchp_ipc_cluster_aggr_isr()
183 if (irq == ipc->cluster_cfg[hartid].irq) in mchp_ipc_cluster_aggr_isr()
188 memcpy(ipc->cluster_cfg[hartid].buf_base, &status_msg, sizeof(struct mchp_ipc_status)); in mchp_ipc_cluster_aggr_isr()
190 ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[hartid].buf_base_addr); in mchp_ipc_cluster_aggr_isr()
192 dev_err_ratelimited(ipc->dev, "could not get IHC irq status ret=%d\n", ret); in mchp_ipc_cluster_aggr_isr()
196 memcpy(&status_msg, ipc->cluster_cfg[hartid].buf_base, sizeof(struct mchp_ipc_status)); in mchp_ipc_cluster_aggr_isr()
215 chan_index--; in mchp_ipc_cluster_aggr_isr()
224 chan = &ipc->chans[chan_id]; in mchp_ipc_cluster_aggr_isr()
225 chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv; in mchp_ipc_cluster_aggr_isr()
230 chan_info->buf_base_rx_addr); in mchp_ipc_cluster_aggr_isr()
235 mbox_chan_received_data(&ipc->chans[chan_id], (void *)&ipc_msg); in mchp_ipc_cluster_aggr_isr()
239 chan_info->buf_base_rx_addr); in mchp_ipc_cluster_aggr_isr()
240 mbox_chan_txdone(&ipc->chans[chan_id], ret); in mchp_ipc_cluster_aggr_isr()
246 static int mchp_ipc_send_data(struct mbox_chan *chan, void *data) in mchp_ipc_send_data() argument
248 struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv; in mchp_ipc_send_data()
249 const struct mchp_ipc_msg *msg = data; in mchp_ipc_send_data()
252 memcpy(chan_info->msg_buf_tx, msg->buf, msg->size); in mchp_ipc_send_data()
253 sbi_payload.buf_addr = chan_info->msg_buf_tx_addr; in mchp_ipc_send_data()
254 sbi_payload.size = msg->size; in mchp_ipc_send_data()
255 memcpy(chan_info->buf_base_tx, &sbi_payload, sizeof(sbi_payload)); in mchp_ipc_send_data()
257 return mchp_ipc_sbi_chan_send(SBI_EXT_IPC_SEND, chan_info->id, chan_info->buf_base_tx_addr); in mchp_ipc_send_data()
262 struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv; in mchp_ipc_startup()
263 struct mchp_ipc_sbi_mbox *ipc = to_mchp_ipc_mbox(chan->mbox); in mchp_ipc_startup()
269 * - struct mchp_ipc_init to initialize the channel in mchp_ipc_startup()
270 * - struct mchp_ipc_sbi_msg to transmit user data/payload in mchp_ipc_startup()
275 chan_info->buf_base_tx = kmalloc(max_size, GFP_KERNEL); in mchp_ipc_startup()
276 if (!chan_info->buf_base_tx) { in mchp_ipc_startup()
277 ret = -ENOMEM; in mchp_ipc_startup()
281 chan_info->buf_base_tx_addr = __pa(chan_info->buf_base_tx); in mchp_ipc_startup()
283 chan_info->buf_base_rx = kmalloc(max_size, GFP_KERNEL); in mchp_ipc_startup()
284 if (!chan_info->buf_base_rx) { in mchp_ipc_startup()
285 ret = -ENOMEM; in mchp_ipc_startup()
289 chan_info->buf_base_rx_addr = __pa(chan_info->buf_base_rx); in mchp_ipc_startup()
291 ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_CH_INIT, chan_info->id, in mchp_ipc_startup()
292 chan_info->buf_base_tx_addr); in mchp_ipc_startup()
294 dev_err(ipc->dev, "channel %u init failed\n", chan_info->id); in mchp_ipc_startup()
298 memcpy(&ch_init_msg, chan_info->buf_base_tx, sizeof(struct mchp_ipc_init)); in mchp_ipc_startup()
299 chan_info->max_msg_size = ch_init_msg.max_msg_size; in mchp_ipc_startup()
301 chan_info->msg_buf_tx = kmalloc(chan_info->max_msg_size, GFP_KERNEL); in mchp_ipc_startup()
302 if (!chan_info->msg_buf_tx) { in mchp_ipc_startup()
303 ret = -ENOMEM; in mchp_ipc_startup()
307 chan_info->msg_buf_tx_addr = __pa(chan_info->msg_buf_tx); in mchp_ipc_startup()
309 chan_info->msg_buf_rx = kmalloc(chan_info->max_msg_size, GFP_KERNEL); in mchp_ipc_startup()
310 if (!chan_info->msg_buf_rx) { in mchp_ipc_startup()
311 ret = -ENOMEM; in mchp_ipc_startup()
315 chan_info->msg_buf_rx_addr = __pa(chan_info->msg_buf_rx); in mchp_ipc_startup()
317 switch (ipc->hw_type) { in mchp_ipc_startup()
325 dev_err(ipc->dev, "failed to register interrupt(s)\n"); in mchp_ipc_startup()
332 kfree(chan_info->msg_buf_rx); in mchp_ipc_startup()
334 kfree(chan_info->msg_buf_tx); in mchp_ipc_startup()
336 kfree(chan_info->buf_base_rx); in mchp_ipc_startup()
338 kfree(chan_info->buf_base_tx); in mchp_ipc_startup()
345 struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv; in mchp_ipc_shutdown()
347 kfree(chan_info->buf_base_tx); in mchp_ipc_shutdown()
348 kfree(chan_info->buf_base_rx); in mchp_ipc_shutdown()
349 kfree(chan_info->msg_buf_tx); in mchp_ipc_shutdown()
350 kfree(chan_info->msg_buf_rx); in mchp_ipc_shutdown()
363 unsigned int chan_id = spec->args[0]; in mchp_ipc_mbox_xlate()
365 if (chan_id >= ipc->controller.num_chans) { in mchp_ipc_mbox_xlate()
366 dev_err(ipc->dev, "invalid channel id %d\n", chan_id); in mchp_ipc_mbox_xlate()
367 return ERR_PTR(-EINVAL); in mchp_ipc_mbox_xlate()
370 return &ipc->chans[chan_id]; in mchp_ipc_mbox_xlate()
375 struct platform_device *pdev = to_platform_device(ipc->dev); in mchp_ipc_get_cluster_aggr_irq()
383 irq_name = devm_kasprintf(ipc->dev, GFP_KERNEL, "hart-%lu", hartid); in mchp_ipc_get_cluster_aggr_irq()
388 ipc->cluster_cfg[hartid].irq = ret; in mchp_ipc_get_cluster_aggr_irq()
389 ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[hartid].irq, in mchp_ipc_get_cluster_aggr_irq()
391 "miv-ihc-irq", ipc); in mchp_ipc_get_cluster_aggr_irq()
395 ipc->cluster_cfg[hartid].buf_base = devm_kmalloc(ipc->dev, in mchp_ipc_get_cluster_aggr_irq()
399 if (!ipc->cluster_cfg[hartid].buf_base) in mchp_ipc_get_cluster_aggr_irq()
400 return -ENOMEM; in mchp_ipc_get_cluster_aggr_irq()
402 ipc->cluster_cfg[hartid].buf_base_addr = __pa(ipc->cluster_cfg[hartid].buf_base); in mchp_ipc_get_cluster_aggr_irq()
412 struct device *dev = &pdev->dev; in mchp_ipc_probe()
426 return -ENOMEM; in mchp_ipc_probe()
430 ipc->buf_base = devm_kmalloc(dev, sizeof(struct mchp_ipc_mbox_info), GFP_KERNEL); in mchp_ipc_probe()
431 if (!ipc->buf_base) in mchp_ipc_probe()
432 return -ENOMEM; in mchp_ipc_probe()
434 ipc->buf_base_addr = __pa(ipc->buf_base); in mchp_ipc_probe()
436 ret = mchp_ipc_sbi_send(SBI_EXT_IPC_PROBE, ipc->buf_base_addr); in mchp_ipc_probe()
440 memcpy(&ipc_info, ipc->buf_base, sizeof(struct mchp_ipc_mbox_info)); in mchp_ipc_probe()
441 ipc->controller.num_chans = ipc_info.num_channels; in mchp_ipc_probe()
442 ipc->hw_type = ipc_info.hw_type; in mchp_ipc_probe()
444 ipc->chans = devm_kcalloc(dev, ipc->controller.num_chans, sizeof(*ipc->chans), GFP_KERNEL); in mchp_ipc_probe()
445 if (!ipc->chans) in mchp_ipc_probe()
446 return -ENOMEM; in mchp_ipc_probe()
448 ipc->dev = dev; in mchp_ipc_probe()
449 ipc->controller.txdone_irq = true; in mchp_ipc_probe()
450 ipc->controller.dev = ipc->dev; in mchp_ipc_probe()
451 ipc->controller.ops = &mchp_ipc_ops; in mchp_ipc_probe()
452 ipc->controller.chans = ipc->chans; in mchp_ipc_probe()
453 ipc->controller.of_xlate = mchp_ipc_mbox_xlate; in mchp_ipc_probe()
455 for (chan_id = 0; chan_id < ipc->controller.num_chans; chan_id++) { in mchp_ipc_probe()
458 return -ENOMEM; in mchp_ipc_probe()
460 ipc->chans[chan_id].con_priv = priv; in mchp_ipc_probe()
461 priv->id = chan_id; in mchp_ipc_probe()
464 if (ipc->hw_type == MIV_IHC) { in mchp_ipc_probe()
465 ipc->cluster_cfg = devm_kcalloc(dev, num_online_cpus(), in mchp_ipc_probe()
468 if (!ipc->cluster_cfg) in mchp_ipc_probe()
469 return -ENOMEM; in mchp_ipc_probe()
476 return dev_err_probe(dev, -ENODEV, "missing interrupt property\n"); in mchp_ipc_probe()
478 ret = devm_mbox_controller_register(dev, &ipc->controller); in mchp_ipc_probe()
481 "Inter-Processor communication (IPC) registration failed\n"); in mchp_ipc_probe()
487 {.compatible = "microchip,sbi-ipc", },
504 MODULE_DESCRIPTION("Microchip Inter-Processor Communication (IPC) driver");