Add shell commands to use the SYSCON driver API with SYSCON devices. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
156 lines
3.5 KiB
C
156 lines
3.5 KiB
C
/*
|
|
* Copyright (c) 2025 Basalte bv
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief SYSCON shell commands.
|
|
*/
|
|
|
|
#include <zephyr/shell/shell.h>
|
|
#include <zephyr/drivers/syscon.h>
|
|
|
|
static int cmd_base(const struct shell *sh, size_t argc, char **argv)
|
|
{
|
|
const struct device *dev;
|
|
uintptr_t base;
|
|
int ret;
|
|
|
|
dev = shell_device_get_binding(argv[1]);
|
|
if (!device_is_ready(dev)) {
|
|
shell_error(sh, "SYSCON device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
ret = syscon_get_base(dev, &base);
|
|
if (ret < 0) {
|
|
shell_error(sh, "Failed to get SYSCON base (%d)", ret);
|
|
return ret;
|
|
}
|
|
|
|
shell_print(sh, "0x%lx", base);
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_read(const struct shell *sh, size_t argc, char **argv)
|
|
{
|
|
const struct device *dev;
|
|
unsigned long addr;
|
|
uint32_t val;
|
|
int ret;
|
|
|
|
dev = shell_device_get_binding(argv[1]);
|
|
if (!device_is_ready(dev)) {
|
|
shell_error(sh, "SYSCON device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
addr = shell_strtoul(argv[2], 0, &ret);
|
|
if (ret < 0 || addr > UINT16_MAX) {
|
|
shell_error(sh, "Invalid address %s (%d)", argv[2], ret);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = syscon_read_reg(dev, addr, &val);
|
|
if (ret < 0) {
|
|
shell_error(sh, "Failed to read (%d)", ret);
|
|
return ret;
|
|
}
|
|
|
|
shell_print(sh, "0x%x", val);
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_write(const struct shell *sh, size_t argc, char **argv)
|
|
{
|
|
const struct device *dev;
|
|
unsigned long addr, val;
|
|
int ret;
|
|
|
|
dev = shell_device_get_binding(argv[1]);
|
|
if (!device_is_ready(dev)) {
|
|
shell_error(sh, "SYSCON device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
addr = shell_strtoul(argv[2], 0, &ret);
|
|
if (ret < 0 || addr > UINT16_MAX) {
|
|
shell_error(sh, "Invalid address %s (%d)", argv[2], ret);
|
|
return -EINVAL;
|
|
}
|
|
|
|
val = shell_strtoul(argv[3], 0, &ret);
|
|
if (ret < 0 || val > UINT32_MAX) {
|
|
shell_error(sh, "Invalid value %s (%d)", argv[3], ret);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = syscon_write_reg(dev, addr, val);
|
|
if (ret < 0) {
|
|
shell_error(sh, "Failed to write (%d)", ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_size(const struct shell *sh, size_t argc, char **argv)
|
|
{
|
|
const struct device *dev;
|
|
size_t size;
|
|
int ret;
|
|
|
|
dev = shell_device_get_binding(argv[1]);
|
|
if (!device_is_ready(dev)) {
|
|
shell_error(sh, "SYSCON device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
ret = syscon_get_size(dev, &size);
|
|
if (ret < 0) {
|
|
shell_error(sh, "Failed to get SYSCON size (%d)", ret);
|
|
return ret;
|
|
}
|
|
|
|
shell_print(sh, "%zu bytes", size);
|
|
return 0;
|
|
}
|
|
|
|
static bool device_is_syscon(const struct device *dev)
|
|
{
|
|
return DEVICE_API_IS(syscon, dev);
|
|
}
|
|
|
|
/* Device name autocompletion support */
|
|
static void device_name_get(size_t idx, struct shell_static_entry *entry)
|
|
{
|
|
const struct device *dev = shell_device_filter(idx, device_is_syscon);
|
|
|
|
entry->syntax = (dev != NULL) ? dev->name : NULL;
|
|
entry->handler = NULL;
|
|
entry->help = NULL;
|
|
entry->subcmd = NULL;
|
|
}
|
|
|
|
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(syscon_cmds,
|
|
SHELL_CMD_ARG(base, &dsub_device_name,
|
|
SHELL_HELP("Get the SYSCON device base address", "<device>"),
|
|
cmd_base, 2, 0),
|
|
SHELL_CMD_ARG(read, &dsub_device_name,
|
|
SHELL_HELP("Read from a SYSCON device register", "<device> <address>"),
|
|
cmd_read, 3, 0),
|
|
SHELL_CMD_ARG(write, &dsub_device_name,
|
|
SHELL_HELP("Write to a SYSCON device register", "<device> <address> <value>"),
|
|
cmd_write, 4, 0),
|
|
SHELL_CMD_ARG(size, &dsub_device_name,
|
|
SHELL_HELP("Print the SYSCON device size in bytes", "<device>"),
|
|
cmd_size, 2, 0),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_CMD_REGISTER(syscon, &syscon_cmds, "SYSCON shell commands", NULL);
|