1 /* $OpenBSD: hitemp.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */ 2 /* 3 * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/sensors.h> 22 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/fdt.h> 28 29 /* Registers */ 30 #define HI3660_OFFSET 0x040 31 #define HI3660_TEMP 0x01c 32 #define HI3660_TH 0x020 33 #define HI3660_LAG 0x028 34 #define HI3660_INT_EN 0x02c 35 #define HI3660_INT_CLR 0x030 36 37 #define HI3670_OFFSET 0x100 38 #define HI3670_INT_EN 0x064 39 40 #define HITEMP_NSENSORS 4 41 42 struct hitemp_softc { 43 struct device sc_dev; 44 bus_space_tag_t sc_iot; 45 bus_space_handle_t sc_ioh; 46 47 bus_size_t sc_offset; 48 uint64_t (*sc_calc_temp)(uint64_t); 49 50 struct ksensor sc_sensors[HITEMP_NSENSORS]; 51 struct ksensordev sc_sensordev; 52 }; 53 54 int hitemp_match(struct device *, void *, void *); 55 void hitemp_attach(struct device *, struct device *, void *); 56 57 const struct cfattach hitemp_ca = { 58 sizeof (struct hitemp_softc), hitemp_match, hitemp_attach 59 }; 60 61 struct cfdriver hitemp_cd = { 62 NULL, "hitemp", DV_DULL 63 }; 64 65 struct hitemp_compat { 66 const char *compat; 67 bus_size_t offset; 68 uint64_t (*calc_temp)(uint64_t); 69 }; 70 71 uint64_t hi3660_calc_temp(uint64_t); 72 uint64_t hi3670_calc_temp(uint64_t); 73 74 struct hitemp_compat hitemp_compat[] = { 75 { 76 "hsilicon,hi3660-tsensor", 77 HI3660_OFFSET, hi3660_calc_temp 78 }, 79 { 80 "hisilicon,kirin970-tsensor", 81 HI3670_OFFSET, hi3670_calc_temp 82 } 83 }; 84 85 void hitemp_refresh_sensors(void *); 86 87 int 88 hitemp_match(struct device *parent, void *match, void *aux) 89 { 90 struct fdt_attach_args *faa = aux; 91 int i; 92 93 for (i = 0; i < nitems(hitemp_compat); i++) { 94 if (OF_is_compatible(faa->fa_node, hitemp_compat[i].compat)) 95 return 1; 96 } 97 98 return 0; 99 } 100 101 void 102 hitemp_attach(struct device *parent, struct device *self, void *aux) 103 { 104 struct hitemp_softc *sc = (struct hitemp_softc *)self; 105 struct fdt_attach_args *faa = aux; 106 int i; 107 108 if (faa->fa_nreg < 1) { 109 printf(": no registers\n"); 110 return; 111 } 112 113 sc->sc_iot = faa->fa_iot; 114 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 115 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 116 printf(": can't map registers\n"); 117 return; 118 } 119 120 printf("\n"); 121 122 for (i = 0; i < nitems(hitemp_compat); i++) { 123 if (OF_is_compatible(faa->fa_node, hitemp_compat[i].compat)) { 124 break; 125 } 126 } 127 KASSERT(i < nitems(hitemp_compat)); 128 129 sc->sc_offset = hitemp_compat[i].offset; 130 sc->sc_calc_temp = hitemp_compat[i].calc_temp; 131 132 /* Register sensors. */ 133 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 134 sizeof(sc->sc_sensordev.xname)); 135 for (i = 0; i < HITEMP_NSENSORS; i++) { 136 sc->sc_sensors[i].type = SENSOR_TEMP; 137 sc->sc_sensors[i].flags = SENSOR_FINVALID; 138 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 139 } 140 sensordev_install(&sc->sc_sensordev); 141 sensor_task_register(sc, hitemp_refresh_sensors, 5); 142 } 143 144 uint64_t 145 hi3660_calc_temp(uint64_t value) 146 { 147 return 273150000 - 63780000 + value * 205000; 148 } 149 150 uint64_t 151 hi3670_calc_temp(uint64_t value) 152 { 153 return 273150000 - 73720000 + value * 216000; 154 } 155 156 void 157 hitemp_refresh_sensors(void *arg) 158 { 159 struct hitemp_softc *sc = arg; 160 bus_size_t offset = 0; 161 uint32_t value; 162 uint64_t temp; 163 int i; 164 165 for (i = 0; i < HITEMP_NSENSORS; i++) { 166 value = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 167 offset + HI3660_TEMP); 168 temp = sc->sc_calc_temp(value); 169 sc->sc_sensors[i].value = temp; 170 sc->sc_sensors[i].flags &= ~SENSOR_FINVALID; 171 offset += sc->sc_offset; 172 } 173 } 174