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