Merge branch '2022-04-08-gpio-updates'
[platform/kernel/u-boot.git] / cmd / rtc.c
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
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 = hextoul(argv[0], NULL);
22         len = hextoul(argv[1], NULL);
23
24         if (argc == 3) {
25                 u8 *addr;
26
27                 addr = map_sysmem(hextoul(argv[2], NULL), 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
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 = hextoul(argv[0], NULL);
63
64         if (argc == 3) {
65                 u8 *addr;
66
67                 len = hextoul(argv[1], NULL);
68                 addr = map_sysmem(hextoul(argv[2], NULL), 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
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 = dectoul(argv[1], NULL);
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 );