Current remoteproc framework provides commands to start/stop remote processor. However, If remote processor is already running before U-Boot then there is no way to connect to remote processor.
Implements attach/detach commands to connect to already running remote processor. During attach operation, remoteproc framework gets resource table from remote processor using platform specific callback and then creates vdev devices and other resources accordingly.
This approach is derived from the Linux kernel remoteproc framework.
kernel version: 6.4-rc2 (d848a4819d85) file: drivers/remoteproc/remoteproc_core
Signed-off-by: Tanmay Shah tanmay.shah@amd.com --- cmd/remoteproc.c | 14 +++++- drivers/remoteproc/rproc-uclass.c | 76 ++++++++++++++++++++++++++++++- include/remoteproc.h | 31 +++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-)
diff --git a/cmd/remoteproc.c b/cmd/remoteproc.c index ca3b436242..200a233114 100644 --- a/cmd/remoteproc.c +++ b/cmd/remoteproc.c @@ -173,6 +173,10 @@ static int do_remoteproc_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, ret = rproc_start(id); } else if (!strcmp(argv[0], "stop")) { ret = rproc_stop(id); + } else if (!strcmp(argv[0], "attach")) { + ret = rproc_attach(id); + } else if (!strcmp(argv[0], "detach")) { + ret = rproc_detach(id); } else if (!strcmp(argv[0], "reset")) { ret = rproc_reset(id); } else if (!strcmp(argv[0], "is_running")) { @@ -220,6 +224,12 @@ static struct cmd_tbl cmd_remoteproc_sub[] = { U_BOOT_CMD_MKENT(stop, 1, 1, do_remoteproc_wrapper, "Stop remote processor", "id - ID of the remote processor (see 'list' cmd)\n"), + U_BOOT_CMD_MKENT(attach, 1, 1, do_remoteproc_wrapper, + "Attach remote processor", + "id - ID of the remote processor (see 'list' cmd)\n"), + U_BOOT_CMD_MKENT(detach, 1, 1, do_remoteproc_wrapper, + "detach remote processor", + "id - ID of the remote processor (see 'list' cmd)\n"), U_BOOT_CMD_MKENT(reset, 1, 1, do_remoteproc_wrapper, "Reset remote processor", "id - ID of the remote processor (see 'list' cmd)\n"), @@ -262,7 +272,7 @@ static int do_remoteproc(struct cmd_tbl *cmdtp, int flag, int argc,
U_BOOT_CMD(rproc, 5, 1, do_remoteproc, "Control operation of remote processors in an SoC", - " [init|list|load|start|stop|reset|is_running|ping]\n" + " [attach|detach|init|list|load|start|stop|reset|is_running|ping]\n" "\t\t Where:\n" "\t\t[addr] is a memory address\n" "\t\t<id> is a numerical identifier for the remote processor\n" @@ -271,6 +281,8 @@ U_BOOT_CMD(rproc, 5, 1, do_remoteproc, "\t\tNote: Services are dependent on the driver capability\n" "\t\t 'list' command shows the capability of each device\n" "\n\tSubcommands:\n" + "\tattach <id> - attach to already running remote processor\n" + "\tdetach <id> - unbind driver with already attached device\n" "\tinit <id> - Enumerate and initalize the remote processor.\n" "\t if id is not passed, initialize all the remote prcessors\n" "\tlist - list available remote processors\n" diff --git a/drivers/remoteproc/rproc-uclass.c b/drivers/remoteproc/rproc-uclass.c index 3aebaf6187..31d2e70a0c 100644 --- a/drivers/remoteproc/rproc-uclass.c +++ b/drivers/remoteproc/rproc-uclass.c @@ -170,7 +170,7 @@ static int rproc_pre_probe(struct udevice *dev) return -EINVAL; }
- if (!ops->load || !ops->start) { + if ((!ops->load || !ops->start) && !ops->attach) { debug("%s driver has missing mandatory ops?\n", dev->name); return -EINVAL; } @@ -438,6 +438,8 @@ enum rproc_ops { RPROC_RESET, RPROC_PING, RPROC_RUNNING, + RPROC_ATTACH, + RPROC_DETACH, };
/** @@ -497,6 +499,14 @@ static int _rproc_ops_wrapper(int id, enum rproc_ops op) fn = ops->ping; op_str = "Pinging"; break; + case RPROC_ATTACH: + fn = ops->attach; + op_str = "Attaching"; + break; + case RPROC_DETACH: + fn = ops->detach; + op_str = "Detaching"; + break; default: debug("what is '%d' operation??\n", op); return -EINVAL; @@ -538,6 +548,15 @@ int rproc_is_running(int id) return _rproc_ops_wrapper(id, RPROC_RUNNING); };
+int rproc_attach(int id) +{ + return _rproc_ops_wrapper(id, RPROC_ATTACH); +}; + +int rproc_detach(int id) +{ + return _rproc_ops_wrapper(id, RPROC_DETACH); +};
static int handle_trace(struct udevice *dev, struct fw_rsc_trace *rsc, int offset, int avail) @@ -993,3 +1012,58 @@ unsigned long rproc_parse_resource_table(struct udevice *dev, struct rproc *cfg)
return 1; } + +unsigned long rproc_attach_resource_table(struct udevice *dev) +{ + struct dm_rproc_ops *ops = rproc_get_ops(dev); + struct resource_table *ptable; + int tablesz = 0, ret; + struct rproc *rproc; + + if (!ops->get_loaded_rsc_table) { + debug("get loaded rsctable op not supported\n"); + return -ENOSYS; + } + + ptable = (struct resource_table *)ops->get_loaded_rsc_table(dev, &tablesz); + if (!ptable) { + debug("can't get loaded resource table\n"); + return -EINVAL; + } + + rproc = rproc_get_cfg(dev); + if (!rproc) { + debug("remoteproc configurations not available\n"); + return -EINVAL; + } + + rproc->table_ptr = ptable; + + rsc_table = kzalloc(tablesz, GFP_KERNEL); + if (!rsc_table) + return -ENOMEM; + + /* + * Copy the resource table into a local buffer before handling the + * resource table. + */ + memcpy(rsc_table, ptable, tablesz); + + ret = handle_resources(dev, tablesz, loading_handlers); + if (ret) { + debug("handle_resources failed: %d\n", ret); + return 0; + } + + /* + * Instead of trying to mimic the kernel flow of copying the + * processed resource table into its post ELF load location in DDR + * copying it into its original location. + */ + memcpy(ptable, rsc_table, tablesz); + + free(rsc_table); + rsc_table = NULL; + + return 0; +} diff --git a/include/remoteproc.h b/include/remoteproc.h index 4251af52bd..8b7be05435 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -498,6 +498,22 @@ struct dm_rproc_ops { */ int (*stop)(struct udevice *dev);
+ /** + * attach() - Attach the remoteproc device (optional) + * + * @dev: Remote proc device + * @return 0 if all ok, else appropriate error value. + */ + int (*attach)(struct udevice *dev); + + /** + * detach() - Detach the remoteproc device (optional) + * + * @dev: Remote proc device + * @return 0 if all ok, else appropriate error value. + */ + int (*detach)(struct udevice *dev); + /** * reset() - Reset the remoteproc device (optional) * @@ -600,6 +616,19 @@ int rproc_start(int id); */ int rproc_stop(int id);
+/** + * rproc_attach() - Attach a remote processor + * @id: id of the remote processor + * Return: 0 if all ok, else appropriate error value. + */ +int rproc_attach(int id); + +/** + * rproc_detach() - Detach a remote processor + * @id: id of the remote processor + * Return: 0 if all ok, else appropriate error value. + */ +int rproc_detach(int id); /** * rproc_reset() - reset a remote processor * @id: id of the remote processor @@ -752,6 +781,8 @@ int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, unsigned long rproc_parse_resource_table(struct udevice *dev, struct rproc *cfg);
+unsigned long rproc_attach_resource_table(struct udevice *dev); + struct resource_table *rproc_find_resource_table(struct udevice *dev, unsigned int addr, int *tablesz);