1 /*
2 * Copyright (c) 2025 Basalte bv
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief SYSCON shell commands.
10 */
11
12 #include <zephyr/shell/shell.h>
13 #include <zephyr/drivers/syscon.h>
14
cmd_base(const struct shell * sh,size_t argc,char ** argv)15 static int cmd_base(const struct shell *sh, size_t argc, char **argv)
16 {
17 const struct device *dev;
18 uintptr_t base;
19 int ret;
20
21 dev = shell_device_get_binding(argv[1]);
22 if (!device_is_ready(dev)) {
23 shell_error(sh, "SYSCON device not ready");
24 return -ENODEV;
25 }
26
27 ret = syscon_get_base(dev, &base);
28 if (ret < 0) {
29 shell_error(sh, "Failed to get SYSCON base (%d)", ret);
30 return ret;
31 }
32
33 shell_print(sh, "0x%lx", base);
34 return 0;
35 }
36
cmd_read(const struct shell * sh,size_t argc,char ** argv)37 static int cmd_read(const struct shell *sh, size_t argc, char **argv)
38 {
39 const struct device *dev;
40 unsigned long addr;
41 uint32_t val;
42 int ret;
43
44 dev = shell_device_get_binding(argv[1]);
45 if (!device_is_ready(dev)) {
46 shell_error(sh, "SYSCON device not ready");
47 return -ENODEV;
48 }
49
50 addr = shell_strtoul(argv[2], 0, &ret);
51 if (ret < 0 || addr > UINT16_MAX) {
52 shell_error(sh, "Invalid address %s (%d)", argv[2], ret);
53 return -EINVAL;
54 }
55
56 ret = syscon_read_reg(dev, addr, &val);
57 if (ret < 0) {
58 shell_error(sh, "Failed to read (%d)", ret);
59 return ret;
60 }
61
62 shell_print(sh, "0x%x", val);
63 return 0;
64 }
65
cmd_write(const struct shell * sh,size_t argc,char ** argv)66 static int cmd_write(const struct shell *sh, size_t argc, char **argv)
67 {
68 const struct device *dev;
69 unsigned long addr, val;
70 int ret;
71
72 dev = shell_device_get_binding(argv[1]);
73 if (!device_is_ready(dev)) {
74 shell_error(sh, "SYSCON device not ready");
75 return -ENODEV;
76 }
77
78 addr = shell_strtoul(argv[2], 0, &ret);
79 if (ret < 0 || addr > UINT16_MAX) {
80 shell_error(sh, "Invalid address %s (%d)", argv[2], ret);
81 return -EINVAL;
82 }
83
84 val = shell_strtoul(argv[3], 0, &ret);
85 if (ret < 0 || val > UINT32_MAX) {
86 shell_error(sh, "Invalid value %s (%d)", argv[3], ret);
87 return -EINVAL;
88 }
89
90 ret = syscon_write_reg(dev, addr, val);
91 if (ret < 0) {
92 shell_error(sh, "Failed to write (%d)", ret);
93 return ret;
94 }
95
96 return 0;
97 }
98
cmd_size(const struct shell * sh,size_t argc,char ** argv)99 static int cmd_size(const struct shell *sh, size_t argc, char **argv)
100 {
101 const struct device *dev;
102 size_t size;
103 int ret;
104
105 dev = shell_device_get_binding(argv[1]);
106 if (!device_is_ready(dev)) {
107 shell_error(sh, "SYSCON device not ready");
108 return -ENODEV;
109 }
110
111 ret = syscon_get_size(dev, &size);
112 if (ret < 0) {
113 shell_error(sh, "Failed to get SYSCON size (%d)", ret);
114 return ret;
115 }
116
117 shell_print(sh, "%zu bytes", size);
118 return 0;
119 }
120
device_is_syscon(const struct device * dev)121 static bool device_is_syscon(const struct device *dev)
122 {
123 return DEVICE_API_IS(syscon, dev);
124 }
125
126 /* Device name autocompletion support */
device_name_get(size_t idx,struct shell_static_entry * entry)127 static void device_name_get(size_t idx, struct shell_static_entry *entry)
128 {
129 const struct device *dev = shell_device_filter(idx, device_is_syscon);
130
131 entry->syntax = (dev != NULL) ? dev->name : NULL;
132 entry->handler = NULL;
133 entry->help = NULL;
134 entry->subcmd = NULL;
135 }
136
137 SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
138
139 SHELL_STATIC_SUBCMD_SET_CREATE(syscon_cmds,
140 SHELL_CMD_ARG(base, &dsub_device_name,
141 SHELL_HELP("Get the SYSCON device base address", "<device>"),
142 cmd_base, 2, 0),
143 SHELL_CMD_ARG(read, &dsub_device_name,
144 SHELL_HELP("Read from a SYSCON device register", "<device> <address>"),
145 cmd_read, 3, 0),
146 SHELL_CMD_ARG(write, &dsub_device_name,
147 SHELL_HELP("Write to a SYSCON device register", "<device> <address> <value>"),
148 cmd_write, 4, 0),
149 SHELL_CMD_ARG(size, &dsub_device_name,
150 SHELL_HELP("Print the SYSCON device size in bytes", "<device>"),
151 cmd_size, 2, 0),
152 SHELL_SUBCMD_SET_END
153 );
154
155 SHELL_CMD_REGISTER(syscon, &syscon_cmds, "SYSCON shell commands", NULL);
156