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