Extend struct todr_chip_handle with a todr_quality member. This allows us
authorkettenis <kettenis@openbsd.org>
Wed, 12 Oct 2022 13:39:50 +0000 (13:39 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 12 Oct 2022 13:39:50 +0000 (13:39 +0000)
to assign a quality to RTC implementation and pick the "best" RTC if a
system has multiple RTCs (or multiple interfaces to an RTC).  This allows
us to prefer a battery-backed I2C RTC over an RTC that is part of the SoC
which is only running of the SoC is powered.  It also allows us to
work around issues with firmware RTC interfaces that may lie to us or
even crash the system.

This change makes sure the todr_quality member of the struct is always
initialized.  In most cases the quality will be set to zero; further
adjustments of the quality for specific subsystems/architectures will follow.

ok cheloha@, patrick@

22 files changed:
sys/arch/arm64/dev/aplpmu.c
sys/arch/arm64/dev/aplsmc.c
sys/arch/arm64/dev/efi_machdep.c
sys/arch/loongson/dev/mcclock.c
sys/arch/octeon/dev/octrtc.c
sys/arch/powerpc64/dev/opal.c
sys/arch/sparc64/dev/prtc.c
sys/arch/sparc64/dev/rtc.c
sys/arch/sparc64/dev/sbbc.c
sys/arch/sparc64/dev/vrtc.c
sys/dev/clock_subr.h
sys/dev/fdt/dapmic.c
sys/dev/fdt/plrtc.c
sys/dev/fdt/rkpmic.c
sys/dev/fdt/sxirtc.c
sys/dev/i2c/m41t8x.c
sys/dev/i2c/pcf85063.c
sys/dev/i2c/pcf8523.c
sys/dev/i2c/pcf8563.c
sys/dev/i2c/rs5c372.c
sys/dev/ic/mk48txx.c
sys/kern/kern_time.c

index 47df97b..b57d799 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aplpmu.c,v 1.5 2022/04/06 18:59:26 naddy Exp $        */
+/*     $OpenBSD: aplpmu.c,v 1.6 2022/10/12 13:39:50 kettenis Exp $     */
 /*
  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -121,6 +121,7 @@ aplpmu_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_todr.cookie = sc;
                sc->sc_todr.todr_gettime = aplpmu_gettime;
                sc->sc_todr.todr_settime = aplpmu_settime;
+               sc->sc_todr.todr_quality = 0;
                todr_attach(&sc->sc_todr);
 
                aplpmu_sc = sc;
index 578711b..b62448e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aplsmc.c,v 1.13 2022/08/27 16:56:25 kettenis Exp $    */
+/*     $OpenBSD: aplsmc.c,v 1.14 2022/10/12 13:39:50 kettenis Exp $    */
 /*
  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -266,6 +266,7 @@ aplsmc_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_todr.cookie = sc;
                sc->sc_todr.todr_gettime = aplsmc_gettime;
                sc->sc_todr.todr_settime = aplsmc_settime;
+               sc->sc_todr.todr_quality = 1000;
                todr_attach(&sc->sc_todr);
        }
 
index 5f6bbb2..2873105 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: efi_machdep.c,v 1.1 2022/10/03 19:32:22 kettenis Exp $        */
+/*     $OpenBSD: efi_machdep.c,v 1.2 2022/10/12 13:39:50 kettenis Exp $        */
 
 /*
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
@@ -40,8 +40,6 @@
  */
 #define EFI_SPACE_BITS 48
 
-extern todr_chip_handle_t todr_handle;
-
 extern uint32_t mmap_size;
 extern uint32_t mmap_desc_size;
 extern uint32_t mmap_desc_ver;
@@ -162,10 +160,17 @@ efi_attach(struct device *parent, struct device *self, void *aux)
        if (status != EFI_SUCCESS)
                return;
 
+       /*
+        * EDK II implementations provide an implementation of
+        * GetTime() that returns a fixed compiled-in time on hardware
+        * without a (supported) RTC.  So only use this interface as a
+        * last resort.
+        */
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = efi_gettime;
        sc->sc_todr.todr_settime = efi_settime;
-       todr_handle = &sc->sc_todr;
+       sc->sc_todr.todr_quality = -1000;
+       todr_attach(&sc->sc_todr);
 }
 
 void
index 34eee09..5c63809 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mcclock.c,v 1.4 2020/05/25 13:16:06 visa Exp $        */
+/*     $OpenBSD: mcclock.c,v 1.5 2022/10/12 13:39:50 kettenis Exp $    */
 /*     $NetBSD: mcclock.c,v 1.4 1996/10/13 02:59:41 christos Exp $     */
 
 /*
@@ -67,6 +67,7 @@ mcclock_attach(sc, busfns)
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = mcclock_gettime;
        sc->sc_todr.todr_settime = mcclock_settime;
+       sc->sc_todr.todr_quality = 0;
        todr_attach(&sc->sc_todr);
 }
 
index e23b6ad..51c0955 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: octrtc.c,v 1.14 2022/04/06 18:59:27 naddy Exp $       */
+/*     $OpenBSD: octrtc.c,v 1.15 2022/10/12 13:39:50 kettenis Exp $    */
 
 /*
  * Copyright (c) 2013, 2014 Paul Irofti.
@@ -113,6 +113,7 @@ octrtc_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = octrtc_gettime;
        sc->sc_todr.todr_settime = octrtc_settime;
+       sc->sc_todr.todr_quality = 0;
        todr_attach(&sc->sc_todr);
 
        printf(": DS1337\n");
index 10418d1..31873cf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: opal.c,v 1.13 2022/04/06 18:59:27 naddy Exp $ */
+/*     $OpenBSD: opal.c,v 1.14 2022/10/12 13:39:50 kettenis Exp $      */
 /*
  * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -146,6 +146,7 @@ opal_attach(struct device *parent, struct device *self, void *aux)
 
        sc->sc_todr.todr_gettime = opal_gettime;
        sc->sc_todr.todr_settime = opal_settime;
+       sc->sc_todr.todr_quality = 0;
        todr_attach(&sc->sc_todr);
 
        node = OF_getnodebyname(faa->fa_node, "power-mgt");
index dbac5af..7d7003c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: prtc.c,v 1.6 2021/10/24 17:05:04 mpi Exp $    */
+/*     $OpenBSD: prtc.c,v 1.7 2022/10/12 13:39:50 kettenis Exp $       */
 
 /*
  * Copyright (c) 2008 Mark Kettenis
@@ -96,7 +96,7 @@ prtc_attach(struct device *parent, struct device *self, void *aux)
 
        handle->bus_cookie = NULL;
        handle->todr_setwen = NULL;
-
+       handle->todr_quality = 0;
        todr_handle = handle;
 }
 
index a7df1ca..b411521 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtc.c,v 1.12 2021/10/24 17:05:04 mpi Exp $    */
+/*     $OpenBSD: rtc.c,v 1.13 2022/10/12 13:39:50 kettenis Exp $       */
 
 /*
  * Copyright (c) 1992, 1993
@@ -164,9 +164,9 @@ rtc_attach(struct device *parent, struct device *self, void *aux)
        handle->cookie = sc;
        handle->todr_gettime = rtc_gettime;
        handle->todr_settime = rtc_settime;
-
        handle->bus_cookie = NULL;
        handle->todr_setwen = NULL;
+       handle->todr_quality = 0;
        todr_handle = handle;
 
        /* The bq4802 is not compatible with the mc146818. */
index 12ea3fb..4259bad 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sbbc.c,v 1.14 2021/10/24 17:05:04 mpi Exp $   */
+/*     $OpenBSD: sbbc.c,v 1.15 2022/10/12 13:39:50 kettenis Exp $      */
 /*
  * Copyright (c) 2008 Mark Kettenis
  *
@@ -330,9 +330,9 @@ sbbc_attach_tod(struct sbbc_softc *sc, uint32_t offset)
        handle->cookie = tod;
        handle->todr_gettime = sbbc_tod_gettime;
        handle->todr_settime = sbbc_tod_settime;
-
        handle->bus_cookie = NULL;
        handle->todr_setwen = NULL;
+       handle->todr_quality = 0;
        todr_handle = handle;
 }
 
index 2d71f57..77e5e03 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vrtc.c,v 1.2 2021/10/24 17:05:04 mpi Exp $    */
+/*     $OpenBSD: vrtc.c,v 1.3 2022/10/12 13:39:50 kettenis Exp $       */
 /*
  * Copyright (c) 2008 Mark Kettenis
  *
@@ -68,9 +68,9 @@ vrtc_attach(struct device *parent, struct device *self, void *aux)
        handle->cookie = self;
        handle->todr_gettime = vrtc_gettime;
        handle->todr_settime = vrtc_settime;
-
        handle->bus_cookie = NULL;
        handle->todr_setwen = NULL;
+       handle->todr_quality = 0;
        todr_handle = handle;
 }
 
index 8a0c9f3..67d7f50 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: clock_subr.h,v 1.7 2021/04/24 10:15:15 mpi Exp $      */
+/*     $OpenBSD: clock_subr.h,v 1.8 2022/10/12 13:39:50 kettenis Exp $ */
 /*     $NetBSD: clock_subr.h,v 1.2 1997/03/15 18:11:17 is Exp $        */
 
 /*-
@@ -45,6 +45,7 @@ struct todr_chip_handle {
        void    *cookie;        /* Device specific data */
        void    *bus_cookie;    /* Bus specific data */
 
+       int     todr_quality;
        int     (*todr_gettime)(struct todr_chip_handle *, struct timeval *);
        int     (*todr_settime)(struct todr_chip_handle *, struct timeval *);
        int     (*todr_setwen)(struct todr_chip_handle *, int);
index 96f59b8..d8e9399 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dapmic.c,v 1.3 2022/10/03 21:02:02 jca Exp $  */
+/*     $OpenBSD: dapmic.c,v 1.4 2022/10/12 13:39:50 kettenis Exp $     */
 /*
  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -139,6 +139,7 @@ dapmic_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = dapmic_gettime;
        sc->sc_todr.todr_settime = dapmic_settime;
+       sc->sc_todr.todr_quality = 0;
        todr_attach(&sc->sc_todr);
 
        if (cpuresetfn == NULL)
index 5f5d785..3f3f956 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: plrtc.c,v 1.2 2021/10/24 17:52:26 mpi Exp $   */
+/*     $OpenBSD: plrtc.c,v 1.3 2022/10/12 13:39:50 kettenis Exp $      */
 
 /*
  * Copyright (c) 2015 Jonathan Gray <jsg@openbsd.org>
@@ -120,6 +120,7 @@ plrtc_attach(struct device *parent, struct device *self, void *aux)
        handle->cookie = sc;
        handle->todr_gettime = plrtc_gettime;
        handle->todr_settime = plrtc_settime;
+       handle->todr_quality = 0;
        todr_handle = handle;
 
        /* enable the rtc */
index 23e0fb7..f867e96 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rkpmic.c,v 1.11 2022/10/10 17:45:35 kettenis Exp $    */
+/*     $OpenBSD: rkpmic.c,v 1.12 2022/10/12 13:39:50 kettenis Exp $    */
 /*
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -28,8 +28,6 @@
 
 #include <dev/clock_subr.h>
 
-extern todr_chip_handle_t todr_handle;
-
 #define RK80X_SECONDS          0x00
 #define RK80X_MINUTES          0x01
 #define RK80X_HOURS            0x02
@@ -310,8 +308,8 @@ rkpmic_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = rkpmic_gettime;
        sc->sc_todr.todr_settime = rkpmic_settime;
-       if (todr_handle == NULL)
-               todr_handle = &sc->sc_todr;
+       sc->sc_todr.todr_quality = 0;
+       todr_attach(&sc->sc_todr);
 
        if (OF_is_compatible(node, "rockchip,rk805")) {
                chip = "RK805";
index c5eab75..b1d305e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sxirtc.c,v 1.6 2021/10/24 17:52:27 mpi Exp $  */
+/*     $OpenBSD: sxirtc.c,v 1.7 2022/10/12 13:39:50 kettenis Exp $     */
 /*
  * Copyright (c) 2008 Mark Kettenis
  * Copyright (c) 2013 Artturi Alm
@@ -148,6 +148,7 @@ sxirtc_attach(struct device *parent, struct device *self, void *aux)
        handle->todr_settime = sxirtc_settime;
        handle->bus_cookie = NULL;
        handle->todr_setwen = NULL;
+       handle->todr_quality = 0;
        todr_handle = handle;
 
        printf("\n");
index fa9a14f..b6e2a90 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: m41t8x.c,v 1.2 2020/10/23 20:55:15 patrick Exp $      */
+/*     $OpenBSD: m41t8x.c,v 1.3 2022/10/12 13:39:50 kettenis Exp $     */
 
 /*
  * Copyright (c) 2010 Miodrag Vallat.
@@ -75,6 +75,7 @@ m41t8xrtc_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = m41t8xrtc_gettime;
        sc->sc_todr.todr_settime = m41t8xrtc_settime;
+       sc->sc_todr.todr_quality = 1000;
        todr_attach(&sc->sc_todr);
 
        printf("\n");
index f94b511..151ca5b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pcf85063.c,v 1.2 2022/04/06 18:59:28 naddy Exp $      */
+/*     $OpenBSD: pcf85063.c,v 1.3 2022/10/12 13:39:50 kettenis Exp $   */
 
 /*
  * Copyright (c) 2005 Kimihiro Nonaka
@@ -110,9 +110,11 @@ pcyrtc_attach(struct device *parent, struct device *self, void *arg)
 
        sc->sc_tag = ia->ia_tag;
        sc->sc_address = ia->ia_addr;
+
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = pcyrtc_gettime;
        sc->sc_todr.todr_settime = pcyrtc_settime;
+       sc->sc_todr.todr_quality = 1000;
        todr_attach(&sc->sc_todr);
 
        /*
index a16047d..3bc2768 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pcf8523.c,v 1.7 2022/04/06 18:59:28 naddy Exp $       */
+/*     $OpenBSD: pcf8523.c,v 1.8 2022/10/12 13:39:50 kettenis Exp $    */
 
 /*
  * Copyright (c) 2005 Kimihiro Nonaka
@@ -126,20 +126,13 @@ pcfrtc_attach(struct device *parent, struct device *self, void *arg)
 
        sc->sc_tag = ia->ia_tag;
        sc->sc_address = ia->ia_addr;
+
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = pcfrtc_gettime;
        sc->sc_todr.todr_settime = pcfrtc_settime;
        sc->sc_todr.todr_setwen = NULL;
-
-#if 0
+       sc->sc_todr.todr_quality = 1000;
        todr_attach(&sc->sc_todr);
-#else
-       /* XXX */
-       {
-       extern todr_chip_handle_t todr_handle;
-       todr_handle = &sc->sc_todr;
-       }
-#endif
 
        /*
         * Enable battery switch-over and battery low detection in
index ec21400..b0683df 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pcf8563.c,v 1.6 2022/04/06 18:59:28 naddy Exp $       */
+/*     $OpenBSD: pcf8563.c,v 1.7 2022/10/12 13:39:50 kettenis Exp $    */
 
 /*
  * Copyright (c) 2005 Kimihiro Nonaka
@@ -113,20 +113,13 @@ pcxrtc_attach(struct device *parent, struct device *self, void *arg)
 
        sc->sc_tag = ia->ia_tag;
        sc->sc_address = ia->ia_addr;
+
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = pcxrtc_gettime;
        sc->sc_todr.todr_settime = pcxrtc_settime;
        sc->sc_todr.todr_setwen = NULL;
-
-#if 0
+       sc->sc_todr.todr_quality = 1000;
        todr_attach(&sc->sc_todr);
-#else
-       /* XXX */
-       {
-       extern todr_chip_handle_t todr_handle;
-       todr_handle = &sc->sc_todr;
-       }
-#endif
 
        /* Enable. */
        reg = pcxrtc_reg_read(sc, PCF8563_CONTROL1);
index 44ba03d..ec187dd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rs5c372.c,v 1.7 2022/04/06 18:59:28 naddy Exp $       */
+/*     $OpenBSD: rs5c372.c,v 1.8 2022/10/12 13:39:50 kettenis Exp $    */
 /*     $NetBSD: rs5c372.c,v 1.5 2006/03/29 06:41:24 thorpej Exp $      */
 
 /*
@@ -181,20 +181,13 @@ ricohrtc_attach(struct device *parent, struct device *self, void *arg)
 
        sc->sc_tag = ia->ia_tag;
        sc->sc_address = ia->ia_addr;
+
        sc->sc_todr.cookie = sc;
        sc->sc_todr.todr_gettime = ricohrtc_gettime;
        sc->sc_todr.todr_settime = ricohrtc_settime;
        sc->sc_todr.todr_setwen = NULL;
-
-#if 0
+       sc->sc_todr.todr_quality = 1000;
        todr_attach(&sc->sc_todr);
-#else
-       /* XXX */
-       {
-       extern todr_chip_handle_t todr_handle;
-       todr_handle = &sc->sc_todr;
-       }
-#endif
 
        /* Initialize RTC */
        ricohrtc_reg_write(sc, RICOHRTC_CONTROL2, RICOHRTC_CONTROL2_24HRS);
index 185e7b1..da6c7ad 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mk48txx.c,v 1.8 2021/04/24 10:15:15 mpi Exp $ */
+/*     $OpenBSD: mk48txx.c,v 1.9 2022/10/12 13:39:50 kettenis Exp $    */
 /*     $NetBSD: mk48txx.c,v 1.7 2001/04/08 17:05:10 tsutsui Exp $ */
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -110,6 +110,7 @@ mk48txx_attach(bt, bh, model, year0)
        handle->todr_gettime = mk48txx_gettime;
        handle->todr_settime = mk48txx_settime;
        handle->todr_setwen = NULL;
+       handle->todr_quality = 0;
        mk->mk_bt = bt;
        mk->mk_bh = bh;
        mk->mk_nvramsz = nvramsz;
index 7745cd8..45911a3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_time.c,v 1.157 2022/08/14 01:58:27 jsg Exp $     */
+/*     $OpenBSD: kern_time.c,v 1.158 2022/10/12 13:39:50 kettenis Exp $        */
 /*     $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $      */
 
 /*
@@ -951,7 +951,9 @@ resettodr(void)
 void
 todr_attach(struct todr_chip_handle *todr)
 {
-       todr_handle = todr;
+       if (todr_handle == NULL ||
+           todr->todr_quality > todr_handle->todr_quality)
+               todr_handle = todr;
 }
 
 #define RESETTODR_PERIOD       1800