Support upstreamed AP806/CP110 bindings in mvtemp(4). Apparently older EDK2
authorpatrick <patrick@openbsd.org>
Tue, 18 Apr 2023 08:35:02 +0000 (08:35 +0000)
committerpatrick <patrick@openbsd.org>
Tue, 18 Apr 2023 08:35:02 +0000 (08:35 +0000)
versions shipped bindings compatible with the Armada 380, but when the ARM64
SoCs were upstreamed from the vendor fork to Linux, those apparently were
adjusted.

With this diff mvtemp(4) now tries and use the parent as syscon regmap in case
the legacy binding cannot be used.  Furthermore this adds some initialization
as apparently the new EDK2 does less of that work during bootup.

Noticed by mbuhl@ who's running an updated EDK2 on the MACCHIATObin.
ok kettenis@

sys/dev/fdt/mvtemp.c

index 1cb95d1..1ee2b96 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mvtemp.c,v 1.4 2023/03/12 10:46:27 jmatthew Exp $     */
+/*     $OpenBSD: mvtemp.c,v 1.5 2023/04/18 08:35:02 patrick Exp $      */
 /*
  * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -24,6 +24,7 @@
 #include <machine/fdt.h>
 
 #include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_misc.h>
 #include <dev/ofw/fdt.h>
 
 /* Registers */
 #define TEMP_CTRL0                     0x0000
 #define  TEMP_CTRL0_TSEN_TC_TRIM_MASK  0x7
 #define  TEMP_CTRL0_TSEN_TC_TRIM_VAL   0x3
+#define  TEMP_CTRL0_TSEN_START         (1 << 0)
+#define  TEMP_CTRL0_TSEN_RESET         (1 << 1)
+#define  TEMP_CTRL0_TSEN_ENABLE                (1 << 2)
+#define  TEMP_CTRL0_TSEN_AVG_BYPASS    (1 << 6)
+#define  TEMP_CTRL0_TSEN_OSR_MAX       (0x3 << 24)
 #define TEMP_CTRL1                     0x0004
-#define  TEMP_CTRL1_TSEN_RESET         (1 << 8)
+#define  TMEP_CTRL1_TSEN_START         (1 << 0)
+#define  TEMP_CTRL1_TSEN_SW_RESET      (1 << 7)
+#define  TEMP_CTRL1_TSEN_HW_RESETN     (1 << 8)
+#define  TEMP_CTRL1_TSEN_AVG_MASK      0x7
+
+#define REG_CTRL0                      0
+#define REG_CTRL1                      1
+#define REG_STAT                       2
+#define REG_MAX                                3
 
 struct mvtemp_softc {
        struct device           sc_dev;
        bus_space_tag_t         sc_iot;
        bus_space_handle_t      sc_stat_ioh;
        bus_space_handle_t      sc_ctrl_ioh;
+       struct regmap           *sc_rm;
 
        uint32_t                sc_stat_valid;
        int32_t                 (*sc_calc_temp)(uint32_t);
+       bus_size_t              sc_offs[REG_MAX];
 
        struct ksensor          sc_sensor;
        struct ksensordev       sc_sensordev;
@@ -63,8 +79,10 @@ struct mvtemp_compat {
        uint32_t stat_valid;
        void    (*init)(struct mvtemp_softc *);
        int32_t (*calc_temp)(uint32_t);
+       bus_size_t offs[REG_MAX];
 };
 
+void   mvtemp_380_init(struct mvtemp_softc *);
 void   mvtemp_ap806_init(struct mvtemp_softc *);
 int32_t mvtemp_ap806_calc_temp(uint32_t);
 void   mvtemp_cp110_init(struct mvtemp_softc *);
@@ -74,14 +92,17 @@ const struct mvtemp_compat mvtemp_compat[] = {
        {
                "marvell,armada-ap806-thermal", (1 << 16),
                mvtemp_ap806_init, mvtemp_ap806_calc_temp,
+               { 0x84, 0x88, 0x8c },
        },
        {
                "marvell,armada-cp110-thermal", (1 << 10),
                mvtemp_cp110_init, mvtemp_cp110_calc_temp,
+               { 0x70, 0x74, 0x78 },
        },
        {
                "marvell,armada380-thermal", (1 << 10),
-               mvtemp_cp110_init, mvtemp_cp110_calc_temp,
+               mvtemp_380_init, mvtemp_cp110_calc_temp,
+               { 0x70, 0x74, 0x78 },
        },
 };
 
@@ -108,23 +129,26 @@ mvtemp_attach(struct device *parent, struct device *self, void *aux)
        struct fdt_attach_args *faa = aux;
        int i;
 
-       if (faa->fa_nreg < 2) {
-               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_stat_ioh)) {
-               printf(": can't map registers\n");
-               return;
-       }
-       if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
-           faa->fa_reg[1].size, 0, &sc->sc_ctrl_ioh)) {
-               bus_space_unmap(sc->sc_iot, sc->sc_stat_ioh,
-                   faa->fa_reg[0].size);
-               printf(": can't map registers\n");
-               return;
+       if (faa->fa_nreg >= 2) {
+               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_stat_ioh)) {
+                       printf(": can't map registers\n");
+                       return;
+               }
+               if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
+                   faa->fa_reg[1].size, 0, &sc->sc_ctrl_ioh)) {
+                       bus_space_unmap(sc->sc_iot, sc->sc_stat_ioh,
+                           faa->fa_reg[0].size);
+                       printf(": can't map registers\n");
+                       return;
+               }
+       } else {
+               sc->sc_rm = regmap_bynode(OF_parent(faa->fa_node));
+               if (sc->sc_rm == NULL) {
+                       printf(": no registers\n");
+                       return;
+               }
        }
 
        printf("\n");
@@ -136,6 +160,18 @@ mvtemp_attach(struct device *parent, struct device *self, void *aux)
        }
        KASSERT(i < nitems(mvtemp_compat));
 
+       /* Legacy offsets */
+       sc->sc_offs[REG_CTRL0] = TEMP_CTRL0;
+       sc->sc_offs[REG_CTRL1] = TEMP_CTRL1;
+       sc->sc_offs[REG_STAT] = TEMP_STAT;
+
+       /* Syscon offsets */
+       if (sc->sc_rm != NULL) {
+               sc->sc_offs[REG_CTRL0] = mvtemp_compat[i].offs[REG_CTRL0];
+               sc->sc_offs[REG_CTRL1] = mvtemp_compat[i].offs[REG_CTRL1];
+               sc->sc_offs[REG_STAT] = mvtemp_compat[i].offs[REG_STAT];
+       }
+
        mvtemp_compat[i].init(sc);
        sc->sc_stat_valid = mvtemp_compat[i].stat_valid;
        sc->sc_calc_temp = mvtemp_compat[i].calc_temp;
@@ -150,11 +186,59 @@ mvtemp_attach(struct device *parent, struct device *self, void *aux)
        sensor_task_register(sc, mvtemp_refresh_sensors, 5);
 }
 
+uint32_t
+mvtemp_read(struct mvtemp_softc *sc, int reg)
+{
+       if (sc->sc_rm != NULL)
+               return regmap_read_4(sc->sc_rm, sc->sc_offs[reg]);
+       else if (reg == REG_STAT)
+               return bus_space_read_4(sc->sc_iot, sc->sc_stat_ioh, sc->sc_offs[reg]);
+       else
+               return bus_space_read_4(sc->sc_iot, sc->sc_ctrl_ioh, sc->sc_offs[reg]);
+}
+
+void
+mvtemp_write(struct mvtemp_softc *sc, int reg, uint32_t val)
+{
+       if (sc->sc_rm != NULL)
+               regmap_write_4(sc->sc_rm, sc->sc_offs[reg], val);
+       else if (reg == REG_STAT)
+               bus_space_write_4(sc->sc_iot, sc->sc_stat_ioh, sc->sc_offs[reg], val);
+       else
+               bus_space_write_4(sc->sc_iot, sc->sc_ctrl_ioh, sc->sc_offs[reg], val);
+}
+
+/* 380 */
+
+void
+mvtemp_380_init(struct mvtemp_softc *sc)
+{
+       uint32_t ctrl;
+
+       ctrl = mvtemp_read(sc, REG_CTRL1);
+       ctrl |= TEMP_CTRL1_TSEN_HW_RESETN;
+       ctrl &= ~TEMP_CTRL1_TSEN_SW_RESET;
+       mvtemp_write(sc, REG_CTRL1, ctrl);
+
+       ctrl = mvtemp_read(sc, REG_CTRL0);
+       ctrl &= ~TEMP_CTRL0_TSEN_TC_TRIM_MASK;
+       ctrl |= TEMP_CTRL0_TSEN_TC_TRIM_VAL;
+       mvtemp_write(sc, REG_CTRL0, ctrl);
+}
+
 /* AP806 */
 
 void
 mvtemp_ap806_init(struct mvtemp_softc *sc)
 {
+       uint32_t ctrl;
+
+       ctrl = mvtemp_read(sc, REG_CTRL0);
+       ctrl &= ~TEMP_CTRL0_TSEN_RESET;
+       ctrl |= TEMP_CTRL0_TSEN_START | TEMP_CTRL0_TSEN_ENABLE;
+       ctrl |= TEMP_CTRL0_TSEN_OSR_MAX;
+       ctrl &= ~TEMP_CTRL0_TSEN_AVG_BYPASS;
+       mvtemp_write(sc, REG_CTRL0, ctrl);
 }
 
 int32_t
@@ -171,14 +255,16 @@ mvtemp_cp110_init(struct mvtemp_softc *sc)
 {
        uint32_t ctrl;
 
-       ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ctrl_ioh, TEMP_CTRL1);
-       ctrl |= TEMP_CTRL1_TSEN_RESET;
-       bus_space_write_4(sc->sc_iot, sc->sc_ctrl_ioh, TEMP_CTRL1, ctrl);
+       mvtemp_380_init(sc);
 
-       ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ctrl_ioh, TEMP_CTRL0);
-       ctrl &= ~TEMP_CTRL0_TSEN_TC_TRIM_MASK;
-       ctrl |= TEMP_CTRL0_TSEN_TC_TRIM_VAL;
-       bus_space_write_4(sc->sc_iot, sc->sc_ctrl_ioh, TEMP_CTRL0, ctrl);
+       ctrl = mvtemp_read(sc, REG_CTRL0);
+       ctrl |= TEMP_CTRL0_TSEN_OSR_MAX;
+       mvtemp_write(sc, REG_CTRL0, ctrl);
+
+       ctrl = mvtemp_read(sc, REG_CTRL1);
+       ctrl |= TMEP_CTRL1_TSEN_START;
+       ctrl &= ~TEMP_CTRL1_TSEN_AVG_MASK;
+       mvtemp_write(sc, REG_CTRL1, ctrl);
 }
 
 int32_t
@@ -193,7 +279,7 @@ mvtemp_refresh_sensors(void *arg)
        struct mvtemp_softc *sc = arg;
        int32_t stat, temp;
 
-       stat = bus_space_read_4(sc->sc_iot, sc->sc_stat_ioh, TEMP_STAT);
+       stat = mvtemp_read(sc, REG_STAT);
        temp = sc->sc_calc_temp(stat);
        sc->sc_sensor.value = temp;
        if ((stat & sc->sc_stat_valid) && temp >= 0)