xref: /openbmc/u-boot/cmd/adc.c (revision ecab65e4)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 BayLibre, SAS
4  * Author: Neil Armstrong <narmstrong@baylibre.com>
5  */
6 #include <common.h>
7 #include <command.h>
8 #include <dm.h>
9 #include <adc.h>
10 
11 static int do_adc_list(cmd_tbl_t *cmdtp, int flag, int argc,
12 		       char *const argv[])
13 {
14 	struct udevice *dev;
15 	int ret;
16 
17 	ret = uclass_first_device_err(UCLASS_ADC, &dev);
18 	if (ret) {
19 		printf("No available ADC device\n");
20 		return CMD_RET_FAILURE;
21 	}
22 
23 	do {
24 		printf("- %s\n", dev->name);
25 
26 		ret = uclass_next_device(&dev);
27 		if (ret)
28 			return CMD_RET_FAILURE;
29 	} while (dev);
30 
31 	return CMD_RET_SUCCESS;
32 }
33 
34 static int do_adc_info(cmd_tbl_t *cmdtp, int flag, int argc,
35 		       char *const argv[])
36 {
37 	struct udevice *dev;
38 	unsigned int data_mask, ch_mask;
39 	int ret, vss, vdd;
40 
41 	if (argc < 2)
42 		return CMD_RET_USAGE;
43 
44 	ret = uclass_get_device_by_name(UCLASS_ADC, argv[1], &dev);
45 	if (ret) {
46 		printf("Unknown ADC device %s\n", argv[1]);
47 		return CMD_RET_FAILURE;
48 	}
49 
50 	printf("ADC Device '%s' :\n", argv[1]);
51 
52 	ret = adc_channel_mask(dev, &ch_mask);
53 	if (!ret)
54 		printf("channel mask: %x\n", ch_mask);
55 
56 	ret = adc_data_mask(dev, &data_mask);
57 	if (!ret)
58 		printf("data mask: %x\n", data_mask);
59 
60 	ret = adc_vdd_value(dev, &vdd);
61 	if (!ret)
62 		printf("vdd: %duV\n", vdd);
63 
64 	ret = adc_vss_value(dev, &vss);
65 	if (!ret)
66 		printf("vss: %duV\n", vss);
67 
68 	return CMD_RET_SUCCESS;
69 }
70 
71 static int do_adc_single(cmd_tbl_t *cmdtp, int flag, int argc,
72 			 char *const argv[])
73 {
74 	struct udevice *dev;
75 	unsigned int data;
76 	int ret, uV;
77 
78 	if (argc < 3)
79 		return CMD_RET_USAGE;
80 
81 	ret = adc_channel_single_shot(argv[1], simple_strtol(argv[2], NULL, 0),
82 				      &data);
83 	if (ret) {
84 		printf("Error getting single shot for device %s channel %s\n",
85 		       argv[1], argv[2]);
86 		return CMD_RET_FAILURE;
87 	}
88 
89 	ret = uclass_get_device_by_name(UCLASS_ADC, argv[1], &dev);
90 	if (!ret && !adc_raw_to_uV(dev, data, &uV))
91 		printf("%u, %d uV\n", data, uV);
92 	else
93 		printf("%u\n", data);
94 
95 	return CMD_RET_SUCCESS;
96 }
97 
98 static int do_adc_scan(cmd_tbl_t *cmdtp, int flag, int argc,
99 		       char *const argv[])
100 {
101 	struct adc_channel ch[ADC_MAX_CHANNEL];
102 	struct udevice *dev;
103 	unsigned int ch_mask;
104 	int i, chan, ret, uV;
105 
106 	if (argc < 2)
107 		return CMD_RET_USAGE;
108 
109 	ret = uclass_get_device_by_name(UCLASS_ADC, argv[1], &dev);
110 	if (ret) {
111 		pr_err("Can't get the ADC %s: %d\n", argv[1], ret);
112 		return CMD_RET_FAILURE;
113 	}
114 
115 	switch (argc) {
116 	case 3:
117 		ch_mask = simple_strtoul(argv[2], NULL, 0);
118 		if (ch_mask)
119 			break;
120 	case 2:
121 		ret = adc_channel_mask(dev, &ch_mask);
122 		if (ret) {
123 			pr_err("Can't get mask for %s: %d\n", dev->name, ret);
124 			return CMD_RET_FAILURE;
125 		}
126 		break;
127 	}
128 
129 	ret = adc_channels_single_shot(dev->name, ch_mask, ch);
130 	if (ret) {
131 		pr_err("Can't get single shot for %s (chans mask: 0x%x): %d\n",
132 		       dev->name, ch_mask, ret);
133 		return CMD_RET_FAILURE;
134 	}
135 
136 	for (chan = 0, i = 0; chan < ADC_MAX_CHANNEL; chan++) {
137 		if (!(ch_mask & ADC_CHANNEL(chan)))
138 			continue;
139 		if (!adc_raw_to_uV(dev, ch[i].data, &uV))
140 			printf("[%02d]: %u, %d uV\n", ch[i].id, ch[i].data, uV);
141 		else
142 			printf("[%02d]: %u\n", ch[i].id, ch[i].data);
143 		i++;
144 	}
145 
146 	return CMD_RET_SUCCESS;
147 }
148 
149 static cmd_tbl_t cmd_adc_sub[] = {
150 	U_BOOT_CMD_MKENT(list, 1, 1, do_adc_list, "", ""),
151 	U_BOOT_CMD_MKENT(info, 2, 1, do_adc_info, "", ""),
152 	U_BOOT_CMD_MKENT(single, 3, 1, do_adc_single, "", ""),
153 	U_BOOT_CMD_MKENT(scan, 3, 1, do_adc_scan, "", ""),
154 };
155 
156 static int do_adc(cmd_tbl_t *cmdtp, int flag, int argc,
157 		  char *const argv[])
158 {
159 	cmd_tbl_t *c;
160 
161 	if (argc < 2)
162 		return CMD_RET_USAGE;
163 
164 	/* Strip off leading 'adc' command argument */
165 	argc--;
166 	argv++;
167 
168 	c = find_cmd_tbl(argv[0], &cmd_adc_sub[0], ARRAY_SIZE(cmd_adc_sub));
169 
170 	if (c)
171 		return c->cmd(cmdtp, flag, argc, argv);
172 	else
173 		return CMD_RET_USAGE;
174 }
175 
176 static char adc_help_text[] =
177 	"list - list ADC devices\n"
178 	"adc info <name> - Get ADC device info\n"
179 	"adc single <name> <channel> - Get Single data of ADC device channel\n"
180 	"adc scan <name> [channel mask] - Scan all [or masked] ADC channels";
181 
182 U_BOOT_CMD(adc, 4, 1, do_adc, "ADC sub-system", adc_help_text);
183