1 /* $OpenBSD: adm1025.c,v 1.25 2007/06/24 05:34:35 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Theo de Raadt 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 /* ADM 1025 registers */ 27 #define ADM1025_V2_5 0x20 28 #define ADM1025_Vccp 0x21 29 #define ADM1025_V3_3 0x22 30 #define ADM1025_V5 0x23 31 #define ADM1025_V12 0x24 32 #define ADM1025_Vcc 0x25 33 #define ADM1025_EXT_TEMP 0x26 34 #define ADM1025_INT_TEMP 0x27 35 #define ADM1025_STATUS2 0x42 36 #define ADM1025_STATUS2_EXT 0x40 37 #define ADM1025_COMPANY 0x3e /* contains 0x41 */ 38 #define ADM1025_STEPPING 0x3f /* contains 0x2? */ 39 #define ADM1025_CONFIG 0x40 40 #define ADM1025_CONFIG_START 0x01 41 #define SMSC47M192_V1_5 0x50 42 #define SMSC47M192_V1_8 0x51 43 #define SMSC47M192_TEMP2 0x52 44 45 /* Sensors */ 46 #define ADMTM_INT 0 47 #define ADMTM_EXT 1 48 #define ADMTM_V2_5 2 49 #define ADMTM_Vccp 3 50 #define ADMTM_V3_3 4 51 #define ADMTM_V5 5 52 #define ADMTM_V12 6 53 #define ADMTM_Vcc 7 54 #define ADMTM_NUM_SENSORS 8 55 #define SMSC_V1_5 8 56 #define SMSC_V1_8 9 57 #define SMSC_TEMP2 10 58 #define SMSC_NUM_SENSORS 3 59 struct admtm_softc { 60 struct device sc_dev; 61 i2c_tag_t sc_tag; 62 i2c_addr_t sc_addr; 63 64 struct ksensor sc_sensor[ADMTM_NUM_SENSORS + SMSC_NUM_SENSORS]; 65 struct ksensordev sc_sensordev; 66 int sc_nsensors; 67 int sc_model; 68 }; 69 70 int admtm_match(struct device *, void *, void *); 71 void admtm_attach(struct device *, struct device *, void *); 72 void admtm_refresh(void *); 73 74 struct cfattach admtm_ca = { 75 sizeof(struct admtm_softc), admtm_match, admtm_attach 76 }; 77 78 struct cfdriver admtm_cd = { 79 NULL, "admtm", DV_DULL 80 }; 81 82 int 83 admtm_match(struct device *parent, void *match, void *aux) 84 { 85 struct i2c_attach_args *ia = aux; 86 87 if (strcmp(ia->ia_name, "adm1025") == 0 || 88 strcmp(ia->ia_name, "47m192") == 0 || 89 strcmp(ia->ia_name, "ne1619") == 0) 90 return (1); 91 return (0); 92 } 93 94 void 95 admtm_attach(struct device *parent, struct device *self, void *aux) 96 { 97 struct admtm_softc *sc = (struct admtm_softc *)self; 98 struct i2c_attach_args *ia = aux; 99 u_int8_t cmd, data, data2; 100 int i; 101 102 sc->sc_tag = ia->ia_tag; 103 sc->sc_addr = ia->ia_addr; 104 105 printf(": %s", ia->ia_name); 106 107 sc->sc_nsensors = ADMTM_NUM_SENSORS; 108 sc->sc_model = 1025; 109 if (strcmp(ia->ia_name, "47m192") == 0) { 110 sc->sc_nsensors += SMSC_NUM_SENSORS; 111 sc->sc_model = 192; 112 } 113 114 iic_acquire_bus(sc->sc_tag, 0); 115 cmd = ADM1025_CONFIG; 116 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 117 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 118 iic_release_bus(sc->sc_tag, 0); 119 printf(", cannot get control register\n"); 120 return; 121 } 122 123 data2 = data | ADM1025_CONFIG_START; 124 if (data != data2) { 125 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 126 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) { 127 iic_release_bus(sc->sc_tag, 0); 128 printf(", cannot set control register\n"); 129 return; 130 } 131 } 132 iic_release_bus(sc->sc_tag, 0); 133 134 /* Initialize sensor data. */ 135 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 136 sizeof(sc->sc_sensordev.xname)); 137 138 sc->sc_sensor[ADMTM_INT].type = SENSOR_TEMP; 139 strlcpy(sc->sc_sensor[ADMTM_INT].desc, "Internal", 140 sizeof(sc->sc_sensor[ADMTM_INT].desc)); 141 142 sc->sc_sensor[ADMTM_EXT].type = SENSOR_TEMP; 143 strlcpy(sc->sc_sensor[ADMTM_EXT].desc, "External", 144 sizeof(sc->sc_sensor[ADMTM_EXT].desc)); 145 146 sc->sc_sensor[ADMTM_V2_5].type = SENSOR_VOLTS_DC; 147 strlcpy(sc->sc_sensor[ADMTM_V2_5].desc, "2.5 V", 148 sizeof(sc->sc_sensor[ADMTM_V2_5].desc)); 149 150 sc->sc_sensor[ADMTM_Vccp].type = SENSOR_VOLTS_DC; 151 strlcpy(sc->sc_sensor[ADMTM_Vccp].desc, "Vccp", 152 sizeof(sc->sc_sensor[ADMTM_Vccp].desc)); 153 154 sc->sc_sensor[ADMTM_V3_3].type = SENSOR_VOLTS_DC; 155 strlcpy(sc->sc_sensor[ADMTM_V3_3].desc, "3.3 V", 156 sizeof(sc->sc_sensor[ADMTM_V3_3].desc)); 157 158 sc->sc_sensor[ADMTM_V5].type = SENSOR_VOLTS_DC; 159 strlcpy(sc->sc_sensor[ADMTM_V5].desc, "5 V", 160 sizeof(sc->sc_sensor[ADMTM_V5].desc)); 161 162 sc->sc_sensor[ADMTM_V12].type = SENSOR_VOLTS_DC; 163 strlcpy(sc->sc_sensor[ADMTM_V12].desc, "12 V", 164 sizeof(sc->sc_sensor[ADMTM_V12].desc)); 165 166 sc->sc_sensor[ADMTM_Vcc].type = SENSOR_VOLTS_DC; 167 strlcpy(sc->sc_sensor[ADMTM_Vcc].desc, "Vcc", 168 sizeof(sc->sc_sensor[ADMTM_Vcc].desc)); 169 170 sc->sc_sensor[SMSC_V1_5].type = SENSOR_VOLTS_DC; 171 strlcpy(sc->sc_sensor[SMSC_V1_5].desc, "1.5 V", 172 sizeof(sc->sc_sensor[SMSC_V1_5].desc)); 173 174 sc->sc_sensor[SMSC_V1_8].type = SENSOR_VOLTS_DC; 175 strlcpy(sc->sc_sensor[SMSC_V1_8].desc, "1.8 V", 176 sizeof(sc->sc_sensor[SMSC_V1_8].desc)); 177 178 sc->sc_sensor[SMSC_TEMP2].type = SENSOR_TEMP; 179 strlcpy(sc->sc_sensor[SMSC_TEMP2].desc, "External", 180 sizeof(sc->sc_sensor[SMSC_TEMP2].desc)); 181 182 if (sensor_task_register(sc, admtm_refresh, 5) == NULL) { 183 printf(", unable to register update task\n"); 184 return; 185 } 186 187 for (i = 0; i < sc->sc_nsensors; i++) 188 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); 189 sensordev_install(&sc->sc_sensordev); 190 191 printf("\n"); 192 } 193 194 void 195 admtm_refresh(void *arg) 196 { 197 struct admtm_softc *sc = arg; 198 u_int8_t cmd, data; 199 int8_t sdata; 200 201 iic_acquire_bus(sc->sc_tag, 0); 202 203 cmd = ADM1025_INT_TEMP; 204 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 205 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 206 sc->sc_sensor[ADMTM_INT].value = 273150000 + 1000000 * sdata; 207 208 cmd = ADM1025_EXT_TEMP; 209 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 210 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 211 sc->sc_sensor[ADMTM_EXT].value = 273150000 + 1000000 * sdata; 212 213 cmd = ADM1025_STATUS2; 214 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 215 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { 216 if (data & ADM1025_STATUS2_EXT) 217 sc->sc_sensor[ADMTM_EXT].flags |= SENSOR_FINVALID; 218 else 219 sc->sc_sensor[ADMTM_EXT].flags &= ~SENSOR_FINVALID; 220 } 221 222 cmd = ADM1025_V2_5; 223 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 224 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 225 sc->sc_sensor[ADMTM_V2_5].value = 2500000 * data / 192; 226 227 cmd = ADM1025_Vccp; 228 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 229 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 230 sc->sc_sensor[ADMTM_Vcc].value = 2249000 * data / 192; 231 232 cmd = ADM1025_V3_3; 233 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 234 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 235 sc->sc_sensor[ADMTM_V3_3].value = 3300000 * data / 192; 236 237 cmd = ADM1025_V5; 238 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 239 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 240 sc->sc_sensor[ADMTM_V5].value = 5000000 * data / 192; 241 242 cmd = ADM1025_V12; 243 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 244 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 245 sc->sc_sensor[ADMTM_V12].value = 12000000 * data / 192; 246 247 cmd = ADM1025_Vcc; 248 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 249 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 250 sc->sc_sensor[ADMTM_Vcc].value = 3300000 * data / 192; 251 252 if (sc->sc_model == 192) { 253 cmd = SMSC47M192_V1_5; 254 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 255 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 256 sc->sc_sensor[SMSC_V1_5].value = 1500000 * data / 192; 257 258 cmd = SMSC47M192_V1_8; 259 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 260 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 261 sc->sc_sensor[SMSC_V1_8].value = 1800000 * data / 192; 262 263 cmd = SMSC47M192_TEMP2; 264 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 265 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 266 0) == 0) 267 sc->sc_sensor[SMSC_TEMP2].value = 273150000 + 1000000 * sdata; 268 269 } 270 271 iic_release_bus(sc->sc_tag, 0); 272 } 273