1 /* $OpenBSD: sdtemp.c,v 1.7 2009/04/22 01:09:23 cnst 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 87 if (sensor_task_register(sc, sdtemp_refresh, 5) == NULL) { 88 printf(", unable to register update task\n"); 89 return; 90 } 91 92 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]); 93 sensordev_install(&sc->sc_sensordev); 94 95 printf("\n"); 96 } 97 98 void 99 sdtemp_refresh(void *arg) 100 { 101 struct sdtemp_softc *sc = arg; 102 u_int8_t cmd; 103 int16_t data, sdata; 104 105 iic_acquire_bus(sc->sc_tag, 0); 106 107 cmd = JC_TEMP; 108 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 109 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { 110 sdata = betoh16(data) & 0x0fff; 111 if (betoh16(data) & JC_TEMP_SIGN) 112 sdata = -sdata; 113 sc->sc_sensor[JCTEMP_TEMP].value = 114 273150000 + 62500 * sdata; 115 sc->sc_sensor[JCTEMP_TEMP].flags &= ~SENSOR_FINVALID; 116 #if 0 117 printf("sdtemp %04x %04x %d\n", data & 0xffff, 118 (u_int)sdata & 0xffff, 119 sc->sc_sensor[JCTEMP_TEMP].value); 120 #endif 121 } 122 123 iic_release_bus(sc->sc_tag, 0); 124 } 125