linux-loongson/drivers/remoteproc/ti_k3_m4_remoteproc.c
Beleswar Padhi 5779f6f9a6 remoteproc: k3: Refactor release_tsp() functions into common driver
The release_tsp() implementations in the TI K3 R5, DSP and M4 remoteproc
drivers release the TI-SCI processor control of a remote processor,
which is auto triggered upon device removal.

Refactor these functions into ti_k3_common.c driver as k3_release_tsp()
and use this common function throughout in R5, DSP and M4 drivers.

Signed-off-by: Beleswar Padhi <b-padhi@ti.com>
Tested-by: Judith Mendez <jm@ti.com>
Reviewed-by: Andrew Davis <afd@ti.com>
Link: https://lore.kernel.org/r/20250513054510.3439842-37-b-padhi@ti.com
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
2025-05-20 11:19:12 -06:00

157 lines
4.2 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* TI K3 Cortex-M4 Remote Processor(s) driver
*
* Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/
* Hari Nagalla <hnagalla@ti.com>
*/
#include <linux/io.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/remoteproc.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include "omap_remoteproc.h"
#include "remoteproc_internal.h"
#include "ti_sci_proc.h"
#include "ti_k3_common.h"
static const struct rproc_ops k3_m4_rproc_ops = {
.prepare = k3_rproc_prepare,
.unprepare = k3_rproc_unprepare,
.start = k3_rproc_start,
.stop = k3_rproc_stop,
.attach = k3_rproc_attach,
.detach = k3_rproc_detach,
.kick = k3_rproc_kick,
.da_to_va = k3_rproc_da_to_va,
.get_loaded_rsc_table = k3_get_loaded_rsc_table,
};
static int k3_m4_rproc_probe(struct platform_device *pdev)
{
const struct k3_rproc_dev_data *data;
struct device *dev = &pdev->dev;
struct k3_rproc *kproc;
struct rproc *rproc;
const char *fw_name;
bool r_state = false;
bool p_state = false;
int ret;
data = of_device_get_match_data(dev);
if (!data)
return -ENODEV;
ret = rproc_of_parse_firmware(dev, 0, &fw_name);
if (ret)
return dev_err_probe(dev, ret, "failed to parse firmware-name property\n");
rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_m4_rproc_ops, fw_name,
sizeof(*kproc));
if (!rproc)
return -ENOMEM;
rproc->has_iommu = false;
rproc->recovery_disabled = true;
kproc = rproc->priv;
kproc->dev = dev;
kproc->rproc = rproc;
kproc->data = data;
platform_set_drvdata(pdev, rproc);
kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");
if (IS_ERR(kproc->ti_sci))
return dev_err_probe(dev, PTR_ERR(kproc->ti_sci),
"failed to get ti-sci handle\n");
ret = of_property_read_u32(dev->of_node, "ti,sci-dev-id", &kproc->ti_sci_id);
if (ret)
return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n");
kproc->reset = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(kproc->reset))
return dev_err_probe(dev, PTR_ERR(kproc->reset), "failed to get reset\n");
kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci);
if (IS_ERR(kproc->tsp))
return dev_err_probe(dev, PTR_ERR(kproc->tsp),
"failed to construct ti-sci proc control\n");
ret = ti_sci_proc_request(kproc->tsp);
if (ret < 0)
return dev_err_probe(dev, ret, "ti_sci_proc_request failed\n");
ret = devm_add_action_or_reset(dev, k3_release_tsp, kproc->tsp);
if (ret)
return ret;
ret = k3_rproc_of_get_memories(pdev, kproc);
if (ret)
return ret;
ret = k3_reserved_mem_init(kproc);
if (ret)
return dev_err_probe(dev, ret, "reserved memory init failed\n");
ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id,
&r_state, &p_state);
if (ret)
return dev_err_probe(dev, ret,
"failed to get initial state, mode cannot be determined\n");
/* configure devices for either remoteproc or IPC-only mode */
if (p_state) {
rproc->state = RPROC_DETACHED;
dev_info(dev, "configured M4F for IPC-only mode\n");
} else {
dev_info(dev, "configured M4F for remoteproc mode\n");
}
ret = k3_rproc_request_mbox(rproc);
if (ret)
return ret;
ret = devm_rproc_add(dev, rproc);
if (ret)
return dev_err_probe(dev, ret,
"failed to register device with remoteproc core\n");
return 0;
}
static const struct k3_rproc_mem_data am64_m4_mems[] = {
{ .name = "iram", .dev_addr = 0x0 },
{ .name = "dram", .dev_addr = 0x30000 },
};
static const struct k3_rproc_dev_data am64_m4_data = {
.mems = am64_m4_mems,
.num_mems = ARRAY_SIZE(am64_m4_mems),
.boot_align_addr = SZ_1K,
.uses_lreset = true,
};
static const struct of_device_id k3_m4_of_match[] = {
{ .compatible = "ti,am64-m4fss", .data = &am64_m4_data, },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, k3_m4_of_match);
static struct platform_driver k3_m4_rproc_driver = {
.probe = k3_m4_rproc_probe,
.driver = {
.name = "k3-m4-rproc",
.of_match_table = k3_m4_of_match,
},
};
module_platform_driver(k3_m4_rproc_driver);
MODULE_AUTHOR("Hari Nagalla <hnagalla@ti.com>");
MODULE_DESCRIPTION("TI K3 M4 Remoteproc driver");
MODULE_LICENSE("GPL");