1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2015 4 * Texas Instruments Incorporated - https://www.ti.com/ 5 */ 6#include <common.h> 7#include <command.h> 8#include <dm.h> 9#include <errno.h> 10#include <malloc.h> 11#include <remoteproc.h> 12 13/** 14 * print_remoteproc_list() - print all the remote processor devices 15 * 16 * Return: 0 if no error, else returns appropriate error value. 17 */ 18static int print_remoteproc_list(void) 19{ 20 struct udevice *dev; 21 struct uclass *uc; 22 int ret; 23 char *type; 24 25 ret = uclass_get(UCLASS_REMOTEPROC, &uc); 26 if (ret) { 27 printf("Cannot find Remote processor class\n"); 28 return ret; 29 } 30 31 uclass_foreach_dev(dev, uc) { 32 struct dm_rproc_uclass_pdata *uc_pdata; 33 const struct dm_rproc_ops *ops = rproc_get_ops(dev); 34 35 uc_pdata = dev_get_uclass_plat(dev); 36 37 /* Do not print if rproc is not probed */ 38 if (!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)) 39 continue; 40 41 switch (uc_pdata->mem_type) { 42 case RPROC_INTERNAL_MEMORY_MAPPED: 43 type = "internal memory mapped"; 44 break; 45 default: 46 type = "unknown"; 47 break; 48 } 49 printf("%d - Name:'%s' type:'%s' supports: %s%s%s%s%s%s\n", 50 dev_seq(dev), 51 uc_pdata->name, 52 type, 53 ops->load ? "load " : "", 54 ops->start ? "start " : "", 55 ops->stop ? "stop " : "", 56 ops->reset ? "reset " : "", 57 ops->is_running ? "is_running " : "", 58 ops->ping ? "ping " : ""); 59 } 60 return 0; 61} 62 63/** 64 * do_rproc_init() - do basic initialization 65 * @cmdtp: unused 66 * @flag: unused 67 * @argc: unused 68 * @argv: unused 69 * 70 * Return: 0 if no error, else returns appropriate error value. 71 */ 72static int do_rproc_init(struct cmd_tbl *cmdtp, int flag, int argc, 73 char *const argv[]) 74{ 75 int id; 76 77 if (rproc_is_initialized()) { 78 printf("\tRemote Processors are already initialized\n"); 79 return CMD_RET_FAILURE; 80 } 81 82 if (argc == 1) { 83 if (!rproc_init()) 84 return 0; 85 printf("Few Remote Processors failed to be initialized\n"); 86 } else if (argc == 2) { 87 id = (int)dectoul(argv[1], NULL); 88 if (!rproc_dev_init(id)) 89 return 0; 90 printf("Remote Processor %d failed to be initialized\n", id); 91 } 92 93 return CMD_RET_FAILURE; 94} 95 96/** 97 * do_remoteproc_list() - print list of remote proc devices. 98 * @cmdtp: unused 99 * @flag: unused 100 * @argc: unused 101 * @argv: unused 102 * 103 * Return: 0 if no error, else returns appropriate error value. 104 */ 105static int do_remoteproc_list(struct cmd_tbl *cmdtp, int flag, int argc, 106 char *const argv[]) 107{ 108 if (print_remoteproc_list()) 109 return CMD_RET_FAILURE; 110 111 return 0; 112} 113 114/** 115 * do_remoteproc_load() - Load a remote processor with binary image 116 * @cmdtp: unused 117 * @flag: unused 118 * @argc: argument count for the load function 119 * @argv: arguments for the load function 120 * 121 * Return: 0 if no error, else returns appropriate error value. 122 */ 123static int do_remoteproc_load(struct cmd_tbl *cmdtp, int flag, int argc, 124 char *const argv[]) 125{ 126 ulong addr, size; 127 int id, ret; 128 129 if (argc != 4) 130 return CMD_RET_USAGE; 131 132 id = (int)dectoul(argv[1], NULL); 133 addr = hextoul(argv[2], NULL); 134 135 size = hextoul(argv[3], NULL); 136 137 if (!size) { 138 printf("\t Expect some size??\n"); 139 return CMD_RET_USAGE; 140 } 141 142 ret = rproc_load(id, addr, size); 143 printf("Load Remote Processor %d with data@addr=0x%08lx %lu bytes:%s\n", 144 id, addr, size, ret ? " Failed!" : " Success!"); 145 146 return ret ? CMD_RET_FAILURE : 0; 147} 148 149/** 150 * do_remoteproc_wrapper() - wrapper for various rproc commands 151 * @cmdtp: unused 152 * @flag: unused 153 * @argc: argument count for the rproc command 154 * @argv: arguments for the rproc command 155 * 156 * Most of the commands just take id as a parameter andinvoke various 157 * helper routines in remote processor core. by using a set of 158 * common checks, we can reduce the amount of code used for this. 159 * 160 * Return: 0 if no error, else returns appropriate error value. 161 */ 162static int do_remoteproc_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, 163 char *const argv[]) 164{ 165 int id, ret = CMD_RET_USAGE; 166 167 if (argc != 2) 168 return CMD_RET_USAGE; 169 170 id = (int)dectoul(argv[1], NULL); 171 172 if (!strcmp(argv[0], "start")) { 173 ret = rproc_start(id); 174 } else if (!strcmp(argv[0], "stop")) { 175 ret = rproc_stop(id); 176 } else if (!strcmp(argv[0], "reset")) { 177 ret = rproc_reset(id); 178 } else if (!strcmp(argv[0], "is_running")) { 179 ret = rproc_is_running(id); 180 if (!ret) { 181 printf("Remote processor is Running\n"); 182 } else if (ret == 1) { 183 printf("Remote processor is NOT Running\n"); 184 ret = 0; 185 } 186 /* Else error.. */ 187 } else if (!strcmp(argv[0], "ping")) { 188 ret = rproc_ping(id); 189 if (!ret) { 190 printf("Remote processor responds 'Pong'\n"); 191 } else if (ret == 1) { 192 printf("No response from Remote processor\n"); 193 ret = 0; 194 } 195 /* Else error.. */ 196 } 197 198 if (ret < 0) 199 printf("Operation Failed with error (%d)\n", ret); 200 201 return ret ? CMD_RET_FAILURE : 0; 202} 203 204static struct cmd_tbl cmd_remoteproc_sub[] = { 205 U_BOOT_CMD_MKENT(init, 1, 1, do_rproc_init, 206 "Enumerate and initialize the remote processor(s)", 207 "id - ID of the remote processor\n" 208 "If id is not passed, initialize all the remote processors"), 209 U_BOOT_CMD_MKENT(list, 0, 1, do_remoteproc_list, 210 "list remote processors", ""), 211 U_BOOT_CMD_MKENT(load, 5, 1, do_remoteproc_load, 212 "Load remote processor with provided image", 213 "<id> [addr] [size]\n" 214 "- id: ID of the remote processor(see 'list' cmd)\n" 215 "- addr: Address in memory of the image to loadup\n" 216 "- size: Size of the image to loadup\n"), 217 U_BOOT_CMD_MKENT(start, 1, 1, do_remoteproc_wrapper, 218 "Start remote processor", 219 "id - ID of the remote processor (see 'list' cmd)\n"), 220 U_BOOT_CMD_MKENT(stop, 1, 1, do_remoteproc_wrapper, 221 "Stop remote processor", 222 "id - ID of the remote processor (see 'list' cmd)\n"), 223 U_BOOT_CMD_MKENT(reset, 1, 1, do_remoteproc_wrapper, 224 "Reset remote processor", 225 "id - ID of the remote processor (see 'list' cmd)\n"), 226 U_BOOT_CMD_MKENT(is_running, 1, 1, do_remoteproc_wrapper, 227 "Check to see if remote processor is running\n", 228 "id - ID of the remote processor (see 'list' cmd)\n"), 229 U_BOOT_CMD_MKENT(ping, 1, 1, do_remoteproc_wrapper, 230 "Ping to communicate with remote processor\n", 231 "id - ID of the remote processor (see 'list' cmd)\n"), 232}; 233 234/** 235 * do_remoteproc() - (replace: short desc) 236 * @cmdtp: unused 237 * @flag: unused 238 * @argc: argument count 239 * @argv: argument list 240 * 241 * parses up the command table to invoke the correct command. 242 * 243 * Return: 0 if no error, else returns appropriate error value. 244 */ 245static int do_remoteproc(struct cmd_tbl *cmdtp, int flag, int argc, 246 char *const argv[]) 247{ 248 struct cmd_tbl *c = NULL; 249 250 /* Strip off leading 'rproc' command argument */ 251 argc--; 252 argv++; 253 254 if (argc) 255 c = find_cmd_tbl(argv[0], cmd_remoteproc_sub, 256 ARRAY_SIZE(cmd_remoteproc_sub)); 257 if (c) 258 return c->cmd(cmdtp, flag, argc, argv); 259 260 return CMD_RET_USAGE; 261} 262 263U_BOOT_CMD(rproc, 5, 1, do_remoteproc, 264 "Control operation of remote processors in an SoC", 265 " [init|list|load|start|stop|reset|is_running|ping]\n" 266 "\t\t Where:\n" 267 "\t\t[addr] is a memory address\n" 268 "\t\t<id> is a numerical identifier for the remote processor\n" 269 "\t\t provided by 'list' command.\n" 270 "\t\tNote: Remote processors must be initalized prior to usage\n" 271 "\t\tNote: Services are dependent on the driver capability\n" 272 "\t\t 'list' command shows the capability of each device\n" 273 "\n\tSubcommands:\n" 274 "\tinit <id> - Enumerate and initalize the remote processor.\n" 275 "\t if id is not passed, initialize all the remote prcessors\n" 276 "\tlist - list available remote processors\n" 277 "\tload <id> [addr] [size]- Load the remote processor with binary\n" 278 "\t image stored at address [addr] in memory\n" 279 "\tstart <id> - Start the remote processor(must be loaded)\n" 280 "\tstop <id> - Stop the remote processor\n" 281 "\treset <id> - Reset the remote processor\n" 282 "\tis_running <id> - Reports if the remote processor is running\n" 283 "\tping <id> - Ping the remote processor for communication\n"); 284