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
60 uint8_t adc741x_config;
61
62 struct 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
72 struct write_data {
73 uint8_t reg;
74 uint8_t val;
75 };
76
77 struct read_data {
78 uint8_t reg;
79 uint16_t val;
80 };
81
82 /* Regular bus attachment functions */
83 static int ad7417_probe(device_t);
84 static int ad7417_attach(device_t);
85
86 /* Utility functions */
87 static int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS);
88 static int ad7417_write(device_t dev, uint32_t addr, uint8_t reg,
89 uint8_t *buf, int len);
90 static int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg,
91 uint8_t *data);
92 static int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg,
93 uint16_t *data);
94 static int ad7417_write_read(device_t dev, uint32_t addr,
95 struct write_data out, struct read_data *in);
96 static int ad7417_diode_read(struct ad7417_sensor *sens);
97 static int ad7417_adc_read(struct ad7417_sensor *sens);
98 static int ad7417_sensor_read(struct ad7417_sensor *sens);
99
100 struct 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 };
107 static 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
114 static driver_t ad7417_driver = {
115 "ad7417",
116 ad7417_methods,
117 sizeof(struct ad7417_softc)
118 };
119
120 DRIVER_MODULE(ad7417, iicbus, ad7417_driver, 0, 0);
121 static MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417");
122
123
124 static int
ad7417_write(device_t dev,uint32_t addr,uint8_t reg,uint8_t * buff,int len)125 ad7417_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
151 static int
ad7417_read_1(device_t dev,uint32_t addr,uint8_t reg,uint8_t * data)152 ad7417_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, ® },
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
179 static int
ad7417_read_2(device_t dev,uint32_t addr,uint8_t reg,uint16_t * data)180 ad7417_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, ® },
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
207 static int
ad7417_write_read(device_t dev,uint32_t addr,struct write_data out,struct read_data * in)208 ad7417_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
242 static int
ad7417_init_adc(device_t dev,uint32_t addr)243 ad7417_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 }
275 static int
ad7417_probe(device_t dev)276 ad7417_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 */
304 static int
ad7417_fill_sensor_prop(device_t dev)305 ad7417_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
398 static int
ad7417_attach(device_t dev)399 ad7417_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
473 static int
ad7417_get_temp(device_t dev,uint32_t addr,int * temp)474 ad7417_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
494 static int
ad7417_get_adc(device_t dev,uint32_t addr,unsigned int * value,uint8_t chan)495 ad7417_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
521 static int
ad7417_diode_read(struct ad7417_sensor * sens)522 ad7417_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
556 static int
ad7417_adc_read(struct ad7417_sensor * sens)557 ad7417_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
593 static int
ad7417_sensor_read(struct ad7417_sensor * sens)594 ad7417_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
616 static int
ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS)617 ad7417_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