blob: ec32b41ed1e96f01bcc27b1d3d2a6226d8966bed [file] [log] [blame]
Bin Meng3bc0db12020-10-14 14:34:52 +08001// 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)) {
Simon Glass8b85dfc2020-12-16 21:20:07 -070037 printf("%-20s %5d %10s\n", dev->name, dev_seq(dev),
Bin Meng3bc0db12020-10-14 14:34:52 +080038 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{
Bin Meng3bc0db12020-10-14 14:34:52 +080047 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
Simon Glass7e5f4602021-07-24 09:03:29 -060059 offset = hextoul(argv[1], NULL);
60 buf = (void *)hextoul(argv[2], NULL);
61 size = hextoul(argv[3], NULL);
Bin Meng3bc0db12020-10-14 14:34:52 +080062
63 if (op == MISC_OP_READ)
Tom Rinic4645fc2022-06-22 16:08:56 -040064 ret = misc_read(dev, offset, buf, size);
Bin Meng3bc0db12020-10-14 14:34:52 +080065 else
Tom Rinic4645fc2022-06-22 16:08:56 -040066 ret = misc_write(dev, offset, buf, size);
Bin Meng3bc0db12020-10-14 14:34:52 +080067
Bin Meng3bc0db12020-10-14 14:34:52 +080068 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);