1 /* $OpenBSD: adm1025.c,v 1.26 2022/04/06 18:59:28 naddy Exp $ */
2
3 /*
4 * Copyright (c) 2005 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 /* ADM 1025 registers */
27 #define ADM1025_V2_5 0x20
28 #define ADM1025_Vccp 0x21
29 #define ADM1025_V3_3 0x22
30 #define ADM1025_V5 0x23
31 #define ADM1025_V12 0x24
32 #define ADM1025_Vcc 0x25
33 #define ADM1025_EXT_TEMP 0x26
34 #define ADM1025_INT_TEMP 0x27
35 #define ADM1025_STATUS2 0x42
36 #define ADM1025_STATUS2_EXT 0x40
37 #define ADM1025_COMPANY 0x3e /* contains 0x41 */
38 #define ADM1025_STEPPING 0x3f /* contains 0x2? */
39 #define ADM1025_CONFIG 0x40
40 #define ADM1025_CONFIG_START 0x01
41 #define SMSC47M192_V1_5 0x50
42 #define SMSC47M192_V1_8 0x51
43 #define SMSC47M192_TEMP2 0x52
44
45 /* Sensors */
46 #define ADMTM_INT 0
47 #define ADMTM_EXT 1
48 #define ADMTM_V2_5 2
49 #define ADMTM_Vccp 3
50 #define ADMTM_V3_3 4
51 #define ADMTM_V5 5
52 #define ADMTM_V12 6
53 #define ADMTM_Vcc 7
54 #define ADMTM_NUM_SENSORS 8
55 #define SMSC_V1_5 8
56 #define SMSC_V1_8 9
57 #define SMSC_TEMP2 10
58 #define SMSC_NUM_SENSORS 3
59 struct admtm_softc {
60 struct device sc_dev;
61 i2c_tag_t sc_tag;
62 i2c_addr_t sc_addr;
63
64 struct ksensor sc_sensor[ADMTM_NUM_SENSORS + SMSC_NUM_SENSORS];
65 struct ksensordev sc_sensordev;
66 int sc_nsensors;
67 int sc_model;
68 };
69
70 int admtm_match(struct device *, void *, void *);
71 void admtm_attach(struct device *, struct device *, void *);
72 void admtm_refresh(void *);
73
74 const struct cfattach admtm_ca = {
75 sizeof(struct admtm_softc), admtm_match, admtm_attach
76 };
77
78 struct cfdriver admtm_cd = {
79 NULL, "admtm", DV_DULL
80 };
81
82 int
admtm_match(struct device * parent,void * match,void * aux)83 admtm_match(struct device *parent, void *match, void *aux)
84 {
85 struct i2c_attach_args *ia = aux;
86
87 if (strcmp(ia->ia_name, "adm1025") == 0 ||
88 strcmp(ia->ia_name, "47m192") == 0 ||
89 strcmp(ia->ia_name, "ne1619") == 0)
90 return (1);
91 return (0);
92 }
93
94 void
admtm_attach(struct device * parent,struct device * self,void * aux)95 admtm_attach(struct device *parent, struct device *self, void *aux)
96 {
97 struct admtm_softc *sc = (struct admtm_softc *)self;
98 struct i2c_attach_args *ia = aux;
99 u_int8_t cmd, data, data2;
100 int i;
101
102 sc->sc_tag = ia->ia_tag;
103 sc->sc_addr = ia->ia_addr;
104
105 printf(": %s", ia->ia_name);
106
107 sc->sc_nsensors = ADMTM_NUM_SENSORS;
108 sc->sc_model = 1025;
109 if (strcmp(ia->ia_name, "47m192") == 0) {
110 sc->sc_nsensors += SMSC_NUM_SENSORS;
111 sc->sc_model = 192;
112 }
113
114 iic_acquire_bus(sc->sc_tag, 0);
115 cmd = ADM1025_CONFIG;
116 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
117 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
118 iic_release_bus(sc->sc_tag, 0);
119 printf(", cannot get control register\n");
120 return;
121 }
122
123 data2 = data | ADM1025_CONFIG_START;
124 if (data != data2) {
125 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
126 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
127 iic_release_bus(sc->sc_tag, 0);
128 printf(", cannot set control register\n");
129 return;
130 }
131 }
132 iic_release_bus(sc->sc_tag, 0);
133
134 /* Initialize sensor data. */
135 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
136 sizeof(sc->sc_sensordev.xname));
137
138 sc->sc_sensor[ADMTM_INT].type = SENSOR_TEMP;
139 strlcpy(sc->sc_sensor[ADMTM_INT].desc, "Internal",
140 sizeof(sc->sc_sensor[ADMTM_INT].desc));
141
142 sc->sc_sensor[ADMTM_EXT].type = SENSOR_TEMP;
143 strlcpy(sc->sc_sensor[ADMTM_EXT].desc, "External",
144 sizeof(sc->sc_sensor[ADMTM_EXT].desc));
145
146 sc->sc_sensor[ADMTM_V2_5].type = SENSOR_VOLTS_DC;
147 strlcpy(sc->sc_sensor[ADMTM_V2_5].desc, "2.5 V",
148 sizeof(sc->sc_sensor[ADMTM_V2_5].desc));
149
150 sc->sc_sensor[ADMTM_Vccp].type = SENSOR_VOLTS_DC;
151 strlcpy(sc->sc_sensor[ADMTM_Vccp].desc, "Vccp",
152 sizeof(sc->sc_sensor[ADMTM_Vccp].desc));
153
154 sc->sc_sensor[ADMTM_V3_3].type = SENSOR_VOLTS_DC;
155 strlcpy(sc->sc_sensor[ADMTM_V3_3].desc, "3.3 V",
156 sizeof(sc->sc_sensor[ADMTM_V3_3].desc));
157
158 sc->sc_sensor[ADMTM_V5].type = SENSOR_VOLTS_DC;
159 strlcpy(sc->sc_sensor[ADMTM_V5].desc, "5 V",
160 sizeof(sc->sc_sensor[ADMTM_V5].desc));
161
162 sc->sc_sensor[ADMTM_V12].type = SENSOR_VOLTS_DC;
163 strlcpy(sc->sc_sensor[ADMTM_V12].desc, "12 V",
164 sizeof(sc->sc_sensor[ADMTM_V12].desc));
165
166 sc->sc_sensor[ADMTM_Vcc].type = SENSOR_VOLTS_DC;
167 strlcpy(sc->sc_sensor[ADMTM_Vcc].desc, "Vcc",
168 sizeof(sc->sc_sensor[ADMTM_Vcc].desc));
169
170 sc->sc_sensor[SMSC_V1_5].type = SENSOR_VOLTS_DC;
171 strlcpy(sc->sc_sensor[SMSC_V1_5].desc, "1.5 V",
172 sizeof(sc->sc_sensor[SMSC_V1_5].desc));
173
174 sc->sc_sensor[SMSC_V1_8].type = SENSOR_VOLTS_DC;
175 strlcpy(sc->sc_sensor[SMSC_V1_8].desc, "1.8 V",
176 sizeof(sc->sc_sensor[SMSC_V1_8].desc));
177
178 sc->sc_sensor[SMSC_TEMP2].type = SENSOR_TEMP;
179 strlcpy(sc->sc_sensor[SMSC_TEMP2].desc, "External",
180 sizeof(sc->sc_sensor[SMSC_TEMP2].desc));
181
182 if (sensor_task_register(sc, admtm_refresh, 5) == NULL) {
183 printf(", unable to register update task\n");
184 return;
185 }
186
187 for (i = 0; i < sc->sc_nsensors; i++)
188 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
189 sensordev_install(&sc->sc_sensordev);
190
191 printf("\n");
192 }
193
194 void
admtm_refresh(void * arg)195 admtm_refresh(void *arg)
196 {
197 struct admtm_softc *sc = arg;
198 u_int8_t cmd, data;
199 int8_t sdata;
200
201 iic_acquire_bus(sc->sc_tag, 0);
202
203 cmd = ADM1025_INT_TEMP;
204 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
205 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
206 sc->sc_sensor[ADMTM_INT].value = 273150000 + 1000000 * sdata;
207
208 cmd = ADM1025_EXT_TEMP;
209 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
210 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
211 sc->sc_sensor[ADMTM_EXT].value = 273150000 + 1000000 * sdata;
212
213 cmd = ADM1025_STATUS2;
214 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
215 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
216 if (data & ADM1025_STATUS2_EXT)
217 sc->sc_sensor[ADMTM_EXT].flags |= SENSOR_FINVALID;
218 else
219 sc->sc_sensor[ADMTM_EXT].flags &= ~SENSOR_FINVALID;
220 }
221
222 cmd = ADM1025_V2_5;
223 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
224 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
225 sc->sc_sensor[ADMTM_V2_5].value = 2500000 * data / 192;
226
227 cmd = ADM1025_Vccp;
228 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
229 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
230 sc->sc_sensor[ADMTM_Vcc].value = 2249000 * data / 192;
231
232 cmd = ADM1025_V3_3;
233 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
234 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
235 sc->sc_sensor[ADMTM_V3_3].value = 3300000 * data / 192;
236
237 cmd = ADM1025_V5;
238 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
239 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
240 sc->sc_sensor[ADMTM_V5].value = 5000000 * data / 192;
241
242 cmd = ADM1025_V12;
243 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
244 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
245 sc->sc_sensor[ADMTM_V12].value = 12000000 * data / 192;
246
247 cmd = ADM1025_Vcc;
248 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
249 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
250 sc->sc_sensor[ADMTM_Vcc].value = 3300000 * data / 192;
251
252 if (sc->sc_model == 192) {
253 cmd = SMSC47M192_V1_5;
254 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
255 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
256 sc->sc_sensor[SMSC_V1_5].value = 1500000 * data / 192;
257
258 cmd = SMSC47M192_V1_8;
259 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
260 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
261 sc->sc_sensor[SMSC_V1_8].value = 1800000 * data / 192;
262
263 cmd = SMSC47M192_TEMP2;
264 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
265 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata,
266 0) == 0)
267 sc->sc_sensor[SMSC_TEMP2].value = 273150000 + 1000000 * sdata;
268
269 }
270
271 iic_release_bus(sc->sc_tag, 0);
272 }
273