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