36#include <sys/module.h>
37#include <sys/callout.h>
41#include <sys/kernel.h>
42#include <sys/reboot.h>
44#include <sys/sysctl.h>
45#include <sys/limits.h>
47#include <machine/bus.h>
48#include <machine/md_var.h>
53#include <dev/ofw/openfirm.h>
54#include <dev/ofw/ofw_bus.h>
55#include <powerpc/powermac/powermac_thermal.h>
58#define ADT746X_TACH1LOW 0x28
59#define ADT746X_TACH1HIGH 0x29
60#define ADT746X_TACH2LOW 0x2a
61#define ADT746X_TACH2HIGH 0x2b
62#define ADT746X_PWM1 0x30
63#define ADT746X_PWM2 0x31
64#define ADT746X_DEVICE_ID 0x3d
65#define ADT746X_COMPANY_ID 0x3e
66#define ADT746X_REV_ID 0x3f
67#define ADT746X_CONFIG 0x40
68#define ADT746X_PWM1_CONF 0x5c
69#define ADT746X_PWM2_CONF 0x5d
70#define ADT746X_MANUAL_MASK 0xe0
72#define ADT7460_DEV_ID 0x27
73#define ADT7467_DEV_ID 0x68
166 memcpy(
buf + 1, buff, 1);
173 device_printf(
dev,
"iicbus write failed\n");
176 pause(
"adt746x_write", hz);
202 device_printf(
dev,
"iicbus read failed\n");
205 pause(
"adt746x_read", hz);
212 const char *name, *compatible;
215 name = ofw_bus_get_name(
dev);
216 compatible = ofw_bus_get_compat(
dev);
221 if (strcmp(name,
"fan") != 0 ||
222 (strcmp(compatible,
"adt7460") != 0 &&
223 strcmp(compatible,
"adt7467") != 0))
226 sc = device_get_softc(
dev);
230 device_set_desc(
dev,
"Apple Thermostat Unit ADT746X");
240 sc = device_get_softc(
dev);
253 if (config_intrhook_establish(&sc->
enum_hook) != 0)
262 uint8_t did, cid, rev, conf;
266 device_t
dev = (device_t)xdev;
268 sc = device_get_softc(
dev);
275 device_printf(
dev,
"Dev ID %#x, Company ID %#x, Rev ID %#x CNF: %#x\n",
276 did, cid, rev, conf);
292 config_intrhook_disestablish(&sc->
enum_hook);
301 uint8_t reg = 0, manual, mode = 0;
305 sc = device_get_softc(fan->
dev);
308 pwm = max(fan->
fan.min_rpm, pwm);
309 pwm = min(fan->
fan.max_rpm, pwm);
318 buf = (pwm * 100 / 39) - (pwm ? 1 : 0);
339 sc = device_get_softc(fan->
dev);
345 pwm = (
buf * 39 / 100) + (
buf ? 1 : 0);
356 int i, id_len,
len = 0, location_len, prev_len = 0;
358 sc = device_get_softc(
dev);
360 child = ofw_bus_get_node(
dev);
363 location_len = OF_getprop_alloc(child,
"hwctrl-location", (
void **)&location);
364 id_len = OF_getprop_alloc_multi(child,
"hwctrl-id",
sizeof(cell_t), (
void **)&
id);
365 if (location_len == -1 || id_len == -1) {
366 OF_prop_free(location);
372 for (i = 0; i < id_len; i++) {
374 prev_len = strlen(location +
len) + 1;
380 }
else if (
id[i] == 7) {
395 OF_prop_free(location);
404 phandle_t child, node;
407 int i = 0, reg, sensid;
409 sc = device_get_softc(
dev);
411 child = ofw_bus_get_node(
dev);
414 for (node = OF_child(child); node != 0; node = OF_peer(node)) {
415 if (OF_getprop(node,
"sensor-id", &sensid,
sizeof(sensid)) == -1)
418 OF_getprop(node,
"device_type", sens_type,
sizeof(sens_type));
419 if (strcmp(sens_type,
"temperature") == 0)
421 else if (strcmp(sens_type,
"voltage") == 0)
425 OF_getprop(node,
"reg", ®,
sizeof(reg));
426 OF_getprop(node,
"sensor-id", &sensid,
458 sc = device_get_softc(adt);
461 error = sysctl_handle_int(oidp, &pwm, 0, req);
463 if (error || !req->newptr)
473 struct sysctl_oid *oid, *fanroot_oid;
474 struct sysctl_ctx_list *ctx;
476 char sysctl_name[32];
479 sc = device_get_softc(
dev);
483 child = ofw_bus_get_node(
dev);
488 device_printf(
dev,
"%d fans detected!\n", sc->
sc_nfans);
491 device_printf(
dev,
"WARNING: No fans detected!\n");
495 ctx = device_get_sysctl_ctx(
dev);
496 fanroot_oid = SYSCTL_ADD_NODE(ctx,
497 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
"fans",
498 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"ADT Fan Information");
505 pmac_thermal_fan_register(&sc->
sc_fans[i].
fan);
508 for (i = 0; i < sc->
sc_nfans; i++) {
509 for (j = 0; j < strlen(sc->
sc_fans[i].
fan.name); j++) {
510 sysctl_name[j] = tolower(sc->
sc_fans[i].
fan.name[j]);
511 if (isspace(sysctl_name[j]))
512 sysctl_name[j] =
'_';
519 oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(fanroot_oid),
520 OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
524 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
525 "pwm", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
dev,
531 for (i = 0; i < sc->
sc_nfans; i++) {
532 device_printf(
dev,
"Fan location: %s",
534 device_printf(
dev,
" id: %d RPM: %d\n",
547 uint8_t
data[1], data1[1];
550 sc = device_get_softc(sens->
dev);
551 if (sens->
type != ADT746X_SENSOR_SPEED) {
555 if (sens->
type == ADT746X_SENSOR_TEMP)
556 tmp = 10 * temp + ZERO_C_TO_K;
566 val =
data[0] + (data1[0] << 8);
568 if (
val == 0 ||
val == 0xffff)
571 tmp = (90000 * 60) /
val;
585 sc = device_get_softc(
dev);
592 error = sysctl_handle_int(oidp, &value, 0, req);
601 struct sysctl_oid *oid, *sensroot_oid;
602 struct sysctl_ctx_list *ctx;
604 char sysctl_name[40];
610 sc = device_get_softc(
dev);
612 child = ofw_bus_get_node(
dev);
618 device_printf(
dev,
"WARNING: No sensors detected!\n");
622 ctx = device_get_sysctl_ctx(
dev);
623 sensroot_oid = SYSCTL_ADD_NODE(ctx,
624 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
"sensors",
625 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"ADT Sensor Information");
631 if (isspace(sysctl_name[j]))
632 sysctl_name[j] =
'_';
635 oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid),
636 OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
637 "Sensor Information");
640 desc =
"sensor unit (C)";
643 desc =
"sensor unit (mV)";
646 desc =
"sensor unit (RPM)";
649 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
650 unit, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
dev, i,
659 device_printf(
dev,
"Sensor location: %s",
661 device_printf(
dev,
" type: %d id: %d reg: 0x%x\n",
static int adt746x_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buf)
#define ADT746X_MANUAL_MASK
static device_method_t adt746x_methods[]
#define ADT746X_DEVICE_ID
static int adt746x_attach(device_t)
static int adt746x_sensor_read(struct adt746x_sensor *sens)
static int adt746x_fill_fan_prop(device_t dev)
static int adt746x_read(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
static void adt746x_attach_sensors(device_t dev)
static driver_t adt746x_driver
static int adt746x_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
#define ADT746X_COMPANY_ID
#define ADT746X_PWM2_CONF
static void adt746x_start(void *xdev)
static MALLOC_DEFINE(M_ADT746X, "adt746x", "ADT Sensor Information")
static devclass_t adt746x_devclass
#define ADT746X_PWM1_CONF
DRIVER_MODULE(adt746x, iicbus, adt746x_driver, adt746x_devclass, 0, 0)
static int adt746x_fill_sensor_prop(device_t dev)
static int adt746x_fan_set_pwm(struct adt746x_fan *fan, int pwm)
static void adt746x_attach_fans(device_t dev)
static int adt746x_sensor_sysctl(SYSCTL_HANDLER_ARGS)
static int adt746x_fan_get_pwm(struct adt746x_fan *fan)
static int adt746x_probe(device_t)
int iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
enum adt746x_sensor::@1 type
struct adt746x_fan sc_fans[4]
struct adt746x_sensor sc_sensors[9]
struct intr_config_hook enum_hook