diff options
author | Joshua Clayton <stillcompiling@gmail.com> | 2016-02-05 15:41:11 -0500 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-03-14 12:08:15 -0400 |
commit | b3967067c273359c7462f4be9a887c3d1a515f49 (patch) | |
tree | 1f2ca90d34dae4961b97d68ccdb93a979ee5e2b8 /drivers/rtc/interface.c | |
parent | 9d1fa4c3737ac82520931d940dcd2426719f8dd2 (diff) |
rtc: Add functions to set and read rtc offset
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million, however they often reference ppm to 2 digits of
precision, which makes integer ppm less than ideal.
We use parts per billion, which more than covers the precision needed
and works nicely within 32 bits
Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5836751b8203..9ef5f6f89f98 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -939,4 +939,58 @@ void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer) | |||
939 | mutex_unlock(&rtc->ops_lock); | 939 | mutex_unlock(&rtc->ops_lock); |
940 | } | 940 | } |
941 | 941 | ||
942 | /** | ||
943 | * rtc_read_offset - Read the amount of rtc offset in parts per billion | ||
944 | * @ rtc: rtc device to be used | ||
945 | * @ offset: the offset in parts per billion | ||
946 | * | ||
947 | * see below for details. | ||
948 | * | ||
949 | * Kernel interface to read rtc clock offset | ||
950 | * Returns 0 on success, or a negative number on error. | ||
951 | * If read_offset() is not implemented for the rtc, return -EINVAL | ||
952 | */ | ||
953 | int rtc_read_offset(struct rtc_device *rtc, long *offset) | ||
954 | { | ||
955 | int ret; | ||
956 | |||
957 | if (!rtc->ops) | ||
958 | return -ENODEV; | ||
959 | |||
960 | if (!rtc->ops->read_offset) | ||
961 | return -EINVAL; | ||
962 | |||
963 | mutex_lock(&rtc->ops_lock); | ||
964 | ret = rtc->ops->read_offset(rtc->dev.parent, offset); | ||
965 | mutex_unlock(&rtc->ops_lock); | ||
966 | return ret; | ||
967 | } | ||
942 | 968 | ||
969 | /** | ||
970 | * rtc_set_offset - Adjusts the duration of the average second | ||
971 | * @ rtc: rtc device to be used | ||
972 | * @ offset: the offset in parts per billion | ||
973 | * | ||
974 | * Some rtc's allow an adjustment to the average duration of a second | ||
975 | * to compensate for differences in the actual clock rate due to temperature, | ||
976 | * the crystal, capacitor, etc. | ||
977 | * | ||
978 | * Kernel interface to adjust an rtc clock offset. | ||
979 | * Return 0 on success, or a negative number on error. | ||
980 | * If the rtc offset is not setable (or not implemented), return -EINVAL | ||
981 | */ | ||
982 | int rtc_set_offset(struct rtc_device *rtc, long offset) | ||
983 | { | ||
984 | int ret; | ||
985 | |||
986 | if (!rtc->ops) | ||
987 | return -ENODEV; | ||
988 | |||
989 | if (!rtc->ops->set_offset) | ||
990 | return -EINVAL; | ||
991 | |||
992 | mutex_lock(&rtc->ops_lock); | ||
993 | ret = rtc->ops->set_offset(rtc->dev.parent, offset); | ||
994 | mutex_unlock(&rtc->ops_lock); | ||
995 | return ret; | ||
996 | } | ||