Lines Matching +full:sci +full:- +full:reset

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>
17 #include <linux/reset.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
55 * @uses_lreset: flag to denote the need for local reset management
65 * struct k3_dsp_rproc - k3 DSP remote processor driver structure
72 * @reset: reset control handle
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
87 struct reset_control *reset; member
97 * k3_dsp_rproc_mbox_callback() - inbound mailbox message handler
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()
119 if (kproc->rproc->state == RPROC_DETACHED) in k3_dsp_rproc_mbox_callback()
139 if (msg > kproc->rproc->max_notifyid) { in k3_dsp_rproc_mbox_callback()
144 if (rproc_vq_interrupt(kproc->rproc, msg) == IRQ_NONE) in k3_dsp_rproc_mbox_callback()
152 * through a simulated GPIO (a bit in an IPC interrupt-triggering register),
157 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_kick()
158 struct device *dev = rproc->dev.parent; in k3_dsp_rproc_kick()
163 if (kproc->rproc->state == RPROC_DETACHED) in k3_dsp_rproc_kick()
167 ret = mbox_send_message(kproc->mbox, (void *)msg); in k3_dsp_rproc_kick()
173 /* Put the DSP processor into reset */
176 struct device *dev = kproc->dev; in k3_dsp_rproc_reset()
179 ret = reset_control_assert(kproc->reset); in k3_dsp_rproc_reset()
181 dev_err(dev, "local-reset assert failed (%pe)\n", ERR_PTR(ret)); in k3_dsp_rproc_reset()
185 if (kproc->data->uses_lreset) in k3_dsp_rproc_reset()
188 ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, in k3_dsp_rproc_reset()
189 kproc->ti_sci_id); in k3_dsp_rproc_reset()
191 dev_err(dev, "module-reset assert failed (%pe)\n", ERR_PTR(ret)); in k3_dsp_rproc_reset()
192 if (reset_control_deassert(kproc->reset)) in k3_dsp_rproc_reset()
193 dev_warn(dev, "local-reset deassert back failed\n"); in k3_dsp_rproc_reset()
199 /* Release the DSP processor from reset */
202 struct device *dev = kproc->dev; in k3_dsp_rproc_release()
205 if (kproc->data->uses_lreset) in k3_dsp_rproc_release()
208 ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci, in k3_dsp_rproc_release()
209 kproc->ti_sci_id); in k3_dsp_rproc_release()
211 dev_err(dev, "module-reset deassert failed (%pe)\n", ERR_PTR(ret)); in k3_dsp_rproc_release()
216 ret = reset_control_deassert(kproc->reset); in k3_dsp_rproc_release()
218 dev_err(dev, "local-reset deassert failed, (%pe)\n", ERR_PTR(ret)); in k3_dsp_rproc_release()
219 if (kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, in k3_dsp_rproc_release()
220 kproc->ti_sci_id)) in k3_dsp_rproc_release()
221 dev_warn(dev, "module-reset assert back failed\n"); in k3_dsp_rproc_release()
229 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_request_mbox()
230 struct mbox_client *client = &kproc->client; in k3_dsp_rproc_request_mbox()
231 struct device *dev = kproc->dev; in k3_dsp_rproc_request_mbox()
234 client->dev = dev; in k3_dsp_rproc_request_mbox()
235 client->tx_done = NULL; in k3_dsp_rproc_request_mbox()
236 client->rx_callback = k3_dsp_rproc_mbox_callback; in k3_dsp_rproc_request_mbox()
237 client->tx_block = false; in k3_dsp_rproc_request_mbox()
238 client->knows_txdone = false; in k3_dsp_rproc_request_mbox()
240 kproc->mbox = mbox_request_channel(client, 0); in k3_dsp_rproc_request_mbox()
241 if (IS_ERR(kproc->mbox)) in k3_dsp_rproc_request_mbox()
242 return dev_err_probe(dev, PTR_ERR(kproc->mbox), in k3_dsp_rproc_request_mbox()
246 * Ping the remote processor, this is only for sanity-sake for now; in k3_dsp_rproc_request_mbox()
252 ret = mbox_send_message(kproc->mbox, (void *)RP_MBOX_ECHO_REQUEST); in k3_dsp_rproc_request_mbox()
255 mbox_free_channel(kproc->mbox); in k3_dsp_rproc_request_mbox()
262 * The C66x DSP cores have a local reset that affects only the CPU, and a
263 * generic module reset that powers on the device and allows the DSP internal
264 * memories to be accessed while the local reset is asserted. This function is
265 * used to release the global reset on C66x DSPs to allow loading into the DSP
273 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_prepare()
274 struct device *dev = kproc->dev; in k3_dsp_rproc_prepare()
277 ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci, in k3_dsp_rproc_prepare()
278 kproc->ti_sci_id); in k3_dsp_rproc_prepare()
280 dev_err(dev, "module-reset deassert failed, cannot enable internal RAM loading (%pe)\n", in k3_dsp_rproc_prepare()
289 * global reset on applicable C66x cores. This completes the second portion of
291 * .stop() callback through the local reset, and the .unprepare() ops is invoked
293 * reset. This callback is invoked only in remoteproc mode.
297 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_unprepare()
298 struct device *dev = kproc->dev; in k3_dsp_rproc_unprepare()
301 ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, in k3_dsp_rproc_unprepare()
302 kproc->ti_sci_id); in k3_dsp_rproc_unprepare()
304 dev_err(dev, "module-reset assert failed (%pe)\n", ERR_PTR(ret)); in k3_dsp_rproc_unprepare()
318 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_start()
319 struct device *dev = kproc->dev; in k3_dsp_rproc_start()
323 boot_addr = rproc->bootaddr; in k3_dsp_rproc_start()
324 if (boot_addr & (kproc->data->boot_align_addr - 1)) { in k3_dsp_rproc_start()
326 boot_addr, kproc->data->boot_align_addr); in k3_dsp_rproc_start()
327 return -EINVAL; in k3_dsp_rproc_start()
331 ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0); in k3_dsp_rproc_start()
345 * This function puts the DSP processor into reset, and finishes processing
350 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_stop()
358 * Attach to a running DSP remote processor (IPC-only mode)
362 * is no need to issue any TI-SCI commands to boot the DSP core. This callback
363 * is invoked only in IPC-only mode and exists because rproc_validate() checks
369 * Detach from a running DSP remote processor (IPC-only mode)
373 * IPC-only mode and exists for sanity sake.
379 * to provide the resource table for a booted DSP in IPC-only mode. The K3 DSP
380 * firmwares follow a design-by-contract approach and are expected to have the
385 * IPC-only mode.
390 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_get_loaded_rsc_table()
391 struct device *dev = kproc->dev; in k3_dsp_get_loaded_rsc_table()
393 if (!kproc->rmem[0].cpu_addr) { in k3_dsp_get_loaded_rsc_table()
394 dev_err(dev, "memory-region #1 does not exist, loaded rsc table can't be found"); in k3_dsp_get_loaded_rsc_table()
395 return ERR_PTR(-ENOMEM); in k3_dsp_get_loaded_rsc_table()
399 * NOTE: The resource table size is currently hard-coded to a maximum in k3_dsp_get_loaded_rsc_table()
403 * the hard-coded value suffices to support the IPC-only mode. in k3_dsp_get_loaded_rsc_table()
406 return (struct resource_table *)kproc->rmem[0].cpu_addr; in k3_dsp_get_loaded_rsc_table()
412 * address visible only from a DSP, or at the SoC-level bus address. Both these
419 struct k3_dsp_rproc *kproc = rproc->priv; in k3_dsp_rproc_da_to_va()
429 for (i = 0; i < kproc->num_mems; i++) { in k3_dsp_rproc_da_to_va()
430 bus_addr = kproc->mem[i].bus_addr; in k3_dsp_rproc_da_to_va()
431 dev_addr = kproc->mem[i].dev_addr; in k3_dsp_rproc_da_to_va()
432 size = kproc->mem[i].size; in k3_dsp_rproc_da_to_va()
435 /* handle DSP-view addresses */ in k3_dsp_rproc_da_to_va()
438 offset = da - dev_addr; in k3_dsp_rproc_da_to_va()
439 va = kproc->mem[i].cpu_addr + offset; in k3_dsp_rproc_da_to_va()
443 /* handle SoC-view addresses */ in k3_dsp_rproc_da_to_va()
446 offset = da - bus_addr; in k3_dsp_rproc_da_to_va()
447 va = kproc->mem[i].cpu_addr + offset; in k3_dsp_rproc_da_to_va()
454 for (i = 0; i < kproc->num_rmems; i++) { in k3_dsp_rproc_da_to_va()
455 dev_addr = kproc->rmem[i].dev_addr; in k3_dsp_rproc_da_to_va()
456 size = kproc->rmem[i].size; in k3_dsp_rproc_da_to_va()
459 offset = da - dev_addr; in k3_dsp_rproc_da_to_va()
460 va = kproc->rmem[i].cpu_addr + offset; in k3_dsp_rproc_da_to_va()
478 const struct k3_dsp_dev_data *data = kproc->data; in k3_dsp_rproc_of_get_memories()
479 struct device *dev = &pdev->dev; in k3_dsp_rproc_of_get_memories()
484 num_mems = kproc->data->num_mems; in k3_dsp_rproc_of_get_memories()
485 kproc->mem = devm_kcalloc(kproc->dev, num_mems, in k3_dsp_rproc_of_get_memories()
486 sizeof(*kproc->mem), GFP_KERNEL); in k3_dsp_rproc_of_get_memories()
487 if (!kproc->mem) in k3_dsp_rproc_of_get_memories()
488 return -ENOMEM; in k3_dsp_rproc_of_get_memories()
492 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
495 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
496 return -EINVAL; in k3_dsp_rproc_of_get_memories()
498 if (!devm_request_mem_region(dev, res->start, in k3_dsp_rproc_of_get_memories()
502 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
503 return -EBUSY; in k3_dsp_rproc_of_get_memories()
506 kproc->mem[i].cpu_addr = devm_ioremap_wc(dev, res->start, in k3_dsp_rproc_of_get_memories()
508 if (!kproc->mem[i].cpu_addr) { in k3_dsp_rproc_of_get_memories()
510 data->mems[i].name); in k3_dsp_rproc_of_get_memories()
511 return -ENOMEM; in k3_dsp_rproc_of_get_memories()
513 kproc->mem[i].bus_addr = res->start; in k3_dsp_rproc_of_get_memories()
514 kproc->mem[i].dev_addr = data->mems[i].dev_addr; in k3_dsp_rproc_of_get_memories()
515 kproc->mem[i].size = resource_size(res); in k3_dsp_rproc_of_get_memories()
518 data->mems[i].name, &kproc->mem[i].bus_addr, in k3_dsp_rproc_of_get_memories()
519 kproc->mem[i].size, kproc->mem[i].cpu_addr, in k3_dsp_rproc_of_get_memories()
520 kproc->mem[i].dev_addr); in k3_dsp_rproc_of_get_memories()
522 kproc->num_mems = num_mems; in k3_dsp_rproc_of_get_memories()
536 struct device *dev = kproc->dev; in k3_dsp_reserved_mem_init()
537 struct device_node *np = dev->of_node; in k3_dsp_reserved_mem_init()
543 num_rmems = of_property_count_elems_of_size(np, "memory-region", in k3_dsp_reserved_mem_init()
548 return -EINVAL; in k3_dsp_reserved_mem_init()
553 return -EINVAL; in k3_dsp_reserved_mem_init()
567 num_rmems--; in k3_dsp_reserved_mem_init()
568 kproc->rmem = devm_kcalloc(dev, num_rmems, sizeof(*kproc->rmem), GFP_KERNEL); in k3_dsp_reserved_mem_init()
569 if (!kproc->rmem) in k3_dsp_reserved_mem_init()
570 return -ENOMEM; in k3_dsp_reserved_mem_init()
574 rmem_np = of_parse_phandle(np, "memory-region", i + 1); in k3_dsp_reserved_mem_init()
576 return -EINVAL; in k3_dsp_reserved_mem_init()
581 return -EINVAL; in k3_dsp_reserved_mem_init()
585 kproc->rmem[i].bus_addr = rmem->base; in k3_dsp_reserved_mem_init()
586 /* 64-bit address regions currently not supported */ in k3_dsp_reserved_mem_init()
587 kproc->rmem[i].dev_addr = (u32)rmem->base; in k3_dsp_reserved_mem_init()
588 kproc->rmem[i].size = rmem->size; in k3_dsp_reserved_mem_init()
589 kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); in k3_dsp_reserved_mem_init()
590 if (!kproc->rmem[i].cpu_addr) { in k3_dsp_reserved_mem_init()
592 i + 1, &rmem->base, &rmem->size); in k3_dsp_reserved_mem_init()
593 return -ENOMEM; in k3_dsp_reserved_mem_init()
597 i + 1, &kproc->rmem[i].bus_addr, in k3_dsp_reserved_mem_init()
598 kproc->rmem[i].size, kproc->rmem[i].cpu_addr, in k3_dsp_reserved_mem_init()
599 kproc->rmem[i].dev_addr); in k3_dsp_reserved_mem_init()
601 kproc->num_rmems = num_rmems; in k3_dsp_reserved_mem_init()
615 struct device *dev = &pdev->dev; in k3_dsp_rproc_probe()
616 struct device_node *np = dev->of_node; in k3_dsp_rproc_probe()
626 return -ENODEV; in k3_dsp_rproc_probe()
630 return dev_err_probe(dev, ret, "failed to parse firmware-name property\n"); in k3_dsp_rproc_probe()
635 return -ENOMEM; in k3_dsp_rproc_probe()
637 rproc->has_iommu = false; in k3_dsp_rproc_probe()
638 rproc->recovery_disabled = true; in k3_dsp_rproc_probe()
639 if (data->uses_lreset) { in k3_dsp_rproc_probe()
640 rproc->ops->prepare = k3_dsp_rproc_prepare; in k3_dsp_rproc_probe()
641 rproc->ops->unprepare = k3_dsp_rproc_unprepare; in k3_dsp_rproc_probe()
643 kproc = rproc->priv; in k3_dsp_rproc_probe()
644 kproc->rproc = rproc; in k3_dsp_rproc_probe()
645 kproc->dev = dev; in k3_dsp_rproc_probe()
646 kproc->data = data; in k3_dsp_rproc_probe()
652 kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); in k3_dsp_rproc_probe()
653 if (IS_ERR(kproc->ti_sci)) in k3_dsp_rproc_probe()
654 return dev_err_probe(dev, PTR_ERR(kproc->ti_sci), in k3_dsp_rproc_probe()
655 "failed to get ti-sci handle\n"); in k3_dsp_rproc_probe()
657 ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id); in k3_dsp_rproc_probe()
659 return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n"); in k3_dsp_rproc_probe()
661 kproc->reset = devm_reset_control_get_exclusive(dev, NULL); in k3_dsp_rproc_probe()
662 if (IS_ERR(kproc->reset)) in k3_dsp_rproc_probe()
663 return dev_err_probe(dev, PTR_ERR(kproc->reset), in k3_dsp_rproc_probe()
664 "failed to get reset\n"); in k3_dsp_rproc_probe()
666 kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci); in k3_dsp_rproc_probe()
667 if (IS_ERR(kproc->tsp)) in k3_dsp_rproc_probe()
668 return dev_err_probe(dev, PTR_ERR(kproc->tsp), in k3_dsp_rproc_probe()
669 "failed to construct ti-sci proc control\n"); in k3_dsp_rproc_probe()
671 ret = ti_sci_proc_request(kproc->tsp); in k3_dsp_rproc_probe()
676 ret = devm_add_action_or_reset(dev, k3_dsp_release_tsp, kproc->tsp); in k3_dsp_rproc_probe()
688 ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id, in k3_dsp_rproc_probe()
693 /* configure J721E devices for either remoteproc or IPC-only mode */ in k3_dsp_rproc_probe()
695 dev_info(dev, "configured DSP for IPC-only mode\n"); in k3_dsp_rproc_probe()
696 rproc->state = RPROC_DETACHED; in k3_dsp_rproc_probe()
697 /* override rproc ops with only required IPC-only mode ops */ in k3_dsp_rproc_probe()
698 rproc->ops->prepare = NULL; in k3_dsp_rproc_probe()
699 rproc->ops->unprepare = NULL; in k3_dsp_rproc_probe()
700 rproc->ops->start = NULL; in k3_dsp_rproc_probe()
701 rproc->ops->stop = NULL; in k3_dsp_rproc_probe()
702 rproc->ops->attach = k3_dsp_rproc_attach; in k3_dsp_rproc_probe()
703 rproc->ops->detach = k3_dsp_rproc_detach; in k3_dsp_rproc_probe()
704 rproc->ops->get_loaded_rsc_table = k3_dsp_get_loaded_rsc_table; in k3_dsp_rproc_probe()
708 * ensure the DSP local reset is asserted to ensure the DSP in k3_dsp_rproc_probe()
710 * reset is released. in k3_dsp_rproc_probe()
712 if (data->uses_lreset) { in k3_dsp_rproc_probe()
713 ret = reset_control_status(kproc->reset); in k3_dsp_rproc_probe()
715 return dev_err_probe(dev, ret, "failed to get reset status\n"); in k3_dsp_rproc_probe()
717 dev_warn(dev, "local reset is deasserted for device\n"); in k3_dsp_rproc_probe()
735 struct rproc *rproc = kproc->rproc; in k3_dsp_rproc_remove()
736 struct device *dev = &pdev->dev; in k3_dsp_rproc_remove()
739 if (rproc->state == RPROC_ATTACHED) { in k3_dsp_rproc_remove()
745 mbox_free_channel(kproc->mbox); in k3_dsp_rproc_remove()
786 { .compatible = "ti,j721e-c66-dsp", .data = &c66_data, },
787 { .compatible = "ti,j721e-c71-dsp", .data = &c71_data, },
788 { .compatible = "ti,j721s2-c71-dsp", .data = &c71_data, },
789 { .compatible = "ti,am62a-c7xv-dsp", .data = &c7xv_data, },
798 .name = "k3-dsp-rproc",
805 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");