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