1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <common.h>
4 #include <command.h>
5 #include <dm.h>
6 #include <hexdump.h>
7 #include <i2c.h>
8 #include <mapmem.h>
9 #include <rtc.h>
10
11 #define MAX_RTC_BYTES 32
12
do_rtc_read(struct udevice * dev,int argc,char * const argv[])13 static int do_rtc_read(struct udevice *dev, int argc, char * const argv[])
14 {
15 u8 buf[MAX_RTC_BYTES];
16 int reg, len, ret, r;
17
18 if (argc < 2 || argc > 3)
19 return CMD_RET_USAGE;
20
21 reg = simple_strtoul(argv[0], NULL, 16);
22 len = simple_strtoul(argv[1], NULL, 16);
23
24 if (argc == 3) {
25 u8 *addr;
26
27 addr = map_sysmem(simple_strtoul(argv[2], NULL, 16), len);
28 ret = dm_rtc_read(dev, reg, addr, len);
29 unmap_sysmem(addr);
30 if (ret) {
31 printf("dm_rtc_read() failed: %d\n", ret);
32 return CMD_RET_FAILURE;
33 }
34 return CMD_RET_SUCCESS;
35 }
36
37 while (len) {
38 r = min_t(int, len, sizeof(buf));
39 ret = dm_rtc_read(dev, reg, buf, r);
40 if (ret) {
41 printf("dm_rtc_read() failed: %d\n", ret);
42 return CMD_RET_FAILURE;
43 }
44 print_buffer(reg, buf, 1, r, 0);
45 len -= r;
46 reg += r;
47 }
48
49 return CMD_RET_SUCCESS;
50 }
51
do_rtc_write(struct udevice * dev,int argc,char * const argv[])52 static int do_rtc_write(struct udevice *dev, int argc, char * const argv[])
53 {
54 u8 buf[MAX_RTC_BYTES];
55 int reg, len, ret;
56 const char *s;
57 int slen;
58
59 if (argc < 2 || argc > 3)
60 return CMD_RET_USAGE;
61
62 reg = simple_strtoul(argv[0], NULL, 16);
63
64 if (argc == 3) {
65 u8 *addr;
66
67 len = simple_strtoul(argv[1], NULL, 16);
68 addr = map_sysmem(simple_strtoul(argv[2], NULL, 16), len);
69 ret = dm_rtc_write(dev, reg, addr, len);
70 unmap_sysmem(addr);
71 if (ret) {
72 printf("dm_rtc_write() failed: %d\n", ret);
73 return CMD_RET_FAILURE;
74 }
75 return CMD_RET_SUCCESS;
76 }
77
78 s = argv[1];
79 slen = strlen(s);
80
81 if (slen % 2) {
82 printf("invalid hex string\n");
83 return CMD_RET_FAILURE;
84 }
85
86 while (slen) {
87 len = min_t(int, slen / 2, sizeof(buf));
88 if (hex2bin(buf, s, len)) {
89 printf("invalid hex string\n");
90 return CMD_RET_FAILURE;
91 }
92
93 ret = dm_rtc_write(dev, reg, buf, len);
94 if (ret) {
95 printf("dm_rtc_write() failed: %d\n", ret);
96 return CMD_RET_FAILURE;
97 }
98 s += 2 * len;
99 slen -= 2 * len;
100 }
101
102 return CMD_RET_SUCCESS;
103 }
104
do_rtc(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])105 int do_rtc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
106 {
107 static int curr_rtc;
108 struct udevice *dev;
109 int ret, idx;
110
111 if (argc < 2)
112 return CMD_RET_USAGE;
113
114 argc--;
115 argv++;
116
117 if (!strcmp(argv[0], "list")) {
118 struct uclass *uc;
119
120 idx = 0;
121 uclass_id_foreach_dev(UCLASS_RTC, dev, uc) {
122 printf("RTC #%d - %s\n", idx++, dev->name);
123 }
124 if (!idx) {
125 printf("*** no RTC devices available ***\n");
126 return CMD_RET_FAILURE;
127 }
128 return CMD_RET_SUCCESS;
129 }
130
131 idx = curr_rtc;
132 if (!strcmp(argv[0], "dev") && argc >= 2)
133 idx = simple_strtoul(argv[1], NULL, 10);
134
135 ret = uclass_get_device(UCLASS_RTC, idx, &dev);
136 if (ret) {
137 printf("Cannot find RTC #%d: err=%d\n", idx, ret);
138 return CMD_RET_FAILURE;
139 }
140
141 if (!strcmp(argv[0], "dev")) {
142 /* Show the existing or newly selected RTC */
143 if (argc >= 2)
144 curr_rtc = idx;
145 printf("RTC #%d - %s\n", idx, dev->name);
146 return CMD_RET_SUCCESS;
147 }
148
149 if (!strcmp(argv[0], "read"))
150 return do_rtc_read(dev, argc - 1, argv + 1);
151
152 if (!strcmp(argv[0], "write"))
153 return do_rtc_write(dev, argc - 1, argv + 1);
154
155 return CMD_RET_USAGE;
156 }
157
158 U_BOOT_CMD(
159 rtc, 5, 0, do_rtc,
160 "RTC subsystem",
161 "list - show available rtc devices\n"
162 "rtc dev [n] - show or set current rtc device\n"
163 "rtc read <reg> <count> - read and display 8-bit registers starting at <reg>\n"
164 "rtc read <reg> <count> <addr> - read 8-bit registers starting at <reg> to memory <addr>\n"
165 "rtc write <reg> <hexstring> - write 8-bit registers starting at <reg>\n"
166 "rtc write <reg> <count> <addr> - write from memory <addr> to 8-bit registers starting at <reg>\n"
167 );
168