xref: /openbsd/sys/dev/i2c/adm1025.c (revision 471aeecf)
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