linux/drivers/rtc/hctosys.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * RTC subsystem, initialize system time on startup
   4 *
   5 * Copyright (C) 2005 Tower Technologies
   6 * Author: Alessandro Zummo <a.zummo@towertech.it>
   7 */
   8
   9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10
  11#include <linux/rtc.h>
  12
  13/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
  14 * whether it stores the most close value or the value with partial
  15 * seconds truncated. However, it is important that we use it to store
  16 * the truncated value. This is because otherwise it is necessary,
  17 * in an rtc sync function, to read both xtime.tv_sec and
  18 * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
  19 * of >32bits is not possible. So storing the most close value would
  20 * slow down the sync API. So here we have the truncated value and
  21 * the best guess is to add 0.5s.
  22 */
  23
  24static int __init rtc_hctosys(void)
  25{
  26        int err = -ENODEV;
  27        struct rtc_time tm;
  28        struct timespec64 tv64 = {
  29                .tv_nsec = NSEC_PER_SEC >> 1,
  30        };
  31        struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
  32
  33        if (!rtc) {
  34                pr_info("unable to open rtc device (%s)\n",
  35                        CONFIG_RTC_HCTOSYS_DEVICE);
  36                goto err_open;
  37        }
  38
  39        err = rtc_read_time(rtc, &tm);
  40        if (err) {
  41                dev_err(rtc->dev.parent,
  42                        "hctosys: unable to read the hardware clock\n");
  43                goto err_read;
  44        }
  45
  46        tv64.tv_sec = rtc_tm_to_time64(&tm);
  47
  48#if BITS_PER_LONG == 32
  49        if (tv64.tv_sec > INT_MAX) {
  50                err = -ERANGE;
  51                goto err_read;
  52        }
  53#endif
  54
  55        err = do_settimeofday64(&tv64);
  56
  57        dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n",
  58                 &tm, (long long)tv64.tv_sec);
  59
  60err_read:
  61        rtc_class_close(rtc);
  62
  63err_open:
  64        rtc_hctosys_ret = err;
  65
  66        return err;
  67}
  68
  69late_initcall(rtc_hctosys);
  70