summaryrefslogtreecommitdiff
path: root/common/usb_pd_console_cmd.c
blob: 3ad19444948912f344a1b085acfb49d521a10ae3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Console commands for USB-PD module.
 */

#include "console.h"
#include "usb_pd.h"
#include "util.h"
#include "usb_pd_tcpm.h"

#ifdef CONFIG_USB_PD_ALT_MODE_DFP
#ifdef CONFIG_CMD_USB_PD_PE
static void dump_pe(int port)
{
	int i, j, idh_ptype;
	struct svdm_amode_data *modep;
	uint32_t mode_caps;
	const union disc_ident_ack *resp;
	enum tcpci_msg_type type;
	/* TODO(b/152417597): Output SOP' discovery results */
	const struct pd_discovery *disc =
		pd_get_am_discovery(port, TCPCI_MSG_SOP);

	static const char * const idh_ptype_names[]  = {
		"UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA",
		"RSV6", "RSV7"};
	static const char * const tx_names[] = {"SOP", "SOP'", "SOP''"};

	for (type = TCPCI_MSG_SOP; type < DISCOVERY_TYPE_COUNT; type++) {
		resp = pd_get_identity_response(port, type);
		if (pd_get_identity_discovery(port, type) != PD_DISC_COMPLETE) {
			ccprintf("No %s identity discovered yet.\n",
								tx_names[type]);
			continue;
		}

		idh_ptype = resp->idh.product_type;
		ccprintf("IDENT %s:\n", tx_names[type]);
		ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n",
			 resp->raw_value[0],
			 idh_ptype_names[idh_ptype],
			 resp->idh.usb_vendor_id);

		ccprintf("\t[Cert Stat] %08x\n", resp->cert.xid);
		for (i = 2; i < ARRAY_SIZE(resp->raw_value); i++) {
			ccprintf("\t");
			if (resp->raw_value[i])
				ccprintf("[%d] %08x ", i, resp->raw_value[i]);
		}
		ccprintf("\n");
	}

	if (pd_get_svid_count(port, TCPCI_MSG_SOP) < 1) {
		ccprintf("No SVIDS discovered yet.\n");
		return;
	}

	/* TODO(b/152418267): Display discovered SVIDs and modes for SOP' */
	for (i = 0; i < pd_get_svid_count(port, TCPCI_MSG_SOP); i++) {
		ccprintf("SVID[%d]: %04x MODES:", i, disc->svids[i].svid);
		for (j = 0; j < disc->svids[j].mode_cnt; j++)
			ccprintf(" [%d] %08x", j + 1,
					disc->svids[i].mode_vdo[j]);
		ccprintf("\n");

		modep = pd_get_amode_data(port, TCPCI_MSG_SOP,
				disc->svids[i].svid);
		if (modep) {
			mode_caps = modep->data->mode_vdo[modep->opos - 1];
			ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos,
				 modep->fx->svid, mode_caps);
		}
	}
}

static int command_pe(int argc, char **argv)
{
	int port;
	char *e;

	if (argc < 3)
		return EC_ERROR_PARAM_COUNT;

	/* command: pe <port> <subcmd> <args> */
	port = strtoi(argv[1], &e, 10);
	if (*e || port >= board_get_usb_pd_port_count())
		return EC_ERROR_PARAM2;
	if (!strncasecmp(argv[2], "dump", 4))
		dump_pe(port);

	return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(pe, command_pe,
			"<port> dump",
			"USB PE");
#endif /* CONFIG_CMD_USB_PD_PE */

#ifdef CONFIG_CMD_USB_PD_CABLE
static const char * const cable_type[] = {
	[IDH_PTYPE_PCABLE] = "Passive",
	[IDH_PTYPE_ACABLE] = "Active",
};

static const char * const cable_curr[] = {
	[USB_VBUS_CUR_3A] = "3A",
	[USB_VBUS_CUR_5A] = "5A",
};

static int command_cable(int argc, char **argv)
{
	int port;
	char *e;
	const struct pd_discovery *disc;
	enum idh_ptype ptype;
	int cable_rev;
	union tbt_mode_resp_cable cable_mode_resp;

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	port = strtoi(argv[1], &e, 0);
	if (*e || port >= board_get_usb_pd_port_count())
		return EC_ERROR_PARAM2;

	ptype = get_usb_pd_cable_type(port);

	ccprintf("Cable Type: ");
	if (ptype != IDH_PTYPE_PCABLE &&
		ptype != IDH_PTYPE_ACABLE) {
		ccprintf("Not Emark Cable\n");
		return EC_SUCCESS;
	}
	ccprintf("%s\n", cable_type[ptype]);

	cable_rev = pd_get_rev(port, TCPCI_MSG_SOP_PRIME);
	disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
	cable_mode_resp.raw_value =
		pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);


	/* Cable revision */
	ccprintf("Cable Rev: %d.0\n", cable_rev + 1);

	/*
	 * For rev 2.0, rev 3.0 active and passive cables have same bits for
	 * connector type (Bit 19:18) and current handling capability bit 6:5
	 */
	ccprintf("Connector Type: %d\n",
				disc->identity.product_t1.p_rev20.connector);

	if (disc->identity.product_t1.p_rev20.vbus_cur) {
		ccprintf("Cable Current: %s\n",
		   disc->identity.product_t1.p_rev20.vbus_cur >
		      ARRAY_SIZE(cable_curr) ? "Invalid" :
		      cable_curr[disc->identity.product_t1.p_rev20.vbus_cur]);
	} else
		ccprintf("Cable Current: Invalid\n");

	/*
	 * For Rev 3.0 passive cables and Rev 2.0 active and passive cables,
	 * USB Superspeed Signaling support have same bits 2:0
	 */
	if (ptype == IDH_PTYPE_PCABLE)
		ccprintf("USB Superspeed Signaling support: %d\n",
			disc->identity.product_t1.p_rev20.ss);

	/*
	 * For Rev 3.0 active cables and Rev 2.0 active and passive cables,
	 * SOP" controller preset have same bit 3
	 */
	if (ptype == IDH_PTYPE_ACABLE)
		ccprintf("SOP'' Controller: %s present\n",
		      disc->identity.product_t1.a_rev20.sop_p_p ? "" : "Not");

	if (cable_rev == PD_REV30) {
		/*
		 * For Rev 3.0 active and passive cables, Max Vbus vtg have
		 * same bits 10:9.
		 */
		ccprintf("Max vbus voltage: %d\n",
			20 + 10 * disc->identity.product_t1.p_rev30.vbus_max);

		/* For Rev 3.0 Active cables */
		if (ptype == IDH_PTYPE_ACABLE) {
			ccprintf("SS signaling: USB_SS_GEN%u\n",
				disc->identity.product_t2.a2_rev30.usb_gen ?
									2 : 1);
			ccprintf("Number of SS lanes supported: %u\n",
				disc->identity.product_t2.a2_rev30.usb_lanes);
		}
	}

	if (!cable_mode_resp.raw_value)
		return EC_SUCCESS;

	ccprintf("Rounded support: %s\n",
		cable_mode_resp.tbt_rounded ==
			TBT_GEN3_GEN4_ROUNDED_NON_ROUNDED ? "Yes" : "No");

	ccprintf("Optical cable: %s\n",
		cable_mode_resp.tbt_cable == TBT_CABLE_OPTICAL ? "Yes" : "No");

	ccprintf("Retimer support: %s\n",
		cable_mode_resp.retimer_type == USB_RETIMER ?
			"Yes" : "No");

	ccprintf("Link training: %s-directional\n",
		cable_mode_resp.lsrx_comm == BIDIR_LSRX_COMM ? "Bi" : "Uni");

	ccprintf("Thunderbolt cable type: %s\n",
		cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ?
		"Active" : "Passive");

	return EC_SUCCESS;
}

DECLARE_CONSOLE_COMMAND(pdcable, command_cable,
			"<port>",
			"Cable Characteristics");
#endif /* CONFIG_CMD_USB_PD_CABLE */

#endif /* CONFIG_USB_PD_ALT_MODE_DFP */