Hello Mark, tech@,
since A64 now supports dynamic frequencies and thermal zones I thought
I could go back to sxisid driver idea.

Device tree excerpts:

&{/soc} {
        ths: thermal_sensor@1c25000 {
                compatible = "allwinner,sun50i-a64-ths";
                reg = <0x01c25000 0x100>;
                interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
                clock-names = "apb", "ths";
                resets = <&ccu RST_BUS_THS>;
                reset-names = "apb";
                #thermal-sensor-cells = <1>;
                status = "okay";

                nvmem-cells = <&ths_calib>;
                nvmem-cell-names = "ths-calib";
        };
};

&{/soc} {
        sid: eeprom@1c14000 {
                compatible = "allwinner,sun50i-a64-sid";
                reg = <0x1c14000 0x400>;

                ths_calib: calib@234 {
                        reg = <0x234 0x6>;
                };
        };
};

Some parts of my original post are stil valid:

> [...] I noticed sxitemp (OpenBSD) and aw_thermal (FreeBSD) are showing
> different values for temperature data and the difference isn't just
> related to the CPU load or environment I think.
> 
> FreeBSD:
> # sysctl dev.aw_thermal
> dev.aw_thermal.0.gpu2: 24C
> dev.aw_thermal.0.gpu1: 22C
> dev.aw_thermal.0.cpu: 24C
> 
> OpenBSD:
> $ sysctl hw
> hw.sensors.sxitemp0.temp0=43.57 degC (CPU)
> hw.sensors.sxitemp0.temp1=43.57 degC (GPU)
> hw.sensors.sxitemp0.temp2=44.39 degC
>

It was on A64+ board, on Pinebook I don't think these differences are that big.

> I started looking at sxitemp driver and found out that FreeBSD driver
> sets calibration data stored in SID memory (e-fuses). Access to this
> memory area is implemented as a separate driver and OpenBSD is missing
> it completely.
> 
> I also thought it may be useful to set 'uuid' value using another SID
> e-fuse called 'chip id'. With the added sxisid and calibration data
> the output is:
> 
> $ sysctl hw
> hw.sensors.sxitemp0.temp0=28.04 degC (CPU)
> hw.sensors.sxitemp0.temp1=26.64 degC (GPU)
> hw.sensors.sxitemp0.temp2=30.14 degC
> hw.uuid=ba00c09220460004080890510e0b1964
> 
> FreeBSD aw_sid shows:
> # sysctl dev.aw_sid
> dev.aw_sid.0.ths-calib: 830775078707
> dev.aw_sid.0.rootkey: ba00c09220460004080890510e0b1964
> 

Now it appears it may be also used to feed /dev/random?

>
> OpenBSD sxisid driver:
> 1. exposes uint32_t sxisid_read(bus_size_t, uint32_t, uint8_t *)
> function (used by sxitemp by passing SID memory offset and size from
> device tree)
> 2. added sxisid driver as 'early' because of this `sxisid_read` that
> could be used later by another driver - was it good idea?
> 3. OpenBSD sxisid does not access information directly - 'public' flag
> in the aw_sid driver - everything is read using SID_PRCTL and SID_READ
> registers. Having only a64 board, not being able to test other I
> wanted to focus on one way to access the data
> 4. Pine A64+ - the only board I have had all fields marked as 'public'
> in aw_sid but it seems they can be accessed same way as '!public'
> e-fuses just fine
> 5. I couldn't find anything in the A64 manual regarding SID/e-fuses so
> I relied on linux-sunxi.org and aw_sid implementation
> 6. I'm not sure if this is a thing in OpenBSD but I assumed access to
> e-fuses (via SID_PRCTL) should be in a critical section (because
> driver requests the data using SID_PRCTL register, waits for the data
> and reads the data using SID_READ register) - I used mutex (IPL_NONE)
> for that
[..]
> 8. with unmodified u-boot sxisid is not attached and sxitemp behaves
> like before (no calibration data is set)
> 
> References:
> http://linux-sunxi.org/SID_Register_Guide
> https://github.com/freebsd/freebsd/blob/master/sys/arm/allwinner/
> (aw_sid and aw_thermal)
> 

-- 
Krystian

Index: share/man/man4/Makefile
===================================================================
RCS file: /cvs/src/share/man/man4/Makefile,v
retrieving revision 1.731
diff -u -p -r1.731 Makefile
--- share/man/man4/Makefile     26 Sep 2019 13:09:55 -0000      1.731
+++ share/man/man4/Makefile     29 Sep 2019 19:06:58 -0000
@@ -70,8 +70,8 @@ MAN=  aac.4 abcrtc.4 ac97.4 acphy.4 acrtc
        sf.4 sili.4 simplefb.4 siop.4 sis.4 sk.4 sli.4 \
        sm.4 smsc.4 softraid.4 spdmem.4 sdtemp.4 speaker.4 sppp.4 sqphy.4 \
        st.4 ste.4 stge.4 sti.4 stp.4 sv.4 switch.4 sxiccmu.4 sximmc.4 \
-       sxipio.4 sxirsb.4 sxirtc.4 sxisyscon.4 sxitemp.4 sxitwi.4 sym.4 \
-       sypwr.4 syscon.4 \
+       sxipio.4 sxirsb.4 sxirtc.4 sxisid.4 sxisyscon.4 sxitemp.4 sxitwi.4 \
+       sym.4 sypwr.4 syscon.4 \
        tcic.4 tcp.4 termios.4 tht.4 ti.4 tipmic.4 tl.4 \
        tlphy.4 thmc.4 tpm.4 tpmr.4 tqphy.4 trm.4 trunk.4 tsl.4 tty.4 \
        tun.4 tap.4 twe.4 \
Index: share/man/man4/sxisid.4
===================================================================
RCS file: share/man/man4/sxisid.4
diff -N share/man/man4/sxisid.4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ share/man/man4/sxisid.4     29 Sep 2019 19:07:01 -0000
@@ -0,0 +1,45 @@
+.\"    $OpenBSD$
+.\"
+.\" Copyright (c) 2019 Krystian Lewandowski
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: September 29 2019 $
+.Dt SXISID 4
+.Os
+.Sh NAME
+.Nm sxisid
+.Nd Allwinner e-fuses interface (read only)
+.Sh SYNOPSIS
+.Cd "sxisid* at fdt? early 1"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the e-fuse registers integrated in Allwinner
+Technology A-series. For now only A64 is tested and supported.
+The
+.Xr sxitemp 4
+driver performs calibration using this interface.
+.Pp
+Chip ID (SID) is available through the
+.Xr sysctl 8
+interface.
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr sxitemp 4 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 6.6 .
Index: sys/arch/arm64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/arm64/conf/GENERIC,v
retrieving revision 1.125
diff -u -p -r1.125 GENERIC
--- sys/arch/arm64/conf/GENERIC 9 Sep 2019 20:00:27 -0000       1.125
+++ sys/arch/arm64/conf/GENERIC 29 Sep 2019 19:07:04 -0000
@@ -199,6 +199,7 @@ sxirtc*             at fdt? early 1 # Real Time Clo
 sximmc*                at fdt?         # SD/MMC card controller
 sdmmc*         at sximmc?      # SD/MMC bus
 sxisyscon*     at fdt? early 1 # System controller
+sxisid*                at fdt? early 1 # SID ROM
 sxitemp*       at fdt?         # Temperature sensor
 sxitwi*                at fdt?         # I2C controller
 iic*           at sxitwi?      # I2C bus
Index: sys/arch/arm64/conf/RAMDISK
===================================================================
RCS file: /cvs/src/sys/arch/arm64/conf/RAMDISK,v
retrieving revision 1.103
diff -u -p -r1.103 RAMDISK
--- sys/arch/arm64/conf/RAMDISK 9 Sep 2019 20:00:27 -0000       1.103
+++ sys/arch/arm64/conf/RAMDISK 29 Sep 2019 19:07:06 -0000
@@ -185,6 +185,7 @@ sxirtc*             at fdt? early 1 # Real Time Clo
 sximmc*                at fdt?         # SD/MMC card controller
 sdmmc*         at sximmc?      # SD/MMC bus
 sxisyscon*     at fdt? early 1 # System controller
+sxisid*                at fdt? early 1 # SID ROM
 sxitwi*                at fdt?         # I2C controller
 iic*           at sxitwi?      # I2C bus
 dwxe*          at fdt?
Index: sys/dev/fdt/files.fdt
===================================================================
RCS file: /cvs/src/sys/dev/fdt/files.fdt,v
retrieving revision 1.93
diff -u -p -r1.93 files.fdt
--- sys/dev/fdt/files.fdt       29 Sep 2019 13:04:03 -0000      1.93
+++ sys/dev/fdt/files.fdt       29 Sep 2019 19:07:09 -0000
@@ -48,6 +48,10 @@ device       sxitwi: i2cbus
 attach sxitwi at fdt
 file   dev/fdt/sxitwi.c                sxitwi
 
+device sxisid
+attach sxisid at fdt
+file   dev/fdt/sxisid.c                sxisid
+
 device axppmic
 attach axppmic at i2c
 attach axppmic at rsb with axppmic_rsb
@@ -197,7 +201,7 @@ attach      rkgpio at fdt
 file   dev/fdt/rkgpio.c                rkgpio
 
 device rkiic: i2cbus
-attach rkiic at fdt                    
+attach rkiic at fdt
 file   dev/fdt/rkiic.c                 rkiic
 
 device rkpmic
Index: sys/dev/fdt/sxisid.c
===================================================================
RCS file: sys/dev/fdt/sxisid.c
diff -N sys/dev/fdt/sxisid.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/dev/fdt/sxisid.c        29 Sep 2019 19:07:12 -0000
@@ -0,0 +1,144 @@
+/*     $OpenBSD$       */
+/*
+ * Copyright (c) 2019 Krystian Lewandowski
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <machine/fdt.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#define EFUSE_OFFSET   0x200
+#define SID_PRCTL_OFFSET(n)    (((n) & 0xff) << 16)
+#define SID_PRCTL_OP_LOCK      (0xac << 8)
+#define SID_PRCTL_READ (0x01 << 1)
+#define SID_PRCTL      0x40
+#define SID_RDKEY      0x60
+#define SID_LEN        0x10
+
+#define HREAD4(sc, reg)                                        \
+               (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh,(reg)))
+
+#define HWRITE4(sc, reg, val)                                  \
+               (bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)))
+
+struct sxisid_softc {
+       struct device sc_dev;
+       bus_space_tag_t sc_iot;
+       bus_space_handle_t sc_ioh;
+       struct mutex sc_mtx;
+};
+
+int sxisid_match(struct device *, void *, void *);
+void sxisid_attach(struct device *, struct device *, void *);
+uint32_t sxisid_read(bus_size_t, uint32_t, uint8_t *);
+
+struct cfattach sxisid_ca = {
+       sizeof(struct sxisid_softc), sxisid_match, sxisid_attach
+};
+
+struct cfdriver sxisid_cd = {
+       NULL, "sxisid", DV_DULL
+};
+
+static struct sxisid_softc *sxisid_sc;
+
+extern char *hw_uuid;
+
+int
+sxisid_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+       return OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-sid");
+}
+
+void
+sxisid_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct sxisid_softc *sc = (struct sxisid_softc *) self;
+       struct fdt_attach_args *faa = aux;
+       uint8_t *sid, hw_uuid_len;
+       uint32_t i;
+
+       if (faa->fa_nreg < 1) {
+               printf(": no registers\n");
+               return;
+       }
+       sc->sc_iot = faa->fa_iot;
+       if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+           faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
+               printf(": can't map registers\n");
+               return;
+       }
+       printf("\n");
+
+       mtx_init(&sc->sc_mtx, IPL_NONE);
+       sxisid_sc = sc;
+
+       hw_uuid_len = SID_LEN * 2 + 1;
+       hw_uuid = malloc(hw_uuid_len, M_DEVBUF, M_NOWAIT);
+       sid = malloc(SID_LEN, M_TEMP, M_NOWAIT);
+       if (hw_uuid != NULL && sid != NULL &&
+           sxisid_read(EFUSE_OFFSET, SID_LEN, sid) == SID_LEN) {
+               for (i = 0; i < SID_LEN; i++) {
+                       snprintf(hw_uuid + (i * 2),
+                           hw_uuid_len - (i * 2),
+                           "%.2x", sid[i]);
+               }
+       }
+       free(sid, M_TEMP, SID_LEN);
+}
+
+uint32_t
+sxisid_read(bus_size_t offset, uint32_t size, uint8_t *out)
+{
+       struct sxisid_softc *sc = sxisid_sc;
+       uint32_t i, j, val;
+
+       if (sc == NULL) {
+               return 0;
+       }
+
+       mtx_enter(&sc->sc_mtx);
+       for (i = 0; i < size; i += 4) {
+
+               val = SID_PRCTL_OFFSET(offset - EFUSE_OFFSET + i) |
+                   SID_PRCTL_OP_LOCK | SID_PRCTL_READ;
+               HWRITE4(sc, SID_PRCTL, val);
+
+               while (HREAD4(sc, SID_PRCTL) & SID_PRCTL_READ) {
+                       continue;
+               }
+
+               val = HREAD4(sc, SID_RDKEY);
+               for (j = i; j < size; j++) {
+                       if (j - i == sizeof(val)) {
+                               break;
+                       }
+                       out[j] = val & 0xFF;
+                       val = val >> 8;
+               }
+       }
+       mtx_leave(&sc->sc_mtx);
+
+       return size;
+}
Index: sys/dev/fdt/sxitemp.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/sxitemp.c,v
retrieving revision 1.5
diff -u -p -r1.5 sxitemp.c
--- sys/dev/fdt/sxitemp.c       21 Sep 2019 15:36:57 -0000      1.5
+++ sys/dev/fdt/sxitemp.c       29 Sep 2019 19:07:15 -0000
@@ -19,6 +19,7 @@
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/sensors.h>
+#include <sys/malloc.h>
 
 #include <machine/intr.h>
 #include <machine/bus.h>
@@ -47,6 +48,7 @@
 #define THS0_DATA                      0x0080
 #define THS1_DATA                      0x0084
 #define THS2_DATA                      0x0088
+#define THS_CALIB0                     0x0074
 
 #define HREAD4(sc, reg)                                                        
\
        (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
@@ -79,12 +81,17 @@ struct cfdriver sxitemp_cd = {
        NULL, "sxitemp", DV_DULL
 };
 
+extern uint32_t sxisid_read(bus_size_t, uint32_t, uint8_t *);
+
 uint64_t sxitemp_h3_calc_temp(int64_t);
 uint64_t sxitemp_r40_calc_temp(int64_t);
 uint64_t sxitemp_a64_calc_temp(int64_t);
 uint64_t sxitemp_h5_calc_temp0(int64_t);
 uint64_t sxitemp_h5_calc_temp1(int64_t);
 void   sxitemp_refresh_sensors(void *);
+void   sxitemp_setup_calib(struct sxitemp_softc *, struct fdt_attach_args *);
+void   sxitemp_tx(struct sxitemp_softc *, uint32_t, uint32_t, uint32_t *);
+uint32_t sxitemp_calib_mask(uint32_t, uint32_t);
 int32_t sxitemp_get_temperature(void *, uint32_t *);
 
 int
@@ -144,6 +151,8 @@ sxitemp_attach(struct device *parent, st
                enable = THS_CTRL2_SENSE0_EN | THS_CTRL2_SENSE1_EN;
        }
 
+       sxitemp_setup_calib(sc, faa);
+
        /* Start data acquisition. */
        HWRITE4(sc, THS_FILTER, THS_FILTER_EN | THS_FILTER_TYPE(1));
        HWRITE4(sc, THS_INT_CTRL, THS_INT_CTRL_THERMAL_PER(800));
@@ -245,6 +254,76 @@ sxitemp_refresh_sensors(void *arg)
                sc->sc_sensors[2].value = sc->sc_calc_temp2(data) + 273150000;
                sc->sc_sensors[2].flags &= ~SENSOR_FINVALID;
        }
+}
+
+void
+sxitemp_setup_calib(struct sxitemp_softc *sc, struct fdt_attach_args *faa)
+{
+       int phandle, node, len;
+       uint32_t *reg, *calib, calib_len;
+
+       phandle = OF_getpropint(faa->fa_node, "nvmem-cells", 0);
+       if (phandle == 0) {
+               return;
+       }
+
+       node = OF_getnodebyphandle(phandle);
+       if (node == 0) {
+               return;
+       }
+
+       len = OF_getproplen(node, "reg");
+       if (len == 0) {
+               return;
+       }
+
+       reg = malloc(len, M_TEMP, M_NOWAIT);
+       if (reg == NULL) {
+               return;
+       }
+
+       if (OF_getpropintarray(node, "reg", reg, len) != len) {
+               free(reg, M_TEMP, len);
+               return;
+       }
+       calib_len = (((reg[1] + 7) / 8) * 8);
+       calib = malloc(calib_len, M_TEMP, M_NOWAIT);
+
+       if (calib != NULL) {
+               sxitemp_tx(sc, reg[0], reg[1], calib);
+       }
+
+       free(calib, M_TEMP, calib_len);
+       free(reg, M_TEMP, len);
+}
+
+void
+sxitemp_tx(struct sxitemp_softc *sc, uint32_t addr, uint32_t len, uint32_t 
*buff)
+{
+       uint32_t i, calib_mask, calib_val;
+
+       if (sxisid_read(addr, len, (uint8_t *) buff) != len) {
+               return;
+       }
+       for (i = 0; i < len; i += 4) {
+               calib_mask = sxitemp_calib_mask(len, i + 4);
+               calib_val = buff[i / 4] & calib_mask;
+               HWRITE4(sc, THS_CALIB0 + i, calib_val);
+       }
+}
+
+uint32_t
+sxitemp_calib_mask(uint32_t total_len, uint32_t sizeof_len)
+{
+       uint32_t i, calib_mask;
+       calib_mask = 0xffffffff;
+
+       if (total_len < sizeof_len) {
+               for (i = 0; i < sizeof_len - total_len; i++) {
+                       calib_mask = calib_mask >> 8;
+               }
+       }
+       return calib_mask;
 }
 
 int32_t

Reply via email to