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 
do_adc_list(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])11 static int do_adc_list(struct cmd_tbl *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 
do_adc_info(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])34 static int do_adc_info(struct cmd_tbl *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 
do_adc_single(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])71 static int do_adc_single(struct cmd_tbl *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 
do_adc_scan(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])98 static int do_adc_scan(struct cmd_tbl *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 char adc_help_text[] =
150 	"list - list ADC devices\n"
151 	"adc info <name> - Get ADC device info\n"
152 	"adc single <name> <channel> - Get Single data of ADC device channel\n"
153 	"adc scan <name> [channel mask] - Scan all [or masked] ADC channels";
154 
155 U_BOOT_CMD_WITH_SUBCMDS(adc, "ADC sub-system", adc_help_text,
156 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_adc_list),
157 	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_adc_info),
158 	U_BOOT_SUBCMD_MKENT(single, 3, 1, do_adc_single),
159 	U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_adc_scan));
160