File Index
Files and directories
Sign in
FILE

ti_k3_dsp_remoteproc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/remoteproc/ti_k3_dsp_remoteproc.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * TI K3 DSP Remote Processor(s) driver
  4 *
  5 * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
  6 *	Suman Anna <s-anna@ti.com>
  7 */
  8
  9#include <linux/io.h>
 10#include <linux/mailbox_client.h>
 11#include <linux/module.h>
 12#include <linux/of.h>
 13#include <linux/of_reserved_mem.h>
 14#include <linux/omap-mailbox.h>
 15#include <linux/platform_device.h>
 16#include <linux/remoteproc.h>
 17#include <linux/reset.h>
 18#include <linux/slab.h>
 19
 20#include "omap_remoteproc.h"
 21#include "remoteproc_internal.h"
 22#include "ti_sci_proc.h"
 23#include "ti_k3_common.h"
 24
 25/*
 26 * Power up the DSP remote processor.
 27 *
 28 * This function will be invoked only after the firmware for this rproc
 29 * was loaded, parsed successfully, and all of its resource requirements
 30 * were met. This callback is invoked only in remoteproc mode.
 31 */
 32static int k3_dsp_rproc_start(struct rproc *rproc)
 33{
 34	struct k3_rproc *kproc = rproc->priv;
 35	struct device *dev = kproc->dev;
 36	u32 boot_addr;
 37	int ret;
 38
 39	boot_addr = rproc->bootaddr;
 40	if (boot_addr & (kproc->data->boot_align_addr - 1)) {
 41		dev_err(dev, "invalid boot address 0x%x, must be aligned on a 0x%x boundary\n",
 42			boot_addr, kproc->data->boot_align_addr);
 43		return -EINVAL;
 44	}
 45
 46	dev_dbg(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr);
 47	ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0);
 48	if (ret)
 49		return ret;
 50
 51	/* Call the K3 common start function after doing DSP specific stuff */
 52	ret = k3_rproc_start(rproc);
 53	if (ret)
 54		return ret;
 55
 56	return 0;
 57}
 58
 59static const struct rproc_ops k3_dsp_rproc_ops = {
 60	.start			= k3_dsp_rproc_start,
 61	.stop			= k3_rproc_stop,
 62	.attach			= k3_rproc_attach,
 63	.detach			= k3_rproc_detach,
 64	.kick			= k3_rproc_kick,
 65	.da_to_va		= k3_rproc_da_to_va,
 66	.get_loaded_rsc_table	= k3_get_loaded_rsc_table,
 67};
 68
 69static int k3_dsp_rproc_probe(struct platform_device *pdev)
 70{
 71	struct device *dev = &pdev->dev;
 72	struct device_node *np = dev->of_node;
 73	const struct k3_rproc_dev_data *data;
 74	struct k3_rproc *kproc;
 75	struct rproc *rproc;
 76	const char *fw_name;
 77	bool p_state = false;
 78	int ret = 0;
 79
 80	data = of_device_get_match_data(dev);
 81	if (!data)
 82		return -ENODEV;
 83
 84	ret = rproc_of_parse_firmware(dev, 0, &fw_name);
 85	if (ret)
 86		return dev_err_probe(dev, ret, "failed to parse firmware-name property\n");
 87
 88	rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_dsp_rproc_ops,
 89				 fw_name, sizeof(*kproc));
 90	if (!rproc)
 91		return -ENOMEM;
 92
 93	rproc->has_iommu = false;
 94	rproc->recovery_disabled = true;
 95	if (data->uses_lreset) {
 96		rproc->ops->prepare = k3_rproc_prepare;
 97		rproc->ops->unprepare = k3_rproc_unprepare;
 98	}
 99	kproc = rproc->priv;
100	kproc->rproc = rproc;
101	kproc->dev = dev;
102	kproc->data = data;
103
104	ret = k3_rproc_request_mbox(rproc);
105	if (ret)
106		return ret;
107
108	kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");
109	if (IS_ERR(kproc->ti_sci))
110		return dev_err_probe(dev, PTR_ERR(kproc->ti_sci),
111				     "failed to get ti-sci handle\n");
112
113	ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id);
114	if (ret)
115		return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n");
116
117	kproc->reset = devm_reset_control_get_exclusive(dev, NULL);
118	if (IS_ERR(kproc->reset))
119		return dev_err_probe(dev, PTR_ERR(kproc->reset),
120				     "failed to get reset\n");
121
122	kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci);
123	if (IS_ERR(kproc->tsp))
124		return dev_err_probe(dev, PTR_ERR(kproc->tsp),
125				     "failed to construct ti-sci proc control\n");
126
127	ret = ti_sci_proc_request(kproc->tsp);
128	if (ret < 0) {
129		dev_err_probe(dev, ret, "ti_sci_proc_request failed\n");
130		return ret;
131	}
132	ret = devm_add_action_or_reset(dev, k3_release_tsp, kproc->tsp);
133	if (ret)
134		return ret;
135
136	ret = k3_rproc_of_get_memories(pdev, kproc);
137	if (ret)
138		return ret;
139
140	ret = k3_reserved_mem_init(kproc);
141	if (ret)
142		return dev_err_probe(dev, ret, "reserved memory init failed\n");
143
144	ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id,
145					       NULL, &p_state);
146	if (ret)
147		return dev_err_probe(dev, ret, "failed to get initial state, mode cannot be determined\n");
148
149	/* configure J721E devices for either remoteproc or IPC-only mode */
150	if (p_state) {
151		dev_info(dev, "configured DSP for IPC-only mode\n");
152		rproc->state = RPROC_DETACHED;
153	} else {
154		dev_info(dev, "configured DSP for remoteproc mode\n");
155	}
156
157	ret = devm_rproc_add(dev, rproc);
158	if (ret)
159		return dev_err_probe(dev, ret, "failed to add register device with remoteproc core\n");
160
161	platform_set_drvdata(pdev, kproc);
162
163	return 0;
164}
165
166static void k3_dsp_rproc_remove(struct platform_device *pdev)
167{
168	struct k3_rproc *kproc = platform_get_drvdata(pdev);
169	struct rproc *rproc = kproc->rproc;
170	struct device *dev = &pdev->dev;
171	int ret;
172
173	if (rproc->state == RPROC_ATTACHED) {
174		ret = rproc_detach(rproc);
175		if (ret)
176			dev_err(dev, "failed to detach proc (%pe)\n", ERR_PTR(ret));
177	}
178}
179
180static const struct k3_rproc_mem_data c66_mems[] = {
181	{ .name = "l2sram", .dev_addr = 0x800000 },
182	{ .name = "l1pram", .dev_addr = 0xe00000 },
183	{ .name = "l1dram", .dev_addr = 0xf00000 },
184};
185
186/* C71x cores only have a L1P Cache, there are no L1P SRAMs */
187static const struct k3_rproc_mem_data c71_mems[] = {
188	{ .name = "l2sram", .dev_addr = 0x800000 },
189	{ .name = "l1dram", .dev_addr = 0xe00000 },
190};
191
192static const struct k3_rproc_mem_data c7xv_mems[] = {
193	{ .name = "l2sram", .dev_addr = 0x800000 },
194};
195
196static const struct k3_rproc_dev_data c66_data = {
197	.mems = c66_mems,
198	.num_mems = ARRAY_SIZE(c66_mems),
199	.boot_align_addr = SZ_1K,
200	.uses_lreset = true,
201};
202
203static const struct k3_rproc_dev_data c71_data = {
204	.mems = c71_mems,
205	.num_mems = ARRAY_SIZE(c71_mems),
206	.boot_align_addr = SZ_2M,
207	.uses_lreset = false,
208};
209
210static const struct k3_rproc_dev_data c7xv_data = {
211	.mems = c7xv_mems,
212	.num_mems = ARRAY_SIZE(c7xv_mems),
213	.boot_align_addr = SZ_2M,
214	.uses_lreset = false,
215};
216
217static const struct of_device_id k3_dsp_of_match[] = {
218	{ .compatible = "ti,j721e-c66-dsp", .data = &c66_data, },
219	{ .compatible = "ti,j721e-c71-dsp", .data = &c71_data, },
220	{ .compatible = "ti,j721s2-c71-dsp", .data = &c71_data, },
221	{ .compatible = "ti,am62a-c7xv-dsp", .data = &c7xv_data, },
222	{ /* sentinel */ },
223};
224MODULE_DEVICE_TABLE(of, k3_dsp_of_match);
225
226static struct platform_driver k3_dsp_rproc_driver = {
227	.probe	= k3_dsp_rproc_probe,
228	.remove = k3_dsp_rproc_remove,
229	.driver	= {
230		.name = "k3-dsp-rproc",
231		.of_match_table = k3_dsp_of_match,
232	},
233};
234
235module_platform_driver(k3_dsp_rproc_driver);
236
237MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
238MODULE_LICENSE("GPL v2");
239MODULE_DESCRIPTION("TI K3 DSP Remoteproc driver");
~/ Read-only file preview.