Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 023f333a authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by John Stultz
Browse files

NTP: Add a CONFIG_RTC_SYSTOHC configuration



The purpose of this option is to allow ARM/etc systems that rely on the
class RTC subsystem to have the same kind of automatic NTP based
synchronization that we have on PC platforms. Today ARM does not
implement update_persistent_clock and makes extensive use of the class
RTC system.

When enabled CONFIG_RTC_SYSTOHC will provide a generic
rtc_update_persistent_clock that stores the current time in the RTC and
is intended complement the existing CONFIG_RTC_HCTOSYS option that loads
the RTC at boot.

Like with RTC_HCTOSYS the platform's update_persistent_clock is used
first, if it works. Platforms with mixed class RTC and non-RTC drivers
need to return ENODEV when class RTC should be used. Such an update for
PPC is included in this patch.

Long term, implementations of update_persistent_clock should migrate to
proper class RTC drivers and use CONFIG_RTC_SYSTOHC instead.

Tested on ARM kirkwood and PPC405

Signed-off-by: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent 50363737
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -667,7 +667,7 @@ int update_persistent_clock(struct timespec now)
	struct rtc_time tm;

	if (!ppc_md.set_rtc_time)
		return 0;
		return -ENODEV;

	to_tm(now.tv_sec + 1 + timezone_offset, &tm);
	tm.tm_year -= 1900;
+9 −1
Original line number Diff line number Diff line
@@ -25,9 +25,17 @@ config RTC_HCTOSYS
	  the value read from a specified RTC device. This is useful to avoid
	  unnecessary fsck runs at boot time, and to network better.

config RTC_SYSTOHC
	bool "Set the RTC time based on NTP synchronization"
	default y
	help
	  If you say yes here, the system time (wall clock) will be stored
	  in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11
	  minutes if userspace reports synchronized NTP status.

config RTC_HCTOSYS_DEVICE
	string "RTC used to set the system time"
	depends on RTC_HCTOSYS = y
	depends on RTC_HCTOSYS = y || RTC_SYSTOHC = y
	default "rtc0"
	help
	  The RTC device that will be used to (re)initialize the system
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG

obj-$(CONFIG_RTC_LIB)		+= rtc-lib.o
obj-$(CONFIG_RTC_HCTOSYS)	+= hctosys.o
obj-$(CONFIG_RTC_SYSTOHC)	+= systohc.o
obj-$(CONFIG_RTC_CLASS)		+= rtc-core.o
rtc-core-y			:= class.o interface.o

drivers/rtc/systohc.c

0 → 100644
+44 −0
Original line number Diff line number Diff line
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 */
#include <linux/rtc.h>
#include <linux/time.h>

/**
 * rtc_set_ntp_time - Save NTP synchronized time to the RTC
 * @now: Current time of day
 *
 * Replacement for the NTP platform function update_persistent_clock
 * that stores time for later retrieval by rtc_hctosys.
 *
 * Returns 0 on successful RTC update, -ENODEV if a RTC update is not
 * possible at all, and various other -errno for specific temporary failure
 * cases.
 *
 * If temporary failure is indicated the caller should try again 'soon'
 */
int rtc_set_ntp_time(struct timespec now)
{
	struct rtc_device *rtc;
	struct rtc_time tm;
	int err = -ENODEV;

	if (now.tv_nsec < (NSEC_PER_SEC >> 1))
		rtc_time_to_tm(now.tv_sec, &tm);
	else
		rtc_time_to_tm(now.tv_sec + 1, &tm);

	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
	if (rtc) {
		/* rtc_hctosys exclusively uses UTC, so we call set_time here,
		 * not set_mmss. */
		if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss))
			err = rtc_set_time(rtc, &tm);
		rtc_class_close(rtc);
	}

	return err;
}
+1 −0
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ extern void rtc_device_unregister(struct rtc_device *rtc);
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs);
extern int rtc_set_ntp_time(struct timespec now);
int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
extern int rtc_read_alarm(struct rtc_device *rtc,
			struct rtc_wkalrm *alrm);
Loading