Lines Matching +full:omap +full:- +full:mailbox

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
6 * Suman Anna <s-anna@ti.com>
14 #include <linux/omap-mailbox.h>
24 #define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK (SZ_16M - 1)
27 * struct k3_dsp_mem - internal memory structure
41 * struct k3_dsp_mem_data - memory definitions for a DSP
51 * struct k3_dsp_dev_data - device data structure for a DSP
65 * struct k3_dsp_rproc - k3 DSP remote processor driver structure
73 * @data: pointer to DSP-specific device data
74 * @tsp: TI-SCI processor control handle
75 * @ti_sci: TI-SCI handle
76 * @ti_sci_id: TI-SCI device identifier
77 * @mbox: mailbox channel handle
78 * @client: mailbox client to request the mailbox channel
97 * k3_dsp_rproc_mbox_callback() - inbound mailbox message handler
98 * @client: mailbox client pointer used for requesting the mailbox channel
99 * @data: mailbox payload
101 * This handler is invoked by the OMAP mailbox driver whenever a mailbox
102 * message is received. Usually, the mailbox payload simply contains
106 * In addition to virtqueue indices, we also have some out-of-band values
114 struct device *dev = kproc->rproc->dev.parent; in k3_dsp_rproc_mbox_callback()
115 const char *name = kproc->rproc->name; in k3_dsp_rproc_mbox_callback()
135 if (msg > kproc->rproc->max_notifyid) { in k3_dsp_rproc_mbox_callback()
140 if (rproc_vq_interrupt(kproc->rproc, msg) == IRQ_NONE) in k3_dsp_rproc_mbox_callback()
148 * through a simulated GPIO (a bit in an IPC interrupt-triggering register),
153 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_kick()
154 struct device *dev = rproc->dev.parent; in k3_dsp_rproc_kick()
158 /* send the index of the triggered virtqueue in the mailbox payload */ in k3_dsp_rproc_kick()
159 ret = mbox_send_message(kproc->mbox, (void *)msg); in k3_dsp_rproc_kick()
161 dev_err(dev, "failed to send mailbox message, status = %d\n", in k3_dsp_rproc_kick()
168 struct device *dev = kproc->dev; in k3_dsp_rproc_reset()
171 ret = reset_control_assert(kproc->reset); in k3_dsp_rproc_reset()
173 dev_err(dev, "local-reset assert failed, ret = %d\n", ret); in k3_dsp_rproc_reset()
177 if (kproc->data->uses_lreset) in k3_dsp_rproc_reset()
180 ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, in k3_dsp_rproc_reset()
181 kproc->ti_sci_id); in k3_dsp_rproc_reset()
183 dev_err(dev, "module-reset assert failed, ret = %d\n", ret); in k3_dsp_rproc_reset()
184 if (reset_control_deassert(kproc->reset)) in k3_dsp_rproc_reset()
185 dev_warn(dev, "local-reset deassert back failed\n"); in k3_dsp_rproc_reset()
194 struct device *dev = kproc->dev; in k3_dsp_rproc_release()
197 if (kproc->data->uses_lreset) in k3_dsp_rproc_release()
200 ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci, in k3_dsp_rproc_release()
201 kproc->ti_sci_id); in k3_dsp_rproc_release()
203 dev_err(dev, "module-reset deassert failed, ret = %d\n", ret); in k3_dsp_rproc_release()
208 ret = reset_control_deassert(kproc->reset); in k3_dsp_rproc_release()
210 dev_err(dev, "local-reset deassert failed, ret = %d\n", ret); in k3_dsp_rproc_release()
211 if (kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, in k3_dsp_rproc_release()
212 kproc->ti_sci_id)) in k3_dsp_rproc_release()
213 dev_warn(dev, "module-reset assert back failed\n"); in k3_dsp_rproc_release()
221 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_request_mbox()
222 struct mbox_client *client = &kproc->client; in k3_dsp_rproc_request_mbox()
223 struct device *dev = kproc->dev; in k3_dsp_rproc_request_mbox()
226 client->dev = dev; in k3_dsp_rproc_request_mbox()
227 client->tx_done = NULL; in k3_dsp_rproc_request_mbox()
228 client->rx_callback = k3_dsp_rproc_mbox_callback; in k3_dsp_rproc_request_mbox()
229 client->tx_block = false; in k3_dsp_rproc_request_mbox()
230 client->knows_txdone = false; in k3_dsp_rproc_request_mbox()
232 kproc->mbox = mbox_request_channel(client, 0); in k3_dsp_rproc_request_mbox()
233 if (IS_ERR(kproc->mbox)) { in k3_dsp_rproc_request_mbox()
234 ret = -EBUSY; in k3_dsp_rproc_request_mbox()
236 PTR_ERR(kproc->mbox)); in k3_dsp_rproc_request_mbox()
241 * Ping the remote processor, this is only for sanity-sake for now; in k3_dsp_rproc_request_mbox()
245 * will wait in the mailbox fifo until the remote processor is booted. in k3_dsp_rproc_request_mbox()
247 ret = mbox_send_message(kproc->mbox, (void *)RP_MBOX_ECHO_REQUEST); in k3_dsp_rproc_request_mbox()
250 mbox_free_channel(kproc->mbox); in k3_dsp_rproc_request_mbox()
268 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_prepare()
269 struct device *dev = kproc->dev; in k3_dsp_rproc_prepare()
272 ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci, in k3_dsp_rproc_prepare()
273 kproc->ti_sci_id); in k3_dsp_rproc_prepare()
275 dev_err(dev, "module-reset deassert failed, cannot enable internal RAM loading, ret = %d\n", in k3_dsp_rproc_prepare()
292 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_unprepare()
293 struct device *dev = kproc->dev; in k3_dsp_rproc_unprepare()
296 ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, in k3_dsp_rproc_unprepare()
297 kproc->ti_sci_id); in k3_dsp_rproc_unprepare()
299 dev_err(dev, "module-reset assert failed, ret = %d\n", ret); in k3_dsp_rproc_unprepare()
313 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_start()
314 struct device *dev = kproc->dev; in k3_dsp_rproc_start()
322 boot_addr = rproc->bootaddr; in k3_dsp_rproc_start()
323 if (boot_addr & (kproc->data->boot_align_addr - 1)) { in k3_dsp_rproc_start()
325 boot_addr, kproc->data->boot_align_addr); in k3_dsp_rproc_start()
326 ret = -EINVAL; in k3_dsp_rproc_start()
331 ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0); in k3_dsp_rproc_start()
342 mbox_free_channel(kproc->mbox); in k3_dsp_rproc_start()
354 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_stop()
356 mbox_free_channel(kproc->mbox); in k3_dsp_rproc_stop()
364 * Attach to a running DSP remote processor (IPC-only mode)
366 * This rproc attach callback only needs to request the mailbox, the remote
367 * processor is already booted, so there is no need to issue any TI-SCI
368 * commands to boot the DSP core. This callback is invoked only in IPC-only
373 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_attach()
374 struct device *dev = kproc->dev; in k3_dsp_rproc_attach()
381 dev_info(dev, "DSP initialized in IPC-only mode\n"); in k3_dsp_rproc_attach()
386 * Detach from a running DSP remote processor (IPC-only mode)
389 * and only needs to release the mailbox, the DSP core is not stopped and will
391 * in IPC-only mode.
395 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_detach()
396 struct device *dev = kproc->dev; in k3_dsp_rproc_detach()
398 mbox_free_channel(kproc->mbox); in k3_dsp_rproc_detach()
399 dev_info(dev, "DSP deinitialized in IPC-only mode\n"); in k3_dsp_rproc_detach()
405 * to provide the resource table for a booted DSP in IPC-only mode. The K3 DSP
406 * firmwares follow a design-by-contract approach and are expected to have the
411 * IPC-only mode.
416 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_get_loaded_rsc_table()
417 struct device *dev = kproc->dev; in k3_dsp_get_loaded_rsc_table()
419 if (!kproc->rmem[0].cpu_addr) { in k3_dsp_get_loaded_rsc_table()
420 dev_err(dev, "memory-region #1 does not exist, loaded rsc table can't be found"); in k3_dsp_get_loaded_rsc_table()
421 return ERR_PTR(-ENOMEM); in k3_dsp_get_loaded_rsc_table()
425 * NOTE: The resource table size is currently hard-coded to a maximum in k3_dsp_get_loaded_rsc_table()
429 * the hard-coded value suffices to support the IPC-only mode. in k3_dsp_get_loaded_rsc_table()
432 return (struct resource_table *)kproc->rmem[0].cpu_addr; in k3_dsp_get_loaded_rsc_table()
438 * address visible only from a DSP, or at the SoC-level bus address. Both these
445 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_da_to_va()
455 for (i = 0; i < kproc->num_mems; i++) { in k3_dsp_rproc_da_to_va()
456 bus_addr = kproc->mem[i].bus_addr; in k3_dsp_rproc_da_to_va()
457 dev_addr = kproc->mem[i].dev_addr; in k3_dsp_rproc_da_to_va()
458 size = kproc->mem[i].size; in k3_dsp_rproc_da_to_va()
461 /* handle DSP-view addresses */ in k3_dsp_rproc_da_to_va()
464 offset = da - dev_addr; in k3_dsp_rproc_da_to_va()
465 va = kproc->mem[i].cpu_addr + offset; in k3_dsp_rproc_da_to_va()
469 /* handle SoC-view addresses */ in k3_dsp_rproc_da_to_va()
472 offset = da - bus_addr; in k3_dsp_rproc_da_to_va()
473 va = kproc->mem[i].cpu_addr + offset; in k3_dsp_rproc_da_to_va()
480 for (i = 0; i < kproc->num_rmems; i++) { in k3_dsp_rproc_da_to_va()
481 dev_addr = kproc->rmem[i].dev_addr; in k3_dsp_rproc_da_to_va()
482 size = kproc->rmem[i].size; in k3_dsp_rproc_da_to_va()
485 offset = da - dev_addr; in k3_dsp_rproc_da_to_va()
486 va = kproc->rmem[i].cpu_addr + offset; in k3_dsp_rproc_da_to_va()
504 const struct k3_dsp_dev_data *data = kproc->data; in k3_dsp_rproc_of_get_memories()
505 struct device *dev = &pdev->dev; in k3_dsp_rproc_of_get_memories()
510 num_mems = kproc->data->num_mems; in k3_dsp_rproc_of_get_memories()
511 kproc->mem = devm_kcalloc(kproc->dev, num_mems, in k3_dsp_rproc_of_get_memories()
512 sizeof(*kproc->mem), GFP_KERNEL); in k3_dsp_rproc_of_get_memories()
513 if (!kproc->mem) in k3_dsp_rproc_of_get_memories()
514 return -ENOMEM; in k3_dsp_rproc_of_get_memories()
518 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
521 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
522 return -EINVAL; in k3_dsp_rproc_of_get_memories()
524 if (!devm_request_mem_region(dev, res->start, in k3_dsp_rproc_of_get_memories()
528 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
529 return -EBUSY; in k3_dsp_rproc_of_get_memories()
532 kproc->mem[i].cpu_addr = devm_ioremap_wc(dev, res->start, in k3_dsp_rproc_of_get_memories()
534 if (!kproc->mem[i].cpu_addr) { in k3_dsp_rproc_of_get_memories()
536 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
537 return -ENOMEM; in k3_dsp_rproc_of_get_memories()
539 kproc->mem[i].bus_addr = res->start; in k3_dsp_rproc_of_get_memories()
540 kproc->mem[i].dev_addr = data->mems[i].dev_addr; in k3_dsp_rproc_of_get_memories()
541 kproc->mem[i].size = resource_size(res); in k3_dsp_rproc_of_get_memories()
544 data->mems[i].name, &kproc->mem[i].bus_addr, in k3_dsp_rproc_of_get_memories()
545 kproc->mem[i].size, kproc->mem[i].cpu_addr, in k3_dsp_rproc_of_get_memories()
546 kproc->mem[i].dev_addr); in k3_dsp_rproc_of_get_memories()
548 kproc->num_mems = num_mems; in k3_dsp_rproc_of_get_memories()
555 struct device *dev = kproc->dev; in k3_dsp_reserved_mem_init()
556 struct device_node *np = dev->of_node; in k3_dsp_reserved_mem_init()
562 num_rmems = of_property_count_elems_of_size(np, "memory-region", in k3_dsp_reserved_mem_init()
567 return -EINVAL; in k3_dsp_reserved_mem_init()
572 return -EINVAL; in k3_dsp_reserved_mem_init()
583 num_rmems--; in k3_dsp_reserved_mem_init()
584 kproc->rmem = kcalloc(num_rmems, sizeof(*kproc->rmem), GFP_KERNEL); in k3_dsp_reserved_mem_init()
585 if (!kproc->rmem) { in k3_dsp_reserved_mem_init()
586 ret = -ENOMEM; in k3_dsp_reserved_mem_init()
592 rmem_np = of_parse_phandle(np, "memory-region", i + 1); in k3_dsp_reserved_mem_init()
594 ret = -EINVAL; in k3_dsp_reserved_mem_init()
601 ret = -EINVAL; in k3_dsp_reserved_mem_init()
606 kproc->rmem[i].bus_addr = rmem->base; in k3_dsp_reserved_mem_init()
607 /* 64-bit address regions currently not supported */ in k3_dsp_reserved_mem_init()
608 kproc->rmem[i].dev_addr = (u32)rmem->base; in k3_dsp_reserved_mem_init()
609 kproc->rmem[i].size = rmem->size; in k3_dsp_reserved_mem_init()
610 kproc->rmem[i].cpu_addr = ioremap_wc(rmem->base, rmem->size); in k3_dsp_reserved_mem_init()
611 if (!kproc->rmem[i].cpu_addr) { in k3_dsp_reserved_mem_init()
613 i + 1, &rmem->base, &rmem->size); in k3_dsp_reserved_mem_init()
614 ret = -ENOMEM; in k3_dsp_reserved_mem_init()
619 i + 1, &kproc->rmem[i].bus_addr, in k3_dsp_reserved_mem_init()
620 kproc->rmem[i].size, kproc->rmem[i].cpu_addr, in k3_dsp_reserved_mem_init()
621 kproc->rmem[i].dev_addr); in k3_dsp_reserved_mem_init()
623 kproc->num_rmems = num_rmems; in k3_dsp_reserved_mem_init()
628 for (i--; i >= 0; i--) in k3_dsp_reserved_mem_init()
629 iounmap(kproc->rmem[i].cpu_addr); in k3_dsp_reserved_mem_init()
630 kfree(kproc->rmem); in k3_dsp_reserved_mem_init()
632 of_reserved_mem_device_release(kproc->dev); in k3_dsp_reserved_mem_init()
640 for (i = 0; i < kproc->num_rmems; i++) in k3_dsp_reserved_mem_exit()
641 iounmap(kproc->rmem[i].cpu_addr); in k3_dsp_reserved_mem_exit()
642 kfree(kproc->rmem); in k3_dsp_reserved_mem_exit()
644 of_reserved_mem_device_release(kproc->dev); in k3_dsp_reserved_mem_exit()
655 ret = of_property_read_u32_array(dev->of_node, "ti,sci-proc-ids", in k3_dsp_rproc_of_get_tsp()
662 return ERR_PTR(-ENOMEM); in k3_dsp_rproc_of_get_tsp()
664 tsp->dev = dev; in k3_dsp_rproc_of_get_tsp()
665 tsp->sci = sci; in k3_dsp_rproc_of_get_tsp()
666 tsp->ops = &sci->ops.proc_ops; in k3_dsp_rproc_of_get_tsp()
667 tsp->proc_id = temp[0]; in k3_dsp_rproc_of_get_tsp()
668 tsp->host_id = temp[1]; in k3_dsp_rproc_of_get_tsp()
675 struct device *dev = &pdev->dev; in k3_dsp_rproc_probe()
676 struct device_node *np = dev->of_node; in k3_dsp_rproc_probe()
687 return -ENODEV; in k3_dsp_rproc_probe()
691 dev_err(dev, "failed to parse firmware-name property, ret = %d\n", in k3_dsp_rproc_probe()
699 return -ENOMEM; in k3_dsp_rproc_probe()
701 rproc->has_iommu = false; in k3_dsp_rproc_probe()
702 rproc->recovery_disabled = true; in k3_dsp_rproc_probe()
703 if (data->uses_lreset) { in k3_dsp_rproc_probe()
704 rproc->ops->prepare = k3_dsp_rproc_prepare; in k3_dsp_rproc_probe()
705 rproc->ops->unprepare = k3_dsp_rproc_unprepare; in k3_dsp_rproc_probe()
707 kproc = rproc->priv; in k3_dsp_rproc_probe()
708 kproc->rproc = rproc; in k3_dsp_rproc_probe()
709 kproc->dev = dev; in k3_dsp_rproc_probe()
710 kproc->data = data; in k3_dsp_rproc_probe()
712 kproc->ti_sci = ti_sci_get_by_phandle(np, "ti,sci"); in k3_dsp_rproc_probe()
713 if (IS_ERR(kproc->ti_sci)) { in k3_dsp_rproc_probe()
714 ret = PTR_ERR(kproc->ti_sci); in k3_dsp_rproc_probe()
715 if (ret != -EPROBE_DEFER) { in k3_dsp_rproc_probe()
716 dev_err(dev, "failed to get ti-sci handle, ret = %d\n", in k3_dsp_rproc_probe()
719 kproc->ti_sci = NULL; in k3_dsp_rproc_probe()
723 ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id); in k3_dsp_rproc_probe()
725 dev_err(dev, "missing 'ti,sci-dev-id' property\n"); in k3_dsp_rproc_probe()
729 kproc->reset = devm_reset_control_get_exclusive(dev, NULL); in k3_dsp_rproc_probe()
730 if (IS_ERR(kproc->reset)) { in k3_dsp_rproc_probe()
731 ret = PTR_ERR(kproc->reset); in k3_dsp_rproc_probe()
736 kproc->tsp = k3_dsp_rproc_of_get_tsp(dev, kproc->ti_sci); in k3_dsp_rproc_probe()
737 if (IS_ERR(kproc->tsp)) { in k3_dsp_rproc_probe()
738 dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n", in k3_dsp_rproc_probe()
740 ret = PTR_ERR(kproc->tsp); in k3_dsp_rproc_probe()
744 ret = ti_sci_proc_request(kproc->tsp); in k3_dsp_rproc_probe()
760 ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id, in k3_dsp_rproc_probe()
768 /* configure J721E devices for either remoteproc or IPC-only mode */ in k3_dsp_rproc_probe()
770 dev_info(dev, "configured DSP for IPC-only mode\n"); in k3_dsp_rproc_probe()
771 rproc->state = RPROC_DETACHED; in k3_dsp_rproc_probe()
772 /* override rproc ops with only required IPC-only mode ops */ in k3_dsp_rproc_probe()
773 rproc->ops->prepare = NULL; in k3_dsp_rproc_probe()
774 rproc->ops->unprepare = NULL; in k3_dsp_rproc_probe()
775 rproc->ops->start = NULL; in k3_dsp_rproc_probe()
776 rproc->ops->stop = NULL; in k3_dsp_rproc_probe()
777 rproc->ops->attach = k3_dsp_rproc_attach; in k3_dsp_rproc_probe()
778 rproc->ops->detach = k3_dsp_rproc_detach; in k3_dsp_rproc_probe()
779 rproc->ops->get_loaded_rsc_table = k3_dsp_get_loaded_rsc_table; in k3_dsp_rproc_probe()
787 if (data->uses_lreset) { in k3_dsp_rproc_probe()
788 ret = reset_control_status(kproc->reset); in k3_dsp_rproc_probe()
814 ret1 = ti_sci_proc_release(kproc->tsp); in k3_dsp_rproc_probe()
818 kfree(kproc->tsp); in k3_dsp_rproc_probe()
820 ret1 = ti_sci_put_handle(kproc->ti_sci); in k3_dsp_rproc_probe()
831 struct rproc *rproc = kproc->rproc; in k3_dsp_rproc_remove()
832 struct device *dev = &pdev->dev; in k3_dsp_rproc_remove()
835 if (rproc->state == RPROC_ATTACHED) { in k3_dsp_rproc_remove()
843 rproc_del(kproc->rproc); in k3_dsp_rproc_remove()
845 ret = ti_sci_proc_release(kproc->tsp); in k3_dsp_rproc_remove()
849 kfree(kproc->tsp); in k3_dsp_rproc_remove()
851 ret = ti_sci_put_handle(kproc->ti_sci); in k3_dsp_rproc_remove()
856 rproc_free(kproc->rproc); in k3_dsp_rproc_remove()
888 { .compatible = "ti,j721e-c66-dsp", .data = &c66_data, },
889 { .compatible = "ti,j721e-c71-dsp", .data = &c71_data, },
890 { .compatible = "ti,j721s2-c71-dsp", .data = &c71_data, },
899 .name = "k3-dsp-rproc",
906 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");