Commit 7b302772 authored by Alexandre Belloni's avatar Alexandre Belloni Committed by Shuah Khan
Browse files

selftests: rtc: rtctest: add alarm test on minute boundary



Unfortunately, some RTC don't have a second resolution for alarm so also
test for alarm on a minute boundary.

Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: default avatarShuah Khan <shuah@kernel.org>
parent fdac9448
Loading
Loading
Loading
Loading
+102 −0
Original line number Diff line number Diff line
@@ -211,6 +211,108 @@ TEST_F(rtc, alarm_wkalm_set) {
	ASSERT_EQ(new, secs);
}

TEST_F(rtc, alarm_alm_set_minute) {
	struct timeval tv = { .tv_sec = 62 };
	unsigned long data;
	struct rtc_time tm;
	fd_set readfds;
	time_t secs, new;
	int rc;

	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
	ASSERT_NE(-1, rc);

	secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec;
	gmtime_r(&secs, (struct tm *)&tm);

	rc = ioctl(self->fd, RTC_ALM_SET, &tm);
	if (rc == -1) {
		ASSERT_EQ(EINVAL, errno);
		TH_LOG("skip alarms are not supported.");
		return;
	}

	rc = ioctl(self->fd, RTC_ALM_READ, &tm);
	ASSERT_NE(-1, rc);

	TH_LOG("Alarm time now set to %02d:%02d:%02d.",
	       tm.tm_hour, tm.tm_min, tm.tm_sec);

	/* Enable alarm interrupts */
	rc = ioctl(self->fd, RTC_AIE_ON, 0);
	ASSERT_NE(-1, rc);

	FD_ZERO(&readfds);
	FD_SET(self->fd, &readfds);

	rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
	ASSERT_NE(-1, rc);
	ASSERT_NE(0, rc);

	/* Disable alarm interrupts */
	rc = ioctl(self->fd, RTC_AIE_OFF, 0);
	ASSERT_NE(-1, rc);

	rc = read(self->fd, &data, sizeof(unsigned long));
	ASSERT_NE(-1, rc);
	TH_LOG("data: %lx", data);

	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
	ASSERT_NE(-1, rc);

	new = timegm((struct tm *)&tm);
	ASSERT_EQ(new, secs);
}

TEST_F(rtc, alarm_wkalm_set_minute) {
	struct timeval tv = { .tv_sec = 62 };
	struct rtc_wkalrm alarm = { 0 };
	struct rtc_time tm;
	unsigned long data;
	fd_set readfds;
	time_t secs, new;
	int rc;

	rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
	ASSERT_NE(-1, rc);

	secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec;
	gmtime_r(&secs, (struct tm *)&alarm.time);

	alarm.enabled = 1;

	rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
	if (rc == -1) {
		ASSERT_EQ(EINVAL, errno);
		TH_LOG("skip alarms are not supported.");
		return;
	}

	rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
	ASSERT_NE(-1, rc);

	TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
	       alarm.time.tm_mday, alarm.time.tm_mon + 1,
	       alarm.time.tm_year + 1900, alarm.time.tm_hour,
	       alarm.time.tm_min, alarm.time.tm_sec);

	FD_ZERO(&readfds);
	FD_SET(self->fd, &readfds);

	rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
	ASSERT_NE(-1, rc);
	ASSERT_NE(0, rc);

	rc = read(self->fd, &data, sizeof(unsigned long));
	ASSERT_NE(-1, rc);

	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
	ASSERT_NE(-1, rc);

	new = timegm((struct tm *)&tm);
	ASSERT_EQ(new, secs);
}

static void __attribute__((constructor))
__constructor_order_last(void)
{