| File: | dev/i2c/asc7611.c |
| Warning: | line 158, column 2 Value stored to 's' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: asc7611.c,v 1.3 2022/04/06 18:59:28 naddy Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 2008 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> |
| 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 | /* |
| 27 | * Andigilog aSC7611 |
| 28 | * Hardware Monitor with Integrated Fan Control |
| 29 | * http://www.andigilog.com/downloads/aSC7611_70A05007.pdf |
| 30 | * October 2006 |
| 31 | */ |
| 32 | |
| 33 | /* Temperature */ |
| 34 | #define ANDL_NUM_TEMPS3 3 |
| 35 | static const struct { |
| 36 | const char *name; |
| 37 | const uint8_t mreg; |
| 38 | const uint8_t lreg; |
| 39 | } andl_temp[ANDL_NUM_TEMPS3] = { |
| 40 | { "External", 0x25, 0x10 }, |
| 41 | { "Internal", 0x26, 0x15 }, |
| 42 | { "External", 0x27, 0x0e } |
| 43 | }; |
| 44 | |
| 45 | /* Voltage */ |
| 46 | #define ANDL_NUM_VOLTS5 5 |
| 47 | static const struct { |
| 48 | const char *name; |
| 49 | const short nominal; |
| 50 | const uint8_t mreg; |
| 51 | } andl_volt[ANDL_NUM_VOLTS5] = { |
| 52 | { "+2.5V", 2500, 0x20 }, |
| 53 | { "Vccp", 2250, 0x21 }, |
| 54 | { "+3.3V", 3300, 0x22 }, |
| 55 | { "+5V", 5000, 0x23 }, |
| 56 | { "+12V", 12000, 0x24 } |
| 57 | }; |
| 58 | |
| 59 | /* Fan */ |
| 60 | #define ANDL_NUM_TACHS4 4 |
| 61 | #define ANDL_TACH_START0x28 0x28 |
| 62 | |
| 63 | #define ANDL_NUM_TOTAL(3 + 5 + 4) (ANDL_NUM_TEMPS3 + ANDL_NUM_VOLTS5 + ANDL_NUM_TACHS4) |
| 64 | |
| 65 | struct andl_softc { |
| 66 | struct device sc_dev; |
| 67 | i2c_tag_t sc_tag; |
| 68 | i2c_addr_t sc_addr; |
| 69 | |
| 70 | struct ksensor sc_sensors[ANDL_NUM_TOTAL(3 + 5 + 4)]; |
| 71 | struct ksensordev sc_sensordev; |
| 72 | }; |
| 73 | |
| 74 | |
| 75 | int andl_match(struct device *, void *, void *); |
| 76 | void andl_attach(struct device *, struct device *, void *); |
| 77 | void andl_refresh(void *); |
| 78 | |
| 79 | int andl_refresh_temps(struct andl_softc *, struct ksensor *); |
| 80 | int andl_refresh_volts(struct andl_softc *, struct ksensor *); |
| 81 | int andl_refresh_tachs(struct andl_softc *, struct ksensor *); |
| 82 | |
| 83 | uint8_t andl_readreg(struct andl_softc *, uint8_t); |
| 84 | void andl_writereg(struct andl_softc *, uint8_t, uint8_t); |
| 85 | |
| 86 | |
| 87 | const struct cfattach andl_ca = { |
| 88 | sizeof(struct andl_softc), andl_match, andl_attach |
| 89 | }; |
| 90 | |
| 91 | struct cfdriver andl_cd = { |
| 92 | NULL((void *)0), "andl", DV_DULL |
| 93 | }; |
| 94 | |
| 95 | |
| 96 | int |
| 97 | andl_match(struct device *parent, void *match, void *aux) |
| 98 | { |
| 99 | struct i2c_attach_args *ia = aux; |
| 100 | |
| 101 | if (strcmp(ia->ia_name, "asc7611") == 0) |
| 102 | return 1; |
| 103 | return 0; |
| 104 | } |
| 105 | |
| 106 | void |
| 107 | andl_attach(struct device *parent, struct device *self, void *aux) |
| 108 | { |
| 109 | struct andl_softc *sc = (struct andl_softc *)self; |
| 110 | struct i2c_attach_args *ia = aux; |
| 111 | int i, j; |
| 112 | |
| 113 | sc->sc_tag = ia->ia_tag; |
| 114 | sc->sc_addr = ia->ia_addr; |
| 115 | |
| 116 | printf(": %s", ia->ia_name); |
| 117 | |
| 118 | strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, |
| 119 | sizeof(sc->sc_sensordev.xname)); |
| 120 | |
| 121 | for (i = 0; i < ANDL_NUM_TEMPS3; i++) { |
| 122 | strlcpy(sc->sc_sensors[i].desc, andl_temp[i].name, |
| 123 | sizeof(sc->sc_sensors[i].desc)); |
| 124 | sc->sc_sensors[i].type = SENSOR_TEMP; |
| 125 | } |
| 126 | |
| 127 | for (j = i; i < j + ANDL_NUM_VOLTS5; i++) { |
| 128 | strlcpy(sc->sc_sensors[i].desc, andl_volt[i - j].name, |
| 129 | sizeof(sc->sc_sensors[i].desc)); |
| 130 | sc->sc_sensors[i].type = SENSOR_VOLTS_DC; |
| 131 | } |
| 132 | |
| 133 | for (j = i + ANDL_NUM_TACHS4; i < j; i++) |
| 134 | sc->sc_sensors[i].type = SENSOR_FANRPM; |
| 135 | |
| 136 | for (i = 0; i < j; i++) |
| 137 | sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); |
| 138 | |
| 139 | if (sensor_task_register(sc, andl_refresh, 5) == NULL((void *)0)) { |
| 140 | printf(", unable to register update task\n"); |
| 141 | return; |
| 142 | } |
| 143 | |
| 144 | sensordev_install(&sc->sc_sensordev); |
| 145 | printf("\n"); |
| 146 | } |
| 147 | |
| 148 | void |
| 149 | andl_refresh(void *arg) |
| 150 | { |
| 151 | struct andl_softc *sc = arg; |
| 152 | struct ksensor *s = sc->sc_sensors; |
| 153 | |
| 154 | iic_acquire_bus(sc->sc_tag, 0)(*(sc->sc_tag)->ic_acquire_bus)((sc->sc_tag)->ic_cookie , (0)); |
| 155 | |
| 156 | s += andl_refresh_temps(sc, s); |
| 157 | s += andl_refresh_volts(sc, s); |
| 158 | s += andl_refresh_tachs(sc, s); |
Value stored to 's' is never read | |
| 159 | |
| 160 | iic_release_bus(sc->sc_tag, 0)(*(sc->sc_tag)->ic_release_bus)((sc->sc_tag)->ic_cookie , (0)); |
| 161 | } |
| 162 | |
| 163 | int |
| 164 | andl_refresh_temps(struct andl_softc *sc, struct ksensor *s) |
| 165 | { |
| 166 | int i; |
| 167 | |
| 168 | for (i = 0; i < ANDL_NUM_TEMPS3; i++) { |
| 169 | uint8_t m = andl_readreg(sc, andl_temp[i].mreg); |
| 170 | uint8_t l = andl_readreg(sc, andl_temp[i].lreg); |
| 171 | int32_t t = (m << 8 | l) >> (16 - 10); |
| 172 | |
| 173 | if (t & 0x200) |
| 174 | t -= 0x400; |
| 175 | t *= 250; |
| 176 | if (t < -55000 || t > 125000) { |
| 177 | s[i].flags |= SENSOR_FINVALID0x0001; |
| 178 | s[i].value = 0; |
| 179 | } else { |
| 180 | s[i].value = t * 1000 + 273150000; |
| 181 | s[i].flags &= ~SENSOR_FINVALID0x0001; |
| 182 | } |
| 183 | } |
| 184 | return i; |
| 185 | } |
| 186 | |
| 187 | int |
| 188 | andl_refresh_volts(struct andl_softc *sc, struct ksensor *s) |
| 189 | { |
| 190 | int i; |
| 191 | |
| 192 | for (i = 0; i < ANDL_NUM_VOLTS5; i++) |
| 193 | s[i].value = 1000ll * andl_readreg(sc, andl_volt[i].mreg) * |
| 194 | andl_volt[i].nominal / 0xc0; |
| 195 | return i; |
| 196 | } |
| 197 | |
| 198 | int |
| 199 | andl_refresh_tachs(struct andl_softc *sc, struct ksensor *s) |
| 200 | { |
| 201 | int i; |
| 202 | |
| 203 | for (i = 0; i < ANDL_NUM_TACHS4; i++) { |
| 204 | uint8_t l = andl_readreg(sc, ANDL_TACH_START0x28 + i * 2); |
| 205 | uint8_t m = andl_readreg(sc, ANDL_TACH_START0x28 + i * 2 + 1); |
| 206 | uint16_t b = m << 8 | l; |
| 207 | |
| 208 | if (b >= 0xfffc || b == 0) { |
| 209 | s[i].flags |= SENSOR_FINVALID0x0001; |
| 210 | s[i].value = 0; |
| 211 | } else { |
| 212 | s[i].value = (90000 * 60) / b; |
| 213 | s[i].flags &= ~SENSOR_FINVALID0x0001; |
| 214 | } |
| 215 | } |
| 216 | return i; |
| 217 | } |
| 218 | |
| 219 | uint8_t |
| 220 | andl_readreg(struct andl_softc *sc, uint8_t reg) |
| 221 | { |
| 222 | uint8_t data; |
| 223 | |
| 224 | iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, |
| 225 | sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); |
| 226 | |
| 227 | return data; |
| 228 | } |
| 229 | |
| 230 | void |
| 231 | andl_writereg(struct andl_softc *sc, uint8_t reg, uint8_t data) |
| 232 | { |
| 233 | iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, |
| 234 | sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); |
| 235 | } |