1/* SPDX-License-Identifier: GPL-2.0+
2 *
3 * (C) Copyright 2018
4 * Microchip Technology, Inc.
5 * Eugen Hristev <eugen.hristev@microchip.com>
6 */
7#include <common.h>
8#include <command.h>
9#include <dm.h>
10#include <w1.h>
11#include <w1-eeprom.h>
12#include <dm/device-internal.h>
13
14static int w1_bus(void)
15{
16	struct udevice *bus, *dev;
17	int ret;
18
19	ret = w1_get_bus(0, &bus);
20	if (ret) {
21		printf("one wire interface not found\n");
22		return CMD_RET_FAILURE;
23	}
24	printf("Bus %d:\t%s", dev_seq(bus), bus->name);
25	if (device_active(bus))
26		printf("  (active)");
27	printf("\n");
28
29	for (device_find_first_child(bus, &dev);
30	     dev;
31	     device_find_next_child(&dev)) {
32		ret = device_probe(dev);
33
34		printf("\t%s (%d) uclass %s : ", dev->name, dev_seq(dev),
35		       dev->uclass->uc_drv->name);
36
37		if (ret)
38			printf("device error\n");
39		else
40			printf("family 0x%x\n", w1_get_device_family(dev));
41	}
42	return CMD_RET_SUCCESS;
43}
44
45static int w1_read(int argc, char *const argv[])
46{
47	int bus_n = 0, dev_n = 0, offset = 0, len = 512;
48	int i;
49	struct udevice *bus, *dev;
50	int ret;
51	u8 buf[512];
52
53	if (argc > 2)
54		bus_n = dectoul(argv[2], NULL);
55
56	if (argc > 3)
57		dev_n = dectoul(argv[3], NULL);
58
59	if (argc > 4)
60		offset = dectoul(argv[4], NULL);
61
62	if (argc > 5)
63		len = dectoul(argv[5], NULL);
64
65	if (len > 512) {
66		printf("len needs to be <= 512\n");
67		return CMD_RET_FAILURE;
68	}
69
70	ret = w1_get_bus(bus_n, &bus);
71	if (ret) {
72		printf("one wire interface not found\n");
73		return CMD_RET_FAILURE;
74	}
75
76	for (device_find_first_child(bus, &dev), i = 0;
77	   dev && i <= dev_n;
78	   device_find_next_child(&dev), i++) {
79		ret = device_probe(dev);
80		if (!ret && i == dev_n)
81			break;
82	}
83
84	if (i != dev_n || ret || !dev) {
85		printf("invalid dev\n");
86		return CMD_RET_FAILURE;
87	}
88
89	if (strcmp(dev->uclass->uc_drv->name, "w1_eeprom")) {
90		printf("the device present on the interface is of unknown device class\n");
91		return CMD_RET_FAILURE;
92	}
93
94	ret = w1_eeprom_read_buf(dev, offset, (u8 *)buf, len);
95	if (ret) {
96		printf("error reading device %s\n", dev->name);
97		return CMD_RET_FAILURE;
98	}
99
100	for (i = 0; i < len; i++)
101		printf("%x", buf[i]);
102	printf("\n");
103
104	return CMD_RET_SUCCESS;
105}
106
107int do_w1(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
108{
109	if (argc < 2)
110		return CMD_RET_USAGE;
111
112	if (!strcmp(argv[1], "bus"))
113		return w1_bus();
114
115	if (!strcmp(argv[1], "read"))
116		return w1_read(argc, argv);
117
118	return CMD_RET_SUCCESS;
119}
120
121U_BOOT_CMD(w1, 6, 0, do_w1,
122	   "onewire interface utility commands",
123	   "bus - show onewire bus info (all)\n"
124	   "w1 read [<bus> [<dev> [offset [length]]]]"
125	   "    - read from onewire device 'dev' on onewire bus 'bus'"
126	   " starting from offset 'offset' and length 'length'\n"
127	   "      defaults: bus 0, dev 0, offset 0, length 512 bytes.");
128