Lines Matching +full:fan +full:- +full:0

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
55 #define ADT746X_TACH1LOW 0x28
56 #define ADT746X_TACH1HIGH 0x29
57 #define ADT746X_TACH2LOW 0x2a
58 #define ADT746X_TACH2HIGH 0x2b
59 #define ADT746X_PWM1 0x30
60 #define ADT746X_PWM2 0x31
61 #define ADT746X_DEVICE_ID 0x3d
62 #define ADT746X_COMPANY_ID 0x3e
63 #define ADT746X_REV_ID 0x3f
64 #define ADT746X_CONFIG 0x40
65 #define ADT746X_PWM1_CONF 0x5c
66 #define ADT746X_PWM2_CONF 0x5d
67 #define ADT746X_MANUAL_MASK 0xe0
69 #define ADT7460_DEV_ID 0x27
70 #define ADT7467_DEV_ID 0x68
73 struct pmac_fan fan; member
119 static int adt746x_fan_set_pwm(struct adt746x_fan *fan, int pwm);
120 static int adt746x_fan_get_pwm(struct adt746x_fan *fan);
134 { 0, 0 },
143 DRIVER_MODULE(adt746x, iicbus, adt746x_driver, 0, 0);
153 int try = 0; in adt746x_write()
160 buf[0] = reg; in adt746x_write()
165 if (iicbus_transfer(dev, msg, 1) == 0) in adt746x_write()
166 return (0); in adt746x_write()
169 return (-1); in adt746x_write()
173 return (0); in adt746x_write()
180 int err, try = 0; in adt746x_read()
190 if (err != 0) in adt746x_read()
194 return (0); in adt746x_read()
198 return (-1); in adt746x_read()
216 if (strcmp(name, "fan") != 0 || in adt746x_probe()
217 (strcmp(compatible, "adt7460") != 0 && in adt746x_probe()
218 strcmp(compatible, "adt7467") != 0)) in adt746x_probe()
222 sc->sc_dev = dev; in adt746x_probe()
223 sc->sc_addr = iicbus_get_addr(dev); in adt746x_probe()
227 return (0); in adt746x_probe()
237 sc->enum_hook.ich_func = adt746x_start; in adt746x_attach()
238 sc->enum_hook.ich_arg = dev; in adt746x_attach()
243 * the master. The openpic on mac-io is controlling the htpic. in adt746x_attach()
244 * This one gets attached after the mac-io probing and then the in adt746x_attach()
248 if (config_intrhook_establish(&sc->enum_hook) != 0) in adt746x_attach()
251 return (0); in adt746x_attach()
265 adt746x_read(sc->sc_dev, sc->sc_addr, ADT746X_DEVICE_ID, &did); in adt746x_start()
266 adt746x_read(sc->sc_dev, sc->sc_addr, ADT746X_COMPANY_ID, &cid); in adt746x_start()
267 adt746x_read(sc->sc_dev, sc->sc_addr, ADT746X_REV_ID, &rev); in adt746x_start()
268 adt746x_read(sc->sc_dev, sc->sc_addr, ADT746X_CONFIG, &conf); in adt746x_start()
277 sc->device_id = did; in adt746x_start()
281 if (sc->device_id == ADT7460_DEV_ID) in adt746x_start()
282 adt746x_write(sc->sc_dev, sc->sc_addr, ADT746X_CONFIG, &conf); in adt746x_start()
287 config_intrhook_disestablish(&sc->enum_hook); in adt746x_start()
291 * Sensor and fan management
294 adt746x_fan_set_pwm(struct adt746x_fan *fan, int pwm) in adt746x_fan_set_pwm() argument
296 uint8_t reg = 0, manual, mode = 0; in adt746x_fan_set_pwm()
300 sc = device_get_softc(fan->dev); in adt746x_fan_set_pwm()
303 pwm = max(fan->fan.min_rpm, pwm); in adt746x_fan_set_pwm()
304 pwm = min(fan->fan.max_rpm, pwm); in adt746x_fan_set_pwm()
306 reg = fan->pwm_reg; in adt746x_fan_set_pwm()
307 mode = fan->conf_reg; in adt746x_fan_set_pwm()
310 PWM dutycycle can be programmed from 0% (0x00) to 100% (0xFF) in adt746x_fan_set_pwm()
313 buf = (pwm * 100 / 39) - (pwm ? 1 : 0); in adt746x_fan_set_pwm()
314 fan->setpoint = buf; in adt746x_fan_set_pwm()
317 adt746x_read(sc->sc_dev, sc->sc_addr, mode, &manual); in adt746x_fan_set_pwm()
319 adt746x_write(sc->sc_dev, sc->sc_addr, mode, &manual); in adt746x_fan_set_pwm()
322 adt746x_write(sc->sc_dev, sc->sc_addr, reg, &buf); in adt746x_fan_set_pwm()
324 return (0); in adt746x_fan_set_pwm()
328 adt746x_fan_get_pwm(struct adt746x_fan *fan) in adt746x_fan_get_pwm() argument
334 sc = device_get_softc(fan->dev); in adt746x_fan_get_pwm()
336 reg = fan->pwm_reg; in adt746x_fan_get_pwm()
338 adt746x_read(sc->sc_dev, sc->sc_addr, reg, &buf); in adt746x_fan_get_pwm()
340 pwm = (buf * 39 / 100) + (buf ? 1 : 0); in adt746x_fan_get_pwm()
351 int i, id_len, len = 0, location_len, prev_len = 0; in adt746x_fill_fan_prop()
357 /* Fill the fan location property. */ in adt746x_fill_fan_prop()
358 location_len = OF_getprop_alloc(child, "hwctrl-location", (void **)&location); in adt746x_fill_fan_prop()
359 id_len = OF_getprop_alloc_multi(child, "hwctrl-id", sizeof(cell_t), (void **)&id); in adt746x_fill_fan_prop()
360 if (location_len == -1 || id_len == -1) { in adt746x_fill_fan_prop()
363 return 0; in adt746x_fill_fan_prop()
366 /* Fill in all the properties for each fan. */ in adt746x_fill_fan_prop()
367 for (i = 0; i < id_len; i++) { in adt746x_fill_fan_prop()
368 strlcpy(sc->sc_fans[i].fan.name, location + len, 32); in adt746x_fill_fan_prop()
371 sc->sc_fans[i].id = id[i]; in adt746x_fill_fan_prop()
373 sc->sc_fans[i].pwm_reg = ADT746X_PWM1; in adt746x_fill_fan_prop()
374 sc->sc_fans[i].conf_reg = ADT746X_PWM1_CONF; in adt746x_fill_fan_prop()
376 sc->sc_fans[i].pwm_reg = ADT746X_PWM2; in adt746x_fill_fan_prop()
377 sc->sc_fans[i].conf_reg = ADT746X_PWM2_CONF; in adt746x_fill_fan_prop()
379 sc->sc_fans[i].pwm_reg = ADT746X_PWM1 + i; in adt746x_fill_fan_prop()
380 sc->sc_fans[i].conf_reg = ADT746X_PWM1_CONF + i; in adt746x_fill_fan_prop()
382 sc->sc_fans[i].dev = sc->sc_dev; in adt746x_fill_fan_prop()
383 sc->sc_fans[i].fan.min_rpm = 5; /* Percent */ in adt746x_fill_fan_prop()
384 sc->sc_fans[i].fan.max_rpm = 100; in adt746x_fill_fan_prop()
385 sc->sc_fans[i].fan.read = NULL; in adt746x_fill_fan_prop()
386 sc->sc_fans[i].fan.set = in adt746x_fill_fan_prop()
388 sc->sc_fans[i].fan.default_rpm = sc->sc_fans[i].fan.max_rpm; in adt746x_fill_fan_prop()
402 int i = 0, reg, sensid; in adt746x_fill_sensor_prop()
409 for (node = OF_child(child); node != 0; node = OF_peer(node)) { in adt746x_fill_sensor_prop()
410 if (OF_getprop(node, "sensor-id", &sensid, sizeof(sensid)) == -1) in adt746x_fill_sensor_prop()
412 OF_getprop(node, "location", sc->sc_sensors[i].therm.name, 32); in adt746x_fill_sensor_prop()
414 if (strcmp(sens_type, "temperature") == 0) in adt746x_fill_sensor_prop()
415 sc->sc_sensors[i].type = ADT746X_SENSOR_TEMP; in adt746x_fill_sensor_prop()
416 else if (strcmp(sens_type, "voltage") == 0) in adt746x_fill_sensor_prop()
417 sc->sc_sensors[i].type = ADT746X_SENSOR_VOLT; in adt746x_fill_sensor_prop()
419 sc->sc_sensors[i].type = ADT746X_SENSOR_SPEED; in adt746x_fill_sensor_prop()
421 OF_getprop(node, "sensor-id", &sensid, in adt746x_fill_sensor_prop()
424 sc->sc_sensors[i].reg = reg; in adt746x_fill_sensor_prop()
425 sc->sc_sensors[i].id = sensid; in adt746x_fill_sensor_prop()
426 OF_getprop(node, "zone", &sc->sc_sensors[i].therm.zone, in adt746x_fill_sensor_prop()
427 sizeof(sc->sc_sensors[i].therm.zone)); in adt746x_fill_sensor_prop()
428 sc->sc_sensors[i].dev = dev; in adt746x_fill_sensor_prop()
429 sc->sc_sensors[i].therm.read = in adt746x_fill_sensor_prop()
431 if (sc->sc_sensors[i].type == ADT746X_SENSOR_TEMP) { in adt746x_fill_sensor_prop()
433 sc->sc_sensors[i].therm.target_temp = 500 + ZERO_C_TO_K; in adt746x_fill_sensor_prop()
434 sc->sc_sensors[i].therm.max_temp = 800 + ZERO_C_TO_K; in adt746x_fill_sensor_prop()
436 pmac_thermal_sensor_register(&sc->sc_sensors[i].therm); in adt746x_fill_sensor_prop()
449 struct adt746x_fan *fan; in adt746x_fanrpm_sysctl() local
450 int pwm = 0, error; in adt746x_fanrpm_sysctl()
454 fan = &sc->sc_fans[arg2]; in adt746x_fanrpm_sysctl()
455 pwm = adt746x_fan_get_pwm(fan); in adt746x_fanrpm_sysctl()
456 error = sysctl_handle_int(oidp, &pwm, 0, req); in adt746x_fanrpm_sysctl()
458 if (error || !req->newptr) in adt746x_fanrpm_sysctl()
461 return (adt746x_fan_set_pwm(fan, pwm)); in adt746x_fanrpm_sysctl()
475 sc->sc_nfans = 0; in adt746x_attach_fans()
478 sc->sc_nfans = adt746x_fill_fan_prop(dev); in adt746x_attach_fans()
480 device_printf(dev, "%d fans detected!\n", sc->sc_nfans); in adt746x_attach_fans()
482 if (sc->sc_nfans == 0) { in adt746x_attach_fans()
490 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "ADT Fan Information"); in adt746x_attach_fans()
493 sc->sc_nfans = adt746x_fill_fan_prop(dev); in adt746x_attach_fans()
496 for (i = 0; i < sc->sc_nfans; i++) in adt746x_attach_fans()
497 pmac_thermal_fan_register(&sc->sc_fans[i].fan); in adt746x_attach_fans()
500 for (i = 0; i < sc->sc_nfans; i++) { in adt746x_attach_fans()
501 for (j = 0; j < strlen(sc->sc_fans[i].fan.name); j++) { in adt746x_attach_fans()
502 sysctl_name[j] = tolower(sc->sc_fans[i].fan.name[j]); in adt746x_attach_fans()
506 sysctl_name[j] = 0; in adt746x_attach_fans()
508 sc->sc_fans[i].setpoint = in adt746x_attach_fans()
509 adt746x_fan_get_pwm(&sc->sc_fans[i]); in adt746x_attach_fans()
512 OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, in adt746x_attach_fans()
513 "Fan Information"); in adt746x_attach_fans()
515 /* I use i to pass the fan id. */ in adt746x_attach_fans()
518 i, adt746x_fanrpm_sysctl, "I", "Fan PWM in %"); in adt746x_attach_fans()
521 /* Dump fan location & type. */ in adt746x_attach_fans()
523 for (i = 0; i < sc->sc_nfans; i++) { in adt746x_attach_fans()
524 device_printf(dev, "Fan location: %s", in adt746x_attach_fans()
525 sc->sc_fans[i].fan.name); in adt746x_attach_fans()
527 sc->sc_fans[i].id, in adt746x_attach_fans()
528 sc->sc_fans[i].setpoint); in adt746x_attach_fans()
537 int tmp = 0; in adt746x_sensor_read()
542 sc = device_get_softc(sens->dev); in adt746x_sensor_read()
543 if (sens->type != ADT746X_SENSOR_SPEED) { in adt746x_sensor_read()
544 if (adt746x_read(sc->sc_dev, sc->sc_addr, sens->reg, in adt746x_sensor_read()
545 &temp) < 0) in adt746x_sensor_read()
546 return (-1); in adt746x_sensor_read()
547 if (sens->type == ADT746X_SENSOR_TEMP) in adt746x_sensor_read()
552 if (adt746x_read(sc->sc_dev, sc->sc_addr, sens->reg, in adt746x_sensor_read()
553 data) < 0) in adt746x_sensor_read()
554 return (-1); in adt746x_sensor_read()
555 if (adt746x_read(sc->sc_dev, sc->sc_addr, sens->reg + 1, in adt746x_sensor_read()
556 data1) < 0) in adt746x_sensor_read()
557 return (-1); in adt746x_sensor_read()
558 val = data[0] + (data1[0] << 8); in adt746x_sensor_read()
559 /* A value of 0xffff means the fan is stopped. */ in adt746x_sensor_read()
560 if (val == 0 || val == 0xffff) in adt746x_sensor_read()
561 tmp = 0; in adt746x_sensor_read()
578 sens = &sc->sc_sensors[arg2]; in adt746x_sensor_sysctl()
580 value = sens->therm.read(&sens->therm); in adt746x_sensor_sysctl()
581 if (value < 0) in adt746x_sensor_sysctl()
584 error = sysctl_handle_int(oidp, &value, 0, req); in adt746x_sensor_sysctl()
602 sc->sc_nsensors = 0; in adt746x_attach_sensors()
605 sc->sc_nsensors = adt746x_fill_sensor_prop(dev); in adt746x_attach_sensors()
606 device_printf(dev, "%d sensors detected!\n", sc->sc_nsensors); in adt746x_attach_sensors()
607 if (sc->sc_nsensors == 0) { in adt746x_attach_sensors()
615 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "ADT Sensor Information"); in adt746x_attach_sensors()
618 for (i = 0; i < sc->sc_nsensors; i++) { in adt746x_attach_sensors()
619 for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) { in adt746x_attach_sensors()
620 sysctl_name[j] = tolower(sc->sc_sensors[i].therm.name[j]); in adt746x_attach_sensors()
624 sysctl_name[j] = 0; in adt746x_attach_sensors()
626 OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, in adt746x_attach_sensors()
628 if (sc->sc_sensors[i].type == ADT746X_SENSOR_TEMP) { in adt746x_attach_sensors()
631 } else if (sc->sc_sensors[i].type == ADT746X_SENSOR_VOLT) { in adt746x_attach_sensors()
642 sc->sc_sensors[i].type == ADT746X_SENSOR_TEMP ? in adt746x_attach_sensors()
648 for (i = 0; i < sc->sc_nsensors; i++) { in adt746x_attach_sensors()
650 sc->sc_sensors[i].therm.name); in adt746x_attach_sensors()
651 device_printf(dev, " type: %d id: %d reg: 0x%x\n", in adt746x_attach_sensors()
652 sc->sc_sensors[i].type, in adt746x_attach_sensors()
653 sc->sc_sensors[i].id, in adt746x_attach_sensors()
654 sc->sc_sensors[i].reg); in adt746x_attach_sensors()