-/* $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>
*
#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;
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 *);
{
"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 },
},
};
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");
}
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;
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
{
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
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)