1 /*
2 * Copyright 2023 Google LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/device.h>
7 #include <zephyr/logging/log.h>
8 #include <zephyr/usb_c/usbc.h>
9 #include <zephyr/shell/shell.h>
10
11 /** Macro used to call the dump_std_reg function from the TCPC device pointer */
12 #define TCPC_DUMP_DEV(dev) ret |= tcpc_dump_std_reg(dev);
13
14 /** Macro used to call the dump_std_reg function from the USB-C connector node */
15 #define TCPC_DUMP_CONN_NODE(node) TCPC_DUMP_DEV(DEVICE_DT_GET(DT_PROP(node, tcpc)))
16
17 /** Macro used to call the vbus_measure function from the VBUS device pointer */
18 #define TCPC_VBUS_DEV(dev) \
19 { \
20 int val; \
21 ret |= usbc_vbus_measure(dev, &val); \
22 shell_print(sh, "%s vbus: %d mV", dev->name, val); \
23 }
24
25 /** Macro used to call the vbus_measure function from the USB-C connector node */
26 #define TCPC_VBUS_CONN_NODE(node) TCPC_VBUS_DEV(DEVICE_DT_GET(DT_PROP(node, vbus)))
27
28 /** Macro used to call the get_chip function from the TCPC device pointer */
29 #define TCPC_GET_CHIP_DEV(dev) \
30 { \
31 ret |= tcpc_get_chip_info(dev, &chip_info); \
32 shell_print(sh, "Chip: %s", dev->name); \
33 shell_print(sh, "\tVendor: %04x", chip_info.vendor_id); \
34 shell_print(sh, "\tProduct: %04x", chip_info.product_id); \
35 shell_print(sh, "\tDevice: %04x", chip_info.device_id); \
36 shell_print(sh, "\tFirmware: %llx", chip_info.fw_version_number); \
37 }
38
39 /** Macro used to call the get_chip function from the USB-C connector node */
40 #define TCPC_GET_CHIP_CONN_NODE(node) TCPC_GET_CHIP_DEV(DEVICE_DT_GET(DT_PROP(node, tcpc)))
41
42 /**
43 * @brief Shell command that dumps standard registers of TCPCs for all available USB-C ports
44 *
45 * @param sh Shell structure
46 * @param argc Arguments count
47 * @param argv Device name
48 * @return int ORed return values of all the functions executed, 0 in case of success
49 */
cmd_tcpc_dump(const struct shell * sh,size_t argc,char ** argv)50 static int cmd_tcpc_dump(const struct shell *sh, size_t argc, char **argv)
51 {
52 int ret = 0;
53
54 if (argc <= 1) {
55 DT_FOREACH_STATUS_OKAY(usb_c_connector, TCPC_DUMP_CONN_NODE);
56 } else {
57 const struct device *dev = shell_device_get_binding(argv[1]);
58
59 if (dev != NULL) {
60 TCPC_DUMP_DEV(dev);
61 } else {
62 ret = -ENODEV;
63 }
64 }
65
66 return ret;
67 }
68
69 /**
70 * @brief Shell command that prints the vbus measures for all available USB-C ports
71 *
72 * @param sh Shell structure
73 * @param argc Arguments count
74 * @param argv Device name
75 * @return int ORed return values of all the functions executed, 0 in case of success
76 */
cmd_tcpc_vbus(const struct shell * sh,size_t argc,char ** argv)77 static int cmd_tcpc_vbus(const struct shell *sh, size_t argc, char **argv)
78 {
79 int ret = 0;
80
81 if (argc <= 1) {
82 DT_FOREACH_STATUS_OKAY(usb_c_connector, TCPC_VBUS_CONN_NODE);
83 } else {
84 const struct device *dev = shell_device_get_binding(argv[1]);
85
86 if (dev != NULL) {
87 TCPC_VBUS_DEV(dev);
88 } else {
89 ret = -ENODEV;
90 }
91 }
92
93 return ret;
94 }
95
96 /**
97 * @brief Shell command that prints the TCPCs chips information for all available USB-C ports
98 *
99 * @param sh Shell structure
100 * @param argc Arguments count
101 * @param argv Device name
102 * @return int ORed return values of all the functions executed, 0 in case of success
103 */
cmd_tcpc_chip_info(const struct shell * sh,size_t argc,char ** argv)104 static int cmd_tcpc_chip_info(const struct shell *sh, size_t argc, char **argv)
105 {
106 struct tcpc_chip_info chip_info;
107 int ret = 0;
108
109 if (argc <= 1) {
110 DT_FOREACH_STATUS_OKAY(usb_c_connector, TCPC_GET_CHIP_CONN_NODE);
111 } else {
112 const struct device *dev = shell_device_get_binding(argv[1]);
113
114 if (dev != NULL) {
115 TCPC_GET_CHIP_DEV(dev);
116 } else {
117 ret = -ENODEV;
118 }
119 }
120
121 return ret;
122 }
123
124 /**
125 * @brief Function used to create subcommands with devices names
126 *
127 * @param idx counter of devices
128 * @param entry shell structure that will be filled
129 */
device_name_get(size_t idx,struct shell_static_entry * entry)130 static void device_name_get(size_t idx, struct shell_static_entry *entry)
131 {
132 const struct device *dev = shell_device_lookup(idx, NULL);
133
134 entry->syntax = (dev != NULL) ? dev->name : NULL;
135 entry->handler = NULL;
136 entry->help = NULL;
137 entry->subcmd = NULL;
138 }
139
140 SHELL_DYNAMIC_CMD_CREATE(list_device_names, device_name_get);
141
142 SHELL_STATIC_SUBCMD_SET_CREATE(sub_tcpc_cmds,
143 SHELL_CMD_ARG(dump, &list_device_names,
144 "Dump TCPC registers\n"
145 "Usage: tcpc dump [<tcpc device>]",
146 cmd_tcpc_dump, 1, 1),
147 SHELL_CMD_ARG(vbus, &list_device_names,
148 "Display VBUS voltage\n"
149 "Usage: tcpc vbus [<vbus device>]",
150 cmd_tcpc_vbus, 1, 1),
151 SHELL_CMD_ARG(chip, &list_device_names,
152 "Display chip information\n"
153 "Usage: tcpc chip [<tcpc device>]",
154 cmd_tcpc_chip_info, 1, 1),
155 SHELL_SUBCMD_SET_END);
156
157 SHELL_CMD_REGISTER(tcpc, &sub_tcpc_cmds, "TCPC (USB-C PD) diagnostics", NULL);
158