diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2023-04-18 08:35:03 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2023-04-18 08:35:03 +0000 |
commit | d194c380a8e26f00a8b96d4cafc186fe72124a77 (patch) | |
tree | 458dcd7569fc8386a485fd7c2fd63f1b7b37a065 /sys/dev | |
parent | bb3ef9f7c8d0cbbcd44d19b91dff690afd317c7e (diff) |
Support upstreamed AP806/CP110 bindings in mvtemp(4). Apparently older EDK2
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@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/fdt/mvtemp.c | 142 |
1 files changed, 114 insertions, 28 deletions
diff --git a/sys/dev/fdt/mvtemp.c b/sys/dev/fdt/mvtemp.c index 1cb95d1a0bf..1ee2b967dbf 100644 --- a/sys/dev/fdt/mvtemp.c +++ b/sys/dev/fdt/mvtemp.c @@ -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 */ @@ -31,17 +32,32 @@ #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) |