1/* $OpenBSD: w83795g.c,v 1.2 2022/04/06 18:59:28 naddy Exp $ */ 2 3/* 4 * Copyright (c) 2011 Mark Kettenis 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/param.h> 20#include <sys/systm.h> 21#include <sys/device.h> 22#include <sys/sensors.h> 23 24#include <dev/i2c/i2cvar.h> 25 26/* Nuvoton W83795G Hardware Monitor */ 27 28#define NVT_BANKSELECT 0x00 29#define NVT_CONFIG 0x01 30#define NVT_CONFIG_48 0x04 31#define NVT_VOLT_CTRL1 0x02 32#define NVT_VOLT_CTRL2 0x03 33#define NVT_TEMP_CTRL1 0x04 34#define NVT_TEMP_CTRL2 0x05 35#define NVT_FANIN_CTRL1 0x06 36#define NVT_FANIN_CTRL2 0x07 37#define NVT_VSEN1 0x10 38#define NVT_3VDD 0x1c 39#define NVT_3VSB 0x1d 40#define NVT_VBAT 0x1e 41#define NVT_TR5 0x1f 42#define NVT_TR6 0x20 43#define NVT_TD1 0x21 44#define NVT_TD2 0x22 45#define NVT_TD3 0x23 46#define NVT_TD4 0x24 47#define NVT_FANIN1_COUNT 0x2e 48#define NVT_VRLSB 0x3c 49 50/* Voltage */ 51#define NVT_NUM_VOLTS 15 52 53static const char *nvt_volt_desc[NVT_NUM_VOLTS] = { 54 "", "", "", "", "", "", "", "", "", "", "", 55 "VTT", "3VDD", "3VSB", "VBat" 56}; 57 58/* Temperature */ 59#define NVT_NUM_TEMPS 6 60#define NVT_NUM_TR 2 61#define NVT_NUM_TD 4 62 63/* Fan */ 64#define NVT_NUM_FANS 14 65 66#define NVT_NUM_SENSORS (NVT_NUM_VOLTS + NVT_NUM_TEMPS + NVT_NUM_FANS) 67 68struct nvt_softc { 69 struct device sc_dev; 70 i2c_tag_t sc_tag; 71 i2c_addr_t sc_addr; 72 73 uint16_t sc_vctrl; 74 uint16_t sc_tctrl1, sc_tctrl2; 75 uint16_t sc_fctrl; 76 77 struct ksensor sc_sensors[NVT_NUM_SENSORS]; 78 struct ksensordev sc_sensordev; 79}; 80 81 82int nvt_match(struct device *, void *, void *); 83void nvt_attach(struct device *, struct device *, void *); 84void nvt_refresh(void *); 85 86void nvt_refresh_volts(struct nvt_softc *); 87void nvt_refresh_temps(struct nvt_softc *); 88void nvt_refresh_fans(struct nvt_softc *); 89 90uint8_t nvt_readreg(struct nvt_softc *, uint8_t); 91void nvt_writereg(struct nvt_softc *, uint8_t, uint8_t); 92 93 94const struct cfattach nvt_ca = { 95 sizeof(struct nvt_softc), nvt_match, nvt_attach 96}; 97 98struct cfdriver nvt_cd = { 99 NULL, "nvt", DV_DULL 100}; 101 102 103int 104nvt_match(struct device *parent, void *match, void *aux) 105{ 106 struct i2c_attach_args *ia = aux; 107 108 if (strcmp(ia->ia_name, "w83795g") == 0) 109 return (1); 110 return (0); 111} 112 113void 114nvt_attach(struct device *parent, struct device *self, void *aux) 115{ 116 struct nvt_softc *sc = (struct nvt_softc *)self; 117 struct i2c_attach_args *ia = aux; 118 uint8_t cfg, vctrl1, vctrl2; 119 uint8_t tctrl1, tctrl2, fctrl1, fctrl2; 120 int i, j; 121 122 sc->sc_tag = ia->ia_tag; 123 sc->sc_addr = ia->ia_addr; 124 125 cfg = nvt_readreg(sc, NVT_CONFIG); 126 if (cfg & NVT_CONFIG_48) 127 printf(": W83795ADG"); 128 else 129 printf(": W83795G"); 130 131 vctrl1 = nvt_readreg(sc, NVT_VOLT_CTRL1); 132 vctrl2 = nvt_readreg(sc, NVT_VOLT_CTRL2); 133 tctrl1 = nvt_readreg(sc, NVT_TEMP_CTRL1); 134 tctrl2 = nvt_readreg(sc, NVT_TEMP_CTRL2); 135 fctrl1 = nvt_readreg(sc, NVT_FANIN_CTRL1); 136 fctrl2 = nvt_readreg(sc, NVT_FANIN_CTRL2); 137 138 sc->sc_vctrl = vctrl2 << 8 | vctrl1; 139 sc->sc_tctrl1 = tctrl1; 140 sc->sc_tctrl2 = tctrl2; 141 sc->sc_fctrl = fctrl2 << 8 | fctrl1; 142 143 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 144 sizeof(sc->sc_sensordev.xname)); 145 146 for (i = 0; i < NVT_NUM_VOLTS; i++) { 147 strlcpy(sc->sc_sensors[i].desc, nvt_volt_desc[i], 148 sizeof(sc->sc_sensors[i].desc)); 149 sc->sc_sensors[i].type = SENSOR_VOLTS_DC; 150 } 151 152 for (j = i + NVT_NUM_TEMPS; i < j; i++) 153 sc->sc_sensors[i].type = SENSOR_TEMP; 154 155 for (j = i + NVT_NUM_FANS; i < j; i++) 156 sc->sc_sensors[i].type = SENSOR_FANRPM; 157 158 for (i = 0; i < NVT_NUM_VOLTS + NVT_NUM_TEMPS + NVT_NUM_FANS; i++) 159 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 160 161 if (sensor_task_register(sc, nvt_refresh, 5) == NULL) { 162 printf(", unable to register update task\n"); 163 return; 164 } 165 166 sensordev_install(&sc->sc_sensordev); 167 printf("\n"); 168} 169 170void 171nvt_refresh(void *arg) 172{ 173 struct nvt_softc *sc = arg; 174 uint8_t bsr; 175 176 iic_acquire_bus(sc->sc_tag, 0); 177 178 bsr = nvt_readreg(sc, NVT_BANKSELECT); 179 if ((bsr & 0x07) != 0x00) 180 nvt_writereg(sc, NVT_BANKSELECT, bsr & 0xf8); 181 182 nvt_refresh_volts(sc); 183 nvt_refresh_temps(sc); 184 nvt_refresh_fans(sc); 185 186 if ((bsr & 0x07) != 0x00) 187 nvt_writereg(sc, NVT_BANKSELECT, bsr); 188 189 iic_release_bus(sc->sc_tag, 0); 190} 191 192void 193nvt_refresh_volts(struct nvt_softc *sc) 194{ 195 struct ksensor *s = &sc->sc_sensors[0]; 196 uint8_t vrlsb, data; 197 int i, reg; 198 199 for (i = 0; i < NVT_NUM_VOLTS; i++) { 200 if ((sc->sc_vctrl & (1 << i)) == 0) { 201 s[i].flags |= SENSOR_FINVALID; 202 s[i].value = 0; 203 continue; 204 } 205 206 reg = NVT_VSEN1 + i; 207 data = nvt_readreg(sc, reg); 208 vrlsb = nvt_readreg(sc, NVT_VRLSB); 209 if (reg != NVT_3VDD && reg != NVT_3VSB && reg != NVT_VBAT) 210 s[i].value = 10000000 - ((data << 3) | (vrlsb >> 6)) * 2000; 211 else 212 s[i].value = 10000000 - ((data << 3) | (vrlsb >> 6)) * 6000; 213 s[i].flags &= ~SENSOR_FINVALID; 214 } 215} 216 217void 218nvt_refresh_temps(struct nvt_softc *sc) 219{ 220 struct ksensor *s = &sc->sc_sensors[NVT_NUM_VOLTS]; 221 uint8_t vrlsb; 222 int8_t data; 223 int i; 224 225 for (i = 0; i < NVT_NUM_TEMPS; i++) { 226 if (i < NVT_NUM_TR 227 && (sc->sc_tctrl1 & (1 << (2 * i))) == 0) { 228 s[i].flags |= SENSOR_FINVALID; 229 s[i].value = 0; 230 continue; 231 } 232 233 if (i >= NVT_NUM_TR 234 && (sc->sc_tctrl2 & (1 << (2 * (i - NVT_NUM_TR)))) == 0) { 235 s[i].flags |= SENSOR_FINVALID; 236 s[i].value = 0; 237 continue; 238 } 239 240 data = nvt_readreg(sc, NVT_TR5 + i); 241 vrlsb = nvt_readreg(sc, NVT_VRLSB); 242 if (data == -128 && (vrlsb >> 6) == 0) { 243 s[i].flags |= SENSOR_FINVALID; 244 s[i].value = 0; 245 continue; 246 } 247 s[i].value = data * 1000000 + (vrlsb >> 6) * 250000; 248 s[i].value += 273150000; 249 s[i].flags &= ~SENSOR_FINVALID; 250 } 251} 252 253void 254nvt_refresh_fans(struct nvt_softc *sc) 255{ 256 struct ksensor *s = &sc->sc_sensors[NVT_NUM_VOLTS + NVT_NUM_TEMPS]; 257 uint8_t data, vrlsb; 258 uint16_t count; 259 int i; 260 261 for (i = 0; i < NVT_NUM_FANS; i++) { 262 if ((sc->sc_fctrl & (1 << i)) == 0) { 263 s[i].flags |= SENSOR_FINVALID; 264 s[i].value = 0; 265 continue; 266 } 267 268 data = nvt_readreg(sc, NVT_FANIN1_COUNT + i); 269 vrlsb = nvt_readreg(sc, NVT_VRLSB); 270 count = (data << 4) + (vrlsb >> 4); 271 if (count == 0) { 272 s[i].flags |= SENSOR_FINVALID; 273 s[i].value = 0; 274 continue; 275 } 276 s[i].value = 1350000 / (count * 2); 277 s[i].flags &= ~SENSOR_FINVALID; 278 } 279} 280 281uint8_t 282nvt_readreg(struct nvt_softc *sc, uint8_t reg) 283{ 284 uint8_t data; 285 286 iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 287 sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); 288 289 return data; 290} 291 292void 293nvt_writereg(struct nvt_softc *sc, uint8_t reg, uint8_t data) 294{ 295 iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 296 sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); 297} 298