1 /* $NetBSD: dbcool.c,v 1.26 2010/11/13 13:51:59 uebayasi Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Goyette 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * a driver for the dbCool(tm) family of environmental controllers 34 * 35 * Data sheets for the various supported chips are available at 36 * 37 * http://www.onsemi.com/pub/Collateral/ADM1027-D.PDF 38 * http://www.onsemi.com/pub/Collateral/ADM1030-D.PDF 39 * http://www.onsemi.com/pub/Collateral/ADT7463-D.PDF 40 * http://www.onsemi.com/pub/Collateral/ADT7466.PDF 41 * http://www.onsemi.com/pub/Collateral/ADT7467-D.PDF 42 * http://www.onsemi.com/pub/Collateral/ADT7468-D.PDF 43 * http://www.onsemi.com/pub/Collateral/ADT7473-D.PDF 44 * http://www.onsemi.com/pub/Collateral/ADT7475-D.PDF 45 * http://www.onsemi.com/pub/Collateral/ADT7476-D.PDF 46 * http://www.onsemi.com/pub/Collateral/ADT7490-D.PDF 47 * 48 * (URLs are correct as of October 5, 2008) 49 */ 50 51 #include <sys/cdefs.h> 52 __KERNEL_RCSID(0, "$NetBSD: dbcool.c,v 1.26 2010/11/13 13:51:59 uebayasi Exp $"); 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/kernel.h> 57 #include <sys/device.h> 58 #include <sys/malloc.h> 59 #include <sys/sysctl.h> 60 61 #include <dev/i2c/dbcool_var.h> 62 #include <dev/i2c/dbcool_reg.h> 63 64 /* Config interface */ 65 static int dbcool_match(device_t, cfdata_t, void *); 66 static void dbcool_attach(device_t, device_t, void *); 67 static int dbcool_detach(device_t, int); 68 69 /* Device attributes */ 70 static int dbcool_supply_voltage(struct dbcool_softc *); 71 static bool dbcool_islocked(struct dbcool_softc *); 72 73 /* Sensor read functions */ 74 static void dbcool_refresh(struct sysmon_envsys *, envsys_data_t *); 75 static int dbcool_read_rpm(struct dbcool_softc *, uint8_t); 76 static int dbcool_read_temp(struct dbcool_softc *, uint8_t, bool); 77 static int dbcool_read_volt(struct dbcool_softc *, uint8_t, int, bool); 78 79 /* Sensor get/set limit functions */ 80 static void dbcool_get_limits(struct sysmon_envsys *, envsys_data_t *, 81 sysmon_envsys_lim_t *, uint32_t *); 82 static void dbcool_get_temp_limits(struct dbcool_softc *, int, 83 sysmon_envsys_lim_t *, uint32_t *); 84 static void dbcool_get_volt_limits(struct dbcool_softc *, int, 85 sysmon_envsys_lim_t *, uint32_t *); 86 static void dbcool_get_fan_limits(struct dbcool_softc *, int, 87 sysmon_envsys_lim_t *, uint32_t *); 88 89 static void dbcool_set_limits(struct sysmon_envsys *, envsys_data_t *, 90 sysmon_envsys_lim_t *, uint32_t *); 91 static void dbcool_set_temp_limits(struct dbcool_softc *, int, 92 sysmon_envsys_lim_t *, uint32_t *); 93 static void dbcool_set_volt_limits(struct dbcool_softc *, int, 94 sysmon_envsys_lim_t *, uint32_t *); 95 static void dbcool_set_fan_limits(struct dbcool_softc *, int, 96 sysmon_envsys_lim_t *, uint32_t *); 97 98 /* SYSCTL Helpers */ 99 static int sysctl_dbcool_temp(SYSCTLFN_PROTO); 100 static int sysctl_adm1030_temp(SYSCTLFN_PROTO); 101 static int sysctl_adm1030_trange(SYSCTLFN_PROTO); 102 static int sysctl_dbcool_duty(SYSCTLFN_PROTO); 103 static int sysctl_dbcool_behavior(SYSCTLFN_PROTO); 104 static int sysctl_dbcool_slope(SYSCTLFN_PROTO); 105 static int sysctl_dbcool_thyst(SYSCTLFN_PROTO); 106 107 /* Set-up subroutines */ 108 static void dbcool_setup_controllers(struct dbcool_softc *); 109 static int dbcool_setup_sensors(struct dbcool_softc *); 110 static int dbcool_attach_sensor(struct dbcool_softc *, int); 111 static int dbcool_attach_temp_control(struct dbcool_softc *, int, 112 struct chip_id *); 113 114 #ifdef DBCOOL_DEBUG 115 static int sysctl_dbcool_reg_select(SYSCTLFN_PROTO); 116 static int sysctl_dbcool_reg_access(SYSCTLFN_PROTO); 117 #endif /* DBCOOL_DEBUG */ 118 119 /* 120 * Descriptions for SYSCTL entries 121 */ 122 struct dbc_sysctl_info { 123 const char *name; 124 const char *desc; 125 bool lockable; 126 int (*helper)(SYSCTLFN_PROTO); 127 }; 128 129 static struct dbc_sysctl_info dbc_sysctl_table[] = { 130 /* 131 * The first several entries must remain in the same order as the 132 * corresponding entries in enum dbc_pwm_params 133 */ 134 { "behavior", "operating behavior and temp selector", 135 true, sysctl_dbcool_behavior }, 136 { "min_duty", "minimum fan controller PWM duty cycle", 137 true, sysctl_dbcool_duty }, 138 { "max_duty", "maximum fan controller PWM duty cycle", 139 true, sysctl_dbcool_duty }, 140 { "cur_duty", "current fan controller PWM duty cycle", 141 false, sysctl_dbcool_duty }, 142 143 /* 144 * The rest of these should be in the order in which they 145 * are to be stored in the sysctl tree; the table index is 146 * used as the high-order bits of the sysctl_num to maintain 147 * the sequence. 148 * 149 * If you rearrange the order of these items, be sure to 150 * update the sysctl_index in the XXX_sensor_table[] for 151 * the various chips! 152 */ 153 { "Trange", "temp slope/range to reach 100% duty cycle", 154 true, sysctl_dbcool_slope }, 155 { "Tmin", "temp at which to start fan controller", 156 true, sysctl_dbcool_temp }, 157 { "Ttherm", "temp at which THERM is asserted", 158 true, sysctl_dbcool_temp }, 159 { "Thyst", "temp hysteresis for stopping fan controller", 160 true, sysctl_dbcool_thyst }, 161 { "Tmin", "temp at which to start fan controller", 162 true, sysctl_adm1030_temp }, 163 { "Trange", "temp slope/range to reach 100% duty cycle", 164 true, sysctl_adm1030_trange }, 165 }; 166 167 static const char *dbc_sensor_names[] = { 168 "l_temp", "r1_temp", "r2_temp", "Vccp", "Vcc", "fan1", 169 "fan2", "fan3", "fan4", "AIN1", "AIN2", "V2dot5", 170 "V5", "V12", "Vtt", "Imon", "VID" 171 }; 172 173 /* 174 * Following table derived from product data-sheets 175 */ 176 static int64_t nominal_voltages[] = { 177 -1, /* Vcc can be either 3.3 or 5.0V 178 at 3/4 scale */ 179 2249939, /* Vccp 2.25V 3/4 scale */ 180 2497436, /* 2.5VIN 2.5V 3/4 scale */ 181 5002466, /* 5VIN 5V 3/4 scale */ 182 12000000, /* 12VIN 12V 3/4 scale */ 183 1690809, /* Vtt, Imon 2.25V full scale */ 184 1689600, /* AIN1, AIN2 2.25V full scale */ 185 0 186 }; 187 188 /* 189 * Sensor-type, { val-reg, hilim-reg, lolim-reg}, name-idx, sysctl-table-idx, 190 * nom-voltage-index 191 */ 192 struct dbcool_sensor ADT7490_sensor_table[] = { 193 { DBC_TEMP, { DBCOOL_LOCAL_TEMP, 194 DBCOOL_LOCAL_HIGHLIM, 195 DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 }, 196 { DBC_TEMP, { DBCOOL_REMOTE1_TEMP, 197 DBCOOL_REMOTE1_HIGHLIM, 198 DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 }, 199 { DBC_TEMP, { DBCOOL_REMOTE2_TEMP, 200 DBCOOL_REMOTE2_HIGHLIM, 201 DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 }, 202 { DBC_VOLT, { DBCOOL_VCCP, 203 DBCOOL_VCCP_HIGHLIM, 204 DBCOOL_VCCP_LOWLIM }, 3, 0, 1 }, 205 { DBC_VOLT, { DBCOOL_VCC, 206 DBCOOL_VCC_HIGHLIM, 207 DBCOOL_VCC_LOWLIM }, 4, 0, 0 }, 208 { DBC_VOLT, { DBCOOL_25VIN, 209 DBCOOL_25VIN_HIGHLIM, 210 DBCOOL_25VIN_LOWLIM }, 11, 0, 2 }, 211 { DBC_VOLT, { DBCOOL_5VIN, 212 DBCOOL_5VIN_HIGHLIM, 213 DBCOOL_5VIN_LOWLIM }, 12, 0, 3 }, 214 { DBC_VOLT, { DBCOOL_12VIN, 215 DBCOOL_12VIN_HIGHLIM, 216 DBCOOL_12VIN_LOWLIM }, 13, 0, 4 }, 217 { DBC_VOLT, { DBCOOL_VTT, 218 DBCOOL_VTT_HIGHLIM, 219 DBCOOL_VTT_LOWLIM }, 14, 0, 5 }, 220 { DBC_VOLT, { DBCOOL_IMON, 221 DBCOOL_IMON_HIGHLIM, 222 DBCOOL_IMON_LOWLIM }, 15, 0, 5 }, 223 { DBC_FAN, { DBCOOL_FAN1_TACH_LSB, 224 DBCOOL_NO_REG, 225 DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 }, 226 { DBC_FAN, { DBCOOL_FAN2_TACH_LSB, 227 DBCOOL_NO_REG, 228 DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 }, 229 { DBC_FAN, { DBCOOL_FAN3_TACH_LSB, 230 DBCOOL_NO_REG, 231 DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 }, 232 { DBC_FAN, { DBCOOL_FAN4_TACH_LSB, 233 DBCOOL_NO_REG, 234 DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 }, 235 { DBC_VID, { DBCOOL_VID_REG, 236 DBCOOL_NO_REG, 237 DBCOOL_NO_REG }, 16, 0, 0 }, 238 { DBC_CTL, { DBCOOL_LOCAL_TMIN, 239 DBCOOL_NO_REG, 240 DBCOOL_NO_REG }, 0, 5, 0 }, 241 { DBC_CTL, { DBCOOL_LOCAL_TTHRESH, 242 DBCOOL_NO_REG, 243 DBCOOL_NO_REG }, 0, 6, 0 }, 244 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80, 245 DBCOOL_NO_REG, 246 DBCOOL_NO_REG }, 0, 7, 0 }, 247 { DBC_CTL, { DBCOOL_REMOTE1_TMIN, 248 DBCOOL_NO_REG, 249 DBCOOL_NO_REG }, 1, 5, 0 }, 250 { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH, 251 DBCOOL_NO_REG, 252 DBCOOL_NO_REG }, 1, 6, 0 }, 253 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST, 254 DBCOOL_NO_REG, 255 DBCOOL_NO_REG }, 1, 7, 0 }, 256 { DBC_CTL, { DBCOOL_REMOTE2_TMIN, 257 DBCOOL_NO_REG, 258 DBCOOL_NO_REG }, 2, 5, 0 }, 259 { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH, 260 DBCOOL_NO_REG, 261 DBCOOL_NO_REG }, 2, 6, 0 }, 262 { DBC_CTL, { DBCOOL_R2_TMIN_HYST, 263 DBCOOL_NO_REG, 264 DBCOOL_NO_REG }, 2, 7, 0 }, 265 { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 } 266 }; 267 268 struct dbcool_sensor ADT7476_sensor_table[] = { 269 { DBC_TEMP, { DBCOOL_LOCAL_TEMP, 270 DBCOOL_LOCAL_HIGHLIM, 271 DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 }, 272 { DBC_TEMP, { DBCOOL_REMOTE1_TEMP, 273 DBCOOL_REMOTE1_HIGHLIM, 274 DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 }, 275 { DBC_TEMP, { DBCOOL_REMOTE2_TEMP, 276 DBCOOL_REMOTE2_HIGHLIM, 277 DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 }, 278 { DBC_VOLT, { DBCOOL_VCCP, 279 DBCOOL_VCCP_HIGHLIM, 280 DBCOOL_VCCP_LOWLIM }, 3, 0, 1 }, 281 { DBC_VOLT, { DBCOOL_VCC, 282 DBCOOL_VCC_HIGHLIM, 283 DBCOOL_VCC_LOWLIM }, 4, 0, 0 }, 284 { DBC_VOLT, { DBCOOL_25VIN, 285 DBCOOL_25VIN_HIGHLIM, 286 DBCOOL_25VIN_LOWLIM }, 11, 0, 2 }, 287 { DBC_VOLT, { DBCOOL_5VIN, 288 DBCOOL_5VIN_HIGHLIM, 289 DBCOOL_5VIN_LOWLIM }, 12, 0, 3 }, 290 { DBC_VOLT, { DBCOOL_12VIN, 291 DBCOOL_12VIN_HIGHLIM, 292 DBCOOL_12VIN_LOWLIM }, 13, 0, 4 }, 293 { DBC_FAN, { DBCOOL_FAN1_TACH_LSB, 294 DBCOOL_NO_REG, 295 DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 }, 296 { DBC_FAN, { DBCOOL_FAN2_TACH_LSB, 297 DBCOOL_NO_REG, 298 DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 }, 299 { DBC_FAN, { DBCOOL_FAN3_TACH_LSB, 300 DBCOOL_NO_REG, 301 DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 }, 302 { DBC_FAN, { DBCOOL_FAN4_TACH_LSB, 303 DBCOOL_NO_REG, 304 DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 }, 305 { DBC_VID, { DBCOOL_VID_REG, 306 DBCOOL_NO_REG, 307 DBCOOL_NO_REG }, 16, 0, 0 }, 308 { DBC_CTL, { DBCOOL_LOCAL_TMIN, 309 DBCOOL_NO_REG, 310 DBCOOL_NO_REG }, 0, 5, 0 }, 311 { DBC_CTL, { DBCOOL_LOCAL_TTHRESH, 312 DBCOOL_NO_REG, 313 DBCOOL_NO_REG }, 0, 6, 0 }, 314 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80, 315 DBCOOL_NO_REG, 316 DBCOOL_NO_REG }, 0, 7, 0 }, 317 { DBC_CTL, { DBCOOL_REMOTE1_TMIN, 318 DBCOOL_NO_REG, 319 DBCOOL_NO_REG }, 1, 5, 0 }, 320 { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH, 321 DBCOOL_NO_REG, 322 DBCOOL_NO_REG }, 1, 6, 0 }, 323 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST, 324 DBCOOL_NO_REG, 325 DBCOOL_NO_REG }, 1, 7, 0 }, 326 { DBC_CTL, { DBCOOL_REMOTE2_TMIN, 327 DBCOOL_NO_REG, 328 DBCOOL_NO_REG }, 2, 5, 0 }, 329 { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH, 330 DBCOOL_NO_REG, 331 DBCOOL_NO_REG }, 2, 6, 0 }, 332 { DBC_CTL, { DBCOOL_R2_TMIN_HYST, 333 DBCOOL_NO_REG, 334 DBCOOL_NO_REG }, 2, 7, 0 }, 335 { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 } 336 }; 337 338 struct dbcool_sensor ADT7475_sensor_table[] = { 339 { DBC_TEMP, { DBCOOL_LOCAL_TEMP, 340 DBCOOL_LOCAL_HIGHLIM, 341 DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 }, 342 { DBC_TEMP, { DBCOOL_REMOTE1_TEMP, 343 DBCOOL_REMOTE1_HIGHLIM, 344 DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 }, 345 { DBC_TEMP, { DBCOOL_REMOTE2_TEMP, 346 DBCOOL_REMOTE2_HIGHLIM, 347 DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 }, 348 { DBC_VOLT, { DBCOOL_VCCP, 349 DBCOOL_VCCP_HIGHLIM, 350 DBCOOL_VCCP_LOWLIM }, 3, 0, 1 }, 351 { DBC_VOLT, { DBCOOL_VCC, 352 DBCOOL_VCC_HIGHLIM, 353 DBCOOL_VCC_LOWLIM }, 4, 0, 0 }, 354 { DBC_FAN, { DBCOOL_FAN1_TACH_LSB, 355 DBCOOL_NO_REG, 356 DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 }, 357 { DBC_FAN, { DBCOOL_FAN2_TACH_LSB, 358 DBCOOL_NO_REG, 359 DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 }, 360 { DBC_FAN, { DBCOOL_FAN3_TACH_LSB, 361 DBCOOL_NO_REG, 362 DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 }, 363 { DBC_FAN, { DBCOOL_FAN4_TACH_LSB, 364 DBCOOL_NO_REG, 365 DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 }, 366 { DBC_CTL, { DBCOOL_LOCAL_TMIN, 367 DBCOOL_NO_REG, 368 DBCOOL_NO_REG }, 0, 5, 0 }, 369 { DBC_CTL, { DBCOOL_LOCAL_TTHRESH, 370 DBCOOL_NO_REG, 371 DBCOOL_NO_REG }, 0, 6, 0 }, 372 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80, 373 DBCOOL_NO_REG, 374 DBCOOL_NO_REG }, 0, 7, 0 }, 375 { DBC_CTL, { DBCOOL_REMOTE1_TMIN, 376 DBCOOL_NO_REG, 377 DBCOOL_NO_REG }, 1, 5, 0 }, 378 { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH, 379 DBCOOL_NO_REG, 380 DBCOOL_NO_REG }, 1, 6, 0 }, 381 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST, 382 DBCOOL_NO_REG, 383 DBCOOL_NO_REG }, 1, 7, 0 }, 384 { DBC_CTL, { DBCOOL_REMOTE2_TMIN, 385 DBCOOL_NO_REG, 386 DBCOOL_NO_REG }, 2, 5, 0 }, 387 { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH, 388 DBCOOL_NO_REG, 389 DBCOOL_NO_REG }, 2, 6, 0 }, 390 { DBC_CTL, { DBCOOL_R2_TMIN_HYST, 391 DBCOOL_NO_REG, 392 DBCOOL_NO_REG }, 2, 7, 0 }, 393 { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 } 394 }; 395 396 /* 397 * The registers of dbcool_power_control must be in the same order as 398 * in enum dbc_pwm_params 399 */ 400 struct dbcool_power_control ADT7475_power_table[] = { 401 { { DBCOOL_PWM1_CTL, DBCOOL_PWM1_MINDUTY, 402 DBCOOL_PWM1_MAXDUTY, DBCOOL_PWM1_CURDUTY }, 403 "fan_control_1" }, 404 { { DBCOOL_PWM2_CTL, DBCOOL_PWM2_MINDUTY, 405 DBCOOL_PWM2_MAXDUTY, DBCOOL_PWM2_CURDUTY }, 406 "fan_control_2" }, 407 { { DBCOOL_PWM3_CTL, DBCOOL_PWM3_MINDUTY, 408 DBCOOL_PWM3_MAXDUTY, DBCOOL_PWM3_CURDUTY }, 409 "fan_control_3" }, 410 { { 0, 0, 0, 0 }, NULL } 411 }; 412 413 struct dbcool_sensor ADT7466_sensor_table[] = { 414 { DBC_TEMP, { DBCOOL_ADT7466_LCL_TEMP_MSB, 415 DBCOOL_ADT7466_LCL_TEMP_HILIM, 416 DBCOOL_ADT7466_LCL_TEMP_LOLIM }, 0, 0, 0 }, 417 { DBC_TEMP, { DBCOOL_ADT7466_REM_TEMP_MSB, 418 DBCOOL_ADT7466_REM_TEMP_HILIM, 419 DBCOOL_ADT7466_REM_TEMP_LOLIM }, 1, 0, 0 }, 420 { DBC_VOLT, { DBCOOL_ADT7466_VCC, 421 DBCOOL_ADT7466_VCC_HILIM, 422 DBCOOL_ADT7466_VCC_LOLIM }, 4, 0, 0 }, 423 { DBC_VOLT, { DBCOOL_ADT7466_AIN1, 424 DBCOOL_ADT7466_AIN1_HILIM, 425 DBCOOL_ADT7466_AIN1_LOLIM }, 9, 0, 6 }, 426 { DBC_VOLT, { DBCOOL_ADT7466_AIN2, 427 DBCOOL_ADT7466_AIN2_HILIM, 428 DBCOOL_ADT7466_AIN2_LOLIM }, 10, 0, 6 }, 429 { DBC_FAN, { DBCOOL_ADT7466_FANA_LSB, 430 DBCOOL_NO_REG, 431 DBCOOL_ADT7466_FANA_LOLIM_LSB }, 5, 0, 0 }, 432 { DBC_FAN, { DBCOOL_ADT7466_FANB_LSB, 433 DBCOOL_NO_REG, 434 DBCOOL_ADT7466_FANB_LOLIM_LSB }, 6, 0, 0 }, 435 { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 } 436 }; 437 438 struct dbcool_sensor ADM1027_sensor_table[] = { 439 { DBC_TEMP, { DBCOOL_LOCAL_TEMP, 440 DBCOOL_LOCAL_HIGHLIM, 441 DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 }, 442 { DBC_TEMP, { DBCOOL_REMOTE1_TEMP, 443 DBCOOL_REMOTE1_HIGHLIM, 444 DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 }, 445 { DBC_TEMP, { DBCOOL_REMOTE2_TEMP, 446 DBCOOL_REMOTE2_HIGHLIM, 447 DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 }, 448 { DBC_VOLT, { DBCOOL_VCCP, 449 DBCOOL_VCCP_HIGHLIM, 450 DBCOOL_VCCP_LOWLIM }, 3, 0, 1 }, 451 { DBC_VOLT, { DBCOOL_VCC, 452 DBCOOL_VCC_HIGHLIM, 453 DBCOOL_VCC_LOWLIM }, 4, 0, 0 }, 454 { DBC_VOLT, { DBCOOL_25VIN, 455 DBCOOL_25VIN_HIGHLIM, 456 DBCOOL_25VIN_LOWLIM }, 11, 0, 2 }, 457 { DBC_VOLT, { DBCOOL_5VIN, 458 DBCOOL_5VIN_HIGHLIM, 459 DBCOOL_5VIN_LOWLIM }, 12, 0, 3 }, 460 { DBC_VOLT, { DBCOOL_12VIN, 461 DBCOOL_12VIN_HIGHLIM, 462 DBCOOL_12VIN_LOWLIM }, 13, 0, 4 }, 463 { DBC_FAN, { DBCOOL_FAN1_TACH_LSB, 464 DBCOOL_NO_REG, 465 DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 }, 466 { DBC_FAN, { DBCOOL_FAN2_TACH_LSB, 467 DBCOOL_NO_REG, 468 DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 }, 469 { DBC_FAN, { DBCOOL_FAN3_TACH_LSB, 470 DBCOOL_NO_REG, 471 DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 }, 472 { DBC_FAN, { DBCOOL_FAN4_TACH_LSB, 473 DBCOOL_NO_REG, 474 DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 }, 475 { DBC_VID, { DBCOOL_VID_REG, 476 DBCOOL_NO_REG, 477 DBCOOL_NO_REG }, 16, 0, 0 }, 478 { DBC_CTL, { DBCOOL_LOCAL_TMIN, 479 DBCOOL_NO_REG, 480 DBCOOL_NO_REG }, 0, 5, 0 }, 481 { DBC_CTL, { DBCOOL_LOCAL_TTHRESH, 482 DBCOOL_NO_REG, 483 DBCOOL_NO_REG }, 0, 6, 0 }, 484 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80, 485 DBCOOL_NO_REG, 486 DBCOOL_NO_REG }, 0, 7, 0 }, 487 { DBC_CTL, { DBCOOL_REMOTE1_TMIN, 488 DBCOOL_NO_REG, 489 DBCOOL_NO_REG }, 1, 5, 0 }, 490 { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH, 491 DBCOOL_NO_REG, 492 DBCOOL_NO_REG }, 1, 6, 0 }, 493 { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST, 494 DBCOOL_NO_REG, 495 DBCOOL_NO_REG }, 1, 7, 0 }, 496 { DBC_CTL, { DBCOOL_REMOTE2_TMIN, 497 DBCOOL_NO_REG, 498 DBCOOL_NO_REG }, 2, 5, 0 }, 499 { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH, 500 DBCOOL_NO_REG, 501 DBCOOL_NO_REG }, 2, 6, 0 }, 502 { DBC_CTL, { DBCOOL_R2_TMIN_HYST, 503 DBCOOL_NO_REG, 504 DBCOOL_NO_REG }, 2, 7, 0 }, 505 { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 } 506 }; 507 508 struct dbcool_sensor ADM1030_sensor_table[] = { 509 { DBC_TEMP, { DBCOOL_ADM1030_L_TEMP, 510 DBCOOL_ADM1030_L_HI_LIM, 511 DBCOOL_ADM1030_L_LO_LIM }, 0, 0, 0 }, 512 { DBC_TEMP, { DBCOOL_ADM1030_R_TEMP, 513 DBCOOL_ADM1030_R_HI_LIM, 514 DBCOOL_ADM1030_R_LO_LIM }, 1, 0, 0 }, 515 { DBC_FAN, { DBCOOL_ADM1030_FAN_TACH, 516 DBCOOL_NO_REG, 517 DBCOOL_ADM1030_FAN_LO_LIM }, 5, 0, 0 }, 518 { DBC_CTL, { DBCOOL_ADM1030_L_TMIN, 519 DBCOOL_NO_REG, 520 DBCOOL_NO_REG }, 0, 8, 0 }, 521 { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH, 522 DBCOOL_NO_REG, 523 DBCOOL_NO_REG }, 0, 9, 0 }, 524 { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH, 525 DBCOOL_NO_REG, 526 DBCOOL_NO_REG }, 0, 6, 0 }, 527 { DBC_CTL, { DBCOOL_ADM1030_R_TMIN, 528 DBCOOL_NO_REG, 529 DBCOOL_NO_REG }, 1, 8, 0 }, 530 { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH, 531 DBCOOL_NO_REG, 532 DBCOOL_NO_REG }, 1, 9, 0 }, 533 { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH, 534 DBCOOL_NO_REG, 535 DBCOOL_NO_REG }, 1, 6, 0 }, 536 { DBC_EOF, {0, 0, 0 }, 0, 0, 0 } 537 }; 538 539 struct dbcool_power_control ADM1030_power_table[] = { 540 { { DBCOOL_ADM1030_CFG1, DBCOOL_NO_REG, DBCOOL_NO_REG, 541 DBCOOL_ADM1030_FAN_SPEED_CFG }, 542 "fan_control_1" }, 543 { { 0, 0, 0, 0 }, NULL } 544 }; 545 546 struct dbcool_sensor ADM1031_sensor_table[] = { 547 { DBC_TEMP, { DBCOOL_ADM1030_L_TEMP, 548 DBCOOL_ADM1030_L_HI_LIM, 549 DBCOOL_ADM1030_L_LO_LIM }, 0, 0, 0 }, 550 { DBC_TEMP, { DBCOOL_ADM1030_R_TEMP, 551 DBCOOL_ADM1030_R_HI_LIM, 552 DBCOOL_ADM1030_R_LO_LIM }, 1, 0, 0 }, 553 { DBC_TEMP, { DBCOOL_ADM1031_R2_TEMP, 554 DBCOOL_ADM1031_R2_HI_LIM, 555 DBCOOL_ADM1031_R2_LO_LIM }, 2, 0, 0 }, 556 { DBC_FAN, { DBCOOL_ADM1030_FAN_TACH, 557 DBCOOL_NO_REG, 558 DBCOOL_ADM1030_FAN_LO_LIM }, 5, 0, 0 }, 559 { DBC_FAN, { DBCOOL_ADM1031_FAN2_TACH, 560 DBCOOL_NO_REG, 561 DBCOOL_ADM1031_FAN2_LO_LIM }, 6, 0, 0 }, 562 { DBC_CTL, { DBCOOL_ADM1030_L_TMIN, 563 DBCOOL_NO_REG, 564 DBCOOL_NO_REG }, 0, 8, 0 }, 565 { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH, 566 DBCOOL_NO_REG, 567 DBCOOL_NO_REG }, 0, 9, 0 }, 568 { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH, 569 DBCOOL_NO_REG, 570 DBCOOL_NO_REG }, 0, 6, 0 }, 571 { DBC_CTL, { DBCOOL_ADM1030_R_TMIN, 572 DBCOOL_NO_REG, 573 DBCOOL_NO_REG }, 1, 8, 0 }, 574 { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH, 575 DBCOOL_NO_REG, 576 DBCOOL_NO_REG }, 1, 9, 0 }, 577 { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH, 578 DBCOOL_NO_REG, 579 DBCOOL_NO_REG }, 1, 6, 0 }, 580 { DBC_CTL, { DBCOOL_ADM1031_R2_TMIN, 581 DBCOOL_NO_REG, 582 DBCOOL_NO_REG }, 2, 8, 0 }, 583 { DBC_CTL, { DBCOOL_ADM1031_R2_TTHRESH, 584 DBCOOL_NO_REG, 585 DBCOOL_NO_REG }, 2, 9, 0 }, 586 { DBC_CTL, { DBCOOL_ADM1031_R2_TTHRESH, 587 DBCOOL_NO_REG, 588 DBCOOL_NO_REG }, 2, 6, 0 }, 589 { DBC_EOF, {0, 0, 0 }, 0, 0, 0 } 590 }; 591 592 struct dbcool_power_control ADM1031_power_table[] = { 593 { { DBCOOL_ADM1030_CFG1, DBCOOL_NO_REG, DBCOOL_NO_REG, 594 DBCOOL_ADM1030_FAN_SPEED_CFG }, 595 "fan_control_1" }, 596 { { DBCOOL_ADM1030_CFG1, DBCOOL_NO_REG, DBCOOL_NO_REG, 597 DBCOOL_ADM1030_FAN_SPEED_CFG }, 598 "fan_control_2" }, 599 { { 0, 0, 0, 0 }, NULL } 600 }; 601 struct chip_id chip_table[] = { 602 { DBCOOL_COMPANYID, ADT7490_DEVICEID, ADT7490_REV_ID, 603 ADT7490_sensor_table, ADT7475_power_table, 604 DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_PECI, 605 90000 * 60, "ADT7490" }, 606 { DBCOOL_COMPANYID, ADT7476_DEVICEID, 0xff, 607 ADT7476_sensor_table, ADT7475_power_table, 608 DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY, 609 90000 * 60, "ADT7476" }, 610 { DBCOOL_COMPANYID, ADT7475_DEVICEID, 0xff, 611 ADT7475_sensor_table, ADT7475_power_table, 612 DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN, 613 90000 * 60, "ADT7475" }, 614 { DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID1, 615 ADT7475_sensor_table, ADT7475_power_table, 616 DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN, 617 90000 * 60, "ADT7460/ADT7463" }, 618 { DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID2, 619 ADT7475_sensor_table, ADT7475_power_table, 620 DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN, 621 90000 * 60, "ADT7463-1" }, 622 { DBCOOL_COMPANYID, ADT7468_DEVICEID, 0xff, 623 ADT7476_sensor_table, ADT7475_power_table, 624 DBCFLAG_TEMPOFFSET | DBCFLAG_MULTI_VCC | DBCFLAG_HAS_MAXDUTY | 625 DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN, 626 90000 * 60, "ADT7467/ADT7468" }, 627 { DBCOOL_COMPANYID, ADT7466_DEVICEID, 0xff, 628 ADT7466_sensor_table, NULL, 629 DBCFLAG_ADT7466 | DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_SHDN, 630 82000 * 60, "ADT7466" }, 631 { DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID1, 632 ADM1027_sensor_table, ADT7475_power_table, 633 DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN, 634 90000 * 60, "ADT7463" }, 635 { DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID2, 636 ADM1027_sensor_table, ADT7475_power_table, 637 DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN | 638 DBCFLAG_HAS_VID_SEL, 639 90000 * 60, "ADT7463" }, 640 { DBCOOL_COMPANYID, ADM1027_DEVICEID, ADM1027_REV_ID, 641 ADM1027_sensor_table, ADT7475_power_table, 642 DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER, 643 90000 * 60, "ADM1027" }, 644 { DBCOOL_COMPANYID, ADM1030_DEVICEID, 0xff, 645 ADM1030_sensor_table, ADM1030_power_table, 646 DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE, 647 11250 * 60, "ADM1030" }, 648 { DBCOOL_COMPANYID, ADM1031_DEVICEID, 0xff, 649 ADM1031_sensor_table, ADM1030_power_table, 650 DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE, 651 11250 * 60, "ADM1031" }, 652 { 0, 0, 0, NULL, NULL, 0, 0, NULL } 653 }; 654 655 static const char *behavior[] = { 656 "remote1", "local", "remote2", "full-speed", 657 "disabled", "local+remote2","all-temps", "manual" 658 }; 659 660 static char dbcool_cur_behav[16]; 661 662 CFATTACH_DECL_NEW(dbcool, sizeof(struct dbcool_softc), 663 dbcool_match, dbcool_attach, dbcool_detach, NULL); 664 665 int 666 dbcool_match(device_t parent, cfdata_t cf, void *aux) 667 { 668 struct i2c_attach_args *ia = aux; 669 struct dbcool_chipset dc; 670 dc.dc_tag = ia->ia_tag; 671 dc.dc_addr = ia->ia_addr; 672 dc.dc_chip = NULL; 673 dc.dc_readreg = dbcool_readreg; 674 dc.dc_writereg = dbcool_writereg; 675 676 /* no probing if we attach to iic, but verify chip id and address */ 677 if ((ia->ia_addr & DBCOOL_ADDRMASK) != DBCOOL_ADDR) 678 return 0; 679 if (dbcool_chip_ident(&dc) >= 0) 680 return 1; 681 682 return 0; 683 } 684 685 void 686 dbcool_attach(device_t parent, device_t self, void *aux) 687 { 688 struct dbcool_softc *sc = device_private(self); 689 struct i2c_attach_args *args = aux; 690 uint8_t ver; 691 692 sc->sc_dc.dc_addr = args->ia_addr; 693 sc->sc_dc.dc_tag = args->ia_tag; 694 sc->sc_dc.dc_chip = NULL; 695 sc->sc_dc.dc_readreg = dbcool_readreg; 696 sc->sc_dc.dc_writereg = dbcool_writereg; 697 (void)dbcool_chip_ident(&sc->sc_dc); 698 sc->sc_dev = self; 699 700 aprint_naive("\n"); 701 aprint_normal("\n"); 702 703 ver = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_REVISION_REG); 704 if (sc->sc_dc.dc_chip->flags & DBCFLAG_4BIT_VER) 705 aprint_normal_dev(self, "%s dBCool(tm) Controller " 706 "(rev 0x%02x, stepping 0x%02x)\n", sc->sc_dc.dc_chip->name, 707 ver >> 4, ver & 0x0f); 708 else 709 aprint_normal_dev(self, "%s dBCool(tm) Controller " 710 "(rev 0x%04x)\n", sc->sc_dc.dc_chip->name, ver); 711 712 dbcool_setup(self); 713 714 if (!pmf_device_register(self, dbcool_pmf_suspend, dbcool_pmf_resume)) 715 aprint_error_dev(self, "couldn't establish power handler\n"); 716 } 717 718 static int 719 dbcool_detach(device_t self, int flags) 720 { 721 struct dbcool_softc *sc = device_private(self); 722 723 sysmon_envsys_unregister(sc->sc_sme); 724 sc->sc_sme = NULL; 725 return 0; 726 } 727 728 /* On suspend, we save the state of the SHDN bit, then set it */ 729 bool dbcool_pmf_suspend(device_t dev, const pmf_qual_t *qual) 730 { 731 struct dbcool_softc *sc = device_private(dev); 732 uint8_t reg, bit, cfg; 733 734 if ((sc->sc_dc.dc_chip->flags && DBCFLAG_HAS_SHDN) == 0) 735 return true; 736 737 if (sc->sc_dc.dc_chip->flags && DBCFLAG_ADT7466) { 738 reg = DBCOOL_ADT7466_CONFIG2; 739 bit = DBCOOL_ADT7466_CFG2_SHDN; 740 } else { 741 reg = DBCOOL_CONFIG2_REG; 742 bit = DBCOOL_CFG2_SHDN; 743 } 744 cfg = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 745 sc->sc_suspend = cfg & bit; 746 cfg |= bit; 747 sc->sc_dc.dc_writereg(&sc->sc_dc, reg, cfg); 748 749 return true; 750 } 751 752 /* On resume, we restore the previous state of the SHDN bit */ 753 bool dbcool_pmf_resume(device_t dev, const pmf_qual_t *qual) 754 { 755 struct dbcool_softc *sc = device_private(dev); 756 uint8_t reg, bit, cfg; 757 758 if ((sc->sc_dc.dc_chip->flags && DBCFLAG_HAS_SHDN) == 0) 759 return true; 760 761 if (sc->sc_dc.dc_chip->flags && DBCFLAG_ADT7466) { 762 reg = DBCOOL_ADT7466_CONFIG2; 763 bit = DBCOOL_ADT7466_CFG2_SHDN; 764 } else { 765 reg = DBCOOL_CONFIG2_REG; 766 bit = DBCOOL_CFG2_SHDN; 767 } 768 cfg = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 769 cfg &= ~sc->sc_suspend; 770 sc->sc_dc.dc_writereg(&sc->sc_dc, reg, cfg); 771 772 return true; 773 774 } 775 776 uint8_t 777 dbcool_readreg(struct dbcool_chipset *dc, uint8_t reg) 778 { 779 uint8_t data = 0; 780 781 if (iic_acquire_bus(dc->dc_tag, 0) != 0) 782 return data; 783 784 if (dc->dc_chip == NULL || dc->dc_chip->flags & DBCFLAG_NO_READBYTE) { 785 /* ADM1027 doesn't support i2c read_byte protocol */ 786 if (iic_smbus_send_byte(dc->dc_tag, dc->dc_addr, reg, 0) != 0) 787 goto bad; 788 (void)iic_smbus_receive_byte(dc->dc_tag, dc->dc_addr, &data, 0); 789 } else 790 (void)iic_smbus_read_byte(dc->dc_tag, dc->dc_addr, reg, &data, 791 0); 792 793 bad: 794 iic_release_bus(dc->dc_tag, 0); 795 return data; 796 } 797 798 void 799 dbcool_writereg(struct dbcool_chipset *dc, uint8_t reg, uint8_t val) 800 { 801 if (iic_acquire_bus(dc->dc_tag, 0) != 0) 802 return; 803 804 (void)iic_smbus_write_byte(dc->dc_tag, dc->dc_addr, reg, val, 0); 805 806 iic_release_bus(dc->dc_tag, 0); 807 } 808 809 static bool 810 dbcool_islocked(struct dbcool_softc *sc) 811 { 812 uint8_t cfg_reg; 813 814 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) 815 return 0; 816 817 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) 818 cfg_reg = DBCOOL_ADT7466_CONFIG1; 819 else 820 cfg_reg = DBCOOL_CONFIG1_REG; 821 822 if (sc->sc_dc.dc_readreg(&sc->sc_dc, cfg_reg) & DBCOOL_CFG1_LOCK) 823 return 1; 824 else 825 return 0; 826 } 827 828 static int 829 dbcool_read_temp(struct dbcool_softc *sc, uint8_t reg, bool extres) 830 { 831 uint8_t t1, t2, t3, val, ext = 0; 832 int temp; 833 834 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) { 835 /* 836 * ADT7466 temps are in strange location 837 */ 838 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADT7466_CONFIG1); 839 val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 840 if (extres) 841 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, reg + 1); 842 } else if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) { 843 /* 844 * ADM1030 temps are in their own special place, too 845 */ 846 if (extres) { 847 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_TEMP_EXTRES); 848 if (reg == DBCOOL_ADM1030_L_TEMP) 849 ext >>= 6; 850 else if (reg == DBCOOL_ADM1031_R2_TEMP) 851 ext >>= 4; 852 else 853 ext >>= 1; 854 ext &= 0x03; 855 } 856 val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 857 } else if (extres) { 858 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES2_REG); 859 860 /* Read all msb regs to unlatch them */ 861 t1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_12VIN); 862 t1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_REMOTE1_TEMP); 863 t2 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_REMOTE2_TEMP); 864 t3 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_LOCAL_TEMP); 865 switch (reg) { 866 case DBCOOL_REMOTE1_TEMP: 867 val = t1; 868 ext >>= 2; 869 break; 870 case DBCOOL_LOCAL_TEMP: 871 val = t3; 872 ext >>= 4; 873 break; 874 case DBCOOL_REMOTE2_TEMP: 875 val = t2; 876 ext >>= 6; 877 break; 878 default: 879 val = 0; 880 break; 881 } 882 ext &= 0x03; 883 } 884 else 885 val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 886 887 /* Check for invalid temp values */ 888 if ((sc->sc_temp_offset == 0 && val == 0x80) || 889 (sc->sc_temp_offset != 0 && val == 0)) 890 return 0; 891 892 /* If using offset mode, adjust, else treat as signed */ 893 if (sc->sc_temp_offset) { 894 temp = val; 895 temp -= sc->sc_temp_offset; 896 } else 897 temp = (int8_t)val; 898 899 /* Convert degC to uK and include extended precision bits */ 900 temp *= 1000000; 901 temp += 250000 * (int)ext; 902 temp += 273150000U; 903 904 return temp; 905 } 906 907 static int 908 dbcool_read_rpm(struct dbcool_softc *sc, uint8_t reg) 909 { 910 int rpm; 911 uint8_t rpm_lo, rpm_hi; 912 913 rpm_lo = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 914 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) 915 rpm_hi = (rpm_lo == 0xff)?0xff:0x0; 916 else 917 rpm_hi = sc->sc_dc.dc_readreg(&sc->sc_dc, reg + 1); 918 919 rpm = (rpm_hi << 8) | rpm_lo; 920 if (rpm == 0xffff) 921 return 0; /* 0xffff indicates stalled/failed fan */ 922 923 /* don't divide by zero */ 924 return (rpm == 0)? 0 : (sc->sc_dc.dc_chip->rpm_dividend / rpm); 925 } 926 927 /* Provide chip's supply voltage, in microvolts */ 928 static int 929 dbcool_supply_voltage(struct dbcool_softc *sc) 930 { 931 if (sc->sc_dc.dc_chip->flags & DBCFLAG_MULTI_VCC) { 932 if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_CONFIG1_REG) & DBCOOL_CFG1_Vcc) 933 return 5002500; 934 else 935 return 3300000; 936 } else if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) { 937 if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADT7466_CONFIG1) & 938 DBCOOL_ADT7466_CFG1_Vcc) 939 return 5000000; 940 else 941 return 3300000; 942 } else 943 return 3300000; 944 } 945 946 /* 947 * Nominal voltages are calculated in microvolts 948 */ 949 static int 950 dbcool_read_volt(struct dbcool_softc *sc, uint8_t reg, int nom_idx, bool extres) 951 { 952 uint8_t ext = 0, v1, v2, v3, v4, val; 953 int64_t ret; 954 int64_t nom; 955 956 nom = nominal_voltages[nom_idx]; 957 if (nom < 0) 958 nom = sc->sc_supply_voltage; 959 960 /* ADT7466 voltages are in strange locations with only 8-bits */ 961 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) 962 val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 963 else 964 /* 965 * It's a "normal" dbCool chip - check for regs that 966 * share extended resolution bits since we have to 967 * read all the MSB registers to unlatch them. 968 */ 969 if (!extres) 970 val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 971 else if (reg == DBCOOL_12VIN) { 972 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES2_REG) && 0x03; 973 val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg); 974 (void)dbcool_read_temp(sc, DBCOOL_LOCAL_TEMP, true); 975 } else if (reg == DBCOOL_VTT || reg == DBCOOL_IMON) { 976 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES_VTT_IMON); 977 v1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_IMON); 978 v2 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VTT); 979 if (reg == DBCOOL_IMON) { 980 val = v1; 981 ext >>= 6; 982 } else 983 val = v2; 984 ext >>= 4; 985 ext &= 0x0f; 986 } else { 987 ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES1_REG); 988 v1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_25VIN); 989 v2 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VCCP); 990 v3 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VCC); 991 v4 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_5VIN); 992 993 switch (reg) { 994 case DBCOOL_25VIN: 995 val = v1; 996 break; 997 case DBCOOL_VCCP: 998 val = v2; 999 ext >>= 2; 1000 break; 1001 case DBCOOL_VCC: 1002 val = v3; 1003 ext >>= 4; 1004 break; 1005 case DBCOOL_5VIN: 1006 val = v4; 1007 ext >>= 6; 1008 break; 1009 default: 1010 val = nom = 0; 1011 } 1012 ext &= 0x03; 1013 } 1014 1015 /* 1016 * Scale the nominal value by the 10-bit fraction 1017 * 1018 * Returned value is in microvolts. 1019 */ 1020 ret = val; 1021 ret <<= 2; 1022 ret |= ext; 1023 ret = (ret * nom) / 0x300; 1024 1025 return ret; 1026 } 1027 1028 SYSCTL_SETUP(sysctl_dbcoolsetup, "sysctl dBCool subtree setup") 1029 { 1030 sysctl_createv(NULL, 0, NULL, NULL, 1031 CTLFLAG_PERMANENT, 1032 CTLTYPE_NODE, "hw", NULL, 1033 NULL, 0, NULL, 0, 1034 CTL_HW, CTL_EOL); 1035 } 1036 1037 static int 1038 sysctl_dbcool_temp(SYSCTLFN_ARGS) 1039 { 1040 struct sysctlnode node; 1041 struct dbcool_softc *sc; 1042 int reg, error; 1043 uint8_t chipreg; 1044 uint8_t newreg; 1045 1046 node = *rnode; 1047 sc = (struct dbcool_softc *)node.sysctl_data; 1048 chipreg = node.sysctl_num & 0xff; 1049 1050 if (sc->sc_temp_offset) { 1051 reg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1052 reg -= sc->sc_temp_offset; 1053 } else 1054 reg = (int8_t)sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1055 1056 node.sysctl_data = ® 1057 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1058 1059 if (error || newp == NULL) 1060 return error; 1061 1062 /* We were asked to update the value - sanity check before writing */ 1063 if (*(int *)node.sysctl_data < -64 || 1064 *(int *)node.sysctl_data > 127 + sc->sc_temp_offset) 1065 return EINVAL; 1066 1067 newreg = *(int *)node.sysctl_data; 1068 newreg += sc->sc_temp_offset; 1069 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1070 return 0; 1071 } 1072 1073 static int 1074 sysctl_adm1030_temp(SYSCTLFN_ARGS) 1075 { 1076 struct sysctlnode node; 1077 struct dbcool_softc *sc; 1078 int reg, error; 1079 uint8_t chipreg, oldreg, newreg; 1080 1081 node = *rnode; 1082 sc = (struct dbcool_softc *)node.sysctl_data; 1083 chipreg = node.sysctl_num & 0xff; 1084 1085 oldreg = (int8_t)sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1086 reg = (oldreg >> 1) & ~0x03; 1087 1088 node.sysctl_data = ® 1089 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1090 1091 if (error || newp == NULL) 1092 return error; 1093 1094 /* We were asked to update the value - sanity check before writing */ 1095 if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 127) 1096 return EINVAL; 1097 1098 newreg = *(int *)node.sysctl_data; 1099 newreg &= ~0x03; 1100 newreg <<= 1; 1101 newreg |= (oldreg & 0x07); 1102 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1103 return 0; 1104 } 1105 1106 static int 1107 sysctl_adm1030_trange(SYSCTLFN_ARGS) 1108 { 1109 struct sysctlnode node; 1110 struct dbcool_softc *sc; 1111 int reg, error, newval; 1112 uint8_t chipreg, oldreg, newreg; 1113 1114 node = *rnode; 1115 sc = (struct dbcool_softc *)node.sysctl_data; 1116 chipreg = node.sysctl_num & 0xff; 1117 1118 oldreg = (int8_t)sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1119 reg = oldreg & 0x07; 1120 1121 node.sysctl_data = ® 1122 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1123 1124 if (error || newp == NULL) 1125 return error; 1126 1127 /* We were asked to update the value - sanity check before writing */ 1128 newval = *(int *)node.sysctl_data; 1129 1130 if (newval == 5) 1131 newreg = 0; 1132 else if (newval == 10) 1133 newreg = 1; 1134 else if (newval == 20) 1135 newreg = 2; 1136 else if (newval == 40) 1137 newreg = 3; 1138 else if (newval == 80) 1139 newreg = 4; 1140 else 1141 return EINVAL; 1142 1143 newreg |= (oldreg & ~0x07); 1144 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1145 return 0; 1146 } 1147 1148 static int 1149 sysctl_dbcool_duty(SYSCTLFN_ARGS) 1150 { 1151 struct sysctlnode node; 1152 struct dbcool_softc *sc; 1153 int reg, error; 1154 uint8_t chipreg, oldreg, newreg; 1155 1156 node = *rnode; 1157 sc = (struct dbcool_softc *)node.sysctl_data; 1158 chipreg = node.sysctl_num & 0xff; 1159 1160 oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1161 reg = (uint32_t)oldreg; 1162 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) 1163 reg = ((reg & 0x0f) * 100) / 15; 1164 else 1165 reg = (reg * 100) / 255; 1166 node.sysctl_data = ® 1167 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1168 1169 if (error || newp == NULL) 1170 return error; 1171 1172 /* We were asked to update the value - sanity check before writing */ 1173 if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 100) 1174 return EINVAL; 1175 1176 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) { 1177 newreg = *(uint8_t *)(node.sysctl_data) * 15 / 100; 1178 newreg |= oldreg & 0xf0; 1179 } else 1180 newreg = *(uint8_t *)(node.sysctl_data) * 255 / 100; 1181 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1182 return 0; 1183 } 1184 1185 static int 1186 sysctl_dbcool_behavior(SYSCTLFN_ARGS) 1187 { 1188 struct sysctlnode node; 1189 struct dbcool_softc *sc; 1190 int i, reg, error; 1191 uint8_t chipreg, oldreg, newreg; 1192 1193 node = *rnode; 1194 sc = (struct dbcool_softc *)node.sysctl_data; 1195 chipreg = node.sysctl_num & 0xff; 1196 1197 oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1198 1199 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) { 1200 if ((sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_CFG2) & 1) == 0) 1201 reg = 4; 1202 else if ((oldreg & 0x80) == 0) 1203 reg = 7; 1204 else if ((oldreg & 0x60) == 0) 1205 reg = 4; 1206 else 1207 reg = 6; 1208 } else 1209 reg = (oldreg >> 5) & 0x07; 1210 1211 strlcpy(dbcool_cur_behav, behavior[reg], sizeof(dbcool_cur_behav)); 1212 node.sysctl_data = dbcool_cur_behav; 1213 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1214 1215 if (error || newp == NULL) 1216 return error; 1217 1218 /* We were asked to update the value - convert string to value */ 1219 newreg = __arraycount(behavior); 1220 for (i = 0; i < __arraycount(behavior); i++) 1221 if (strcmp(node.sysctl_data, behavior[i]) == 0) 1222 break; 1223 if (i >= __arraycount(behavior)) 1224 return EINVAL; 1225 1226 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) { 1227 /* 1228 * ADM1030 splits fan controller behavior across two 1229 * registers. We also do not support Auto-Filter mode 1230 * nor do we support Manual-RPM-feedback. 1231 */ 1232 if (newreg == 4) { 1233 oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_CFG2); 1234 oldreg &= ~0x01; 1235 sc->sc_dc.dc_writereg(&sc->sc_dc, DBCOOL_ADM1030_CFG2, oldreg); 1236 } else { 1237 if (newreg == 0) 1238 newreg = 4; 1239 else if (newreg == 6) 1240 newreg = 7; 1241 else if (newreg == 7) 1242 newreg = 0; 1243 else 1244 return EINVAL; 1245 newreg <<= 5; 1246 newreg |= (oldreg & 0x1f); 1247 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1248 oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_CFG2) | 1; 1249 sc->sc_dc.dc_writereg(&sc->sc_dc, DBCOOL_ADM1030_CFG2, oldreg); 1250 } 1251 } else { 1252 newreg = (sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg) & 0x1f) | (i << 5); 1253 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1254 } 1255 return 0; 1256 } 1257 1258 static int 1259 sysctl_dbcool_slope(SYSCTLFN_ARGS) 1260 { 1261 struct sysctlnode node; 1262 struct dbcool_softc *sc; 1263 int reg, error; 1264 uint8_t chipreg; 1265 uint8_t newreg; 1266 1267 node = *rnode; 1268 sc = (struct dbcool_softc *)node.sysctl_data; 1269 chipreg = node.sysctl_num & 0xff; 1270 1271 reg = (sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg) >> 4) & 0x0f; 1272 node.sysctl_data = ® 1273 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1274 1275 if (error || newp == NULL) 1276 return error; 1277 1278 /* We were asked to update the value - sanity check before writing */ 1279 if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 0x0f) 1280 return EINVAL; 1281 1282 newreg = (sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg) & 0x0f) | 1283 (*(int *)node.sysctl_data << 4); 1284 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1285 return 0; 1286 } 1287 1288 static int 1289 sysctl_dbcool_thyst(SYSCTLFN_ARGS) 1290 { 1291 struct sysctlnode node; 1292 struct dbcool_softc *sc; 1293 int reg, error; 1294 uint8_t chipreg; 1295 uint8_t newreg, newhyst; 1296 1297 node = *rnode; 1298 sc = (struct dbcool_softc *)node.sysctl_data; 1299 chipreg = node.sysctl_num & 0x7f; 1300 1301 /* retrieve 4-bit value */ 1302 newreg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1303 if ((node.sysctl_num & 0x80) == 0) 1304 reg = newreg >> 4; 1305 else 1306 reg = newreg; 1307 reg = reg & 0x0f; 1308 1309 node.sysctl_data = ® 1310 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1311 1312 if (error || newp == NULL) 1313 return error; 1314 1315 /* We were asked to update the value - sanity check before writing */ 1316 newhyst = *(int *)node.sysctl_data; 1317 if (newhyst > 0x0f) 1318 return EINVAL; 1319 1320 /* Insert new value into field and update register */ 1321 if ((node.sysctl_num & 0x80) == 0) { 1322 newreg &= 0x0f; 1323 newreg |= (newhyst << 4); 1324 } else { 1325 newreg &= 0xf0; 1326 newreg |= newhyst; 1327 } 1328 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1329 return 0; 1330 } 1331 1332 #ifdef DBCOOL_DEBUG 1333 1334 /* 1335 * These routines can be used for debugging. reg_select is used to 1336 * select any arbitrary register in the device. reg_access is used 1337 * to read (and optionally update) the selected register. 1338 * 1339 * No attempt is made to validate the data passed. If you use these 1340 * routines, you are assumed to know what you're doing! 1341 * 1342 * Caveat user 1343 */ 1344 static int 1345 sysctl_dbcool_reg_select(SYSCTLFN_ARGS) 1346 { 1347 struct sysctlnode node; 1348 struct dbcool_softc *sc; 1349 int reg, error; 1350 1351 node = *rnode; 1352 sc = (struct dbcool_softc *)node.sysctl_data; 1353 1354 reg = sc->sc_user_reg; 1355 node.sysctl_data = ® 1356 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1357 1358 if (error || newp == NULL) 1359 return error; 1360 1361 sc->sc_user_reg = *(int *)node.sysctl_data; 1362 return 0; 1363 } 1364 1365 static int 1366 sysctl_dbcool_reg_access(SYSCTLFN_ARGS) 1367 { 1368 struct sysctlnode node; 1369 struct dbcool_softc *sc; 1370 int reg, error; 1371 uint8_t chipreg; 1372 uint8_t newreg; 1373 1374 node = *rnode; 1375 sc = (struct dbcool_softc *)node.sysctl_data; 1376 chipreg = sc->sc_user_reg; 1377 1378 reg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg); 1379 node.sysctl_data = ® 1380 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1381 1382 if (error || newp == NULL) 1383 return error; 1384 1385 newreg = *(int *)node.sysctl_data; 1386 sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg); 1387 return 0; 1388 } 1389 #endif /* DBCOOL_DEBUG */ 1390 1391 /* 1392 * Encode an index number and register number for use as a sysctl_num 1393 * so we can select the correct device register later. 1394 */ 1395 #define DBC_PWM_SYSCTL(seq, reg) ((seq << 8) | reg) 1396 1397 void 1398 dbcool_setup(device_t self) 1399 { 1400 struct dbcool_softc *sc = device_private(self); 1401 const struct sysctlnode *me = NULL; 1402 #ifdef DBCOOL_DEBUG 1403 struct sysctlnode *node = NULL; 1404 #endif 1405 uint8_t cfg_val, cfg_reg; 1406 int ret, error; 1407 1408 /* 1409 * Some chips are capable of reporting an extended temperature range 1410 * by default. On these models, config register 5 bit 0 can be set 1411 * to 1 for compatability with other chips that report 2s complement. 1412 */ 1413 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) { 1414 if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADT7466_CONFIG1) & 0x80) 1415 sc->sc_temp_offset = 64; 1416 else 1417 sc->sc_temp_offset = 0; 1418 } else if (sc->sc_dc.dc_chip->flags & DBCFLAG_TEMPOFFSET) { 1419 if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_CONFIG5_REG) & 1420 DBCOOL_CFG5_TWOSCOMP) 1421 sc->sc_temp_offset = 0; 1422 else 1423 sc->sc_temp_offset = 64; 1424 } else 1425 sc->sc_temp_offset = 0; 1426 1427 /* Determine Vcc for this chip */ 1428 sc->sc_supply_voltage = dbcool_supply_voltage(sc); 1429 1430 ret = sysctl_createv(NULL, 0, NULL, &me, 1431 CTLFLAG_READWRITE, 1432 CTLTYPE_NODE, device_xname(self), NULL, 1433 NULL, 0, NULL, 0, 1434 CTL_HW, CTL_CREATE, CTL_EOL); 1435 if (ret == 0) 1436 sc->sc_root_sysctl_num = me->sysctl_num; 1437 else 1438 sc->sc_root_sysctl_num = 0; 1439 1440 aprint_debug_dev(self, 1441 "Supply voltage %"PRId64".%06"PRId64"V, %s temp range\n", 1442 sc->sc_supply_voltage / 1000000, 1443 sc->sc_supply_voltage % 1000000, 1444 sc->sc_temp_offset ? "extended" : "normal"); 1445 1446 /* Create the sensors for this device */ 1447 sc->sc_sme = sysmon_envsys_create(); 1448 if (dbcool_setup_sensors(sc)) 1449 goto out; 1450 1451 if (sc->sc_root_sysctl_num != 0) { 1452 /* If supported, create sysctl tree for fan PWM controllers */ 1453 if (sc->sc_dc.dc_chip->power != NULL) 1454 dbcool_setup_controllers(sc); 1455 1456 #ifdef DBCOOL_DEBUG 1457 ret = sysctl_createv(NULL, 0, NULL, 1458 (const struct sysctlnode **)&node, 1459 CTLFLAG_READWRITE, CTLTYPE_INT, "reg_select", NULL, 1460 sysctl_dbcool_reg_select, 1461 0, sc, sizeof(int), 1462 CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL); 1463 if (node != NULL) 1464 node->sysctl_data = sc; 1465 1466 ret = sysctl_createv(NULL, 0, NULL, 1467 (const struct sysctlnode **)&node, 1468 CTLFLAG_READWRITE, CTLTYPE_INT, "reg_access", NULL, 1469 sysctl_dbcool_reg_access, 1470 0, sc, sizeof(int), 1471 CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL); 1472 if (node != NULL) 1473 node->sysctl_data = sc; 1474 #endif /* DBCOOL_DEBUG */ 1475 } 1476 1477 /* 1478 * Read and rewrite config register to activate device 1479 */ 1480 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) 1481 cfg_reg = DBCOOL_ADM1030_CFG1; 1482 else if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) 1483 cfg_reg = DBCOOL_ADT7466_CONFIG1; 1484 else 1485 cfg_reg = DBCOOL_CONFIG1_REG; 1486 cfg_val = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_CONFIG1_REG); 1487 if ((cfg_val & DBCOOL_CFG1_START) == 0) { 1488 cfg_val |= DBCOOL_CFG1_START; 1489 sc->sc_dc.dc_writereg(&sc->sc_dc, cfg_reg, cfg_val); 1490 } 1491 if (dbcool_islocked(sc)) 1492 aprint_normal_dev(self, "configuration locked\n"); 1493 1494 sc->sc_sme->sme_name = device_xname(self); 1495 sc->sc_sme->sme_cookie = sc; 1496 sc->sc_sme->sme_refresh = dbcool_refresh; 1497 sc->sc_sme->sme_set_limits = dbcool_set_limits; 1498 sc->sc_sme->sme_get_limits = dbcool_get_limits; 1499 1500 if ((error = sysmon_envsys_register(sc->sc_sme)) != 0) { 1501 aprint_error_dev(self, 1502 "unable to register with sysmon (%d)\n", error); 1503 goto out; 1504 } 1505 1506 return; 1507 1508 out: 1509 sysmon_envsys_destroy(sc->sc_sme); 1510 } 1511 1512 static int 1513 dbcool_setup_sensors(struct dbcool_softc *sc) 1514 { 1515 int i; 1516 int error = 0; 1517 uint8_t vid_reg, vid_val; 1518 struct chip_id *chip = sc->sc_dc.dc_chip; 1519 1520 for (i=0; chip->table[i].type != DBC_EOF; i++) { 1521 if (i < DBCOOL_MAXSENSORS) 1522 sc->sc_sysctl_num[i] = -1; 1523 else if (chip->table[i].type != DBC_CTL) { 1524 aprint_normal_dev(sc->sc_dev, "chip table too big!\n"); 1525 break; 1526 } 1527 switch (chip->table[i].type) { 1528 case DBC_TEMP: 1529 sc->sc_sensor[i].units = ENVSYS_STEMP; 1530 sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS; 1531 error = dbcool_attach_sensor(sc, i); 1532 break; 1533 case DBC_VOLT: 1534 /* 1535 * If 12V-In pin has been reconfigured as 6th bit 1536 * of VID code, don't create a 12V-In sensor 1537 */ 1538 if ((chip->flags & DBCFLAG_HAS_VID_SEL) && 1539 (chip->table[i].reg.val_reg == DBCOOL_12VIN) && 1540 (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VID_REG) & 1541 0x80)) 1542 break; 1543 1544 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 1545 sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS; 1546 error = dbcool_attach_sensor(sc, i); 1547 break; 1548 case DBC_FAN: 1549 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 1550 sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS; 1551 error = dbcool_attach_sensor(sc, i); 1552 break; 1553 case DBC_VID: 1554 sc->sc_sensor[i].units = ENVSYS_INTEGER; 1555 sc->sc_sensor[i].flags |= ENVSYS_FMONNOTSUPP; 1556 1557 /* retrieve 5- or 6-bit value */ 1558 vid_reg = chip->table[i].reg.val_reg; 1559 vid_val = sc->sc_dc.dc_readreg(&sc->sc_dc, vid_reg); 1560 if (chip->flags & DBCFLAG_HAS_VID_SEL) 1561 vid_val &= 0x3f; 1562 else 1563 vid_val &= 0x1f; 1564 sc->sc_sensor[i].value_cur = vid_val; 1565 1566 error = dbcool_attach_sensor(sc, i); 1567 break; 1568 case DBC_CTL: 1569 error = dbcool_attach_temp_control(sc, i, chip); 1570 if (error) { 1571 aprint_error_dev(sc->sc_dev, 1572 "attach index %d failed %d\n", 1573 i, error); 1574 error = 0; 1575 } 1576 break; 1577 default: 1578 aprint_error_dev(sc->sc_dev, 1579 "sensor_table index %d has bad type %d\n", 1580 i, chip->table[i].type); 1581 break; 1582 } 1583 if (error) 1584 break; 1585 } 1586 return error; 1587 } 1588 1589 static int 1590 dbcool_attach_sensor(struct dbcool_softc *sc, int idx) 1591 { 1592 int name_index; 1593 int error = 0; 1594 1595 name_index = sc->sc_dc.dc_chip->table[idx].name_index; 1596 strlcpy(sc->sc_sensor[idx].desc, dbc_sensor_names[name_index], 1597 sizeof(sc->sc_sensor[idx].desc)); 1598 sc->sc_regs[idx] = &sc->sc_dc.dc_chip->table[idx].reg; 1599 sc->sc_nom_volt[idx] = sc->sc_dc.dc_chip->table[idx].nom_volt_index; 1600 1601 error = sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[idx]); 1602 return error; 1603 } 1604 1605 static int 1606 dbcool_attach_temp_control(struct dbcool_softc *sc, int idx, 1607 struct chip_id *chip) 1608 { 1609 const struct sysctlnode *me2 = NULL; 1610 struct sysctlnode *node = NULL; 1611 int j, ret, sysctl_index, rw_flag; 1612 uint8_t sysctl_reg; 1613 char name[SYSCTL_NAMELEN]; 1614 1615 /* Search for the corresponding temp sensor */ 1616 for (j = 0; j < idx; j++) { 1617 if (j >= DBCOOL_MAXSENSORS || chip->table[j].type != DBC_TEMP) 1618 continue; 1619 if (chip->table[j].name_index == chip->table[idx].name_index) 1620 break; 1621 } 1622 if (j >= idx) /* Temp sensor not found */ 1623 return ENOENT; 1624 1625 /* create sysctl node for the sensor if not one already there */ 1626 if (sc->sc_sysctl_num[j] == -1) { 1627 ret = sysctl_createv(NULL, 0, NULL, &me2, CTLFLAG_READWRITE, 1628 CTLTYPE_NODE, sc->sc_sensor[j].desc, NULL, 1629 NULL, 0, NULL, 0, 1630 CTL_HW, sc->sc_root_sysctl_num, CTL_CREATE, 1631 CTL_EOL); 1632 if (me2 != NULL) 1633 sc->sc_sysctl_num[j] = me2->sysctl_num; 1634 else 1635 return ret; 1636 } 1637 /* add sysctl leaf node for this control variable */ 1638 sysctl_index = chip->table[idx].sysctl_index; 1639 sysctl_reg = chip->table[idx].reg.val_reg; 1640 strlcpy(name, dbc_sysctl_table[sysctl_index].name, sizeof(name)); 1641 if (dbc_sysctl_table[sysctl_index].lockable && dbcool_islocked(sc)) 1642 rw_flag = CTLFLAG_READONLY | CTLFLAG_OWNDESC; 1643 else 1644 rw_flag = CTLFLAG_READWRITE | CTLFLAG_OWNDESC; 1645 ret = sysctl_createv(NULL, 0, NULL, 1646 (const struct sysctlnode **)&node, rw_flag, 1647 CTLTYPE_INT, name, 1648 SYSCTL_DESCR(dbc_sysctl_table[sysctl_index].desc), 1649 dbc_sysctl_table[sysctl_index].helper, 1650 0, sc, sizeof(int), 1651 CTL_HW, sc->sc_root_sysctl_num, 1652 sc->sc_sysctl_num[j], 1653 DBC_PWM_SYSCTL(idx, sysctl_reg), CTL_EOL); 1654 if (node != NULL) 1655 node->sysctl_data = sc; 1656 1657 return ret; 1658 } 1659 1660 static void 1661 dbcool_setup_controllers(struct dbcool_softc *sc) 1662 { 1663 int i, j, ret, rw_flag; 1664 uint8_t sysctl_reg; 1665 struct chip_id *chip = sc->sc_dc.dc_chip; 1666 const struct sysctlnode *me2 = NULL; 1667 struct sysctlnode *node = NULL; 1668 char name[SYSCTL_NAMELEN]; 1669 1670 for (i = 0; chip->power[i].desc != NULL; i++) { 1671 snprintf(name, sizeof(name), "fan_ctl_%d", i); 1672 ret = sysctl_createv(NULL, 0, NULL, &me2, 1673 CTLFLAG_READWRITE | CTLFLAG_OWNDESC, 1674 CTLTYPE_NODE, name, NULL, 1675 NULL, 0, NULL, 0, 1676 CTL_HW, sc->sc_root_sysctl_num, CTL_CREATE, CTL_EOL); 1677 1678 for (j = DBC_PWM_BEHAVIOR; j < DBC_PWM_LAST_PARAM; j++) { 1679 if (j == DBC_PWM_MAX_DUTY && 1680 (chip->flags & DBCFLAG_HAS_MAXDUTY) == 0) 1681 continue; 1682 sysctl_reg = chip->power[i].power_regs[j]; 1683 if (sysctl_reg == DBCOOL_NO_REG) 1684 continue; 1685 strlcpy(name, dbc_sysctl_table[j].name, sizeof(name)); 1686 if (dbc_sysctl_table[j].lockable && dbcool_islocked(sc)) 1687 rw_flag = CTLFLAG_READONLY | CTLFLAG_OWNDESC; 1688 else 1689 rw_flag = CTLFLAG_READWRITE | CTLFLAG_OWNDESC; 1690 ret = sysctl_createv(NULL, 0, NULL, 1691 (const struct sysctlnode **)&node, rw_flag, 1692 (j == DBC_PWM_BEHAVIOR)? 1693 CTLTYPE_STRING:CTLTYPE_INT, 1694 name, 1695 SYSCTL_DESCR(dbc_sysctl_table[j].desc), 1696 dbc_sysctl_table[j].helper, 1697 0, sc, 1698 ( j == DBC_PWM_BEHAVIOR)? 1699 sizeof(dbcool_cur_behav): sizeof(int), 1700 CTL_HW, sc->sc_root_sysctl_num, me2->sysctl_num, 1701 DBC_PWM_SYSCTL(j, sysctl_reg), CTL_EOL); 1702 if (node != NULL) 1703 node->sysctl_data = sc; 1704 } 1705 } 1706 } 1707 1708 static void 1709 dbcool_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 1710 { 1711 struct dbcool_softc *sc=sme->sme_cookie; 1712 int i, nom_volt_idx, cur; 1713 struct reg_list *reg; 1714 1715 i = edata->sensor; 1716 reg = sc->sc_regs[i]; 1717 1718 edata->state = ENVSYS_SVALID; 1719 switch (edata->units) 1720 { 1721 case ENVSYS_STEMP: 1722 cur = dbcool_read_temp(sc, reg->val_reg, true); 1723 break; 1724 case ENVSYS_SVOLTS_DC: 1725 nom_volt_idx = sc->sc_nom_volt[i]; 1726 cur = dbcool_read_volt(sc, reg->val_reg, nom_volt_idx, 1727 true); 1728 break; 1729 case ENVSYS_SFANRPM: 1730 cur = dbcool_read_rpm(sc, reg->val_reg); 1731 break; 1732 case ENVSYS_INTEGER: 1733 return; 1734 default: 1735 edata->state = ENVSYS_SINVALID; 1736 return; 1737 } 1738 1739 if (cur == 0 && (edata->units != ENVSYS_SFANRPM)) 1740 edata->state = ENVSYS_SINVALID; 1741 1742 /* 1743 * If fan is "stalled" but has no low limit, treat 1744 * it as though the fan is not installed. 1745 */ 1746 else if (edata->units == ENVSYS_SFANRPM && cur == 0 && 1747 !(edata->upropset & (PROP_CRITMIN | PROP_WARNMIN))) 1748 edata->state = ENVSYS_SINVALID; 1749 1750 edata->value_cur = cur; 1751 } 1752 1753 int 1754 dbcool_chip_ident(struct dbcool_chipset *dc) 1755 { 1756 /* verify this is a supported dbCool chip */ 1757 uint8_t c_id, d_id, r_id; 1758 int i; 1759 1760 c_id = dc->dc_readreg(dc, DBCOOL_COMPANYID_REG); 1761 d_id = dc->dc_readreg(dc, DBCOOL_DEVICEID_REG); 1762 r_id = dc->dc_readreg(dc, DBCOOL_REVISION_REG); 1763 1764 for (i = 0; chip_table[i].company != 0; i++) 1765 if ((c_id == chip_table[i].company) && 1766 (d_id == chip_table[i].device || 1767 chip_table[i].device == 0xff) && 1768 (r_id == chip_table[i].rev || 1769 chip_table[i].rev == 0xff)) { 1770 dc->dc_chip = &chip_table[i]; 1771 return i; 1772 } 1773 1774 aprint_verbose("dbcool_chip_ident: addr 0x%02x c_id 0x%02x d_id 0x%02x" 1775 " r_id 0x%02x: No match.\n", dc->dc_addr, c_id, d_id, 1776 r_id); 1777 1778 return -1; 1779 } 1780 1781 /* 1782 * Retrieve sensor limits from the chip registers 1783 */ 1784 static void 1785 dbcool_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 1786 sysmon_envsys_lim_t *limits, uint32_t *props) 1787 { 1788 int index = edata->sensor; 1789 struct dbcool_softc *sc = sme->sme_cookie; 1790 1791 *props &= ~(PROP_CRITMIN | PROP_CRITMAX); 1792 switch (edata->units) { 1793 case ENVSYS_STEMP: 1794 dbcool_get_temp_limits(sc, index, limits, props); 1795 break; 1796 case ENVSYS_SVOLTS_DC: 1797 dbcool_get_volt_limits(sc, index, limits, props); 1798 break; 1799 case ENVSYS_SFANRPM: 1800 dbcool_get_fan_limits(sc, index, limits, props); 1801 1802 /* FALLTHROUGH */ 1803 default: 1804 break; 1805 } 1806 *props &= ~PROP_DRIVER_LIMITS; 1807 1808 /* If both limits provided, make sure they're sane */ 1809 if ((*props & PROP_CRITMIN) && 1810 (*props & PROP_CRITMAX) && 1811 (limits->sel_critmin >= limits->sel_critmax)) 1812 *props &= ~(PROP_CRITMIN | PROP_CRITMAX); 1813 1814 /* 1815 * If this is the first time through, save these values 1816 * in case user overrides them and then requests a reset. 1817 */ 1818 if (sc->sc_defprops[index] == 0) { 1819 sc->sc_defprops[index] = *props | PROP_DRIVER_LIMITS; 1820 sc->sc_deflims[index] = *limits; 1821 } 1822 } 1823 1824 static void 1825 dbcool_get_temp_limits(struct dbcool_softc *sc, int idx, 1826 sysmon_envsys_lim_t *lims, uint32_t *props) 1827 { 1828 struct reg_list *reg = sc->sc_regs[idx]; 1829 uint8_t lo_lim, hi_lim; 1830 1831 lo_lim = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->lo_lim_reg); 1832 hi_lim = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->hi_lim_reg); 1833 1834 if (sc->sc_temp_offset) { 1835 if (lo_lim > 0x01) { 1836 lims->sel_critmin = lo_lim - sc->sc_temp_offset; 1837 *props |= PROP_CRITMIN; 1838 } 1839 if (hi_lim != 0xff) { 1840 lims->sel_critmax = hi_lim - sc->sc_temp_offset; 1841 *props |= PROP_CRITMAX; 1842 } 1843 } else { 1844 if (lo_lim != 0x80 && lo_lim != 0x81) { 1845 lims->sel_critmin = (int8_t)lo_lim; 1846 *props |= PROP_CRITMIN; 1847 } 1848 1849 if (hi_lim != 0x7f) { 1850 lims->sel_critmax = (int8_t)hi_lim; 1851 *props |= PROP_CRITMAX; 1852 } 1853 } 1854 1855 /* Convert temp limits to microKelvin */ 1856 lims->sel_critmin *= 1000000; 1857 lims->sel_critmin += 273150000; 1858 lims->sel_critmax *= 1000000; 1859 lims->sel_critmax += 273150000; 1860 } 1861 1862 static void 1863 dbcool_get_volt_limits(struct dbcool_softc *sc, int idx, 1864 sysmon_envsys_lim_t *lims, uint32_t *props) 1865 { 1866 struct reg_list *reg = sc->sc_regs[idx]; 1867 int64_t limit; 1868 int nom; 1869 1870 nom = nominal_voltages[sc->sc_dc.dc_chip->table[idx].nom_volt_index]; 1871 if (nom < 0) 1872 nom = dbcool_supply_voltage(sc); 1873 nom *= 1000000; /* scale for microvolts */ 1874 1875 limit = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->lo_lim_reg); 1876 if (limit != 0x00 && limit != 0xff) { 1877 limit *= nom; 1878 limit /= 0xc0; 1879 lims->sel_critmin = limit; 1880 *props |= PROP_CRITMIN; 1881 } 1882 limit = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->hi_lim_reg); 1883 if (limit != 0x00 && limit != 0xff) { 1884 limit *= nom; 1885 limit /= 0xc0; 1886 lims->sel_critmax = limit; 1887 *props |= PROP_CRITMAX; 1888 } 1889 } 1890 1891 static void 1892 dbcool_get_fan_limits(struct dbcool_softc *sc, int idx, 1893 sysmon_envsys_lim_t *lims, uint32_t *props) 1894 { 1895 struct reg_list *reg = sc->sc_regs[idx]; 1896 int32_t limit; 1897 1898 limit = dbcool_read_rpm(sc, reg->lo_lim_reg); 1899 if (limit) { 1900 lims->sel_critmin = limit; 1901 *props |= PROP_CRITMIN; 1902 } 1903 } 1904 1905 /* 1906 * Update sensor limits in the chip registers 1907 */ 1908 static void 1909 dbcool_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 1910 sysmon_envsys_lim_t *limits, uint32_t *props) 1911 { 1912 int index = edata->sensor; 1913 struct dbcool_softc *sc = sme->sme_cookie; 1914 1915 if (limits == NULL) { 1916 limits = &sc->sc_deflims[index]; 1917 props = &sc->sc_defprops[index]; 1918 } 1919 switch (edata->units) { 1920 case ENVSYS_STEMP: 1921 dbcool_set_temp_limits(sc, index, limits, props); 1922 break; 1923 case ENVSYS_SVOLTS_DC: 1924 dbcool_set_volt_limits(sc, index, limits, props); 1925 break; 1926 case ENVSYS_SFANRPM: 1927 dbcool_set_fan_limits(sc, index, limits, props); 1928 1929 /* FALLTHROUGH */ 1930 default: 1931 break; 1932 } 1933 *props &= ~PROP_DRIVER_LIMITS; 1934 } 1935 1936 static void 1937 dbcool_set_temp_limits(struct dbcool_softc *sc, int idx, 1938 sysmon_envsys_lim_t *lims, uint32_t *props) 1939 { 1940 struct reg_list *reg = sc->sc_regs[idx]; 1941 int32_t limit; 1942 1943 if (*props & PROP_CRITMIN) { 1944 limit = lims->sel_critmin - 273150000; 1945 limit /= 1000000; 1946 if (sc->sc_temp_offset) { 1947 limit += sc->sc_temp_offset; 1948 if (limit < 0) 1949 limit = 0; 1950 else if (limit > 255) 1951 limit = 255; 1952 } else { 1953 if (limit < -127) 1954 limit = -127; 1955 else if (limit > 127) 1956 limit = 127; 1957 } 1958 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 1959 (uint8_t)limit); 1960 } else if (*props & PROP_DRIVER_LIMITS) { 1961 if (sc->sc_temp_offset) 1962 limit = 0x00; 1963 else 1964 limit = 0x80; 1965 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 1966 (uint8_t)limit); 1967 } 1968 1969 if (*props & PROP_CRITMAX) { 1970 limit = lims->sel_critmax - 273150000; 1971 limit /= 1000000; 1972 if (sc->sc_temp_offset) { 1973 limit += sc->sc_temp_offset; 1974 if (limit < 0) 1975 limit = 0; 1976 else if (limit > 255) 1977 limit = 255; 1978 } else { 1979 if (limit < -127) 1980 limit = -127; 1981 else if (limit > 127) 1982 limit = 127; 1983 } 1984 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg, 1985 (uint8_t)limit); 1986 } else if (*props & PROP_DRIVER_LIMITS) { 1987 if (sc->sc_temp_offset) 1988 limit = 0xff; 1989 else 1990 limit = 0x7f; 1991 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg, 1992 (uint8_t)limit); 1993 } 1994 } 1995 1996 static void 1997 dbcool_set_volt_limits(struct dbcool_softc *sc, int idx, 1998 sysmon_envsys_lim_t *lims, uint32_t *props) 1999 { 2000 struct reg_list *reg = sc->sc_regs[idx]; 2001 int64_t limit; 2002 int nom; 2003 2004 nom = nominal_voltages[sc->sc_dc.dc_chip->table[idx].nom_volt_index]; 2005 if (nom < 0) 2006 nom = dbcool_supply_voltage(sc); 2007 nom *= 1000000; /* scale for microvolts */ 2008 2009 if (*props & PROP_CRITMIN) { 2010 limit = lims->sel_critmin; 2011 limit *= 0xc0; 2012 limit /= nom; 2013 if (limit > 0xff) 2014 limit = 0xff; 2015 else if (limit < 0) 2016 limit = 0; 2017 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, limit); 2018 } else if (*props & PROP_DRIVER_LIMITS) 2019 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 0); 2020 2021 if (*props & PROP_CRITMAX) { 2022 limit = lims->sel_critmax; 2023 limit *= 0xc0; 2024 limit /= nom; 2025 if (limit > 0xff) 2026 limit = 0xff; 2027 else if (limit < 0) 2028 limit = 0; 2029 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg, limit); 2030 } else if (*props & PROP_DRIVER_LIMITS) 2031 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg, 0xff); 2032 } 2033 2034 static void 2035 dbcool_set_fan_limits(struct dbcool_softc *sc, int idx, 2036 sysmon_envsys_lim_t *lims, uint32_t *props) 2037 { 2038 struct reg_list *reg = sc->sc_regs[idx]; 2039 int32_t limit, dividend; 2040 2041 if (*props & PROP_CRITMIN) { 2042 limit = lims->sel_critmin; 2043 if (limit == 0) 2044 limit = 0xffff; 2045 else { 2046 if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) 2047 dividend = 11250 * 60; 2048 else 2049 dividend = 90000 * 60; 2050 limit = limit / dividend; 2051 if (limit > 0xffff) 2052 limit = 0xffff; 2053 } 2054 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 2055 limit & 0xff); 2056 limit >>= 8; 2057 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg + 1, 2058 limit & 0xff); 2059 } else if (*props & PROP_DRIVER_LIMITS) { 2060 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 0xff); 2061 sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg + 1, 0xff); 2062 } 2063 } 2064