Module Name: src Committed By: macallan Date: Tue Mar 9 01:17:37 UTC 2021
Modified Files: src/sys/arch/macppc/dev: smu.c Log Message: add support for the CPU temperature sensor found in iMac G5s To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/sys/arch/macppc/dev/smu.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/macppc/dev/smu.c diff -u src/sys/arch/macppc/dev/smu.c:1.11 src/sys/arch/macppc/dev/smu.c:1.12 --- src/sys/arch/macppc/dev/smu.c:1.11 Fri Mar 5 07:15:53 2021 +++ src/sys/arch/macppc/dev/smu.c Tue Mar 9 01:17:37 2021 @@ -80,7 +80,7 @@ struct smu_iicbus { #define SMU_MAX_FANS 8 #define SMU_MAX_IICBUS 3 -#define SMU_MAX_SME_SENSORS SMU_MAX_FANS +#define SMU_MAX_SME_SENSORS (SMU_MAX_FANS + 8) struct smu_zone { bool (*filter)(const envsys_data_t *); @@ -120,6 +120,8 @@ struct smu_softc { struct sysmon_envsys *sc_sme; envsys_data_t sc_sme_sensors[SMU_MAX_SME_SENSORS]; + uint32_t cpu_m; + int32_t cpu_b; struct smu_zone sc_zones[SMU_ZONES]; lwp_t *sc_thread; @@ -130,7 +132,7 @@ struct smu_softc { #define SMU_CMD_RTC 0x8e #define SMU_CMD_I2C 0x9a #define SMU_CMD_POWER 0xaa -#define SMU_ADC 0xd8 +#define SMU_CMD_ADC 0xd8 #define SMU_MISC 0xee #define SMU_MISC_GET_DATA 0x02 #define SMU_MISC_LED_CTRL 0x04 @@ -165,6 +167,8 @@ static int smu_todr_settime_ymdhms(todr_ static int smu_fan_update_rpm(struct smu_fan *); static int smu_fan_get_rpm(struct smu_fan *, int *); static int smu_fan_set_rpm(struct smu_fan *, int); +static int smu_read_adc(struct smu_softc *, int); + static int smu_iicbus_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, void *, size_t, int); static int smu_sysctl_fan_rpm(SYSCTLFN_ARGS); @@ -199,6 +203,7 @@ smu_attach(device_t parent, device_t sel { struct confargs *ca = aux; struct smu_softc *sc = device_private(self); + uint16_t data[4]; sc->sc_dev = self; sc->sc_node = ca->ca_node; @@ -227,6 +232,13 @@ smu_attach(device_t parent, device_t sel sc->sc_todr.cookie = sc; todr_attach(&sc->sc_todr); + /* calibration data */ + memset(data, 0, 8); + smu_get_datablock(SMU_CPUTEMP_CAL, (void *)data, 8); + DPRINTF("data %04x %04x %04x %04x\n", data[0], data[1], data[2], data[3]); + sc->cpu_m = data[2]; + sc->cpu_b = (int16_t)data[3]; + smu_setup_sme(sc); smu_setup_zones(sc); @@ -476,7 +488,8 @@ smu_setup_sme(struct smu_softc *sc) { struct smu_fan *fan; envsys_data_t *sme_sensor; - int i; + int i, sensors, child, reg; + char loc[32], type[32]; sc->sc_sme = sysmon_envsys_create(); @@ -494,7 +507,26 @@ smu_setup_sme(struct smu_softc *sc) return; } } - + sensors = OF_finddevice("/smu/sensors"); + child = OF_child(sensors); + while (child != 0) { + sme_sensor = &sc->sc_sme_sensors[i]; + if (OF_getprop(child, "location", loc, 32) == 0) goto next; + if (OF_getprop(child, "device_type", type, 32) == 0) goto next; + if (OF_getprop(child, "reg", ®, 4) == 0) goto next; + if (strcmp(type, "temp-sensor") == 0) { + sme_sensor->units = ENVSYS_STEMP; + sme_sensor->state = ENVSYS_SINVALID; + strncpy(sme_sensor->desc, loc, sizeof(sme_sensor->desc)); + sme_sensor->private = reg; + sysmon_envsys_sensor_attach(sc->sc_sme, sme_sensor); + i++; + printf("%s: %s@%x\n", loc, type, reg); + } +next: + child = OF_peer(child); + } + sc->sc_sme->sme_name = device_xname(sc->sc_dev); sc->sc_sme->sme_cookie = sc; sc->sc_sme->sme_refresh = smu_sme_refresh; @@ -535,6 +567,19 @@ smu_sme_refresh(struct sysmon_envsys *sm edata->value_cur = fan->current_rpm; edata->state = ENVSYS_SVALID; } + } else if (edata->private > 0) { + /* this works only for the CPU diode */ + int64_t r = smu_read_adc(sc, edata->private); + if (r != -1) { + r = r * sc->cpu_m; + r >>= 3; + r += (int64_t)sc->cpu_b << 9; + r <<= 1; + r *= 15625; + r /= 1024; + edata->value_cur = r + 273150000; + edata->state = ENVSYS_SVALID; + } } } @@ -771,6 +816,23 @@ smu_fan_set_rpm(struct smu_fan *fan, int } static int +smu_read_adc(struct smu_softc *sc, int id) +{ + struct smu_cmd cmd; + int ret; + + cmd.cmd = SMU_CMD_ADC; + cmd.len = 1; + cmd.data[0] = id; + + ret = smu_do_cmd(sc, &cmd, 800); + if (ret == 0) { + return cmd.data[0] << 8 | cmd.data[1]; + } + return -1; +} + +static int smu_iicbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *send, size_t send_len, void *recv, size_t recv_len, int flags) {