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