1 /* $OpenBSD: sdtemp.c,v 1.5 2008/04/17 19:01:48 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2008 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 /* JDEC JC-42.4 registers */ 27 #define JC_TEMP 0x05 28 #define JC_TEMP_SIGN 0x10 29 30 /* Sensors */ 31 #define JCTEMP_TEMP 0 32 #define JCTEMP_NUM_SENSORS 1 33 34 struct sdtemp_softc { 35 struct device sc_dev; 36 i2c_tag_t sc_tag; 37 i2c_addr_t sc_addr; 38 39 struct ksensor sc_sensor[JCTEMP_NUM_SENSORS]; 40 struct ksensordev sc_sensordev; 41 }; 42 43 int sdtemp_match(struct device *, void *, void *); 44 void sdtemp_attach(struct device *, struct device *, void *); 45 void sdtemp_refresh(void *); 46 47 struct cfattach sdtemp_ca = { 48 sizeof(struct sdtemp_softc), sdtemp_match, sdtemp_attach 49 }; 50 51 struct cfdriver sdtemp_cd = { 52 NULL, "sdtemp", DV_DULL 53 }; 54 55 int 56 sdtemp_match(struct device *parent, void *match, void *aux) 57 { 58 struct i2c_attach_args *ia = aux; 59 60 if (strcmp(ia->ia_name, "se97") == 0 || 61 strcmp(ia->ia_name, "se98") == 0 || 62 strcmp(ia->ia_name, "mcp9805") == 0 || 63 strcmp(ia->ia_name, "mcp98242") == 0 || 64 strcmp(ia->ia_name, "adt7408") == 0) 65 return (1); 66 return (0); 67 } 68 69 void 70 sdtemp_attach(struct device *parent, struct device *self, void *aux) 71 { 72 struct sdtemp_softc *sc = (struct sdtemp_softc *)self; 73 struct i2c_attach_args *ia = aux; 74 75 sc->sc_tag = ia->ia_tag; 76 sc->sc_addr = ia->ia_addr; 77 78 printf(": %s", ia->ia_name); 79 80 /* Initialize sensor data. */ 81 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 82 sizeof(sc->sc_sensordev.xname)); 83 84 sc->sc_sensor[JCTEMP_TEMP].type = SENSOR_TEMP; 85 strlcpy(sc->sc_sensor[JCTEMP_TEMP].desc, "Temperature", 86 sizeof(sc->sc_sensor[JCTEMP_TEMP].desc)); 87 88 if (sensor_task_register(sc, sdtemp_refresh, 5) == NULL) { 89 printf(", unable to register update task\n"); 90 return; 91 } 92 93 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]); 94 sensordev_install(&sc->sc_sensordev); 95 96 printf("\n"); 97 } 98 99 void 100 sdtemp_refresh(void *arg) 101 { 102 struct sdtemp_softc *sc = arg; 103 u_int8_t cmd; 104 int16_t data, sdata; 105 106 iic_acquire_bus(sc->sc_tag, 0); 107 108 cmd = JC_TEMP; 109 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 110 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { 111 sdata = betoh16(data) & 0x0fff; 112 if (betoh16(data) & JC_TEMP_SIGN) 113 sdata = -sdata; 114 sc->sc_sensor[JCTEMP_TEMP].value = 115 273150000 + 62500 * sdata; 116 sc->sc_sensor[JCTEMP_TEMP].flags &= ~SENSOR_FINVALID; 117 #if 0 118 printf("sdtemp %04x %04x %d\n", data & 0xffff, 119 (u_int)sdata & 0xffff, 120 sc->sc_sensor[JCTEMP_TEMP].value); 121 #endif 122 } 123 124 iic_release_bus(sc->sc_tag, 0); 125 } 126