1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7 #include <common.h>
8 #include <console.h>
9 #include <dm.h>
10 #include <i2c.h>
11 #include <log.h>
12 #include <rtc.h>
13 #include <asm/io.h>
14 #include <asm/rtc.h>
15 #include <asm/test.h>
16 #include <dm/test.h>
17 #include <test/test.h>
18 #include <test/ut.h>
19
20 /* Simple RTC sanity check */
dm_test_rtc_base(struct unit_test_state * uts)21 static int dm_test_rtc_base(struct unit_test_state *uts)
22 {
23 struct udevice *dev;
24
25 ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_RTC, 2, &dev));
26 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
27 ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev));
28
29 return 0;
30 }
31 DM_TEST(dm_test_rtc_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
32
show_time(const char * msg,struct rtc_time * time)33 static void show_time(const char *msg, struct rtc_time *time)
34 {
35 printf("%s: %02d/%02d/%04d %02d:%02d:%02d\n", msg,
36 time->tm_mday, time->tm_mon, time->tm_year,
37 time->tm_hour, time->tm_min, time->tm_sec);
38 }
39
cmp_times(struct rtc_time * expect,struct rtc_time * time,bool show)40 static int cmp_times(struct rtc_time *expect, struct rtc_time *time, bool show)
41 {
42 bool same;
43
44 same = expect->tm_sec == time->tm_sec;
45 same &= expect->tm_min == time->tm_min;
46 same &= expect->tm_hour == time->tm_hour;
47 same &= expect->tm_mday == time->tm_mday;
48 same &= expect->tm_mon == time->tm_mon;
49 same &= expect->tm_year == time->tm_year;
50 if (!same && show) {
51 show_time("expected", expect);
52 show_time("actual", time);
53 }
54
55 return same ? 0 : -EINVAL;
56 }
57
58 /* Set and get the time */
dm_test_rtc_set_get(struct unit_test_state * uts)59 static int dm_test_rtc_set_get(struct unit_test_state *uts)
60 {
61 struct rtc_time now, time, cmp;
62 struct udevice *dev, *emul;
63 long offset, check_offset, old_offset, old_base_time;
64 int i;
65
66 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
67
68 ut_assertok(i2c_emul_find(dev, &emul));
69 ut_assertnonnull(emul);
70
71 /* Get the offset, putting the RTC into manual mode */
72 i = 0;
73 do {
74 check_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
75 ut_assertok(dm_rtc_get(dev, &now));
76
77 /* Tell the RTC to go into manual mode */
78 old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
79
80 /* If the times changed in that period, read it again */
81 } while (++i < 2 && check_offset != old_offset);
82 ut_asserteq(check_offset, old_offset);
83
84 old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
85
86 memset(&time, '\0', sizeof(time));
87 time.tm_mday = 3;
88 time.tm_mon = 6;
89 time.tm_year = 2004;
90 time.tm_sec = 0;
91 time.tm_min = 18;
92 time.tm_hour = 18;
93 ut_assertok(dm_rtc_set(dev, &time));
94
95 memset(&cmp, '\0', sizeof(cmp));
96 ut_assertok(dm_rtc_get(dev, &cmp));
97 ut_assertok(cmp_times(&time, &cmp, true));
98
99 memset(&time, '\0', sizeof(time));
100 time.tm_mday = 31;
101 time.tm_mon = 8;
102 time.tm_year = 2004;
103 time.tm_sec = 0;
104 time.tm_min = 18;
105 time.tm_hour = 18;
106 ut_assertok(dm_rtc_set(dev, &time));
107
108 memset(&cmp, '\0', sizeof(cmp));
109 ut_assertok(dm_rtc_get(dev, &cmp));
110 ut_assertok(cmp_times(&time, &cmp, true));
111
112 /* Increment by 1 second */
113 offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
114 sandbox_i2c_rtc_set_offset(emul, false, offset + 1);
115
116 memset(&cmp, '\0', sizeof(cmp));
117 ut_assertok(dm_rtc_get(dev, &cmp));
118 ut_asserteq(1, cmp.tm_sec);
119
120 /* Check against original offset */
121 sandbox_i2c_rtc_set_offset(emul, false, old_offset);
122 ut_assertok(dm_rtc_get(dev, &cmp));
123 ut_assertok(cmp_times(&now, &cmp, true));
124
125 /* Back to the original offset */
126 sandbox_i2c_rtc_set_offset(emul, false, 0);
127 memset(&cmp, '\0', sizeof(cmp));
128 ut_assertok(dm_rtc_get(dev, &cmp));
129 ut_assertok(cmp_times(&now, &cmp, true));
130
131 /* Increment the base time by 1 emul */
132 sandbox_i2c_rtc_get_set_base_time(emul, old_base_time + 1);
133 memset(&cmp, '\0', sizeof(cmp));
134 ut_assertok(dm_rtc_get(dev, &cmp));
135 if (now.tm_sec == 59) {
136 ut_asserteq(0, cmp.tm_sec);
137 } else {
138 ut_asserteq(now.tm_sec + 1, cmp.tm_sec);
139 }
140
141 /* return RTC to normal mode */
142 sandbox_i2c_rtc_set_offset(emul, true, 0);
143
144 return 0;
145 }
146 DM_TEST(dm_test_rtc_set_get, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
147
dm_test_rtc_read_write(struct unit_test_state * uts)148 static int dm_test_rtc_read_write(struct unit_test_state *uts)
149 {
150 struct rtc_time time;
151 struct udevice *dev, *emul;
152 long old_offset;
153 u8 buf[4], reg;
154
155 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
156
157 memcpy(buf, "car", 4);
158 ut_assertok(dm_rtc_write(dev, REG_AUX0, buf, 4));
159 memset(buf, '\0', sizeof(buf));
160 ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4));
161 ut_asserteq(memcmp(buf, "car", 4), 0);
162
163 reg = 'b';
164 ut_assertok(dm_rtc_write(dev, REG_AUX0, ®, 1));
165 memset(buf, '\0', sizeof(buf));
166 ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4));
167 ut_asserteq(memcmp(buf, "bar", 4), 0);
168
169 reg = 't';
170 ut_assertok(dm_rtc_write(dev, REG_AUX2, ®, 1));
171 memset(buf, '\0', sizeof(buf));
172 ut_assertok(dm_rtc_read(dev, REG_AUX1, buf, 3));
173 ut_asserteq(memcmp(buf, "at", 3), 0);
174
175 ut_assertok(i2c_emul_find(dev, &emul));
176 ut_assertnonnull(emul);
177
178 old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
179 ut_assertok(dm_rtc_get(dev, &time));
180
181 ut_assertok(dm_rtc_read(dev, REG_SEC, ®, 1));
182 ut_asserteq(time.tm_sec, reg);
183 ut_assertok(dm_rtc_read(dev, REG_MDAY, ®, 1));
184 ut_asserteq(time.tm_mday, reg);
185
186 sandbox_i2c_rtc_set_offset(emul, true, old_offset);
187
188 return 0;
189 }
190 DM_TEST(dm_test_rtc_read_write, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
191
192 /* Test 'rtc list' command */
dm_test_rtc_cmd_list(struct unit_test_state * uts)193 static int dm_test_rtc_cmd_list(struct unit_test_state *uts)
194 {
195 console_record_reset();
196
197 run_command("rtc list", 0);
198 ut_assert_nextline("RTC #0 - rtc@43");
199 ut_assert_nextline("RTC #1 - rtc@61");
200 ut_assert_console_end();
201
202 return 0;
203 }
204 DM_TEST(dm_test_rtc_cmd_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
205
206 /* Test 'rtc read' and 'rtc write' commands */
dm_test_rtc_cmd_rw(struct unit_test_state * uts)207 static int dm_test_rtc_cmd_rw(struct unit_test_state *uts)
208 {
209 console_record_reset();
210
211 run_command("rtc dev 0", 0);
212 ut_assert_nextline("RTC #0 - rtc@43");
213 ut_assert_console_end();
214
215 run_command("rtc write 0x30 aabb", 0);
216 ut_assert_console_end();
217
218 run_command("rtc read 0x30 2", 0);
219 ut_assert_nextline("00000030: aa bb ..");
220 ut_assert_console_end();
221
222 run_command("rtc dev 1", 0);
223 ut_assert_nextline("RTC #1 - rtc@61");
224 ut_assert_console_end();
225
226 run_command("rtc write 0x30 ccdd", 0);
227 ut_assert_console_end();
228
229 run_command("rtc read 0x30 2", 0);
230 ut_assert_nextline("00000030: cc dd ..");
231 ut_assert_console_end();
232
233 /*
234 * Switch back to device #0, check that its aux registers
235 * still have the same values.
236 */
237 run_command("rtc dev 0", 0);
238 ut_assert_nextline("RTC #0 - rtc@43");
239 ut_assert_console_end();
240
241 run_command("rtc read 0x30 2", 0);
242 ut_assert_nextline("00000030: aa bb ..");
243 ut_assert_console_end();
244
245 return 0;
246 }
247 DM_TEST(dm_test_rtc_cmd_rw, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
248
249 /* Reset the time */
dm_test_rtc_reset(struct unit_test_state * uts)250 static int dm_test_rtc_reset(struct unit_test_state *uts)
251 {
252 struct rtc_time now;
253 struct udevice *dev, *emul;
254 long old_base_time, base_time;
255 int i;
256
257 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
258 ut_assertok(dm_rtc_get(dev, &now));
259
260 ut_assertok(i2c_emul_find(dev, &emul));
261 ut_assertnonnull(emul);
262
263 i = 0;
264 do {
265 old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0);
266
267 ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1));
268
269 ut_assertok(dm_rtc_reset(dev));
270 base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
271
272 /*
273 * Resetting the RTC should put the base time back to normal.
274 * Allow for a one-timeadjustment in case the time flips over
275 * while this test process is pre-empted (either by a second
276 * or a daylight-saving change), since reset_time() in
277 * i2c_rtc_emul.c reads the time from the OS.
278 */
279 } while (++i < 2 && base_time != old_base_time);
280 ut_asserteq(old_base_time, base_time);
281
282 return 0;
283 }
284 DM_TEST(dm_test_rtc_reset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
285
286 /* Check that two RTC devices can be used independently */
dm_test_rtc_dual(struct unit_test_state * uts)287 static int dm_test_rtc_dual(struct unit_test_state *uts)
288 {
289 struct rtc_time now1, now2, cmp;
290 struct udevice *dev1, *dev2;
291 struct udevice *emul1, *emul2;
292 long offset;
293
294 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev1));
295 ut_assertok(dm_rtc_get(dev1, &now1));
296 ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev2));
297 ut_assertok(dm_rtc_get(dev2, &now2));
298
299 ut_assertok(i2c_emul_find(dev1, &emul1));
300 ut_assertnonnull(emul1);
301 ut_assertok(i2c_emul_find(dev2, &emul2));
302 ut_assertnonnull(emul2);
303
304 offset = sandbox_i2c_rtc_set_offset(emul1, false, -1);
305 sandbox_i2c_rtc_set_offset(emul2, false, offset + 1);
306 memset(&cmp, '\0', sizeof(cmp));
307 ut_assertok(dm_rtc_get(dev2, &cmp));
308 ut_asserteq(-EINVAL, cmp_times(&now1, &cmp, false));
309
310 memset(&cmp, '\0', sizeof(cmp));
311 ut_assertok(dm_rtc_get(dev1, &cmp));
312 ut_assertok(cmp_times(&now1, &cmp, true));
313
314 return 0;
315 }
316 DM_TEST(dm_test_rtc_dual, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
317