Index: src/sys/kern/kern_todr.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_todr.c,v retrieving revision 1.52 diff -u -r1.52 kern_todr.c --- src/sys/kern/kern_todr.c 4 Jan 2026 02:09:03 -0000 1.52 +++ src/sys/kern/kern_todr.c 4 Sep 2026 13:52:55 -0000 @@ -78,7 +78,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -89,8 +91,14 @@ static int todr_gettime(todr_chip_handle_t, struct timeval *); static int todr_settime(todr_chip_handle_t, struct timeval *); +struct todr_entry { + todr_chip_handle_t todr_handle; + SIMPLEQ_ENTRY(todr_entry) todr_entries; +}; +static SIMPLEQ_HEAD(, todr_entry) todr_head = + SIMPLEQ_HEAD_INITIALIZER(todr_head); + static kmutex_t todr_mutex; -static todr_chip_handle_t todr_handle; static bool todr_initialized; /* The minimum reasonable RTC date before preposterousness */ @@ -179,6 +187,7 @@ void todr_attach(todr_chip_handle_t todr) { + struct todr_entry *todrp; /* * todr_init() is called very early in main(), but this is @@ -191,13 +200,15 @@ return; } + todrp = kmem_alloc(sizeof(struct todr_entry), KM_SLEEP); todr_lock(); - if (todr_handle) { - todr_unlock(); - printf("todr_attach: TOD already configured\n"); - return; + if (SIMPLEQ_EMPTY(&todr_head)) { + SIMPLEQ_INSERT_HEAD(&todr_head, todrp, todr_entries); + } else { + SIMPLEQ_INSERT_TAIL(&todr_head, todrp, todr_entries); + printf("%s: secondary clock\n", device_xname(todr->todr_dev)); } - todr_handle = todr; + todrp->todr_handle = todr; todr_unlock(); } @@ -217,7 +228,10 @@ bool goodtime = false; bool badrtc = false; struct timespec ts; - struct timeval tv; + struct timeval tv, tv2; + struct todr_entry *todrp; + device_t t_dev; + time_t deltat; KASSERT(todr_lock_owned()); @@ -246,22 +260,28 @@ /* * Some ports need to be supplied base in order to fabricate a time_t. */ - if (todr_handle) - todr_handle->todr_base_time = base; + if (SIMPLEQ_EMPTY(&todr_head)) { + todrp = NULL; + } else { + todrp = SIMPLEQ_FIRST(&todr_head); + if (todrp->todr_handle != NULL) + todrp->todr_handle->todr_base_time = base; + } memset(&tv, 0, sizeof(tv)); - if ((todr_handle == NULL) || - (todr_gettime(todr_handle, &tv) != 0) || + /* Note, that we use the first RTC for system time. */ + if ((todrp == NULL) || (todrp->todr_handle == NULL) || + (todr_gettime(todrp->todr_handle, &tv) != 0) || (tv.tv_sec < (PREPOSTEROUS_YEARS * SECS_PER_COMMON_YEAR))) { - if (todr_handle != NULL) + if ((todrp != NULL) && (todrp->todr_handle != NULL)) printf("WARNING: preposterous TOD clock time\n"); else printf("WARNING: no TOD clock present\n"); badrtc = true; } else { - time_t deltat = tv.tv_sec - base; + deltat = tv.tv_sec - base; if (deltat < 0) deltat = -deltat; @@ -301,6 +321,29 @@ tv.tv_usec = 0; } + /* Check other clocks, if any, against our time */ + todrp = SIMPLEQ_FIRST(&todr_head); + while ((todrp = SIMPLEQ_NEXT(todrp, todr_entries)) != NULL) { + if ((todrp->todr_handle == NULL) || + (todr_gettime(todrp->todr_handle, &tv2) != 0)) + continue; + t_dev = todrp->todr_handle->todr_dev; + if (tv2.tv_sec < (PREPOSTEROUS_YEARS * SECS_PER_COMMON_YEAR)) { + printf("WARNING: preposterous %s clock time\n", + device_xname(t_dev)); + deltat = 0; + } else { + deltat = tv.tv_sec - tv2.tv_sec; + rnd_add_data(NULL, &tv, sizeof(tv), 0); + } + if (deltat < -10) + printf("WARNING: %s clock lost %" PRId64 " seconds\n", + device_xname(t_dev), deltat); + if (deltat > 10) + printf("WARNING: %s clock gained %" PRId64 " seconds\n", + device_xname(t_dev), deltat); + } + timeset = true; ts.tv_sec = tv.tv_sec; @@ -315,13 +358,14 @@ /* * todr_save_systime: - * Save the current system time back to the TOD clock. + * Save the current system time back to the TOD clock(s). * Must be called with the TODR lock held. */ void todr_save_systime(void) { struct timeval tv; + struct todr_entry *todrp; KASSERT(todr_lock_owned()); @@ -338,9 +382,12 @@ if (tv.tv_sec == 0) return; - if (todr_handle) - if (todr_settime(todr_handle, &tv) != 0) - printf("Cannot set TOD clock time\n"); + todrp = SIMPLEQ_FIRST(&todr_head); + SIMPLEQ_FOREACH(todrp, &todr_head, todr_entries) + if ((todrp->todr_handle != NULL) && + (todr_settime(todrp->todr_handle, &tv) != 0)) + printf("Cannot set %s TOD clock time\n", + device_xname(todrp->todr_handle->todr_dev)); } /* Index: src/sys/arch/sparc64/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/conf/GENERIC,v retrieving revision 1.253 diff -u -r1.253 GENERIC --- src/sys/arch/sparc64/conf/GENERIC 28 Aug 2026 21:16:34 -0000 1.253 +++ src/sys/arch/sparc64/conf/GENERIC 3 Sep 2026 07:34:58 -0000 @@ -847,6 +847,7 @@ seeprom* at iic? addr? # i2c-at24c64 fru's pcagpio* at iic? addr? # V210/V240 GPIO's pcf8574io* at iic? addr? # E250 GPIO's +dsrtc* at iic? addr? # RSC clock found on V210/V240 auxfan* at iic? addr? # iic fan sensor found on SB2500