1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2020 Wind River Systems, Inc. 4 * 5 * Author: 6 * Bin Meng <bin.meng@windriver.com> 7 * 8 * A command interface to access misc devices with MISC uclass driver APIs. 9 */ 10 11#include <common.h> 12#include <command.h> 13#include <dm.h> 14#include <errno.h> 15#include <misc.h> 16 17enum misc_op { 18 MISC_OP_READ, 19 MISC_OP_WRITE 20}; 21 22static char *misc_op_str[] = { 23 "read", 24 "write" 25}; 26 27static int do_misc_list(struct cmd_tbl *cmdtp, int flag, 28 int argc, char *const argv[]) 29{ 30 struct udevice *dev; 31 32 printf("Device Index Driver\n"); 33 printf("-------------------------------------\n"); 34 for (uclass_first_device(UCLASS_MISC, &dev); 35 dev; 36 uclass_next_device(&dev)) { 37 printf("%-20s %5d %10s\n", dev->name, dev_seq(dev), 38 dev->driver->name); 39 } 40 41 return 0; 42} 43 44static int do_misc_op(struct cmd_tbl *cmdtp, int flag, 45 int argc, char *const argv[], enum misc_op op) 46{ 47 struct udevice *dev; 48 int offset; 49 void *buf; 50 int size; 51 int ret; 52 53 ret = uclass_get_device_by_name(UCLASS_MISC, argv[0], &dev); 54 if (ret) { 55 printf("Unable to find device %s\n", argv[0]); 56 return ret; 57 } 58 59 offset = hextoul(argv[1], NULL); 60 buf = (void *)hextoul(argv[2], NULL); 61 size = hextoul(argv[3], NULL); 62 63 if (op == MISC_OP_READ) 64 ret = misc_read(dev, offset, buf, size); 65 else 66 ret = misc_write(dev, offset, buf, size); 67 68 if (ret < 0) { 69 if (ret == -ENOSYS) { 70 printf("The device does not support %s\n", 71 misc_op_str[op]); 72 ret = 0; 73 } 74 } else { 75 if (ret == size) 76 ret = 0; 77 else 78 printf("Partially %s %d bytes\n", misc_op_str[op], ret); 79 } 80 81 return ret; 82} 83 84static int do_misc_read(struct cmd_tbl *cmdtp, int flag, 85 int argc, char *const argv[]) 86{ 87 return do_misc_op(cmdtp, flag, argc, argv, MISC_OP_READ); 88} 89 90static int do_misc_write(struct cmd_tbl *cmdtp, int flag, 91 int argc, char *const argv[]) 92{ 93 return do_misc_op(cmdtp, flag, argc, argv, MISC_OP_WRITE); 94} 95 96static struct cmd_tbl misc_commands[] = { 97 U_BOOT_CMD_MKENT(list, 0, 1, do_misc_list, "", ""), 98 U_BOOT_CMD_MKENT(read, 4, 1, do_misc_read, "", ""), 99 U_BOOT_CMD_MKENT(write, 4, 1, do_misc_write, "", ""), 100}; 101 102static int do_misc(struct cmd_tbl *cmdtp, int flag, 103 int argc, char *const argv[]) 104{ 105 struct cmd_tbl *misc_cmd; 106 int ret; 107 108 if (argc < 2) 109 return CMD_RET_USAGE; 110 misc_cmd = find_cmd_tbl(argv[1], misc_commands, 111 ARRAY_SIZE(misc_commands)); 112 argc -= 2; 113 argv += 2; 114 if (!misc_cmd || argc != misc_cmd->maxargs) 115 return CMD_RET_USAGE; 116 117 ret = misc_cmd->cmd(misc_cmd, flag, argc, argv); 118 119 return cmd_process_error(misc_cmd, ret); 120} 121 122U_BOOT_CMD( 123 misc, 6, 1, do_misc, 124 "Access miscellaneous devices with MISC uclass driver APIs", 125 "list - list all miscellaneous devices\n" 126 "misc read name offset addr len - read `len' bytes starting at\n" 127 " `offset' of device `name'\n" 128 " to memory at `addr'\n" 129 "misc write name offset addr len - write `len' bytes starting at\n" 130 " `offset' of device `name'\n" 131 " from memory at `addr'" 132); 133