1 /* $NetBSD: tmp121.c,v 1.2 2007/07/01 07:37:21 xtraeme Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Urbana-Champaign Independent Media Center. 5 * Copyright (c) 2006 Garrett D'Amore. 6 * All rights reserved. 7 * 8 * Portions of this code were written by Garrett D'Amore for the 9 * Champaign-Urbana Community Wireless Network Project. 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer in the documentation and/or other materials provided 19 * with the distribution. 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgements: 22 * This product includes software developed by the Urbana-Champaign 23 * Independent Media Center. 24 * This product includes software developed by Garrett D'Amore. 25 * 4. Urbana-Champaign Independent Media Center's name and Garrett 26 * D'Amore's name may not be used to endorse or promote products 27 * derived from this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT 30 * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT 34 * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 #include <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: tmp121.c,v 1.2 2007/07/01 07:37:21 xtraeme Exp $"); 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/device.h> 50 #include <sys/kernel.h> 51 52 #include <dev/sysmon/sysmonvar.h> 53 54 #include <dev/spi/spivar.h> 55 56 struct tmp121temp_softc { 57 struct device sc_dev; 58 59 struct spi_handle *sc_sh; 60 61 struct envsys_data sc_sensor[1]; 62 63 struct sysmon_envsys sc_sysmon; 64 }; 65 66 static int tmp121temp_match(struct device *, struct cfdata *, void *); 67 static void tmp121temp_attach(struct device *, struct device *, void *); 68 69 static int tmp121temp_gtredata(struct sysmon_envsys *, envsys_data_t *); 70 71 CFATTACH_DECL(tmp121temp, sizeof(struct tmp121temp_softc), 72 tmp121temp_match, tmp121temp_attach, NULL, NULL); 73 74 static int 75 tmp121temp_match(struct device *parent, struct cfdata *cf, void *aux) 76 { 77 struct spi_attach_args *sa = aux; 78 79 /* configure for 10MHz */ 80 if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000)) 81 return 0; 82 83 return 1; 84 } 85 86 static void 87 tmp121temp_attach(struct device *parent, struct device *self, void *aux) 88 { 89 struct tmp121temp_softc *sc = device_private(self); 90 struct spi_attach_args *sa = aux; 91 prop_string_t desc; 92 93 aprint_naive(": Temperature Sensor\n"); 94 aprint_normal(": TI TMP121 Temperature Sensor\n"); 95 96 sc->sc_sh = sa->sa_handle; 97 98 sc->sc_sensor[0].sensor = 0; 99 sc->sc_sensor[0].state = ENVSYS_SVALID; 100 sc->sc_sensor[0].units = ENVSYS_STEMP; 101 102 /* 103 * set up the description, which we allow MD code to override in 104 * a property. 105 */ 106 desc = prop_dictionary_get(device_properties(self), 107 "envsys-description"); 108 if (desc != NULL && 109 prop_object_type(desc) == PROP_TYPE_STRING && 110 prop_string_size(desc) > 0) 111 strcpy(sc->sc_sensor[0].desc, prop_string_cstring_nocopy(desc)); 112 else 113 strcpy(sc->sc_sensor[0].desc, device_xname(self)); 114 115 sc->sc_sysmon.sme_name = device_xname(self); 116 sc->sc_sysmon.sme_sensor_data = sc->sc_sensor; 117 sc->sc_sysmon.sme_gtredata = tmp121temp_gtredata; 118 sc->sc_sysmon.sme_cookie = sc; 119 sc->sc_sysmon.sme_nsensors = 1; 120 121 if (sysmon_envsys_register(&sc->sc_sysmon)) 122 aprint_error("%s: unable to register with sysmon\n", 123 device_xname(self)); 124 125 } 126 127 static void 128 tmp121temp_refresh(struct tmp121temp_softc *sc) 129 { 130 uint16_t reg; 131 int16_t sreg; 132 int val; 133 134 if (spi_recv(sc->sc_sh, 2, (uint8_t *)®) != 0) { 135 sc->sc_sensor[0].state = ENVSYS_SINVALID; 136 return; 137 } 138 139 sreg = (int16_t)be16toh(reg); 140 141 /* 142 * convert to uK: 143 * 144 * TMP121 bits: 145 * D15 : sign bit 146 * D14-D3 : data (D14 is MSB) 147 * D2-D0 : zero 148 * 149 * The data is represented in units of 0.0625 deg C. 150 */ 151 sreg >>= 3; 152 val = sreg * 62500 + 273150000; 153 154 sc->sc_sensor[0].value_cur = val; 155 sc->sc_sensor[0].state = ENVSYS_SVALID; 156 } 157 158 static int 159 tmp121temp_gtredata(struct sysmon_envsys *sme, envsys_data_t *edata) 160 { 161 struct tmp121temp_softc *sc = sme->sme_cookie; 162 163 tmp121temp_refresh(sc); 164 return (0); 165 } 166