1 /* $OpenBSD: thmc50.c,v 1.5 2022/04/06 18:59:28 naddy Exp $ */ 2 3 /* 4 * Copyright (c) 2007 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 /* THMC50 registers */ 27 #define THMC50_TEMP0 0x27 28 #define THMC50_TEMP1 0x26 29 #define THMC50_TEMP2 0x20 30 31 /* Sensors */ 32 #define THMC_TEMP0 0 33 #define THMC_TEMP1 1 34 #define THMC_TEMP2 2 35 #define THMC_NUM_SENSORS 3 36 37 struct thmc_softc { 38 struct device sc_dev; 39 i2c_tag_t sc_tag; 40 i2c_addr_t sc_addr; 41 42 struct ksensor sc_sensor[THMC_NUM_SENSORS]; 43 struct ksensordev sc_sensordev; 44 }; 45 46 int thmc_match(struct device *, void *, void *); 47 void thmc_attach(struct device *, struct device *, void *); 48 void thmc_refresh(void *); 49 50 const struct cfattach thmc_ca = { 51 sizeof(struct thmc_softc), thmc_match, thmc_attach 52 }; 53 54 struct cfdriver thmc_cd = { 55 NULL, "thmc", DV_DULL 56 }; 57 58 int 59 thmc_match(struct device *parent, void *match, void *aux) 60 { 61 struct i2c_attach_args *ia = aux; 62 63 if (strcmp(ia->ia_name, "thmc50") == 0 || 64 strcmp(ia->ia_name, "adm1022") == 0 || 65 strcmp(ia->ia_name, "adm1028") == 0) 66 return (1); 67 return (0); 68 } 69 70 void 71 thmc_attach(struct device *parent, struct device *self, void *aux) 72 { 73 struct thmc_softc *sc = (struct thmc_softc *)self; 74 struct i2c_attach_args *ia = aux; 75 int numsensors = THMC_NUM_SENSORS; 76 int i; 77 78 sc->sc_tag = ia->ia_tag; 79 sc->sc_addr = ia->ia_addr; 80 81 printf(": %s", ia->ia_name); 82 83 /* Initialize sensor data. */ 84 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 85 sizeof(sc->sc_sensordev.xname)); 86 87 sc->sc_sensor[THMC_TEMP0].type = SENSOR_TEMP; 88 strlcpy(sc->sc_sensor[THMC_TEMP0].desc, "Internal", 89 sizeof(sc->sc_sensor[THMC_TEMP0].desc)); 90 91 sc->sc_sensor[THMC_TEMP1].type = SENSOR_TEMP; 92 strlcpy(sc->sc_sensor[THMC_TEMP1].desc, "External", 93 sizeof(sc->sc_sensor[THMC_TEMP1].desc)); 94 95 if (strcmp(ia->ia_name, "adm1022") == 0) { 96 /* Only the adm1022 has a THMC50_TEMP2 sensor */ 97 sc->sc_sensor[THMC_TEMP2].type = SENSOR_TEMP; 98 strlcpy(sc->sc_sensor[THMC_TEMP2].desc, "External", 99 sizeof(sc->sc_sensor[THMC_TEMP2].desc)); 100 } else { 101 sc->sc_sensor[THMC_TEMP2].type = -1; 102 numsensors--; 103 } 104 105 if (sensor_task_register(sc, thmc_refresh, 5) == NULL) { 106 printf(", unable to register update task\n"); 107 return; 108 } 109 110 for (i = 0; i < numsensors; i++) 111 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); 112 sensordev_install(&sc->sc_sensordev); 113 114 printf("\n"); 115 } 116 117 void 118 thmc_refresh(void *arg) 119 { 120 struct thmc_softc *sc = arg; 121 u_int8_t cmd; 122 int8_t sdata; 123 124 iic_acquire_bus(sc->sc_tag, 0); 125 126 cmd = THMC50_TEMP0; 127 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 128 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) { 129 sc->sc_sensor[THMC_TEMP0].value = 273150000 + 1000000 * sdata; 130 sc->sc_sensor[THMC_TEMP0].flags &= ~SENSOR_FINVALID; 131 } else 132 sc->sc_sensor[THMC_TEMP0].flags |= SENSOR_FINVALID; 133 134 cmd = THMC50_TEMP1; 135 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 136 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) { 137 sc->sc_sensor[THMC_TEMP1].value = 273150000 + 1000000 * sdata; 138 sc->sc_sensor[THMC_TEMP1].flags &= ~SENSOR_FINVALID; 139 } else 140 sc->sc_sensor[THMC_TEMP1].flags |= SENSOR_FINVALID; 141 142 if (sc->sc_sensor[THMC_TEMP2].type > 0) { 143 cmd = THMC50_TEMP2; 144 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 145 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) { 146 sc->sc_sensor[THMC_TEMP2].value = 273150000 + 1000000 * sdata; 147 sc->sc_sensor[THMC_TEMP2].flags &= ~SENSOR_FINVALID; 148 } else 149 sc->sc_sensor[THMC_TEMP2].flags |= SENSOR_FINVALID; 150 } 151 152 iic_release_bus(sc->sc_tag, 0); 153 } 154