Fri Mar 9 22:27:15 2018 UTC ()
remove some unused code, add comments for credits & explanations


(macallan)
diff -r1.1 -r1.2 src/sys/dev/i2c/adadc.c

cvs diff -r1.1 -r1.2 src/sys/dev/i2c/adadc.c (switch to unified diff)

--- src/sys/dev/i2c/adadc.c 2018/03/09 20:16:54 1.1
+++ src/sys/dev/i2c/adadc.c 2018/03/09 22:27:15 1.2
@@ -1,240 +1,259 @@ @@ -1,240 +1,259 @@
1/* $NetBSD: adadc.c,v 1.1 2018/03/09 20:16:54 macallan Exp $ */ 1/* $NetBSD: adadc.c,v 1.2 2018/03/09 22:27:15 macallan Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Michael Lorenz 4 * Copyright (c) 2018 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/* a driver for Analog Devices AD7417 temperature sensors / ADCs */ 29/*
 30 * a driver for Analog Devices AD7417 temperature sensors / ADCs
 31 * very much macppc only for now since we need calibaration data to make sense
 32 * of the ADC inputs
 33 * info on how to get these from FreeBSD and Linux
 34 */
30 35
31#include <sys/cdefs.h> 36#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: adadc.c,v 1.1 2018/03/09 20:16:54 macallan Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: adadc.c,v 1.2 2018/03/09 22:27:15 macallan Exp $");
33 38
34#include <sys/param.h> 39#include <sys/param.h>
35#include <sys/systm.h> 40#include <sys/systm.h>
36#include <sys/device.h> 41#include <sys/device.h>
37#include <sys/conf.h> 42#include <sys/conf.h>
38#include <sys/bus.h> 43#include <sys/bus.h>
39 44
40#include <dev/i2c/i2cvar.h> 45#include <dev/i2c/i2cvar.h>
41 46
42#include <dev/sysmon/sysmonvar.h> 47#include <dev/sysmon/sysmonvar.h>
43 48
44#include <dev/ofw/openfirm.h> 49#include <dev/ofw/openfirm.h>
45 50
46/* commands */ 51/* commands */
47#define ADADC_TEMP 0x00 /* temperature, 16bit */ 52#define ADADC_TEMP 0x00 /* temperature, 16bit */
48#define ADADC_CONFIG 0x01 /* 8bit */ 53#define ADADC_CONFIG 0x01 /* 8bit */
49#define ADADC_THYST 0x02 /* 16bit */ 54#define ADADC_THYST 0x02 /* 16bit */
50#define ADADC_TOTI 0x03 /* 16bit, temperature threshold */ 55#define ADADC_TOTI 0x03 /* 16bit, temperature threshold */
51#define ADADC_ADC 0x04 /* 16bit, ADC value */ 56#define ADADC_ADC 0x04 /* 16bit, ADC value */
52#define ADADC_CONFIG2 0x05 /* 8bit */ 57#define ADADC_CONFIG2 0x05 /* 8bit */
53 58
54/*  59/*
55 * registers 60 * registers
56 * ADADC_TEMP has signed temperature in C in first byte, left aligned fraction 61 * ADADC_TEMP has signed temperature in C in first byte, left aligned fraction
57 * in 2nd byte. 62 * in 2nd byte.
58 */ 63 */
59 64
60#define ADADC_CFG_CHANNEL_0 0x00 65#define ADADC_CFG_CHANNEL_0 0x00
61#define ADADC_CFG_CHANNEL_1 0x20 66#define ADADC_CFG_CHANNEL_1 0x20
62#define ADADC_CFG_CHANNEL_2 0x40 67#define ADADC_CFG_CHANNEL_2 0x40
63#define ADADC_CFG_CHANNEL_3 0x60 68#define ADADC_CFG_CHANNEL_3 0x60
64#define ADADC_CFG_CHANNEL_4 0x80 69#define ADADC_CFG_CHANNEL_4 0x80
65#define ADADC_CFG_CHANNEL_MASK 0xe0 70#define ADADC_CFG_CHANNEL_MASK 0xe0
66#define ADADC_CFG_FAULT_MASK 0x18 71#define ADADC_CFG_FAULT_MASK 0x18
67#define ADADC_CFG_OTI_POL 0x04 /* overtemp output polarity */ 72#define ADADC_CFG_OTI_POL 0x04 /* overtemp output polarity */
68#define ADADC_CFG_INTMODE 0x02 /* interrupt mode */ 73#define ADADC_CFG_INTMODE 0x02 /* interrupt mode */
69#define ADADC_CFG_SHUTDOWN 0x01 /* shutdown mode */ 74#define ADADC_CFG_SHUTDOWN 0x01 /* shutdown mode */
70 75
71 76
72struct adadc_softc { 77struct adadc_softc {
73 device_t sc_dev; 78 device_t sc_dev;
74 i2c_tag_t sc_i2c; 79 i2c_tag_t sc_i2c;
75 i2c_addr_t sc_addr; 80 i2c_addr_t sc_addr;
76 81
77 struct sysmon_envsys *sc_sme; 82 struct sysmon_envsys *sc_sme;
78 envsys_data_t sc_sensors[5]; 83 envsys_data_t sc_sensors[5];
79 int sc_nsensors; 84 int sc_nsensors;
80 int sc_diode_offset, sc_diode_slope; 85 int sc_diode_offset, sc_diode_slope;
81}; 86};
82 87
83static int adadc_match(device_t, cfdata_t, void *); 88static int adadc_match(device_t, cfdata_t, void *);
84static void adadc_attach(device_t, device_t, void *); 89static void adadc_attach(device_t, device_t, void *);
85 90
86static void adadc_sensors_refresh(struct sysmon_envsys *, envsys_data_t *); 91static void adadc_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
87 92
88CFATTACH_DECL_NEW(adadc, sizeof(struct adadc_softc), 93CFATTACH_DECL_NEW(adadc, sizeof(struct adadc_softc),
89 adadc_match, adadc_attach, NULL, NULL); 94 adadc_match, adadc_attach, NULL, NULL);
90 95
91static const char * dstemp_compats[] = { 96static const char * dstemp_compats[] = {
92 "ad7417", 97 "ad7417",
93 NULL 98 NULL
94}; 99};
95 100
 101/* calibaration table from Darwin via Linux */
96static int slope[5] = {0, 0, 0x0320, 0x00a0, 0x1f40}; 102static int slope[5] = {0, 0, 0x0320, 0x00a0, 0x1f40};
97 103
98static int 104static int
99adadc_match(device_t parent, cfdata_t match, void *aux) 105adadc_match(device_t parent, cfdata_t match, void *aux)
100{ 106{
101 struct i2c_attach_args *ia = aux; 107 struct i2c_attach_args *ia = aux;
102 108
103 if (ia->ia_name == NULL) { 109 if (ia->ia_name == NULL) {
104 /* no ID registers on this chip */ 110 /*
 111 * XXX
 112 * this driver is pretty much useless without OF, should
 113 * probably remove this
 114 */
105 if ((ia->ia_addr & 0x2b) == 0x2b) 115 if ((ia->ia_addr & 0x2b) == 0x2b)
106 return 1; 116 return 1;
107 return 0; 117 return 0;
108 } else { 118 } else {
109 return iic_compat_match(ia, dstemp_compats); 119 return iic_compat_match(ia, dstemp_compats);
110 } 120 }
111} 121}
112 122
113static void 123static void
114adadc_attach(device_t parent, device_t self, void *aux) 124adadc_attach(device_t parent, device_t self, void *aux)
115{ 125{
116 struct adadc_softc *sc = device_private(self); 126 struct adadc_softc *sc = device_private(self);
117 struct i2c_attach_args *ia = aux; 127 struct i2c_attach_args *ia = aux;
118 envsys_data_t *s; 128 envsys_data_t *s;
119 int error, ch, cpuid; 129 int error, ch, cpuid;
120 uint32_t eeprom[40]; 130 uint32_t eeprom[40];
121 uint8_t cmd, data; 
122 char loc[256]; 131 char loc[256];
123 int which_cpu; 132 int which_cpu;
124 133
125 sc->sc_dev = self; 134 sc->sc_dev = self;
126 sc->sc_i2c = ia->ia_tag; 135 sc->sc_i2c = ia->ia_tag;
127 sc->sc_addr = ia->ia_addr; 136 sc->sc_addr = ia->ia_addr;
128 137
129 aprint_naive("\n"); 138 aprint_naive("\n");
130 aprint_normal(": AD7417\n"); 139 aprint_normal(": AD7417\n");
131 140
132 cmd = ADADC_CONFIG; 
133 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, 
134 sc->sc_addr, &cmd, 1, &data, 1, 0); 
135 
136 sc->sc_sme = sysmon_envsys_create(); 141 sc->sc_sme = sysmon_envsys_create();
137 sc->sc_sme->sme_name = device_xname(self); 142 sc->sc_sme->sme_name = device_xname(self);
138 sc->sc_sme->sme_cookie = sc; 143 sc->sc_sme->sme_cookie = sc;
139 sc->sc_sme->sme_refresh = adadc_sensors_refresh; 144 sc->sc_sme->sme_refresh = adadc_sensors_refresh;
140 sc->sc_nsensors = 0; 145 sc->sc_nsensors = 0;
141 146
 147 /*
 148 * XXX
 149 * without OpenFirmware telling us how to interpret the ADC inputs we
 150 * should probably just expose the temperature and four ENVSYS_INTEGERs
 151 */
142 which_cpu = 0; 152 which_cpu = 0;
143 ch = OF_child(ia->ia_cookie); 153 ch = OF_child(ia->ia_cookie);
144 while (ch != 0) { 154 while (ch != 0) {
145 if (OF_getprop(ch, "location", loc, 32) > 0) { 155 if (OF_getprop(ch, "location", loc, 32) > 0) {
146 int reg = 0; 156 int reg = 0;
147 OF_getprop(ch, "reg", &reg, sizeof(reg)); 157 OF_getprop(ch, "reg", &reg, sizeof(reg));
148 s = &sc->sc_sensors[sc->sc_nsensors]; 158 s = &sc->sc_sensors[sc->sc_nsensors];
 159 /*
 160 * this setup matches my 2x 2.5GHz PCI-X G5, Linux and
 161 * FreeBSD hardcode these as well so we should be safe
 162 */
149 switch (reg) { 163 switch (reg) {
150 case 0: 164 case 0:
151 if (strstr(loc, "CPU B") != NULL) 165 if (strstr(loc, "CPU B") != NULL)
152 which_cpu = 1; 166 which_cpu = 1;
153 /* FALLTHROUGH */  167 /* FALLTHROUGH */
154 case 1: 168 case 1:
155 s->units = ENVSYS_STEMP; 169 s->units = ENVSYS_STEMP;
156 break; 170 break;
157 case 2: 171 case 2:
158 case 4: 172 case 4:
159 s->units = ENVSYS_SAMPS; 173 s->units = ENVSYS_SAMPS;
160 break; 174 break;
161 case 3: 175 case 3:
162 s->units = ENVSYS_SVOLTS_DC; 176 s->units = ENVSYS_SVOLTS_DC;
163 break; 177 break;
164 default: 178 default:
165 s->units = ENVSYS_INTEGER; 179 s->units = ENVSYS_INTEGER;
166 } 180 }
167 strncpy(s->desc, loc, sizeof(s->desc)); 181 strncpy(s->desc, loc, sizeof(s->desc));
168 s->private = reg; 182 s->private = reg;
169 sysmon_envsys_sensor_attach(sc->sc_sme, s); 183 sysmon_envsys_sensor_attach(sc->sc_sme, s);
170 sc->sc_nsensors++; 184 sc->sc_nsensors++;
171 } 185 }
172 ch = OF_peer(ch); 186 ch = OF_peer(ch);
173 } 187 }
174 aprint_debug_dev(self, "monitoring CPU %d\n", which_cpu); 188 aprint_debug_dev(self, "monitoring CPU %d\n", which_cpu);
175 if (which_cpu == 0) { 189 if (which_cpu == 0) {
176 cpuid = OF_finddevice("/u3/i2c/cpuid@a0"); 190 cpuid = OF_finddevice("/u3/i2c/cpuid@a0");
177 } else 191 } else
178 cpuid = OF_finddevice("/u3/i2c/cpuid@a2"); 192 cpuid = OF_finddevice("/u3/i2c/cpuid@a2");
179 error = OF_getprop(cpuid, "cpuid", eeprom, sizeof(eeprom)); 193 error = OF_getprop(cpuid, "cpuid", eeprom, sizeof(eeprom));
180 if (error >= 0) { 194 if (error >= 0) {
181 sc->sc_diode_slope = eeprom[0x11] >> 16; 195 sc->sc_diode_slope = eeprom[0x11] >> 16;
182 sc->sc_diode_offset = (int16_t)(eeprom[0x11] & 0xffff) << 12; 196 sc->sc_diode_offset = (int16_t)(eeprom[0x11] & 0xffff) << 12;
183 } 197 }
184 sysmon_envsys_register(sc->sc_sme); 198 sysmon_envsys_register(sc->sc_sme);
185} 199}
186 200
187static void 201static void
188adadc_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 202adadc_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
189{ 203{
190 struct adadc_softc *sc = sme->sme_cookie; 204 struct adadc_softc *sc = sme->sme_cookie;
191 uint8_t cmd = ADADC_CONFIG; 205 uint8_t cmd = ADADC_CONFIG;
192 int16_t data = 0; 206 int16_t data = 0;
193 uint16_t rdata; 207 uint16_t rdata;
194 uint8_t cfg; 208 uint8_t cfg;
195 int error, ch; 209 int error, ch;
196 210
197  211
198 iic_acquire_bus(sc->sc_i2c, 0); 212 iic_acquire_bus(sc->sc_i2c, 0);
199 if (edata->private > 0) { 213 if (edata->private > 0) {
200 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, 214 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
201 sc->sc_addr, &cmd, 1, &cfg, 1, 0); 215 sc->sc_addr, &cmd, 1, &cfg, 1, 0);
202 ch = cfg >> 5; 216 ch = cfg >> 5;
203 /* are we on the right channel already? */ 217 /* are we on the right channel already? */
204 if (ch != edata->private) { 218 if (ch != edata->private) {
205 /* nope */ 219 /* nope */
206 cfg &= 0x1f; 220 cfg &= 0x1f;
207 cfg |= (edata->private & 7) << 5; 221 cfg |= (edata->private & 7) << 5;
208 iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, 222 iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP,
209 sc->sc_addr, &cmd, 1, &cfg, 1, 0); 223 sc->sc_addr, &cmd, 1, &cfg, 1, 0);
210 } 224 }
211 cmd = ADADC_ADC; 225 cmd = ADADC_ADC;
212 /* now read the ADC register */ 226 /* now read the ADC register */
213 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, 227 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
214 sc->sc_addr, &cmd, 1, &rdata, 2, 0); 228 sc->sc_addr, &cmd, 1, &rdata, 2, 0);
215 rdata = be16toh(rdata) >> 6; 229 rdata = be16toh(rdata) >> 6;
216 if (edata->private == 1) { 230 if (edata->private == 1) {
217 int temp; 231 int temp;
218 temp = (rdata * sc->sc_diode_slope +  232 temp = (rdata * sc->sc_diode_slope +
219 sc->sc_diode_offset) >> 2; 233 sc->sc_diode_offset) >> 2;
220 /* 16.16 fixed point */ 234 /* 16.16 fixed point */
221 edata->value_cur = (temp >> 12) * 62500 + 273150000; 235 edata->value_cur = (temp >> 12) * 62500 + 273150000;
222 } else { 236 } else {
 237 /*
 238 * the input is 10bit, so converting to 8.4 fixed point
 239 * is more than enough
 240 */
223 int temp = rdata * slope[edata->private]; 241 int temp = rdata * slope[edata->private];
224 edata->value_cur = (temp >> 12) * 62500; 242 edata->value_cur = (temp >> 12) * 62500;
225 } 243 }
226 } else { 244 } else {
227 cmd = ADADC_TEMP; 245 cmd = ADADC_TEMP;
228 /* just read the temperature register */ 246 /* just read the temperature register */
229 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, 247 error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
230 sc->sc_addr, &cmd, 1, &data, 2, 0); 248 sc->sc_addr, &cmd, 1, &data, 2, 0);
 249 /* 8.2 bit fixed point Celsius -> microkelvin */
231 edata->value_cur = ((data >> 6) * 250000) + 273150000; 250 edata->value_cur = ((data >> 6) * 250000) + 273150000;
232 } 251 }
233 iic_release_bus(sc->sc_i2c, 0); 252 iic_release_bus(sc->sc_i2c, 0);
234 253
235 if (error) { 254 if (error) {
236 edata->state = ENVSYS_SINVALID; 255 edata->state = ENVSYS_SINVALID;
237 } else { 256 } else {
238 edata->state = ENVSYS_SVALID; 257 edata->state = ENVSYS_SVALID;
239 } 258 }
240} 259}