Skip to content

Commit

Permalink
drivers: reset: arm_scmi: add shell interface
Browse files Browse the repository at this point in the history
Add ARM SCMI Reset shell interface for demo and testing purposes, which is
defined as sub-command of *arm_scmi* command.
It's optional and can be enabled by CONFIG_ARM_SCMI_RESET_SHELL option.

The ARM SCMI Reset shell interface defined as following:

$arm_scmi reset
reset - SCMI Reset proto commands.
Subcommands:
  revision   : SCMI Reset proto show revision information
              Usage: arm_scmi reset revision

  list       : SCMI Reset domains list
              Usage: arm_scmi reset list

  info       : SCMI Reset domain show info
              Usage: arm_scmi reset info <domain_id>

  assert     : SCMI Reset domain assert
              Usage: arm_scmi reset assert <domain_id>

  deassert   : SCMI Reset domain de-assert
              Usage: arm_scmi reset deassert <domain_id>

  autoreset  : SCMI Reset domain Autonomous reset
              Usage: arm_scmi reset autoreset <domain_id>

Signed-off-by: Grygorii Strashko <[email protected]>
  • Loading branch information
Grygorii Strashko committed Aug 19, 2024
1 parent fec1e5d commit 848f152
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/reset/Kconfig.arm_scmi
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ config ARM_SCMI_RESET
default y
help
Enable ARM SCMI reset driver based on Reset domain management protocol.

config ARM_SCMI_RESET_SHELL
bool "ARM SCMI reset shell interface"
depends on ARM_SCMI_SHELL
default y
help
Enable ARM SCMI reset shell interface used for testing/demo purposes.
175 changes: 175 additions & 0 deletions drivers/reset/reset_arm_scmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,30 @@ static int scmi_reset_proto_attr_get(const struct device *scmi_dev, uint16_t *nu
return 0;
}

#if defined(CONFIG_ARM_SCMI_RESET_SHELL)
static int scmi_reset_domain_attr_get(const struct device *scmi_dev, uint32_t id,
struct scmi_msg_reset_domain_attr_resp *dom_attr)
{
struct scmi_msg_reset_domain_attr_req dom_attr_req = {0};
int ret;

dom_attr_req.domain_id = sys_cpu_to_le32(id);

ret = scmi_xfer(scmi_dev, SCMI_PROTOCOL_RESET, SCMI_RESET_DOMAIN_ATTRIBUTES,
(uint8_t *)&dom_attr_req, sizeof(struct scmi_msg_reset_domain_attr_req),
(uint8_t *)dom_attr, sizeof(struct scmi_msg_reset_domain_attr_resp));
if (ret) {
LOG_ERR("reset domain get attributes failed (%d)", ret);
return ret;
}

dom_attr->attr = sys_le32_to_cpu(dom_attr->attr);
dom_attr->latency = sys_le32_to_cpu(dom_attr->latency);

return 0;
}
#endif /* CONFIG_ARM_SCMI_RESET_SHELL */

static int scmi_reset_line_assert(const struct device *dev, uint32_t id)
{
const struct scmi_reset_config *cfg = dev->config;
Expand Down Expand Up @@ -190,3 +214,154 @@ static const struct scmi_reset_config scmi_reset_config = {

DEVICE_DT_INST_DEFINE(0, scmi_reset_init, NULL, &scmi_reset_data, &scmi_reset_config, PRE_KERNEL_2,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &scmi_reset_driver_api);

#if defined(CONFIG_ARM_SCMI_RESET_SHELL)
#include <zephyr/shell/shell.h>

#if defined(CONFIG_DT_HAS_ARM_SCMI_RESET_ENABLED)
static const struct device *reset_dev = DEVICE_DT_GET_ANY(DT_DRV_COMPAT);
#else
BUILD_ASSERT(1, "unsupported scmi reset interface");
#endif

static int scmi_shell_reset_revision(const struct shell *sh, size_t argc, char **argv)
{
struct scmi_reset_drv_data *data = reset_dev->data;

shell_print(sh, "ARM SCMI Reset protocol version 0x%04x.%04x num_domains:%u",
data->version.ver.major, data->version.ver.minor, data->num_domains);

return 0;
}

static int scmi_shell_reset_dom_list(const struct shell *sh, size_t argc, char **argv)
{
const struct scmi_reset_config *cfg = reset_dev->config;
struct scmi_msg_reset_domain_attr_resp dom_attr = {0};
struct scmi_reset_drv_data *data = reset_dev->data;
uint16_t i;
int ret;

shell_print(sh, "domain_id,name,latency,attributes");

for (i = 0; i < data->num_domains; i++) {
ret = scmi_reset_domain_attr_get(cfg->scmi_dev, i, &dom_attr);
if (ret) {
shell_error(sh, "reset domain:%u get attributes failed (%d)", ret, i);
return ret;
}

shell_print(sh, "%u,%s,0x%08x,0x%08x", i, dom_attr.name, dom_attr.latency,
dom_attr.attr);
}

return 0;
}

static int scmi_shell_reset_info(const struct shell *sh, size_t argc, char **argv)
{
const struct scmi_reset_config *cfg = reset_dev->config;
struct scmi_msg_reset_domain_attr_resp dom_attr = {0};
struct scmi_reset_drv_data *data = reset_dev->data;
uint32_t domain_id;
int ret;

domain_id = atoi(argv[1]);
if (domain_id >= data->num_domains) {
shell_error(sh, "invalid reset domain index %s\n", argv[1]);
return -ENOENT;
}

ret = scmi_reset_domain_attr_get(cfg->scmi_dev, domain_id, &dom_attr);
if (ret) {
shell_error(sh, "reset domain get attributes failed (%d)", ret);
return ret;
}

shell_print(sh, "ARM SCMI reset domain: %u", domain_id);
shell_print(sh, " name\t\t: %s", dom_attr.name);
if (dom_attr.latency == SCMI_RESET_ATTR_LATENCY_UNK1 ||
dom_attr.latency == SCMI_RESET_ATTR_LATENCY_UNK1) {
shell_print(sh, " latency\t: unk");
} else {
shell_print(sh, " latency\t: %u", dom_attr.latency);
}
shell_print(sh, " attr\t\t: 0x%08x", dom_attr.attr);

return 0;
}

static int scmi_shell_reset_assert(const struct shell *sh, size_t argc, char **argv)
{
struct scmi_reset_drv_data *data = reset_dev->data;
uint32_t domain_id;

domain_id = atoi(argv[1]);
if (domain_id >= data->num_domains) {
shell_error(sh, "invalid reset domain index %s\n", argv[1]);
return -ENOENT;
}

return scmi_reset_line_assert(reset_dev, domain_id);
}

static int scmi_shell_reset_deassert(const struct shell *sh, size_t argc, char **argv)
{
struct scmi_reset_drv_data *data = reset_dev->data;
uint32_t domain_id;

domain_id = atoi(argv[1]);
if (domain_id >= data->num_domains) {
shell_error(sh, "invalid reset domain index %s\n", argv[1]);
return -ENOENT;
}

return scmi_reset_line_deassert(reset_dev, domain_id);
}

static int scmi_shell_reset_toggle(const struct shell *sh, size_t argc, char **argv)
{
struct scmi_reset_drv_data *data = reset_dev->data;
uint32_t domain_id;

domain_id = atoi(argv[1]);
if (domain_id >= data->num_domains) {
shell_error(sh, "invalid reset domain index %s\n", argv[1]);
return -ENOENT;
}

return scmi_reset_line_toggle(reset_dev, domain_id);
}

SHELL_STATIC_SUBCMD_SET_CREATE(sub_scmi_reset_cmds,
SHELL_CMD_ARG(revision, NULL,
"SCMI Reset proto show revision information\n"
"Usage: arm_scmi reset revision\n",
scmi_shell_reset_revision, 1, 0),
SHELL_CMD_ARG(list, NULL,
"SCMI Reset domains list\n"
"Usage: arm_scmi reset list\n",
scmi_shell_reset_dom_list, 1, 0),
SHELL_CMD_ARG(info, NULL,
"SCMI Reset domain show info\n"
"Usage: arm_scmi reset info <domain_id>\n",
scmi_shell_reset_info, 2, 0),
SHELL_CMD_ARG(assert, NULL,
"SCMI Reset domain assert\n"
"Usage: arm_scmi reset assert <domain_id>\n",
scmi_shell_reset_assert, 2, 0),
SHELL_CMD_ARG(deassert, NULL,
"SCMI Reset domain de-assert\n"
"Usage: arm_scmi reset deassert <domain_id>\n",
scmi_shell_reset_deassert, 2, 0),
SHELL_CMD_ARG(autoreset, NULL,
"SCMI Reset domain Autonomous reset\n"
"Usage: arm_scmi reset autoreset <domain_id>\n",
scmi_shell_reset_toggle, 2, 0),
SHELL_SUBCMD_SET_END);

SHELL_SUBCMD_ADD((arm_scmi), reset, &sub_scmi_reset_cmds,
"SCMI Reset proto commands.",
NULL, 1, 1);

#endif /* CONFIG_ARM_SCMI_RESET_SHELL */

0 comments on commit 848f152

Please sign in to comment.