1 /* $OpenBSD: sdtemp.c,v 1.6 2008/11/13 17:57:15 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 strcmp(ia->ia_name, "stts424e02") == 0) 66 return (1); 67 return (0); 68 } 69 70 void 71 sdtemp_attach(struct device *parent, struct device *self, void *aux) 72 { 73 struct sdtemp_softc *sc = (struct sdtemp_softc *)self; 74 struct i2c_attach_args *ia = aux; 75 76 sc->sc_tag = ia->ia_tag; 77 sc->sc_addr = ia->ia_addr; 78 79 printf(": %s", ia->ia_name); 80 81 /* Initialize sensor data. */ 82 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 83 sizeof(sc->sc_sensordev.xname)); 84 85 sc->sc_sensor[JCTEMP_TEMP].type = SENSOR_TEMP; 86 strlcpy(sc->sc_sensor[JCTEMP_TEMP].desc, "Temperature", 87 sizeof(sc->sc_sensor[JCTEMP_TEMP].desc)); 88 89 if (sensor_task_register(sc, sdtemp_refresh, 5) == NULL) { 90 printf(", unable to register update task\n"); 91 return; 92 } 93 94 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]); 95 sensordev_install(&sc->sc_sensordev); 96 97 printf("\n"); 98 } 99 100 void 101 sdtemp_refresh(void *arg) 102 { 103 struct sdtemp_softc *sc = arg; 104 u_int8_t cmd; 105 int16_t data, sdata; 106 107 iic_acquire_bus(sc->sc_tag, 0); 108 109 cmd = JC_TEMP; 110 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 111 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { 112 sdata = betoh16(data) & 0x0fff; 113 if (betoh16(data) & JC_TEMP_SIGN) 114 sdata = -sdata; 115 sc->sc_sensor[JCTEMP_TEMP].value = 116 273150000 + 62500 * sdata; 117 sc->sc_sensor[JCTEMP_TEMP].flags &= ~SENSOR_FINVALID; 118 #if 0 119 printf("sdtemp %04x %04x %d\n", data & 0xffff, 120 (u_int)sdata & 0xffff, 121 sc->sc_sensor[JCTEMP_TEMP].value); 122 #endif 123 } 124 125 iic_release_bus(sc->sc_tag, 0); 126 } 127