1 /* $OpenBSD: w83795g.c,v 1.1 2011/07/03 21:30:20 kettenis 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 53 static 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 68 struct 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 82 int nvt_match(struct device *, void *, void *); 83 void nvt_attach(struct device *, struct device *, void *); 84 void nvt_refresh(void *); 85 86 void nvt_refresh_volts(struct nvt_softc *); 87 void nvt_refresh_temps(struct nvt_softc *); 88 void nvt_refresh_fans(struct nvt_softc *); 89 90 uint8_t nvt_readreg(struct nvt_softc *, uint8_t); 91 void nvt_writereg(struct nvt_softc *, uint8_t, uint8_t); 92 93 94 struct cfattach nvt_ca = { 95 sizeof(struct nvt_softc), nvt_match, nvt_attach 96 }; 97 98 struct cfdriver nvt_cd = { 99 NULL, "nvt", DV_DULL 100 }; 101 102 103 int 104 nvt_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 113 void 114 nvt_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 170 void 171 nvt_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 192 void 193 nvt_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 217 void 218 nvt_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 253 void 254 nvt_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 281 uint8_t 282 nvt_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 292 void 293 nvt_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