blob: 2f6c08b8b079432d86ac603387e71f8c3a7d3102 [file] [log] [blame]
Pratyush Yadav05115ab2020-10-16 16:16:35 +05301// SPDX-License-Identifier: GPL-2.0
2/*
3 * List, select, and deselect mux controllers on the fly.
4 *
5 * Copyright (c) 2020 Texas Instruments Inc.
6 * Author: Pratyush Yadav <p.yadav@ti.com>
7 */
8
Pratyush Yadav05115ab2020-10-16 16:16:35 +05309#include <command.h>
10#include <errno.h>
11#include <dm.h>
12#include <dm/device_compat.h>
13#include <mux.h>
14#include <mux-internal.h>
15#include <linux/err.h>
16#include <dt-bindings/mux/mux.h>
17
18#define COLUMN_SIZE 16
19
20/*
21 * Print a member of a column. The total size of the text printed, including
22 * trailing whitespace, will always be COLUMN_SIZE.
23 */
24#define PRINT_COLUMN(fmt, args...) do { \
25 char buf[COLUMN_SIZE + 1]; \
26 snprintf(buf, COLUMN_SIZE + 1, fmt, ##args); \
27 printf("%-*s", COLUMN_SIZE, buf); \
28} while (0)
29
30/*
31 * Find a mux based on its device name in argv[1] and index in the chip in
32 * argv[2].
33 */
34static struct mux_control *cmd_mux_find(char *const argv[])
35{
36 struct udevice *dev;
37 struct mux_chip *chip;
38 int ret;
39 unsigned long id;
40
41 ret = strict_strtoul(argv[2], 10, &id);
42 if (ret)
43 return ERR_PTR(ret);
44
45 ret = uclass_get_device_by_name(UCLASS_MUX, argv[1], &dev);
46 if (ret)
47 return ERR_PTR(ret);
48
49 chip = dev_get_uclass_priv(dev);
50 if (!chip)
Dan Carpenter1ded89e2023-07-25 09:50:08 +030051 return ERR_PTR(-EINVAL);
Pratyush Yadav05115ab2020-10-16 16:16:35 +053052
53 if (id >= chip->controllers)
54 return ERR_PTR(-EINVAL);
55
56 return &chip->mux[id];
57}
58
59/*
60 * Print the details of a mux. The columns printed correspond to: "Selected",
61 * "Current State", "Idle State", and "Num States".
62 */
63static void print_mux(struct mux_control *mux)
64{
65 PRINT_COLUMN("%s", mux->in_use ? "yes" : "no");
66
67 if (mux->cached_state == MUX_IDLE_AS_IS)
68 PRINT_COLUMN("%s", "unknown");
69 else
70 PRINT_COLUMN("0x%x", mux->cached_state);
71
72 if (mux->idle_state == MUX_IDLE_AS_IS)
73 PRINT_COLUMN("%s", "as-is");
74 else if (mux->idle_state == MUX_IDLE_DISCONNECT)
75 PRINT_COLUMN("%s", "disconnect");
76 else
77 PRINT_COLUMN("0x%x", mux->idle_state);
78
79 PRINT_COLUMN("0x%x", mux->states);
80
81 printf("\n");
82}
83
84static int do_mux_list(struct cmd_tbl *cmdtp, int flag, int argc,
85 char *const argv[])
86{
87 struct udevice *dev;
88 struct mux_chip *chip;
89 int j;
90
91 for (uclass_first_device(UCLASS_MUX, &dev);
92 dev;
93 uclass_next_device(&dev)) {
94 chip = dev_get_uclass_priv(dev);
95 if (!chip) {
96 dev_err(dev, "can't find mux chip\n");
97 continue;
98 }
99
100 printf("%s:\n", dev->name);
101
102 printf(" ");
103 PRINT_COLUMN("ID");
104 PRINT_COLUMN("Selected");
105 PRINT_COLUMN("Current State");
106 PRINT_COLUMN("Idle State");
107 PRINT_COLUMN("Num States");
108 printf("\n");
109 for (j = 0; j < chip->controllers; j++) {
110 printf(" ");
111 PRINT_COLUMN("%d", j);
112 print_mux(&chip->mux[j]);
113 }
114 printf("\n");
115 }
116
117 return 0;
118}
119
120static int do_mux_select(struct cmd_tbl *cmdtp, int flag, int argc,
121 char *const argv[])
122{
123 struct mux_control *mux;
124 int ret;
125 unsigned long state;
126
127 if (argc != 4)
128 return CMD_RET_USAGE;
129
130 mux = cmd_mux_find(argv);
131 if (IS_ERR_OR_NULL(mux)) {
132 printf("Failed to find the specified mux\n");
133 return CMD_RET_FAILURE;
134 }
135
136 ret = strict_strtoul(argv[3], 16, &state);
137 if (ret) {
138 printf("Invalid state\n");
139 return CMD_RET_FAILURE;
140 }
141
142 ret = mux_control_select(mux, state);
143 if (ret) {
144 printf("Failed to select requested state\n");
145 return CMD_RET_FAILURE;
146 }
147
148 return CMD_RET_SUCCESS;
149}
150
151static int do_mux_deselect(struct cmd_tbl *cmdtp, int flag, int argc,
152 char *const argv[])
153{
154 struct mux_control *mux;
155 int ret;
156
157 if (argc != 3)
158 return CMD_RET_USAGE;
159
160 mux = cmd_mux_find(argv);
161 if (IS_ERR_OR_NULL(mux)) {
162 printf("Failed to find the specified mux\n");
163 return CMD_RET_FAILURE;
164 }
165
166 ret = mux_control_deselect(mux);
167 if (ret) {
168 printf("Failed to deselect mux\n");
169 return CMD_RET_FAILURE;
170 }
171
172 return CMD_RET_SUCCESS;
173}
174
Tom Rini36162182023-10-07 15:13:08 -0400175U_BOOT_LONGHELP(mux,
Pratyush Yadav05115ab2020-10-16 16:16:35 +0530176 "list - List all Muxes and their states\n"
177 "select <chip> <id> <state> - Select the given mux state\n"
Tom Rini36162182023-10-07 15:13:08 -0400178 "deselect <chip> <id> - Deselect the given mux and reset it to its idle state");
Pratyush Yadav05115ab2020-10-16 16:16:35 +0530179
180U_BOOT_CMD_WITH_SUBCMDS(mux, "List, select, and deselect muxes", mux_help_text,
181 U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mux_list),
182 U_BOOT_SUBCMD_MKENT(select, 4, 0, do_mux_select),
183 U_BOOT_SUBCMD_MKENT(deselect, 3, 0, do_mux_deselect));