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$");
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
62 uint8_t adc741x_config;
63
64 struct 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
74 struct write_data {
75 uint8_t reg;
76 uint8_t val;
77 };
78
79 struct read_data {
80 uint8_t reg;
81 uint16_t val;
82 };
83
84 /* Regular bus attachment functions */
85 static int ad7417_probe(device_t);
86 static int ad7417_attach(device_t);
87
88 /* Utility functions */
89 static int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS);
90 static int ad7417_write(device_t dev, uint32_t addr, uint8_t reg,
91 uint8_t *buf, int len);
92 static int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg,
93 uint8_t *data);
94 static int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg,
95 uint16_t *data);
96 static int ad7417_write_read(device_t dev, uint32_t addr,
97 struct write_data out, struct read_data *in);
98 static int ad7417_diode_read(struct ad7417_sensor *sens);
99 static int ad7417_adc_read(struct ad7417_sensor *sens);
100 static int ad7417_sensor_read(struct ad7417_sensor *sens);
101
102 struct ad7417_softc {
103 device_t sc_dev;
104 uint32_t sc_addr;
105 struct ad7417_sensor *sc_sensors;
106 int sc_nsensors;
107 };
108 static device_method_t ad7417_methods[] = {
109 /* Device interface */
110 DEVMETHOD(device_probe, ad7417_probe),
111 DEVMETHOD(device_attach, ad7417_attach),
112 { 0, 0 },
113 };
114
115 static driver_t ad7417_driver = {
116 "ad7417",
117 ad7417_methods,
118 sizeof(struct ad7417_softc)
119 };
120
121 static devclass_t ad7417_devclass;
122
123 DRIVER_MODULE(ad7417, iicbus, ad7417_driver, ad7417_devclass, 0, 0);
124 static MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417");
125
126
127 static int
128 ad7417_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len)
129 {
130 unsigned char buf[4];
131 int try = 0;
132
133 struct iic_msg msg[] = {
134 { addr, IIC_M_WR, 0, buf }
135 };
136
137 msg[0].len = len + 1;
138 buf[0] = reg;
139 memcpy(buf + 1, buff, len);
140
141 for (;;)
142 {
143 if (iicbus_transfer(dev, msg, 1) == 0)
144 return (0);
145
146 if (++try > 5) {
147 device_printf(dev, "iicbus write failed\n");
148 return (-1);
149 }
150 pause("ad7417_write", hz);
151 }
152 }
153
154 static int
155 ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
156 {
157 uint8_t buf[4];
158 int err, try = 0;
159
160 struct iic_msg msg[2] = {
161 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® },
162 { addr, IIC_M_RD, 1, buf },
163 };
164
165 for (;;)
166 {
167 err = iicbus_transfer(dev, msg, 2);
168 if (err != 0)
169 goto retry;
170
171 *data = *((uint8_t*)buf);
172 return (0);
173 retry:
174 if (++try > 5) {
175 device_printf(dev, "iicbus read failed\n");
176 return (-1);
177 }
178 pause("ad7417_read_1", hz);
179 }
180 }
181
182 static int
183 ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data)
184 {
185 uint8_t buf[4];
186 int err, try = 0;
187
188 struct iic_msg msg[2] = {
189 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® },
190 { addr, IIC_M_RD, 2, buf },
191 };
192
193 for (;;)
194 {
195 err = iicbus_transfer(dev, msg, 2);
196 if (err != 0)
197 goto retry;
198
199 *data = *((uint16_t*)buf);
200 return (0);
201 retry:
202 if (++try > 5) {
203 device_printf(dev, "iicbus read failed\n");
204 return (-1);
205 }
206 pause("ad7417_read_2", hz);
207 }
208 }
209
210 static int
211 ad7417_write_read(device_t dev, uint32_t addr, struct write_data out,
212 struct read_data *in)
213 {
214 uint8_t buf[4];
215 int err, try = 0;
216
217 /* Do a combined write/read. */
218 struct iic_msg msg[3] = {
219 { addr, IIC_M_WR, 2, buf },
220 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &in->reg },
221 { addr, IIC_M_RD, 2, buf },
222 };
223
224 /* Prepare the write msg. */
225 buf[0] = out.reg;
226 buf[1] = out.val & 0xff;
227
228 for (;;)
229 {
230 err = iicbus_transfer(dev, msg, 3);
231 if (err != 0)
232 goto retry;
233
234 in->val = *((uint16_t*)buf);
235 return (0);
236 retry:
237 if (++try > 5) {
238 device_printf(dev, "iicbus write/read failed\n");
239 return (-1);
240 }
241 pause("ad7417_write_read", hz);
242 }
243 }
244
245 static int
246 ad7417_init_adc(device_t dev, uint32_t addr)
247 {
248 uint8_t buf;
249 int err;
250
251 adc741x_config = 0;
252 /* Clear Config2 */
253 buf = 0;
254
255 err = ad7417_write(dev, addr, AD7417_CONFIG2, &buf, 1);
256
257 /* Read & cache Config1 */
258 buf = 0;
259 err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1);
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, 1);
267 if (err < 0)
268 return (-1);
269
270 return (0);
271
272 }
273 static int
274 ad7417_probe(device_t dev)
275 {
276 const char *name, *compatible;
277 struct ad7417_softc *sc;
278
279 name = ofw_bus_get_name(dev);
280 compatible = ofw_bus_get_compat(dev);
281
282 if (!name)
283 return (ENXIO);
284
285 if (strcmp(name, "supply-monitor") != 0 ||
286 strcmp(compatible, "ad7417") != 0)
287 return (ENXIO);
288
289 sc = device_get_softc(dev);
290 sc->sc_dev = dev;
291 sc->sc_addr = iicbus_get_addr(dev);
292
293 device_set_desc(dev, "Supply-Monitor AD7417");
294
295 return (0);
296 }
297
298 /*
299 * This function returns the number of sensors. If we call it the second time
300 * and we have allocated memory for sc->sc_sensors, we fill in the properties.
301 */
302 static int
303 ad7417_fill_sensor_prop(device_t dev)
304 {
305 phandle_t child;
306 struct ad7417_softc *sc;
307 u_int id[10];
308 char location[96];
309 char type[32];
310 int i = 0, j, len = 0, prop_len, prev_len = 0;
311
312 sc = device_get_softc(dev);
313
314 child = ofw_bus_get_node(dev);
315
316 /* Fill the sensor location property. */
317 prop_len = OF_getprop(child, "hwsensor-location", location,
318 sizeof(location));
319 while (len < prop_len) {
320 if (sc->sc_sensors != NULL)
321 strcpy(sc->sc_sensors[i].therm.name, location + len);
322 prev_len = strlen(location + len) + 1;
323 len += prev_len;
324 i++;
325 }
326 if (sc->sc_sensors == NULL)
327 return (i);
328
329 /* Fill the sensor type property. */
330 len = 0;
331 i = 0;
332 prev_len = 0;
333 prop_len = OF_getprop(child, "hwsensor-type", type, sizeof(type));
334 while (len < prop_len) {
335 if (strcmp(type + len, "temperature") == 0)
336 sc->sc_sensors[i].type = ADC7417_TEMP_SENSOR;
337 else
338 sc->sc_sensors[i].type = ADC7417_ADC_SENSOR;
339 prev_len = strlen(type + len) + 1;
340 len += prev_len;
341 i++;
342 }
343
344 /* Fill the sensor id property. Taken from OF. */
345 prop_len = OF_getprop(child, "hwsensor-id", id, sizeof(id));
346 for (j = 0; j < i; j++)
347 sc->sc_sensors[j].id = id[j];
348
349 /* Fill the sensor zone property. Taken from OF. */
350 prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id));
351 for (j = 0; j < i; j++)
352 sc->sc_sensors[j].therm.zone = id[j];
353
354 /* Finish setting up sensor properties */
355 for (j = 0; j < i; j++) {
356 sc->sc_sensors[j].dev = dev;
357
358 /* HACK: Apple wired a random diode to the ADC line */
359 if (strstr(sc->sc_sensors[j].therm.name, "DIODE TEMP")
360 != NULL) {
361 sc->sc_sensors[j].type = ADC7417_TEMP_SENSOR;
362 sc->sc_sensors[j].therm.read =
363 (int (*)(struct pmac_therm *))(ad7417_diode_read);
364 } else {
365 sc->sc_sensors[j].therm.read =
366 (int (*)(struct pmac_therm *))(ad7417_sensor_read);
367 }
368
369 if (sc->sc_sensors[j].type != ADC7417_TEMP_SENSOR)
370 continue;
371
372 /* Make up some ranges */
373 sc->sc_sensors[j].therm.target_temp = 500 + ZERO_C_TO_K;
374 sc->sc_sensors[j].therm.max_temp = 900 + ZERO_C_TO_K;
375
376 pmac_thermal_sensor_register(&sc->sc_sensors[j].therm);
377 }
378
379 return (i);
380 }
381
382 static int
383 ad7417_attach(device_t dev)
384 {
385 struct ad7417_softc *sc;
386 struct sysctl_oid *oid, *sensroot_oid;
387 struct sysctl_ctx_list *ctx;
388 char sysctl_name[32];
389 int i, j;
390 const char *unit;
391 const char *desc;
392
393 sc = device_get_softc(dev);
394
395 sc->sc_nsensors = 0;
396
397 /* Count the actual number of sensors. */
398 sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
399
400 device_printf(dev, "%d sensors detected.\n", sc->sc_nsensors);
401
402 if (sc->sc_nsensors == 0)
403 device_printf(dev, "WARNING: No AD7417 sensors detected!\n");
404
405 sc->sc_sensors = malloc (sc->sc_nsensors * sizeof(struct ad7417_sensor),
406 M_AD7417, M_WAITOK | M_ZERO);
407
408 ctx = device_get_sysctl_ctx(dev);
409 sensroot_oid = SYSCTL_ADD_NODE(ctx,
410 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor",
411 CTLFLAG_RD, 0, "AD7417 Sensor Information");
412
413 /* Now we can fill the properties into the allocated struct. */
414 sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
415
416 /* Add sysctls for the sensors. */
417 for (i = 0; i < sc->sc_nsensors; i++) {
418 for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) {
419 sysctl_name[j] =
420 tolower(sc->sc_sensors[i].therm.name[j]);
421 if (isspace(sysctl_name[j]))
422 sysctl_name[j] = '_';
423 }
424 sysctl_name[j] = 0;
425
426 oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid),
427 OID_AUTO,
428 sysctl_name, CTLFLAG_RD, 0,
429 "Sensor Information");
430
431 if (sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR) {
432 unit = "temp";
433 desc = "Sensor temp in C";
434 } else {
435 unit = "volt";
436 desc = "Sensor Volt in V";
437 }
438 /* I use i to pass the sensor id. */
439 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
440 unit, CTLTYPE_INT | CTLFLAG_RD, dev,
441 i, ad7417_sensor_sysctl,
442 sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ?
443 "IK" : "I", desc);
444 }
445 /* Dump sensor location, ID & type. */
446 if (bootverbose) {
447 device_printf(dev, "Sensors\n");
448 for (i = 0; i < sc->sc_nsensors; i++) {
449 device_printf(dev, "Location: %s ID: %d type: %d\n",
450 sc->sc_sensors[i].therm.name,
451 sc->sc_sensors[i].id,
452 sc->sc_sensors[i].type);
453 }
454 }
455
456 return (0);
457 }
458
459 static int
460 ad7417_get_temp(device_t dev, uint32_t addr, int *temp)
461 {
462 uint16_t buf[2];
463 uint16_t read;
464 int err;
465
466 err = ad7417_read_2(dev, addr, AD7417_TEMP, buf);
467
468 if (err < 0)
469 return (-1);
470
471 read = *((int16_t*)buf);
472
473 /* The ADC is 10 bit, the resolution is 0.25 C.
474 The temperature is in tenth kelvin.
475 */
476 *temp = (((int16_t)(read & 0xffc0)) >> 6) * 25 / 10;
477 return (0);
478 }
479
480 static int
481 ad7417_get_adc(device_t dev, uint32_t addr, unsigned int *value,
482 uint8_t chan)
483 {
484 uint8_t tmp;
485 int err;
486 struct write_data config;
487 struct read_data data;
488
489 tmp = chan << 5;
490 config.reg = AD7417_CONFIG;
491 data.reg = AD7417_ADC;
492 data.val = 0;
493
494 err = ad7417_read_1(dev, addr, AD7417_CONFIG, &config.val);
495
496 config.val = (config.val & ~AD7417_CONFMASK) | (tmp & AD7417_CONFMASK);
497
498 err = ad7417_write_read(dev, addr, config, &data);
499 if (err < 0)
500 return (-1);
501
502 *value = ((uint32_t)data.val) >> 6;
503
504 return (0);
505 }
506
507 static int
508 ad7417_diode_read(struct ad7417_sensor *sens)
509 {
510 static int eeprom_read = 0;
511 static cell_t eeprom[2][40];
512 phandle_t eeprom_node;
513 int rawval, diode_slope, diode_offset;
514 int temp;
515
516 if (!eeprom_read) {
517 eeprom_node = OF_finddevice("/u3/i2c/cpuid@a0");
518 OF_getprop(eeprom_node, "cpuid", eeprom[0], sizeof(eeprom[0]));
519 eeprom_node = OF_finddevice("/u3/i2c/cpuid@a2");
520 OF_getprop(eeprom_node, "cpuid", eeprom[1], sizeof(eeprom[1]));
521 eeprom_read = 1;
522 }
523
524 rawval = ad7417_adc_read(sens);
525 if (rawval < 0)
526 return (-1);
527
528 if (strstr(sens->therm.name, "CPU B") != NULL) {
529 diode_slope = eeprom[1][0x11] >> 16;
530 diode_offset = (int16_t)(eeprom[1][0x11] & 0xffff) << 12;
531 } else {
532 diode_slope = eeprom[0][0x11] >> 16;
533 diode_offset = (int16_t)(eeprom[0][0x11] & 0xffff) << 12;
534 }
535
536 temp = (rawval*diode_slope + diode_offset) >> 2;
537 temp = (10*(temp >> 16)) + ((10*(temp & 0xffff)) >> 16);
538
539 return (temp + ZERO_C_TO_K);
540 }
541
542 static int
543 ad7417_adc_read(struct ad7417_sensor *sens)
544 {
545 struct ad7417_softc *sc;
546 uint8_t chan;
547 int temp;
548
549 sc = device_get_softc(sens->dev);
550
551 switch (sens->id) {
552 case 11:
553 case 16:
554 chan = 1;
555 break;
556 case 12:
557 case 17:
558 chan = 2;
559 break;
560 case 13:
561 case 18:
562 chan = 3;
563 break;
564 case 14:
565 case 19:
566 chan = 4;
567 break;
568 default:
569 chan = 1;
570 }
571
572 if (ad7417_get_adc(sc->sc_dev, sc->sc_addr, &temp, chan) < 0)
573 return (-1);
574
575 return (temp);
576 }
577
578
579 static int
580 ad7417_sensor_read(struct ad7417_sensor *sens)
581 {
582 struct ad7417_softc *sc;
583 int temp;
584
585 sc = device_get_softc(sens->dev);
586
587 /* Init the ADC. */
588 if (ad7417_init_adc(sc->sc_dev, sc->sc_addr) < 0)
589 return (-1);
590
591 if (sens->type == ADC7417_TEMP_SENSOR) {
592 if (ad7417_get_temp(sc->sc_dev, sc->sc_addr, &temp) < 0)
593 return (-1);
594 temp += ZERO_C_TO_K;
595 } else {
596 temp = ad7417_adc_read(sens);
597 }
598 return (temp);
599 }
600
601 static int
602 ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS)
603 {
604 device_t dev;
605 struct ad7417_softc *sc;
606 struct ad7417_sensor *sens;
607 int value = 0;
608 int error;
609
610 dev = arg1;
611 sc = device_get_softc(dev);
612 sens = &sc->sc_sensors[arg2];
613
614 value = sens->therm.read(&sens->therm);
615 if (value < 0)
616 return (ENXIO);
617
618 error = sysctl_handle_int(oidp, &value, 0, req);
619
620 return (error);
621 }
Cache object: 1a03c77de51250c73a8b3d69ec8bda90
|