Use the PMIC SDAM scratch-register blocks to manage the RTC offset instead
authorpatrick <patrick@openbsd.org>
Sat, 22 Jul 2023 22:48:35 +0000 (22:48 +0000)
committerpatrick <patrick@openbsd.org>
Sat, 22 Jul 2023 22:48:35 +0000 (22:48 +0000)
of accessing UEFI variables through the qcscm(4) TEE interface.

ok kettenis@

sys/dev/fdt/qcrtc.c
sys/dev/fdt/qcscm.c

index bc1e78d..22783cd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: qcrtc.c,v 1.2 2023/01/16 20:12:38 patrick Exp $       */
+/*     $OpenBSD: qcrtc.c,v 1.3 2023/07/22 22:48:35 patrick Exp $       */
 /*
  * Copyright (c) 2022 Patrick Wildt <patrick@blueri.se>
  *
@@ -25,6 +25,7 @@
 #include <dev/fdt/spmivar.h>
 
 #include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_misc.h>
 #include <dev/ofw/fdt.h>
 
 #include <dev/clock_subr.h>
@@ -114,12 +115,14 @@ qcrtc_gettime(struct todr_chip_handle *handle, struct timeval *tv)
                return error;
        }
 
-       /* Retrieve RTC offset stored in UEFI. */
-       if (qcscm_uefi_rtc_get(&off) != 0)
-               return EIO;
+       /* Retrieve RTC offset from either NVRAM or UEFI. */
+       error = nvmem_read_cell(sc->sc_node, "offset", &off, sizeof(off));
+       if (error == ENXIO || (!error && off == 0))
+               error = qcscm_uefi_rtc_get(&off);
+       if (error)
+               return error;
 
-       /* Add RTC counter and 10y+1w to get seconds from epoch. */
-       tv->tv_sec = off + (reg + (10 * 365 * 86400 + 7 * 86400));
+       tv->tv_sec = off + reg;
        tv->tv_usec = 0;
        return 0;
 }
@@ -138,9 +141,11 @@ qcrtc_settime(struct todr_chip_handle *handle, struct timeval *tv)
                return error;
        }
 
-       /* Subtract RTC counter and 10y+1w to get offset for UEFI. */
-       off = tv->tv_sec - (reg + (10 * 365 * 86400 + 7 * 86400));
+       /* Store RTC offset in either NVRAM or UEFI. */
+       off = tv->tv_sec - reg;
+       error = nvmem_write_cell(sc->sc_node, "offset", &off, sizeof(off));
+       if (error == ENXIO)
+               error = qcscm_uefi_rtc_set(off);
 
-       /* Store offset in UEFI. */
-       return qcscm_uefi_rtc_set(off);
+       return error;
 }
index c5d2daa..1e39742 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: qcscm.c,v 1.4 2023/05/17 23:12:04 patrick Exp $ */
+/* $OpenBSD: qcscm.c,v 1.5 2023/07/22 22:48:35 patrick Exp $ */
 /*
  * Copyright (c) 2022 Patrick Wildt <patrick@blueri.se>
  *
@@ -90,6 +90,8 @@
 #define EFI_VARIABLE_BOOTSERVICE_ACCESS        0x00000002
 #define EFI_VARIABLE_RUNTIME_ACCESS    0x00000004
 
+#define UNIX_GPS_EPOCH_OFFSET          315964800
+
 struct qcscm_dmamem {
        bus_dmamap_t            qdm_map;
        bus_dma_segment_t       qdm_seg;
@@ -703,7 +705,8 @@ qcscm_uefi_rtc_get(uint32_t *off)
            &rtcinfosize) != 0)
                return EIO;
 
-       *off = rtcinfo[0];
+       /* UEFI stores the offset based on GPS epoch */
+       *off = rtcinfo[0] + UNIX_GPS_EPOCH_OFFSET;
        return 0;
 }
 
@@ -722,6 +725,9 @@ qcscm_uefi_rtc_set(uint32_t off)
            &rtcinfosize) != 0)
                return EIO;
 
+       /* UEFI stores the offset based on GPS epoch */
+       off -= UNIX_GPS_EPOCH_OFFSET;
+
        /* No need to set if we're not changing anything */
        if (rtcinfo[0] == off)
                return 0;