Annotation of sys/dev/onewire/owsbm.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: owsbm.c,v 1.4 2007/06/24 05:34:35 dlg Exp $ */
2:
3: /*
4: * Copyright (c) 2007 Aaron Linville <aaron@linville.org>
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: /*
20: * 1-Wire Smart Battery Monitor family type device driver.
21: * Provides on-board temperature, an A/D converter for voltage/current,
22: * current accumulator, elapsed time metter, and 40 bytes of nonvolatile
23: * memory.
24: */
25:
26: #include <sys/param.h>
27: #include <sys/systm.h>
28: #include <sys/device.h>
29: #include <sys/kernel.h>
30: #include <sys/proc.h>
31: #include <sys/rwlock.h>
32: #include <sys/sensors.h>
33:
34: #include <dev/onewire/onewiredevs.h>
35: #include <dev/onewire/onewirereg.h>
36: #include <dev/onewire/onewirevar.h>
37:
38: /* Commands */
39: #define DSSBM_CMD_READ_SCRATCHPAD 0xbe
40: #define DSSBM_CMD_WRITE_SCRATCHPAD 0x4e
41: #define DSSBM_CMD_COPY_SCRATCHPAD 0x48
42:
43: #define DSSBM_CMD_RECALL_MEMORY 0xb8
44:
45: #define DSSBM_CMD_CONVERT_T 0x44
46: #define DSSBM_CMD_CONVERT_V 0xb4
47:
48: /* Scratchpad layout */
49: #define DS2438_SP_STATUS 0
50: #define DS2438_SP_TEMP_LSB 1
51: #define DS2438_SP_TEMP_MSB 2
52: #define DS2438_SP_VOLT_LSB 3
53: #define DS2438_SP_VOLT_MSB 4
54: #define DS2438_SP_CURRENT_LSB 5
55: #define DS2438_SP_CURRENT_MSB 6
56: #define DS2438_SP_THRESHOLD 7
57: #define DS2438_SP_CRC 8
58:
59: struct owsbm_softc {
60: struct device sc_dev;
61:
62: void * sc_onewire;
63: u_int64_t sc_rom;
64:
65: struct ksensordev sc_sensordev;
66:
67: struct ksensor sc_temp;
68: struct ksensor sc_voltage_vdd; /* Battery, AD = 1*/
69: struct ksensor sc_voltage_vad; /* General purpose, AD = 0 */
70: struct ksensor sc_voltage_cr; /* Current Register */
71:
72: struct sensor_task *sc_sensortask;
73:
74: struct rwlock sc_lock;
75: };
76:
77: int owsbm_match(struct device *, void *, void *);
78: void owsbm_attach(struct device *, struct device *, void *);
79: int owsbm_detach(struct device *, int);
80: int owsbm_activate(struct device *, enum devact);
81:
82: void owsbm_update(void *);
83:
84: struct cfattach owsbm_ca = {
85: sizeof(struct owsbm_softc),
86: owsbm_match,
87: owsbm_attach,
88: owsbm_detach,
89: owsbm_activate
90: };
91:
92: struct cfdriver owsbm_cd = {
93: NULL, "owsbm", DV_DULL
94: };
95:
96: static const struct onewire_matchfam owsbm_fams[] = {
97: { ONEWIRE_FAMILY_DS2438 }
98: };
99:
100: int
101: owsbm_match(struct device *parent, void *match, void *aux)
102: {
103: return (onewire_matchbyfam(aux, owsbm_fams,
104: sizeof(owsbm_fams) /sizeof(owsbm_fams[0])));
105: }
106:
107: void
108: owsbm_attach(struct device *parent, struct device *self, void *aux)
109: {
110: struct owsbm_softc *sc = (struct owsbm_softc *)self;
111: struct onewire_attach_args *oa = aux;
112:
113: sc->sc_onewire = oa->oa_onewire;
114: sc->sc_rom = oa->oa_rom;
115:
116: /* Initialize temp sensor */
117: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
118: sizeof(sc->sc_sensordev.xname));
119: sc->sc_temp.type = SENSOR_TEMP;
120: sensor_attach(&sc->sc_sensordev, &sc->sc_temp);
121:
122: /* Initialize voltage sensor */
123: sc->sc_voltage_vdd.type = SENSOR_VOLTS_DC;
124: strlcpy(sc->sc_voltage_vdd.desc, "VDD", sizeof(sc->sc_voltage_vdd.desc));
125: sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_vdd);
126:
127: /* Initialize voltage sensor */
128: sc->sc_voltage_vad.type = SENSOR_VOLTS_DC;
129: strlcpy(sc->sc_voltage_vad.desc, "VAD", sizeof(sc->sc_voltage_vad.desc));
130: sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_vad);
131:
132: /* Initialize the current sensor */
133: sc->sc_voltage_cr.type = SENSOR_VOLTS_DC;
134: strlcpy(sc->sc_voltage_cr.desc, "CR", sizeof(sc->sc_voltage_cr.desc));
135: sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_cr);
136:
137: sc->sc_sensortask = sensor_task_register(sc, owsbm_update, 10);
138: if (sc->sc_sensortask == NULL) {
139: printf(": unable to register owsbm update task\n");
140: return;
141: }
142:
143: sensordev_install(&sc->sc_sensordev);
144:
145: rw_init(&sc->sc_lock, sc->sc_dev.dv_xname);
146: printf("\n");
147: }
148:
149: int
150: owsbm_detach(struct device *self, int flags)
151: {
152: struct owsbm_softc *sc = (struct owsbm_softc *)self;
153:
154: rw_enter_write(&sc->sc_lock);
155: sensordev_deinstall(&sc->sc_sensordev);
156: if (sc->sc_sensortask != NULL)
157: sensor_task_unregister(sc->sc_sensortask);
158: rw_exit_write(&sc->sc_lock);
159:
160: return (0);
161: }
162:
163: int
164: owsbm_activate(struct device *self, enum devact act)
165: {
166: return (0);
167: }
168:
169: void
170: owsbm_update(void *arg)
171: {
172: struct owsbm_softc *sc = arg;
173: u_int8_t data[9];
174:
175: rw_enter_write(&sc->sc_lock);
176: onewire_lock(sc->sc_onewire, 0);
177: if (onewire_reset(sc->sc_onewire) != 0)
178: goto done;
179:
180: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
181: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_CONVERT_T);
182: if (onewire_reset(sc->sc_onewire) != 0)
183: goto done;
184:
185: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
186: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_CONVERT_V);
187: if (onewire_reset(sc->sc_onewire) != 0)
188: goto done;
189:
190: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
191: /* Issue Recall Memory page 00h cmd */
192: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_RECALL_MEMORY);
193: onewire_write_byte(sc->sc_onewire, 0);
194:
195: if (onewire_reset(sc->sc_onewire) != 0)
196: goto done;
197:
198: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
199: /* Read page 0 of Memory Map from Scratchpad */
200: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_READ_SCRATCHPAD);
201: onewire_write_byte(sc->sc_onewire, 0);
202: onewire_read_block(sc->sc_onewire, data, 9);
203: if (onewire_crc(data, 8) == data[DS2438_SP_CRC]) {
204: sc->sc_temp.value = 273150000 +
205: (int)(((u_int16_t)data[DS2438_SP_TEMP_MSB] << 5) |
206: ((u_int16_t)data[DS2438_SP_TEMP_LSB] >> 3)) * 31250;
207: sc->sc_voltage_vdd.value =
208: (int)(((u_int16_t)data[DS2438_SP_VOLT_MSB] << 8) |
209: data[DS2438_SP_VOLT_LSB]) * 10000;
210:
211: sc->sc_voltage_cr.value =
212: (int)(((u_int16_t)data[DS2438_SP_CURRENT_MSB] << 8) |
213: data[DS2438_SP_CURRENT_LSB]) * 244;
214: }
215:
216: /* Reconfigure DS2438 to measure VAD */
217:
218: if (onewire_reset(sc->sc_onewire) != 0)
219: goto done;
220:
221: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
222: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_WRITE_SCRATCHPAD);
223: onewire_write_byte(sc->sc_onewire, 0);
224: onewire_write_byte(sc->sc_onewire, 0x7); /* AD = 0 */
225:
226: if (onewire_reset(sc->sc_onewire) != 0)
227: goto done;
228:
229: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
230: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_CONVERT_V);
231: if (onewire_reset(sc->sc_onewire) != 0)
232: goto done;
233:
234: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
235: /* Issue Recall Memory page 00h cmd */
236: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_RECALL_MEMORY);
237: onewire_write_byte(sc->sc_onewire, 0);
238:
239: if (onewire_reset(sc->sc_onewire) != 0)
240: goto done;
241:
242: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
243: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_READ_SCRATCHPAD);
244: onewire_write_byte(sc->sc_onewire, 0);
245: onewire_read_block(sc->sc_onewire, data, 9);
246: if (onewire_crc(data, 8) == data[8]) {
247: sc->sc_voltage_vad.value =
248: (int)(((u_int16_t)data[DS2438_SP_VOLT_MSB] << 8) |
249: data[DS2438_SP_VOLT_LSB]) * 10000;
250: }
251:
252: /* Reconfigure back DS2438 to measure VDD (default) */
253:
254: if (onewire_reset(sc->sc_onewire) != 0)
255: goto done;
256:
257: onewire_matchrom(sc->sc_onewire, sc->sc_rom);
258: onewire_write_byte(sc->sc_onewire, DSSBM_CMD_WRITE_SCRATCHPAD);
259: onewire_write_byte(sc->sc_onewire, 0);
260: onewire_write_byte(sc->sc_onewire, 0xf); /* AD = 1 */
261: onewire_reset(sc->sc_onewire);
262:
263: done:
264: onewire_unlock(sc->sc_onewire);
265: rw_exit_write(&sc->sc_lock);
266: }
CVSweb