xref: /netbsd-src/sys/dev/spi/tmp121.c (revision ce2c90c7c172d95d2402a5b3d96d8f8e6d138a21)
1 /* $NetBSD: tmp121.c,v 1.1 2006/10/02 07:18:19 gdamore 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.1 2006/10/02 07:18:19 gdamore 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_tre_data sc_sensor[1];
62 	struct envsys_basic_info sc_info[1];
63 
64 	struct sysmon_envsys sc_sysmon;
65 };
66 
67 static int tmp121temp_match(struct device *, struct cfdata *, void *);
68 static void tmp121temp_attach(struct device *, struct device *, void *);
69 
70 static int tmp121temp_gtredata(struct sysmon_envsys *,
71     struct envsys_tre_data *);
72 static int tmp121temp_streinfo(struct sysmon_envsys *,
73     struct envsys_basic_info *);
74 
75 CFATTACH_DECL(tmp121temp, sizeof(struct tmp121temp_softc),
76     tmp121temp_match, tmp121temp_attach, NULL, NULL);
77 
78 
79 static const struct envsys_range tmp121temp_ranges[] = {
80 	/* this looks suspect to me, manual says ranges are inclusive */
81 	{ 0, 1,	ENVSYS_STEMP },
82 	{ 1, 0,	-1 },
83 };
84 
85 static int
86 tmp121temp_match(struct device *parent, struct cfdata *cf, void *aux)
87 {
88 	struct spi_attach_args *sa = aux;
89 
90 	/* configure for 10MHz */
91 	if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000))
92 		return 0;
93 
94 	return 1;
95 }
96 
97 static void
98 tmp121temp_attach(struct device *parent, struct device *self, void *aux)
99 {
100 	struct tmp121temp_softc *sc = device_private(self);
101 	struct spi_attach_args *sa = aux;
102 	prop_string_t desc;
103 
104 	aprint_naive(": Temperature Sensor\n");
105 	aprint_normal(": TI TMP121 Temperature Sensor\n");
106 
107 	sc->sc_sh = sa->sa_handle;
108 
109 	sc->sc_info[0].sensor = 0;
110 	sc->sc_info[0].validflags = ENVSYS_FVALID;
111 
112 	sc->sc_sensor[0].sensor = 0;
113 	sc->sc_sensor[0].validflags = ENVSYS_FVALID;
114 	sc->sc_sensor[0].warnflags = ENVSYS_WARN_OK;
115 	sc->sc_sensor[0].units = sc->sc_info[0].units = ENVSYS_STEMP;
116 
117 	/*
118 	 * set up the description, which we allow MD code to override in
119 	 * a property.
120 	 */
121 	desc = prop_dictionary_get(device_properties(self),
122 	    "envsys-description");
123 	if (desc != NULL &&
124 	    prop_object_type(desc) == PROP_TYPE_STRING &&
125 	    prop_string_size(desc) > 0)
126 		strcpy(sc->sc_info[0].desc, prop_string_cstring_nocopy(desc));
127 	else
128 		strcpy(sc->sc_info[0].desc, device_xname(self));
129 
130 
131 	sc->sc_sysmon.sme_ranges = tmp121temp_ranges;
132 	sc->sc_sysmon.sme_sensor_info = sc->sc_info;
133 	sc->sc_sysmon.sme_sensor_data = sc->sc_sensor;
134 	sc->sc_sysmon.sme_gtredata = tmp121temp_gtredata;
135 	sc->sc_sysmon.sme_streinfo = tmp121temp_streinfo;
136 	sc->sc_sysmon.sme_cookie = sc;
137 	sc->sc_sysmon.sme_nsensors = 1;
138 	sc->sc_sysmon.sme_envsys_version = 1000;
139 
140 	if (sysmon_envsys_register(&sc->sc_sysmon))
141 		aprint_error("%s: unable to register with sysmon\n",
142 		    device_xname(self));
143 
144 }
145 
146 static void
147 tmp121temp_refresh(struct tmp121temp_softc *sc)
148 {
149 	uint16_t		reg;
150 	int16_t			sreg;
151 	int			val;
152 
153 	if (spi_recv(sc->sc_sh, 2, (uint8_t *)&reg) != 0) {
154 		sc->sc_sensor[0].validflags &= ~ENVSYS_FCURVALID;
155 		return;
156 	}
157 
158 	sreg = (int16_t)be16toh(reg);
159 
160 	/*
161 	 * convert to uK:
162 	 *
163 	 * TMP121 bits:
164 	 * D15		: sign bit
165 	 * D14-D3	: data (D14 is MSB)
166 	 * D2-D0	: zero
167 	 *
168 	 * The data is represented in units of 0.0625 deg C.
169 	 */
170 	sreg >>= 3;
171 	val = sreg * 62500 + 273150000;
172 
173 	sc->sc_sensor[0].cur.data_us = val;
174 	sc->sc_sensor[0].validflags |= ENVSYS_FCURVALID;
175 }
176 
177 static int
178 tmp121temp_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
179 {
180 	struct tmp121temp_softc *sc = sme->sme_cookie;
181 
182 	/*
183 	 * XXX: locking?  possibly we could copy out bad sensor data.
184 	 * I'm not going to worry about it right now -- sysmon is probably
185 	 * single threaded anyway.
186 	 */
187 
188 	tmp121temp_refresh(sc);
189 	*tred = sc->sc_sensor[tred->sensor];
190 
191 	return (0);
192 }
193 
194 static int
195 tmp121temp_streinfo(struct sysmon_envsys *sme, struct envsys_basic_info *binfo)
196 {
197 	struct tmp121temp_softc *sc = sme->sme_cookie;
198 
199 	memcpy(sc->sc_info[binfo->sensor].desc, binfo->desc,
200 	    sizeof(sc->sc_info[binfo->sensor].desc));
201 	sc->sc_info[binfo->sensor].desc[
202 	    sizeof(sc->sc_info[binfo->sensor].desc) - 1] = '\0';
203 
204 	binfo->validflags = ENVSYS_FVALID;
205 
206 	return (0);
207 }
208