aboutsummaryrefslogtreecommitdiff
path: root/cmd/rtc.c
blob: a931fd9d54f0199bbfdb94689840d67a84d7ccf6 (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// SPDX-License-Identifier: GPL-2.0+

#include <command.h>
#include <display_options.h>
#include <dm.h>
#include <hexdump.h>
#include <i2c.h>
#include <mapmem.h>
#include <rtc.h>

#define MAX_RTC_BYTES 32

static int do_rtc_read(struct udevice *dev, int argc, char * const argv[])
{
	u8 buf[MAX_RTC_BYTES];
	int reg, len, ret, r;

	if (argc < 2 || argc > 3)
		return CMD_RET_USAGE;

	reg = hextoul(argv[0], NULL);
	len = hextoul(argv[1], NULL);

	if (argc == 3) {
		u8 *addr;

		addr = map_sysmem(hextoul(argv[2], NULL), len);
		ret = dm_rtc_read(dev, reg, addr, len);
		unmap_sysmem(addr);
		if (ret) {
			printf("dm_rtc_read() failed: %d\n", ret);
			return CMD_RET_FAILURE;
		}
		return CMD_RET_SUCCESS;
	}

	while (len) {
		r = min_t(int, len, sizeof(buf));
		ret = dm_rtc_read(dev, reg, buf, r);
		if (ret) {
			printf("dm_rtc_read() failed: %d\n", ret);
			return CMD_RET_FAILURE;
		}
		print_buffer(reg, buf, 1, r, 0);
		len -= r;
		reg += r;
	}

	return CMD_RET_SUCCESS;
}

static int do_rtc_write(struct udevice *dev, int argc, char * const argv[])
{
	u8 buf[MAX_RTC_BYTES];
	int reg, len, ret;
	const char *s;
	int slen;

	if (argc < 2 || argc > 3)
		return CMD_RET_USAGE;

	reg = hextoul(argv[0], NULL);

	if (argc == 3) {
		u8 *addr;

		len = hextoul(argv[1], NULL);
		addr = map_sysmem(hextoul(argv[2], NULL), len);
		ret = dm_rtc_write(dev, reg, addr, len);
		unmap_sysmem(addr);
		if (ret) {
			printf("dm_rtc_write() failed: %d\n", ret);
			return CMD_RET_FAILURE;
		}
		return CMD_RET_SUCCESS;
	}

	s = argv[1];
	slen = strlen(s);

	if (slen % 2) {
		printf("invalid hex string\n");
		return CMD_RET_FAILURE;
	}

	while (slen) {
		len = min_t(int, slen / 2, sizeof(buf));
		if (hex2bin(buf, s, len)) {
			printf("invalid hex string\n");
			return CMD_RET_FAILURE;
		}

		ret = dm_rtc_write(dev, reg, buf, len);
		if (ret) {
			printf("dm_rtc_write() failed: %d\n", ret);
			return CMD_RET_FAILURE;
		}
		s += 2 * len;
		slen -= 2 * len;
	}

	return CMD_RET_SUCCESS;
}

int do_rtc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
{
	static int curr_rtc;
	struct udevice *dev;
	int ret, idx;

	if (argc < 2)
		return CMD_RET_USAGE;

	argc--;
	argv++;

	if (!strcmp(argv[0], "list")) {
		struct uclass *uc;

		idx = 0;
		uclass_id_foreach_dev(UCLASS_RTC, dev, uc) {
			printf("RTC #%d - %s\n", idx++, dev->name);
		}
		if (!idx) {
			printf("*** no RTC devices available ***\n");
			return CMD_RET_FAILURE;
		}
		return CMD_RET_SUCCESS;
	}

	idx = curr_rtc;
	if (!strcmp(argv[0], "dev") && argc >= 2)
		idx = dectoul(argv[1], NULL);

	ret = uclass_get_device(UCLASS_RTC, idx, &dev);
	if (ret) {
		printf("Cannot find RTC #%d: err=%d\n", idx, ret);
		return CMD_RET_FAILURE;
	}

	if (!strcmp(argv[0], "dev")) {
		/* Show the existing or newly selected RTC */
		if (argc >= 2)
			curr_rtc = idx;
		printf("RTC #%d - %s\n", idx, dev->name);
		return CMD_RET_SUCCESS;
	}

	if (!strcmp(argv[0], "read"))
		return do_rtc_read(dev, argc - 1, argv + 1);

	if (!strcmp(argv[0], "write"))
		return do_rtc_write(dev, argc - 1, argv + 1);

	return CMD_RET_USAGE;
}

U_BOOT_CMD(
	rtc,	5,	0,	do_rtc,
	"RTC subsystem",
	"list                        - show available rtc devices\n"
	"rtc dev [n]                     - show or set current rtc device\n"
	"rtc read <reg> <count>          - read and display 8-bit registers starting at <reg>\n"
	"rtc read <reg> <count> <addr>   - read 8-bit registers starting at <reg> to memory <addr>\n"
	"rtc write <reg> <hexstring>     - write 8-bit registers starting at <reg>\n"
	"rtc write <reg> <count> <addr>  - write from memory <addr> to 8-bit registers starting at <reg>\n"
);