xref: /openbmc/u-boot/test/dm/rtc.c (revision 172e3c11901229f0fb88317ac73a47d944a74f46)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
247725114SSimon Glass /*
347725114SSimon Glass  * Copyright (C) 2015 Google, Inc
447725114SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
547725114SSimon Glass  */
647725114SSimon Glass 
747725114SSimon Glass #include <common.h>
847725114SSimon Glass #include <dm.h>
9*031a650eSSimon Glass #include <i2c.h>
1047725114SSimon Glass #include <rtc.h>
1147725114SSimon Glass #include <asm/io.h>
1247725114SSimon Glass #include <asm/test.h>
13e721b882SJoe Hershberger #include <dm/test.h>
14e721b882SJoe Hershberger #include <test/ut.h>
1547725114SSimon Glass 
1647725114SSimon Glass /* Simple RTC sanity check */
dm_test_rtc_base(struct unit_test_state * uts)17e721b882SJoe Hershberger static int dm_test_rtc_base(struct unit_test_state *uts)
1847725114SSimon Glass {
1947725114SSimon Glass 	struct udevice *dev;
2047725114SSimon Glass 
2147725114SSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_RTC, 2, &dev));
2247725114SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
2347725114SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev));
2447725114SSimon Glass 
2547725114SSimon Glass 	return 0;
2647725114SSimon Glass }
2747725114SSimon Glass DM_TEST(dm_test_rtc_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
2847725114SSimon Glass 
show_time(const char * msg,struct rtc_time * time)2947725114SSimon Glass static void show_time(const char *msg, struct rtc_time *time)
3047725114SSimon Glass {
3147725114SSimon Glass 	printf("%s: %02d/%02d/%04d %02d:%02d:%02d\n", msg,
3247725114SSimon Glass 	       time->tm_mday, time->tm_mon, time->tm_year,
3347725114SSimon Glass 	       time->tm_hour, time->tm_min, time->tm_sec);
3447725114SSimon Glass }
3547725114SSimon Glass 
cmp_times(struct rtc_time * expect,struct rtc_time * time,bool show)3647725114SSimon Glass static int cmp_times(struct rtc_time *expect, struct rtc_time *time, bool show)
3747725114SSimon Glass {
3847725114SSimon Glass 	bool same;
3947725114SSimon Glass 
4047725114SSimon Glass 	same = expect->tm_sec == time->tm_sec;
4147725114SSimon Glass 	same &= expect->tm_min == time->tm_min;
4247725114SSimon Glass 	same &= expect->tm_hour == time->tm_hour;
4347725114SSimon Glass 	same &= expect->tm_mday == time->tm_mday;
4447725114SSimon Glass 	same &= expect->tm_mon == time->tm_mon;
4547725114SSimon Glass 	same &= expect->tm_year == time->tm_year;
4647725114SSimon Glass 	if (!same && show) {
4747725114SSimon Glass 		show_time("expected", expect);
4847725114SSimon Glass 		show_time("actual", time);
4947725114SSimon Glass 	}
5047725114SSimon Glass 
5147725114SSimon Glass 	return same ? 0 : -EINVAL;
5247725114SSimon Glass }
5347725114SSimon Glass 
5447725114SSimon Glass /* Set and get the time */
dm_test_rtc_set_get(struct unit_test_state * uts)55e721b882SJoe Hershberger static int dm_test_rtc_set_get(struct unit_test_state *uts)
5647725114SSimon Glass {
5747725114SSimon Glass 	struct rtc_time now, time, cmp;
5847725114SSimon Glass 	struct udevice *dev, *emul;
5947725114SSimon Glass 	long offset, old_offset, old_base_time;
6047725114SSimon Glass 
6147725114SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
6247725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &now));
6347725114SSimon Glass 
64*031a650eSSimon Glass 	ut_assertok(i2c_emul_find(dev, &emul));
6547725114SSimon Glass 	ut_assert(emul != NULL);
6647725114SSimon Glass 
6747725114SSimon Glass 	/* Tell the RTC to go into manual mode */
6847725114SSimon Glass 	old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
6947725114SSimon Glass 	old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
7047725114SSimon Glass 
7147725114SSimon Glass 	memset(&time, '\0', sizeof(time));
7247725114SSimon Glass 	time.tm_mday = 25;
7347725114SSimon Glass 	time.tm_mon = 8;
7447725114SSimon Glass 	time.tm_year = 2004;
7547725114SSimon Glass 	time.tm_sec = 0;
7647725114SSimon Glass 	time.tm_min = 18;
7747725114SSimon Glass 	time.tm_hour = 18;
7847725114SSimon Glass 	ut_assertok(dm_rtc_set(dev, &time));
7947725114SSimon Glass 
8047725114SSimon Glass 	memset(&cmp, '\0', sizeof(cmp));
8147725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &cmp));
8247725114SSimon Glass 	ut_assertok(cmp_times(&time, &cmp, true));
8347725114SSimon Glass 
8447725114SSimon Glass 	/* Increment by 1 second */
8547725114SSimon Glass 	offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
8647725114SSimon Glass 	sandbox_i2c_rtc_set_offset(emul, false, offset + 1);
8747725114SSimon Glass 
8847725114SSimon Glass 	memset(&cmp, '\0', sizeof(cmp));
8947725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &cmp));
9047725114SSimon Glass 	ut_asserteq(1, cmp.tm_sec);
9147725114SSimon Glass 
9247725114SSimon Glass 	/* Check against original offset */
9347725114SSimon Glass 	sandbox_i2c_rtc_set_offset(emul, false, old_offset);
9447725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &cmp));
9547725114SSimon Glass 	ut_assertok(cmp_times(&now, &cmp, true));
9647725114SSimon Glass 
9747725114SSimon Glass 	/* Back to the original offset */
9847725114SSimon Glass 	sandbox_i2c_rtc_set_offset(emul, false, 0);
9947725114SSimon Glass 	memset(&cmp, '\0', sizeof(cmp));
10047725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &cmp));
10147725114SSimon Glass 	ut_assertok(cmp_times(&now, &cmp, true));
10247725114SSimon Glass 
10347725114SSimon Glass 	/* Increment the base time by 1 emul */
10447725114SSimon Glass 	sandbox_i2c_rtc_get_set_base_time(emul, old_base_time + 1);
10547725114SSimon Glass 	memset(&cmp, '\0', sizeof(cmp));
10647725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &cmp));
10747725114SSimon Glass 	if (now.tm_sec == 59) {
10847725114SSimon Glass 		ut_asserteq(0, cmp.tm_sec);
10947725114SSimon Glass 	} else {
11047725114SSimon Glass 		ut_asserteq(now.tm_sec + 1, cmp.tm_sec);
11147725114SSimon Glass 	}
11247725114SSimon Glass 
11347725114SSimon Glass 	old_offset = sandbox_i2c_rtc_set_offset(emul, true, 0);
11447725114SSimon Glass 
11547725114SSimon Glass 	return 0;
11647725114SSimon Glass }
11747725114SSimon Glass DM_TEST(dm_test_rtc_set_get, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
11847725114SSimon Glass 
11947725114SSimon Glass /* Reset the time */
dm_test_rtc_reset(struct unit_test_state * uts)120e721b882SJoe Hershberger static int dm_test_rtc_reset(struct unit_test_state *uts)
12147725114SSimon Glass {
12247725114SSimon Glass 	struct rtc_time now;
12347725114SSimon Glass 	struct udevice *dev, *emul;
12447725114SSimon Glass 	long old_base_time, base_time;
12547725114SSimon Glass 
12647725114SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
12747725114SSimon Glass 	ut_assertok(dm_rtc_get(dev, &now));
12847725114SSimon Glass 
129*031a650eSSimon Glass 	ut_assertok(i2c_emul_find(dev, &emul));
13047725114SSimon Glass 	ut_assert(emul != NULL);
13147725114SSimon Glass 
13247725114SSimon Glass 	old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0);
13347725114SSimon Glass 
13447725114SSimon Glass 	ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1));
13547725114SSimon Glass 
13647725114SSimon Glass 	/* Resetting the RTC should put he base time back to normal */
13747725114SSimon Glass 	ut_assertok(dm_rtc_reset(dev));
13847725114SSimon Glass 	base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
13947725114SSimon Glass 	ut_asserteq(old_base_time, base_time);
14047725114SSimon Glass 
14147725114SSimon Glass 	return 0;
14247725114SSimon Glass }
14347725114SSimon Glass DM_TEST(dm_test_rtc_reset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
14447725114SSimon Glass 
14547725114SSimon Glass /* Check that two RTC devices can be used independently */
dm_test_rtc_dual(struct unit_test_state * uts)146e721b882SJoe Hershberger static int dm_test_rtc_dual(struct unit_test_state *uts)
14747725114SSimon Glass {
14847725114SSimon Glass 	struct rtc_time now1, now2, cmp;
14947725114SSimon Glass 	struct udevice *dev1, *dev2;
15047725114SSimon Glass 	struct udevice *emul1, *emul2;
15147725114SSimon Glass 	long offset;
15247725114SSimon Glass 
15347725114SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev1));
15447725114SSimon Glass 	ut_assertok(dm_rtc_get(dev1, &now1));
15547725114SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev2));
15647725114SSimon Glass 	ut_assertok(dm_rtc_get(dev2, &now2));
15747725114SSimon Glass 
158*031a650eSSimon Glass 	ut_assertok(i2c_emul_find(dev1, &emul1));
15947725114SSimon Glass 	ut_assert(emul1 != NULL);
160*031a650eSSimon Glass 	ut_assertok(i2c_emul_find(dev2, &emul2));
16147725114SSimon Glass 	ut_assert(emul2 != NULL);
16247725114SSimon Glass 
16347725114SSimon Glass 	offset = sandbox_i2c_rtc_set_offset(emul1, false, -1);
16447725114SSimon Glass 	sandbox_i2c_rtc_set_offset(emul2, false, offset + 1);
16547725114SSimon Glass 	memset(&cmp, '\0', sizeof(cmp));
16647725114SSimon Glass 	ut_assertok(dm_rtc_get(dev2, &cmp));
16747725114SSimon Glass 	ut_asserteq(-EINVAL, cmp_times(&now1, &cmp, false));
16847725114SSimon Glass 
16947725114SSimon Glass 	memset(&cmp, '\0', sizeof(cmp));
17047725114SSimon Glass 	ut_assertok(dm_rtc_get(dev1, &cmp));
17147725114SSimon Glass 	ut_assertok(cmp_times(&now1, &cmp, true));
17247725114SSimon Glass 
17347725114SSimon Glass 	return 0;
17447725114SSimon Glass }
17547725114SSimon Glass DM_TEST(dm_test_rtc_dual, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
176