usbc: add shell commands for PPC manipulation

Add support for ppc shell command with subcommands that can print
the status of PPC (dead battery, sinking, sourcing, vbus detected),
dump registers and request the PPC to exit dead battery mode.

Signed-off-by: Michał Barnaś <mb@semihalf.com>
This commit is contained in:
Michał Barnaś 2023-10-13 17:57:17 +02:00 committed by Carles Cufí
parent 85219ed13c
commit 6bd26a0575
4 changed files with 145 additions and 0 deletions

View file

@ -2,3 +2,4 @@
add_subdirectory_ifdef(CONFIG_USBC_TCPC_DRIVER tcpc)
add_subdirectory_ifdef(CONFIG_USBC_VBUS_DRIVER vbus)
add_subdirectory_ifdef(CONFIG_USBC_PPC_DRIVER ppc)

View file

@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_USBC_PPC_SHELL shell.c)

View file

@ -16,6 +16,11 @@ config USBC_PPC_INIT_PRIORITY
help
Initialization priority of the USB-C PPC drivers in POST_KERNEL.
config USBC_PPC_SHELL
bool "Shell commands for PPC"
help
Add useful shell commands to manipulate and debug the PPCs
module = USBC_PPC
module-str = usbc-ppc
source "subsys/logging/Kconfig.template.log_config"

134
drivers/usb_c/ppc/shell.c Normal file
View file

@ -0,0 +1,134 @@
/*
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/shell/shell.h>
#include <zephyr/drivers/usb_c/usbc_ppc.h>
/** Macro used to iterate over USB-C connector and call a function if the node has PPC property */
#define CALL_IF_HAS_PPC(usb_node, func) \
COND_CODE_1(DT_NODE_HAS_PROP(usb_node, ppc), \
(ret |= func(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(usb_node, ppc, 0)));), ())
/**
* @brief Command that dumps registers of one or all of the PPCs
*
* @param sh Shell structure
* @param argc Arguments count
* @param argv Device name
* @return int ORed return values of all the functions executed, 0 in case of success
*/
static int cmd_ppc_dump(const struct shell *sh, size_t argc, char **argv)
{
int ret = 0;
if (argc <= 1) {
DT_FOREACH_STATUS_OKAY_VARGS(usb_c_connector, CALL_IF_HAS_PPC, ppc_dump_regs);
} else {
const struct device *dev = device_get_binding(argv[1]);
ret = ppc_dump_regs(dev);
}
return ret;
}
/**
* @brief Function used to pretty print status of the PPC
*
* @param dev Pointer to the PPC device structure
*/
static int print_status(const struct device *dev)
{
printk("PPC %s:\n", dev->name);
printk(" Dead battery: %d\n", ppc_is_dead_battery_mode(dev));
printk(" Is sourcing: %d\n", ppc_is_vbus_source(dev));
printk(" Is sinking: %d\n", ppc_is_vbus_sink(dev));
printk(" Is VBUS present: %d\n", ppc_is_vbus_present(dev));
return 0;
}
/**
* @brief Command that prints the status of one or all of the PPCs
*
* @param sh Shell structure
* @param argc Arguments count
* @param argv Device name
* @return int ORed return values of all the functions executed, 0 in case of success
*/
static int cmd_ppc_status(const struct shell *sh, size_t argc, char **argv)
{
int ret = 0;
if (argc <= 1) {
DT_FOREACH_STATUS_OKAY_VARGS(usb_c_connector, CALL_IF_HAS_PPC, print_status);
} else {
const struct device *dev = device_get_binding(argv[1]);
ret = print_status(dev);
}
return ret;
}
/**
* @brief Command that requests one or all of the PPCs to try exiting the dead battery mode
*
* @param sh Shell structure
* @param argc Arguments count
* @param argv Device name
* @return int ORed return values of all the functions executed, 0 in case of success
*/
static int cmd_ppc_exit_db(const struct shell *sh, size_t argc, char **argv)
{
int ret = 0;
if (argc <= 1) {
DT_FOREACH_STATUS_OKAY_VARGS(usb_c_connector, CALL_IF_HAS_PPC,
ppc_exit_dead_battery_mode);
} else {
const struct device *dev = device_get_binding(argv[1]);
ret = ppc_exit_dead_battery_mode(dev);
}
return ret;
}
/**
* @brief Function used to create subcommands with devices names
*
* @param idx counter of devices
* @param entry shell structure that will be filled
*/
static void device_name_get(size_t idx, struct shell_static_entry *entry)
{
const struct device *dev = shell_device_lookup(idx, NULL);
entry->syntax = (dev != NULL) ? dev->name : NULL;
entry->handler = NULL;
entry->help = NULL;
entry->subcmd = NULL;
}
SHELL_DYNAMIC_CMD_CREATE(list_device_names, device_name_get);
SHELL_STATIC_SUBCMD_SET_CREATE(sub_ppc_cmds,
SHELL_CMD_ARG(dump, &list_device_names,
"Dump PPC registers\n"
"Usage: ppc dump [<ppc device>]",
cmd_ppc_dump, 1, 1),
SHELL_CMD_ARG(status, &list_device_names,
"Write PPC power status\n"
"Usage: ppc statuc [<ppc device>]",
cmd_ppc_status, 1, 1),
SHELL_CMD_ARG(exitdb, &list_device_names,
"Exit from the dead battery mode\n"
"Usage: ppc exitdb [<ppc device>]",
cmd_ppc_exit_db, 1, 1),
SHELL_SUBCMD_SET_END);
SHELL_CMD_REGISTER(ppc, &sub_ppc_cmds, "PPC (USB-C PD) diagnostics", NULL);