aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/tcpm.c
blob: 39578f6ccc0bfc9a1c1451a619fcafa555a42832 (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
// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2024 Collabora
 */

#include <command.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <usb/tcpm.h>

#define LIMIT_DEV	32
#define LIMIT_PARENT	20

static struct udevice *currdev;

static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
	int devnum, ret;

	switch (argc) {
	case 2:
		devnum = (int)dectoul(argv[1], NULL);
		ret = tcpm_get(devnum, &currdev);
		if (ret) {
			log_err("Can't get TCPM %d: %d (%s)!\n", devnum, ret, errno_str(ret));
			return CMD_RET_FAILURE;
		}
	case 1:
		if (!currdev) {
			log_err("TCPM device is not set!\n\n");
			return CMD_RET_USAGE;
		}

		printf("dev: %d @ %s\n", dev_seq(currdev), currdev->name);
	}

	return CMD_RET_SUCCESS;
}

static int do_list(struct cmd_tbl *cmdtp, int flag, int argc,
		   char *const argv[])
{
	struct udevice *dev;
	int ret, err = 0;

	printf("| ID | %-*.*s| %-*.*s| %s @ %s\n",
	       LIMIT_DEV, LIMIT_DEV, "Name",
	       LIMIT_PARENT, LIMIT_PARENT, "Parent name",
	       "Parent uclass", "seq");

	for (ret = uclass_first_device_check(UCLASS_TCPM, &dev); dev;
	     ret = uclass_next_device_check(&dev)) {
		if (ret)
			err = ret;

		printf("| %2d | %-*.*s| %-*.*s| %s @ %d | status: %i\n",
		       dev_seq(dev),
		       LIMIT_DEV, LIMIT_DEV, dev->name,
		       LIMIT_PARENT, LIMIT_PARENT, dev->parent->name,
		       dev_get_uclass_name(dev->parent), dev_seq(dev->parent),
		       ret);
	}

	if (err)
		return CMD_RET_FAILURE;

	return CMD_RET_SUCCESS;
}

int do_print_info(struct udevice *dev)
{
	enum typec_orientation orientation = tcpm_get_orientation(dev);
	const char *state = tcpm_get_state(dev);
	int pd_rev = tcpm_get_pd_rev(dev);
	int mv = tcpm_get_voltage(dev);
	int ma = tcpm_get_current(dev);
	enum typec_role pwr_role = tcpm_get_pwr_role(dev);
	enum typec_data_role data_role = tcpm_get_data_role(dev);
	bool connected = tcpm_is_connected(dev);

	if (!connected) {
		printf("TCPM State: %s\n", state);
		return 0;
	}

	printf("Orientation: %s\n", typec_orientation_name[orientation]);
	printf("PD Revision: %s\n", typec_pd_rev_name[pd_rev]);
	printf("Power Role:  %s\n", typec_role_name[pwr_role]);
	printf("Data Role:   %s\n", typec_data_role_name[data_role]);
	printf("Voltage:     %2d.%03d V\n", mv / 1000, mv % 1000);
	printf("Current:     %2d.%03d A\n", ma / 1000, ma % 1000);

	return 0;
}

static int do_info(struct cmd_tbl *cmdtp, int flag, int argc,
		   char *const argv[])
{
	if (!currdev) {
		printf("First, set the TCPM device!\n");
		return CMD_RET_USAGE;
	}

	return do_print_info(currdev);
}

static struct cmd_tbl subcmd[] = {
	U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
	U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
	U_BOOT_CMD_MKENT(info, 1, 1, do_info, "", ""),
};

static int do_tcpm(struct cmd_tbl *cmdtp, int flag, int argc,
		   char *const argv[])
{
	struct cmd_tbl *cmd;

	argc--;
	argv++;

	cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd));
	if (!cmd || argc > cmd->maxargs)
		return CMD_RET_USAGE;

	return cmd->cmd(cmdtp, flag, argc, argv);
}

 /**************************************************/

U_BOOT_CMD(tcpm, CONFIG_SYS_MAXARGS, 1, do_tcpm,
	"TCPM sub-system",
	"list          - list TCPM devices\n"
	"tcpm dev [ID]      - show or [set] operating TCPM device\n"
	"tcpm info          - dump information\n"
);