xref: /freebsd-12.1/sys/dev/iicbus/ad7417.c (revision 718cf2cc)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010 Andreas Tobler
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/systm.h>
35 #include <sys/module.h>
36 #include <sys/callout.h>
37 #include <sys/conf.h>
38 #include <sys/cpu.h>
39 #include <sys/ctype.h>
40 #include <sys/kernel.h>
41 #include <sys/reboot.h>
42 #include <sys/rman.h>
43 #include <sys/sysctl.h>
44 #include <sys/limits.h>
45 
46 #include <machine/bus.h>
47 #include <machine/md_var.h>
48 
49 #include <dev/iicbus/iicbus.h>
50 #include <dev/iicbus/iiconf.h>
51 
52 #include <dev/ofw/openfirm.h>
53 #include <dev/ofw/ofw_bus.h>
54 #include <powerpc/powermac/powermac_thermal.h>
55 
56 /* CPU A/B sensors, temp and adc: AD7417. */
57 
58 #define AD7417_TEMP         0x00
59 #define AD7417_CONFIG       0x01
60 #define AD7417_ADC          0x04
61 #define AD7417_CONFIG2      0x05
62 #define AD7417_CONFMASK     0xe0
63 
64 uint8_t adc741x_config;
65 
66 struct ad7417_sensor {
67 	struct	pmac_therm therm;
68 	device_t dev;
69 	int     id;
70 	enum {
71 		ADC7417_TEMP_SENSOR,
72 		ADC7417_ADC_SENSOR
73 	} type;
74 };
75 
76 struct write_data {
77 	uint8_t reg;
78 	uint8_t val;
79 };
80 
81 struct read_data {
82 	uint8_t reg;
83 	uint16_t val;
84 };
85 
86 /* Regular bus attachment functions */
87 static int ad7417_probe(device_t);
88 static int ad7417_attach(device_t);
89 
90 /* Utility functions */
91 static int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS);
92 static int ad7417_write(device_t dev, uint32_t addr, uint8_t reg,
93 			uint8_t *buf, int len);
94 static int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg,
95 			 uint8_t *data);
96 static int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg,
97 			 uint16_t *data);
98 static int ad7417_write_read(device_t dev, uint32_t addr,
99 			     struct write_data out, struct read_data *in);
100 static int ad7417_diode_read(struct ad7417_sensor *sens);
101 static int ad7417_adc_read(struct ad7417_sensor *sens);
102 static int ad7417_sensor_read(struct ad7417_sensor *sens);
103 
104 struct ad7417_softc {
105 	device_t		sc_dev;
106 	uint32_t                sc_addr;
107 	struct ad7417_sensor    *sc_sensors;
108 	int                     sc_nsensors;
109 	int                     init_done;
110 };
111 static device_method_t  ad7417_methods[] = {
112 	/* Device interface */
113 	DEVMETHOD(device_probe,		ad7417_probe),
114 	DEVMETHOD(device_attach,	ad7417_attach),
115 	{ 0, 0 },
116 };
117 
118 static driver_t ad7417_driver = {
119 	"ad7417",
120 	ad7417_methods,
121 	sizeof(struct ad7417_softc)
122 };
123 
124 static devclass_t ad7417_devclass;
125 
126 DRIVER_MODULE(ad7417, iicbus, ad7417_driver, ad7417_devclass, 0, 0);
127 static MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417");
128 
129 
130 static int
ad7417_write(device_t dev,uint32_t addr,uint8_t reg,uint8_t * buff,int len)131 ad7417_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len)
132 {
133 	unsigned char buf[4];
134 	int try = 0;
135 
136 	struct iic_msg msg[] = {
137 		{ addr, IIC_M_WR, 0, buf }
138 	};
139 
140 	msg[0].len = len + 1;
141 	buf[0] = reg;
142 	memcpy(buf + 1, buff, len);
143 
144 	for (;;)
145 	{
146 		if (iicbus_transfer(dev, msg, 1) == 0)
147 			return (0);
148 
149 		if (++try > 5) {
150 			device_printf(dev, "iicbus write failed\n");
151 			return (-1);
152 		}
153 		pause("ad7417_write", hz);
154 	}
155 }
156 
157 static int
ad7417_read_1(device_t dev,uint32_t addr,uint8_t reg,uint8_t * data)158 ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
159 {
160 	uint8_t buf[4];
161 	int err, try = 0;
162 
163 	struct iic_msg msg[2] = {
164 	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
165 	    { addr, IIC_M_RD, 1, buf },
166 	};
167 
168 	for (;;)
169 	{
170 		err = iicbus_transfer(dev, msg, 2);
171 		if (err != 0)
172 			goto retry;
173 
174 		*data = *((uint8_t*)buf);
175 		return (0);
176 	retry:
177 		if (++try > 5) {
178 			device_printf(dev, "iicbus read failed\n");
179 			return (-1);
180 		}
181 		pause("ad7417_read_1", hz);
182 	}
183 }
184 
185 static int
ad7417_read_2(device_t dev,uint32_t addr,uint8_t reg,uint16_t * data)186 ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data)
187 {
188 	uint8_t buf[4];
189 	int err, try = 0;
190 
191 	struct iic_msg msg[2] = {
192 	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
193 	    { addr, IIC_M_RD, 2, buf },
194 	};
195 
196 	for (;;)
197 	{
198 		err = iicbus_transfer(dev, msg, 2);
199 		if (err != 0)
200 			goto retry;
201 
202 		*data = *((uint16_t*)buf);
203 		return (0);
204 	retry:
205 		if (++try > 5) {
206 			device_printf(dev, "iicbus read failed\n");
207 			return (-1);
208 		}
209 		pause("ad7417_read_2", hz);
210 	}
211 }
212 
213 static int
ad7417_write_read(device_t dev,uint32_t addr,struct write_data out,struct read_data * in)214 ad7417_write_read(device_t dev, uint32_t addr, struct write_data out,
215 		  struct read_data *in)
216 {
217 	uint8_t buf[4];
218 	int err, try = 0;
219 
220 	/* Do a combined write/read. */
221 	struct iic_msg msg[3] = {
222 	    { addr, IIC_M_WR, 2, buf },
223 	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &in->reg },
224 	    { addr, IIC_M_RD, 2, buf },
225 	};
226 
227 	/* Prepare the write msg. */
228 	buf[0] = out.reg;
229 	buf[1] = out.val & 0xff;
230 
231 	for (;;)
232 	{
233 		err = iicbus_transfer(dev, msg, 3);
234 		if (err != 0)
235 			goto retry;
236 
237 		in->val = *((uint16_t*)buf);
238 		return (0);
239 	retry:
240 		if (++try > 5) {
241 			device_printf(dev, "iicbus write/read failed\n");
242 			return (-1);
243 		}
244 		pause("ad7417_write_read", hz);
245 	}
246 }
247 
248 static int
ad7417_init_adc(device_t dev,uint32_t addr)249 ad7417_init_adc(device_t dev, uint32_t addr)
250 {
251 	uint8_t buf;
252 	int err;
253 	struct ad7417_softc *sc;
254 
255 	sc = device_get_softc(dev);
256 
257 	adc741x_config = 0;
258 	/* Clear Config2 */
259 	buf = 0;
260 
261 	err = ad7417_write(dev, addr, AD7417_CONFIG2, &buf, 1);
262 
263 	 /* Read & cache Config1 */
264 	buf = 0;
265 	err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1);
266 	err = ad7417_read_1(dev, addr, AD7417_CONFIG, &buf);
267 	adc741x_config = (uint8_t)buf;
268 
269 	/* Disable shutdown mode */
270 	adc741x_config &= 0xfe;
271 	buf = adc741x_config;
272 	err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1);
273 	if (err < 0)
274 		return (-1);
275 
276 	sc->init_done = 1;
277 
278 	return (0);
279 
280 }
281 static int
ad7417_probe(device_t dev)282 ad7417_probe(device_t dev)
283 {
284 	const char  *name, *compatible;
285 	struct ad7417_softc *sc;
286 
287 	name = ofw_bus_get_name(dev);
288 	compatible = ofw_bus_get_compat(dev);
289 
290 	if (!name)
291 		return (ENXIO);
292 
293 	if (strcmp(name, "supply-monitor") != 0 ||
294 	    strcmp(compatible, "ad7417") != 0)
295 		return (ENXIO);
296 
297 	sc = device_get_softc(dev);
298 	sc->sc_dev = dev;
299 	sc->sc_addr = iicbus_get_addr(dev);
300 
301 	device_set_desc(dev, "Supply-Monitor AD7417");
302 
303 	return (0);
304 }
305 
306 /*
307  * This function returns the number of sensors. If we call it the second time
308  * and we have allocated memory for sc->sc_sensors, we fill in the properties.
309  */
310 static int
ad7417_fill_sensor_prop(device_t dev)311 ad7417_fill_sensor_prop(device_t dev)
312 {
313 	phandle_t child;
314 	struct ad7417_softc *sc;
315 	u_int id[10];
316 	char location[96];
317 	char type[32];
318 	int i = 0, j, len = 0, prop_len, prev_len = 0;
319 
320 	sc = device_get_softc(dev);
321 
322 	child = ofw_bus_get_node(dev);
323 
324 	/* Fill the sensor location property. */
325 	prop_len = OF_getprop(child, "hwsensor-location", location,
326 			      sizeof(location));
327 	while (len < prop_len) {
328 		if (sc->sc_sensors != NULL)
329 			strcpy(sc->sc_sensors[i].therm.name, location + len);
330 		prev_len = strlen(location + len) + 1;
331 		len += prev_len;
332 		i++;
333 	}
334 	if (sc->sc_sensors == NULL)
335 		return (i);
336 
337 	/* Fill the sensor type property. */
338 	len = 0;
339 	i = 0;
340 	prev_len = 0;
341 	prop_len = OF_getprop(child, "hwsensor-type", type, sizeof(type));
342 	while (len < prop_len) {
343 		if (strcmp(type + len, "temperature") == 0)
344 			sc->sc_sensors[i].type = ADC7417_TEMP_SENSOR;
345 		else
346 			sc->sc_sensors[i].type = ADC7417_ADC_SENSOR;
347 		prev_len = strlen(type + len) + 1;
348 		len += prev_len;
349 		i++;
350 	}
351 
352 	/* Fill the sensor id property. Taken from OF. */
353 	prop_len = OF_getprop(child, "hwsensor-id", id, sizeof(id));
354 	for (j = 0; j < i; j++)
355 		sc->sc_sensors[j].id = id[j];
356 
357 	/* Fill the sensor zone property. Taken from OF. */
358 	prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id));
359 	for (j = 0; j < i; j++)
360 		sc->sc_sensors[j].therm.zone = id[j];
361 
362 	/* Finish setting up sensor properties */
363 	for (j = 0; j < i; j++) {
364 		sc->sc_sensors[j].dev = dev;
365 
366 		/* HACK: Apple wired a random diode to the ADC line */
367 		if (strstr(sc->sc_sensors[j].therm.name, "DIODE TEMP")
368 		    != NULL) {
369 			sc->sc_sensors[j].type = ADC7417_TEMP_SENSOR;
370 			sc->sc_sensors[j].therm.read =
371 			    (int (*)(struct pmac_therm *))(ad7417_diode_read);
372 		} else {
373 			sc->sc_sensors[j].therm.read =
374 			    (int (*)(struct pmac_therm *))(ad7417_sensor_read);
375 		}
376 
377 		if (sc->sc_sensors[j].type != ADC7417_TEMP_SENSOR)
378 			continue;
379 
380 		/* Make up some ranges */
381 		sc->sc_sensors[j].therm.target_temp = 500 + ZERO_C_TO_K;
382 		sc->sc_sensors[j].therm.max_temp = 900 + ZERO_C_TO_K;
383 
384 		pmac_thermal_sensor_register(&sc->sc_sensors[j].therm);
385 	}
386 
387 	return (i);
388 }
389 
390 static int
ad7417_attach(device_t dev)391 ad7417_attach(device_t dev)
392 {
393 	struct ad7417_softc *sc;
394 	struct sysctl_oid *oid, *sensroot_oid;
395 	struct sysctl_ctx_list *ctx;
396 	char sysctl_name[32];
397 	int i, j;
398 	const char *unit;
399 	const char *desc;
400 
401 	sc = device_get_softc(dev);
402 
403 	sc->sc_nsensors = 0;
404 
405 	/* Count the actual number of sensors. */
406 	sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
407 
408 	device_printf(dev, "%d sensors detected.\n", sc->sc_nsensors);
409 
410 	if (sc->sc_nsensors == 0)
411 		device_printf(dev, "WARNING: No AD7417 sensors detected!\n");
412 
413 	sc->sc_sensors = malloc (sc->sc_nsensors * sizeof(struct ad7417_sensor),
414 				 M_AD7417, M_WAITOK | M_ZERO);
415 
416 	ctx = device_get_sysctl_ctx(dev);
417 	sensroot_oid = SYSCTL_ADD_NODE(ctx,
418 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor",
419 	    CTLFLAG_RD, 0, "AD7417 Sensor Information");
420 
421 	/* Now we can fill the properties into the allocated struct. */
422 	sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
423 
424 	/* Add sysctls for the sensors. */
425 	for (i = 0; i < sc->sc_nsensors; i++) {
426 		for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) {
427 			sysctl_name[j] =
428 			    tolower(sc->sc_sensors[i].therm.name[j]);
429 			if (isspace(sysctl_name[j]))
430 				sysctl_name[j] = '_';
431 		}
432 		sysctl_name[j] = 0;
433 
434 		oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid),
435 				      OID_AUTO,
436 				      sysctl_name, CTLFLAG_RD, 0,
437 				      "Sensor Information");
438 
439 		if (sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR) {
440 			unit = "temp";
441 			desc = "sensor unit (C)";
442 		} else {
443 			unit = "volt";
444 			desc = "sensor unit (mV)";
445 		}
446 		/* I use i to pass the sensor id. */
447 		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
448 				unit, CTLTYPE_INT | CTLFLAG_RD, dev,
449 				i, ad7417_sensor_sysctl,
450 				sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ?
451 				"IK" : "I", desc);
452 	}
453 	/* Dump sensor location, ID & type. */
454 	if (bootverbose) {
455 		device_printf(dev, "Sensors\n");
456 		for (i = 0; i < sc->sc_nsensors; i++) {
457 			device_printf(dev, "Location: %s ID: %d type: %d\n",
458 				      sc->sc_sensors[i].therm.name,
459 				      sc->sc_sensors[i].id,
460 				      sc->sc_sensors[i].type);
461 		}
462 	}
463 
464 	return (0);
465 }
466 
467 static int
ad7417_get_temp(device_t dev,uint32_t addr,int * temp)468 ad7417_get_temp(device_t dev, uint32_t addr, int *temp)
469 {
470 	uint16_t buf[2];
471 	uint16_t read;
472 	int err;
473 
474 	err = ad7417_read_2(dev, addr, AD7417_TEMP, buf);
475 
476 	if (err < 0)
477 		return (-1);
478 
479 	read = *((int16_t*)buf);
480 
481 	/* The ADC is 10 bit, the resolution is 0.25 C.
482 	   The temperature is in tenth kelvin.
483 	*/
484 	*temp = (((int16_t)(read & 0xffc0)) >> 6) * 25 / 10;
485 	return (0);
486 }
487 
488 static int
ad7417_get_adc(device_t dev,uint32_t addr,unsigned int * value,uint8_t chan)489 ad7417_get_adc(device_t dev, uint32_t addr, unsigned int *value,
490 	       uint8_t chan)
491 {
492 	uint8_t tmp;
493 	int err;
494 	struct write_data config;
495 	struct read_data data;
496 
497 	tmp = chan << 5;
498 	config.reg = AD7417_CONFIG;
499 	data.reg = AD7417_ADC;
500 	data.val = 0;
501 
502 	err = ad7417_read_1(dev, addr, AD7417_CONFIG, &config.val);
503 
504 	config.val = (config.val & ~AD7417_CONFMASK) | (tmp & AD7417_CONFMASK);
505 
506 	err = ad7417_write_read(dev, addr, config, &data);
507 	if (err < 0)
508 		return (-1);
509 
510 	*value = ((uint32_t)data.val) >> 6;
511 
512 	return (0);
513 }
514 
515 static int
ad7417_diode_read(struct ad7417_sensor * sens)516 ad7417_diode_read(struct ad7417_sensor *sens)
517 {
518 	static int eeprom_read = 0;
519 	static cell_t eeprom[2][40];
520 	phandle_t eeprom_node;
521 	int rawval, diode_slope, diode_offset;
522 	int temp;
523 
524 	if (!eeprom_read) {
525 		eeprom_node = OF_finddevice("/u3/i2c/cpuid@a0");
526 		OF_getprop(eeprom_node, "cpuid", eeprom[0], sizeof(eeprom[0]));
527 		eeprom_node = OF_finddevice("/u3/i2c/cpuid@a2");
528 		OF_getprop(eeprom_node, "cpuid", eeprom[1], sizeof(eeprom[1]));
529 		eeprom_read = 1;
530 	}
531 
532 	rawval = ad7417_adc_read(sens);
533 	if (rawval < 0)
534 		return (-1);
535 
536 	if (strstr(sens->therm.name, "CPU B") != NULL) {
537 		diode_slope = eeprom[1][0x11] >> 16;
538 		diode_offset = (int16_t)(eeprom[1][0x11] & 0xffff) << 12;
539 	} else {
540 		diode_slope = eeprom[0][0x11] >> 16;
541 		diode_offset = (int16_t)(eeprom[0][0x11] & 0xffff) << 12;
542 	}
543 
544 	temp = (rawval*diode_slope + diode_offset) >> 2;
545 	temp = (10*(temp >> 16)) + ((10*(temp & 0xffff)) >> 16);
546 
547 	return (temp + ZERO_C_TO_K);
548 }
549 
550 static int
ad7417_adc_read(struct ad7417_sensor * sens)551 ad7417_adc_read(struct ad7417_sensor *sens)
552 {
553 	struct ad7417_softc *sc;
554 	uint8_t chan;
555 	int temp;
556 
557 	sc = device_get_softc(sens->dev);
558 
559 	switch (sens->id) {
560 	case 11:
561 	case 16:
562 		chan = 1;
563 		break;
564 	case 12:
565 	case 17:
566 		chan = 2;
567 		break;
568 	case 13:
569 	case 18:
570 		chan = 3;
571 		break;
572 	case 14:
573 	case 19:
574 		chan = 4;
575 		break;
576 	default:
577 		chan = 1;
578 	}
579 
580 	if (ad7417_get_adc(sc->sc_dev, sc->sc_addr, &temp, chan) < 0)
581 		return (-1);
582 
583 	return (temp);
584 }
585 
586 
587 static int
ad7417_sensor_read(struct ad7417_sensor * sens)588 ad7417_sensor_read(struct ad7417_sensor *sens)
589 {
590 	struct ad7417_softc *sc;
591 	int temp;
592 
593 	sc = device_get_softc(sens->dev);
594 
595 	/* Init the ADC if not already done.*/
596 	if (!sc->init_done)
597 		if (ad7417_init_adc(sc->sc_dev, sc->sc_addr) < 0)
598 			return (-1);
599 
600 	if (sens->type == ADC7417_TEMP_SENSOR) {
601 		if (ad7417_get_temp(sc->sc_dev, sc->sc_addr, &temp) < 0)
602 			return (-1);
603 		temp += ZERO_C_TO_K;
604 	} else {
605 		temp = ad7417_adc_read(sens);
606 	}
607 	return (temp);
608 }
609 
610 static int
ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS)611 ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS)
612 {
613 	device_t dev;
614 	struct ad7417_softc *sc;
615 	struct ad7417_sensor *sens;
616 	int value = 0;
617 	int error;
618 
619 	dev = arg1;
620 	sc = device_get_softc(dev);
621 	sens = &sc->sc_sensors[arg2];
622 
623 	value = sens->therm.read(&sens->therm);
624 	if (value < 0)
625 		return (ENXIO);
626 
627 	error = sysctl_handle_int(oidp, &value, 0, req);
628 
629 	return (error);
630 }
631