Index: sys/dev/i2c/lm75.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/lm75.c,v retrieving revision 1.36 diff -u -r1.36 lm75.c --- sys/dev/i2c/lm75.c 21 Aug 2020 20:41:43 -0000 1.36 +++ sys/dev/i2c/lm75.c 7 Dec 2020 15:00:25 -0000 @@ -201,7 +201,8 @@ sc->sc_lmtemp_decode = lmtemptbl[i].lmtemp_decode; sc->sc_lmtemp_encode = lmtemptbl[i].lmtemp_encode; - iic_acquire_bus(sc->sc_tag, 0); + if (iic_acquire_bus(sc->sc_tag, 0)) + return; /* Read temperature limit(s) and remember initial value(s). */ if (i == lmtemp_lm77) { @@ -349,9 +350,10 @@ { struct lmtemp_softc *sc = sme->sme_cookie; - iic_acquire_bus(sc->sc_tag, 0); /* also locks our instance */ + if (iic_acquire_bus(sc->sc_tag, 0)) /* also locks our instance */ + return; lmtemp_refresh_sensor_data(sc); - iic_release_bus(sc->sc_tag, 0); /* also unlocks our instance */ + iic_release_bus(sc->sc_tag, 0); /* also unlocks our instance */ } static void @@ -363,7 +365,8 @@ *props &= ~(PROP_CRITMAX); - iic_acquire_bus(sc->sc_tag, 0); + if (iic_acquire_bus(sc->sc_tag, 0)) + return; if (lmtemp_temp_read(sc, LM75_REG_TOS_SET_POINT, &val, 0) == 0) { limits->sel_critmax = val; *props |= PROP_CRITMAX; @@ -380,7 +383,8 @@ *props &= ~(PROP_CRITMAX | PROP_WARNMAX | PROP_WARNMIN); - iic_acquire_bus(sc->sc_tag, 0); + if (iic_acquire_bus(sc->sc_tag, 0)) + return; if (lmtemp_temp_read(sc, LM77_REG_TCRIT_SET_POINT, &val, 0) == 0) { limits->sel_critmax = val; *props |= PROP_CRITMAX; @@ -408,7 +412,8 @@ limit = sc->sc_smax; else limit = limits->sel_critmax; - iic_acquire_bus(sc->sc_tag, 0); + if (iic_acquire_bus(sc->sc_tag, 0)) + return; lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT, limit - 5000000, 0); lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, limit, 0); @@ -426,7 +431,8 @@ struct lmtemp_softc *sc = sme->sme_cookie; int32_t limit; - iic_acquire_bus(sc->sc_tag, 0); + if (iic_acquire_bus(sc->sc_tag, 0)) + return; if (*props & PROP_CRITMAX) { if (limits == NULL) /* Restore defaults */ limit = sc->sc_scrit; @@ -589,7 +595,8 @@ temp = *(int *)node.sysctl_data; sc->sc_tmax = temp; - iic_acquire_bus(sc->sc_tag, 0); + if (iic_acquire_bus(sc->sc_tag, 0)) + return EBUSY; lmtemp_temp_write(sc, LM75_REG_THYST_SET_POINT, sc->sc_tmax - 5, 1); lmtemp_temp_write(sc, LM75_REG_TOS_SET_POINT, Index: sys/arch/sparc64/dev/pcf8591_envctrl.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/dev/pcf8591_envctrl.c,v retrieving revision 1.14 diff -u -r1.14 pcf8591_envctrl.c --- sys/arch/sparc64/dev/pcf8591_envctrl.c 7 Dec 2020 13:24:15 -0000 1.14 +++ sys/arch/sparc64/dev/pcf8591_envctrl.c 7 Dec 2020 15:00:25 -0000 @@ -55,7 +55,6 @@ #define PCF8591_TEMP_SENS 0x00 #define PCF8591_CPU_FAN_CTRL 0x01 -#define PCF8591_PS_FAN_CTRL 0x02 struct ecadc_channel { u_int chan_num; @@ -89,6 +88,7 @@ static void ecadc_refresh(struct sysmon_envsys *, envsys_data_t *); static void ecadc_get_limits(struct sysmon_envsys *, envsys_data_t *, sysmon_envsys_lim_t *, u_int32_t *); +static int ecadc_set_fan_speed(struct ecadc_softc *, u_int8_t, u_int8_t); static void ecadc_timeout(void *); static void ecadc_fan_adjust(void *); @@ -205,6 +205,21 @@ sc->sc_nchan++; } + sc->sc_tag = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + + iic_acquire_bus(sc->sc_tag, 0); + + /* Try a read now, so we can fail if this component isn't present */ + if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, + NULL, 0, junk, sc->sc_nchan + 1, 0)) { + aprint_normal(": read failed\n"); + iic_release_bus(sc->sc_tag, 0); + return; + } + + iic_release_bus(sc->sc_tag, 0); + /* * Fan speed changing information is missing from OFW * The E250 CPU fan is connected to the sensor at addr 0x4a, channel 1 @@ -214,7 +229,6 @@ XLATE_MAX) > 0) { sc->sc_channels[sc->sc_nchan].chan_num = 1; sc->sc_channels[sc->sc_nchan].chan_type = PCF8591_CPU_FAN_CTRL; - sc->sc_channels[sc->sc_nchan].chan_speed = 0; sensor = &sc->sc_channels[sc->sc_nchan].chan_sensor; sensor->units = ENVSYS_INTEGER; sensor->flags = ENVSYS_FMONNOTSUPP; @@ -225,26 +239,17 @@ "added CPUFAN sensor (chan %d) with cpu-fan xlate\n", device_xname(sc->sc_dev), sc->sc_channels[sc->sc_nchan].chan_num); - sc->sc_nchan++; - sc->sc_hastimer = 1; - } + /* Set the fan to medium speed */ + sc->sc_channels[sc->sc_nchan].chan_speed = + (sc->sc_cpu_fan_spd[0]+sc->sc_cpu_fan_spd[XLATE_MAX])/2; + ecadc_set_fan_speed(sc, sc->sc_channels[sc->sc_nchan].chan_num, + sc->sc_channels[sc->sc_nchan].chan_speed); - sc->sc_tag = ia->ia_tag; - sc->sc_addr = ia->ia_addr; - - iic_acquire_bus(sc->sc_tag, 0); - - /* Try a read now, so we can fail if this component isn't present */ - if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, - NULL, 0, junk, sc->sc_nchan + 1, 0)) { - aprint_normal(": read failed\n"); - iic_release_bus(sc->sc_tag, 0); - return; + sc->sc_nchan++; + sc->sc_hastimer = 1; } - iic_release_bus(sc->sc_tag, 0); - /* Hook us into the sysmon_envsys subsystem */ sc->sc_sme = sysmon_envsys_create(); sc->sc_sme->sme_name = device_xname(self); @@ -280,6 +285,8 @@ ecadc_detach(device_t self, int flags) { struct ecadc_softc *sc = device_private(self); + int c, i; + if (sc->sc_hastimer) { callout_halt(&sc->sc_timer, NULL); callout_destroy(&sc->sc_timer); @@ -288,6 +295,23 @@ if (sc->sc_sme != NULL) sysmon_envsys_unregister(sc->sc_sme); + for (i = 0; i < sc->sc_nchan; i++) { + struct ecadc_channel *chp = &sc->sc_channels[i]; + + if (chp->chan_type == PCF8591_CPU_FAN_CTRL) { + /* Loop in case the bus is busy */ + for (c = 0; c < 5; c++) { + chp->chan_speed = sc->sc_cpu_fan_spd[0]; + if (!ecadc_set_fan_speed(sc, chp->chan_num, + chp->chan_speed)) + return 0; + delay(10000); + } + aprint_error_dev(sc->sc_dev, + "cannot set fan speed (chan %d)\n", chp->chan_num); + } + } + return 0; } @@ -350,8 +374,7 @@ } chp->chan_sensor.flags |= ENVSYS_FMONLIMITS; } - if (chp->chan_type == PCF8591_CPU_FAN_CTRL || - chp->chan_type == PCF8591_PS_FAN_CTRL) + if (chp->chan_type == PCF8591_CPU_FAN_CTRL) chp->chan_sensor.value_cur = data[1 + chp->chan_num]; chp->chan_sensor.state = ENVSYS_SVALID; Index: sys/arch/sparc64/dev/tda.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/dev/tda.c,v retrieving revision 1.14 diff -u -r1.14 tda.c --- sys/arch/sparc64/dev/tda.c 31 Oct 2020 13:17:34 -0000 1.14 +++ sys/arch/sparc64/dev/tda.c 7 Dec 2020 15:00:25 -0000 @@ -33,10 +33,24 @@ #include -/* fan control registers */ -#define TDA_SYSFAN_REG 0xf0 -#define TDA_CPUFAN_REG 0xf2 -#define TDA_PSFAN_REG 0xf4 +#ifdef TDA_DEBUG +#define DPRINTF printf +#else +#define DPRINTF if (0) printf +#endif + +/* fan control registers: instruction bits 4-7, subaddress (port) bits 0-3 */ +#define TDA_REG_AUTOINC 0x00 +#define TDA_REG_NO_INC 0xf0 + +/* SB1000/2000 */ +#define TDA_B_SYSFAN_REG 0x0 +#define TDA_B_CPUFAN_REG 0x2 +#define TDA_B_PSFAN_REG 0x4 +/* E450 */ +#define TDA_E_CPUFAN_REG 0x0 +#define TDA_E_PSUFAN_REG 0x1 +#define TDA_E_AFBFAN_REG 0x2 #define TDA_FANSPEED_MIN 0x0c #define TDA_FANSPEED_MAX 0x3f @@ -44,41 +58,59 @@ #define TDA_PSFAN_ON 0x1f #define TDA_PSFAN_OFF 0x00 -/* Internal and External temperature sensor numbers */ -#define SENSOR_TEMP_EXT 0 -#define SENSOR_TEMP_INT 1 - +#define TDA_NUM_REG 3 /* There are 8, but we use max 3 */ /* Fan sensor numbers */ #define SENSOR_FAN_CPU 0 #define SENSOR_FAN_SYS 1 +#define SENSOR_FAN_AFB 2 #define DEGC_TO_mK(c) (((c) * 1000000) + 273150000) +#define mK_TO_DEGC(k) ((k - 273150000) / 1000000) #define CPU_TEMP_MAX DEGC_TO_mK(67) #define CPU_TEMP_MIN DEGC_TO_mK(57) #define SYS_TEMP_MAX DEGC_TO_mK(30) #define SYS_TEMP_MIN DEGC_TO_mK(20) +#define XLATE_SIZE 0x6f /* Translation tables: 112 entries */ + +/* E450 temperature difference constants (from OpenSolaris) */ +#define CPU_TEMP_OFFSET -20 +#define PS_TEMP_OFFSET -30 + +struct tda_channel { + u_int8_t chan_fan_type; + u_int8_t chan_fan_speed; + u_int8_t chan_reg_num; + u_char *chan_xlate; + int chan_xlate_off; + u_int64_t chan_temp_max; + u_int64_t chan_temp_min; + envsys_data_t chan_sensor; +}; + struct tda_softc { device_t sc_dev; i2c_tag_t sc_tag; i2c_addr_t sc_addr; - u_int16_t sc_cfan_speed; /* current CPU fan speed */ - u_int16_t sc_sfan_speed; /* current SYS fan speed */ + u_char sc_cpu_fan_spd[XLATE_SIZE]; + u_char sc_ps_fan_spd[XLATE_SIZE]; + + u_int8_t sc_num_fans; + struct tda_channel sc_channels[TDA_NUM_REG]; struct sysmon_envsys *sc_sme; - envsys_data_t sc_sensor[2]; callout_t sc_timer; }; int tda_match(device_t, cfdata_t, void *); void tda_attach(device_t, device_t, void *); -static int tda_detach(device_t, int); +int tda_detach(device_t, int); void tda_refresh(struct sysmon_envsys *, envsys_data_t *); -void tda_setspeed(struct tda_softc *); +static int tda_setspeed(struct tda_softc *); static void tda_adjust(void *); static void tda_timeout(void *); @@ -92,8 +124,9 @@ { struct i2c_attach_args *ia = aux; - /* Only attach on the Sun Blade 1000/2000. */ - if (strcmp(machine_model, "SUNW,Sun-Blade-1000") != 0) + /* Only attach on the Sun Blade 1000/2000 and E450. */ + if (strcmp(machine_model, "SUNW,Sun-Blade-1000") != 0 && + strcmp(machine_model, "SUNW,Ultra-4") != 0) return (0); /* @@ -112,7 +145,7 @@ { struct tda_softc *sc = device_private(self); struct i2c_attach_args *ia = aux; - int rc; + int i, rc, node; sc->sc_dev = self; sc->sc_tag = ia->ia_tag; @@ -121,43 +154,104 @@ aprint_normal(": %s\n", ia->ia_name); aprint_naive(": Environment sensor\n"); + /* Set the fan parameters according to the machine model */ + if (!strcmp(machine_model, "SUNW,Sun-Blade-1000")) { + sc->sc_num_fans = 2; + sc->sc_channels[0].chan_fan_type = SENSOR_FAN_CPU; + sc->sc_channels[0].chan_reg_num = TDA_B_CPUFAN_REG; + sc->sc_channels[0].chan_xlate = NULL; + sc->sc_channels[0].chan_temp_max = CPU_TEMP_MAX; + sc->sc_channels[0].chan_temp_min = CPU_TEMP_MIN; + strlcpy(sc->sc_channels[0].chan_sensor.desc, + "fan.cpu",sizeof("fan.cpu")); + sc->sc_channels[1].chan_fan_type = SENSOR_FAN_SYS; + sc->sc_channels[1].chan_reg_num = TDA_B_SYSFAN_REG; + sc->sc_channels[1].chan_xlate = NULL; + sc->sc_channels[1].chan_temp_max = SYS_TEMP_MAX; + sc->sc_channels[1].chan_temp_min = SYS_TEMP_MIN; + strlcpy(sc->sc_channels[1].chan_sensor.desc, + "fan.sys",sizeof("fan.sys")); + } else if (!strcmp(machine_model, "SUNW,Ultra-4")) { + node = (int)ia->ia_cookie; + sc->sc_num_fans = 3; + sc->sc_channels[0].chan_fan_type = SENSOR_FAN_CPU; + sc->sc_channels[0].chan_reg_num = TDA_E_CPUFAN_REG; + if (OF_getprop(node, "cpu-fan-speeds", &sc->sc_cpu_fan_spd, + XLATE_SIZE) > 0) { + sc->sc_channels[0].chan_xlate = sc->sc_cpu_fan_spd; + sc->sc_channels[0].chan_xlate_off = CPU_TEMP_OFFSET; + } else { + aprint_error_dev(self, + "couldn't find \"cpu-fan-speeds\" property\n"); + return; + } + strlcpy(sc->sc_channels[0].chan_sensor.desc, + "CPUFAN",sizeof("CPUFAN")); + sc->sc_channels[1].chan_fan_type = SENSOR_FAN_SYS; + sc->sc_channels[1].chan_reg_num = TDA_E_PSUFAN_REG; + if (OF_getprop(node, "ps-fan-speeds", &sc->sc_ps_fan_spd, + XLATE_SIZE) > 0) { + sc->sc_channels[1].chan_xlate = sc->sc_ps_fan_spd; + sc->sc_channels[1].chan_xlate_off = PS_TEMP_OFFSET; + } else { + aprint_error_dev(self, + "couldn't find \"ps-fan-speeds\" property\n"); + return; + } + strlcpy(sc->sc_channels[1].chan_sensor.desc, + "PSUFAN",sizeof("PSUFAN")); + sc->sc_channels[2].chan_fan_type = SENSOR_FAN_AFB; + sc->sc_channels[2].chan_reg_num = TDA_E_AFBFAN_REG; + sc->sc_channels[2].chan_xlate = NULL; + /* AFB fan always runs at full speed */ + sc->sc_channels[2].chan_temp_max = 0; + sc->sc_channels[2].chan_temp_min = 0; + strlcpy(sc->sc_channels[2].chan_sensor.desc, + "AFBFAN",sizeof("AFBFAN")); + } else { + aprint_error_dev(self, + "unsupported: %s\n", machine_model); + return; + } /* - * Set the fans to maximum speed and save the power levels; + * Set the fans to medium speed and save the power levels; * the controller is write-only. */ - sc->sc_cfan_speed = sc->sc_sfan_speed = (TDA_FANSPEED_MAX+TDA_FANSPEED_MIN)/2; + for (i = 0; i < sc->sc_num_fans; i++) + switch (sc->sc_channels[i].chan_fan_type) { + case SENSOR_FAN_CPU: + /* Fallthrough */ + case SENSOR_FAN_SYS: + sc->sc_channels[i].chan_fan_speed = + (TDA_FANSPEED_MAX+TDA_FANSPEED_MIN)/2; + break; + default: + sc->sc_channels[i].chan_fan_speed = TDA_FANSPEED_MAX; + break; + } tda_setspeed(sc); - + callout_init(&sc->sc_timer, CALLOUT_MPSAFE); callout_reset(&sc->sc_timer, hz*20, tda_timeout, sc); /* Initialise sensor data */ - sc->sc_sensor[SENSOR_FAN_CPU].state = ENVSYS_SINVALID; - sc->sc_sensor[SENSOR_FAN_CPU].units = ENVSYS_INTEGER; - sc->sc_sensor[SENSOR_FAN_CPU].flags = ENVSYS_FMONNOTSUPP; - strlcpy(sc->sc_sensor[SENSOR_FAN_CPU].desc, - "fan.cpu",sizeof("fan.cpu")); - sc->sc_sensor[SENSOR_FAN_SYS].state = ENVSYS_SINVALID; - sc->sc_sensor[SENSOR_FAN_SYS].units = ENVSYS_INTEGER; - sc->sc_sensor[SENSOR_FAN_SYS].flags = ENVSYS_FMONNOTSUPP; - strlcpy(sc->sc_sensor[SENSOR_FAN_SYS].desc, - "fan.sys",sizeof("fan.sys")); - sc->sc_sme = sysmon_envsys_create(); - rc = sysmon_envsys_sensor_attach( - sc->sc_sme, &sc->sc_sensor[SENSOR_FAN_CPU]); - if (rc) { - sysmon_envsys_destroy(sc->sc_sme); - aprint_error_dev(self, - "unable to attach cpu fan at sysmon, error %d\n", rc); - return; + for (i = 0; i < sc->sc_num_fans; i++) { + sc->sc_channels[i].chan_sensor.state = ENVSYS_SINVALID; + sc->sc_channels[i].chan_sensor.units = ENVSYS_INTEGER; + sc->sc_channels[i].chan_sensor.flags = ENVSYS_FMONNOTSUPP; } - rc = sysmon_envsys_sensor_attach( - sc->sc_sme, &sc->sc_sensor[SENSOR_FAN_SYS]); - if (rc) { - sysmon_envsys_destroy(sc->sc_sme); - aprint_error_dev(self, - "unable to attach sys fan at sysmon, error %d\n", rc); - return; + sc->sc_sme = sysmon_envsys_create(); + for (i = 0; i < sc->sc_num_fans; i++) { + rc = sysmon_envsys_sensor_attach( + sc->sc_sme, &sc->sc_channels[i].chan_sensor); + if (rc) { + sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; + aprint_error_dev(self, + "unable to attach %s fan at sysmon, error %d\n", + sc->sc_channels[i].chan_sensor.desc, rc); + return; + } } sc->sc_sme->sme_name = device_xname(self); sc->sc_sme->sme_cookie = sc; @@ -167,6 +261,7 @@ aprint_error_dev(self, "unable to register with sysmon, error %d\n", rc); sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; return; } } @@ -175,15 +270,26 @@ tda_detach(device_t self, int flags) { struct tda_softc *sc = device_private(self); + int i; - if (sc->sc_sme != NULL) + if (sc->sc_sme != NULL) { sysmon_envsys_unregister(sc->sc_sme); + sc->sc_sme = NULL; + } callout_halt(&sc->sc_timer, NULL); callout_destroy(&sc->sc_timer); - sc->sc_cfan_speed = sc->sc_sfan_speed = TDA_FANSPEED_MAX; - tda_setspeed(sc); + for (i = 0; i < sc->sc_num_fans; i++) + sc->sc_channels[i].chan_fan_speed = TDA_FANSPEED_MAX; + + for (i = 0; i < 5; i++) { /* Loop in case the bus is busy */ + if (!tda_setspeed(sc)) + return 0; + delay(10000); + } + + aprint_error_dev(sc->sc_dev, "cannot set fan speeds\n"); return 0; } @@ -196,108 +302,162 @@ callout_reset(&sc->sc_timer, hz*60, tda_timeout, sc); } -void +static int tda_setspeed(struct tda_softc *sc) { u_int8_t cmd[2]; + int i, rc; - if (sc->sc_cfan_speed < TDA_FANSPEED_MIN) - sc->sc_cfan_speed = TDA_FANSPEED_MIN; - if (sc->sc_sfan_speed < TDA_FANSPEED_MIN) - sc->sc_sfan_speed = TDA_FANSPEED_MIN; - if (sc->sc_cfan_speed > TDA_FANSPEED_MAX) - sc->sc_cfan_speed = TDA_FANSPEED_MAX; - if (sc->sc_sfan_speed > TDA_FANSPEED_MAX) - sc->sc_sfan_speed = TDA_FANSPEED_MAX; - - iic_acquire_bus(sc->sc_tag, 0); - - cmd[0] = TDA_CPUFAN_REG; - cmd[1] = sc->sc_cfan_speed; - if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, - sc->sc_addr, &cmd, sizeof(cmd), NULL, 0, 0)) { - aprint_error_dev(sc->sc_dev, "cannot write cpu-fan register\n"); + for (i = 0; i < sc->sc_num_fans; i++) { + if (sc->sc_channels[i].chan_fan_speed < TDA_FANSPEED_MIN) + sc->sc_channels[i].chan_fan_speed = TDA_FANSPEED_MIN; + if (sc->sc_channels[i].chan_fan_speed > TDA_FANSPEED_MAX) + sc->sc_channels[i].chan_fan_speed = TDA_FANSPEED_MAX; + + rc = iic_acquire_bus(sc->sc_tag, 0); + if (rc) { + aprint_error_dev(sc->sc_dev, + "cannot acquire i2c bus for %s\n", + sc->sc_channels[i].chan_sensor.desc); + return rc; + } + cmd[0] = sc->sc_channels[i].chan_reg_num | TDA_REG_NO_INC; + cmd[1] = sc->sc_channels[i].chan_fan_speed; + rc = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &cmd, sizeof(cmd), NULL, 0, 0); + if (rc) { + aprint_error_dev(sc->sc_dev, + "cannot write register for %s\n", + sc->sc_channels[i].chan_sensor.desc); + iic_release_bus(sc->sc_tag, 0); + return rc; + } iic_release_bus(sc->sc_tag, 0); - return; - } - cmd[0] = TDA_SYSFAN_REG; - cmd[1] = sc->sc_sfan_speed; - if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, - sc->sc_addr, &cmd, sizeof(cmd), NULL, 0, 0)) { - aprint_error_dev(sc->sc_dev, "cannot write system-fan register\n"); - iic_release_bus(sc->sc_tag, 0); - return; + DPRINTF("%s: changed %s fan speed to %d\n", + device_xname(sc->sc_dev), + sc->sc_channels[i].chan_sensor.desc, + sc->sc_channels[i].chan_fan_speed); } - - iic_release_bus(sc->sc_tag, 0); - - aprint_debug_dev(sc->sc_dev, "changed fan speed to cpu=%d system=%d\n", - sc->sc_cfan_speed, sc->sc_sfan_speed); + return 0; } static bool is_cpu_sensor(const envsys_data_t *edata) { + int i; + char name[8]; + if (edata->units != ENVSYS_STEMP) return false; - return strcmp(edata->desc, "external") == 0; + if (!strcmp(machine_model, "SUNW,Sun-Blade-1000")) + return strcmp(edata->desc, "external") == 0; + if (!strcmp(machine_model, "SUNW,Ultra-4")) + for (i = 0; i < 4; i++) { + snprintf(name, 8, "CPU%d", i); + if (strcmp(edata->desc, name) == 0) + return true; + } + return false; } static bool is_system_sensor(const envsys_data_t *edata) { + int i; + char name[8]; + if (edata->units != ENVSYS_STEMP) return false; - return strcmp(edata->desc, "internal") == 0; + if (!strcmp(machine_model, "SUNW,Sun-Blade-1000")) + return strcmp(edata->desc, "internal") == 0; + if (!strcmp(machine_model, "SUNW,Ultra-4")) + for (i = 0; i < 4; i++) { + snprintf(name, 8, "PS%d", i); + if (strcmp(edata->desc, name) == 0) + return true; + } + return false; } static void tda_adjust(void *v) { struct tda_softc *sc = v; - u_int64_t ctemp, stemp; - u_int16_t cspeed, sspeed; - - /* Default to running the fans at maximum speed. */ - sspeed = cspeed = TDA_FANSPEED_MAX; - - /* fetch maximum current temperature */ - ctemp = sysmon_envsys_get_max_value(is_cpu_sensor, true); - stemp = sysmon_envsys_get_max_value(is_system_sensor, true); - - /* the predicates for selecting sensors must have gone wrong */ - if (ctemp == 0 || stemp == 0) { - aprint_error_dev(sc->sc_dev, "skipping temp adjustment" - " - no sensor values\n"); - return; + struct tda_channel *chp; + u_int64_t temp, temp_max, temp_min; + u_int8_t speed; + int i, idx, changed = 0; + + for (i = 0; i < sc->sc_num_fans; i++) { + chp = &sc->sc_channels[i]; + temp = 0; + + /* Default to running the fans at maximum speed. */ + speed = TDA_FANSPEED_MAX; + + /* fetch maximum current temperature */ + switch (chp->chan_fan_type) { + case SENSOR_FAN_CPU: + temp = sysmon_envsys_get_max_value(is_cpu_sensor, + true); + break; + case SENSOR_FAN_SYS: + temp = sysmon_envsys_get_max_value(is_system_sensor, + true); + break; + default: + temp = 1; /* Any temperature > 0 */ + break; + } + + /* the predicates for selecting sensors must have gone wrong */ + if (temp == 0) { + aprint_error_dev(sc->sc_dev, "skipping temp adjustment" + " - no sensor values for %s\n", + chp->chan_sensor.desc); + return; + } + + DPRINTF("%s: current temperature for %s: %" PRIu64 " mK\n", + device_xname(sc->sc_dev), chp->chan_sensor.desc, temp); + + if (chp->chan_xlate == NULL) { + temp_max = chp->chan_temp_max; + temp_min = chp->chan_temp_min; + DPRINTF("%s: temperature range: %" PRIu64 + " - %" PRIu64 "\n", device_xname(sc->sc_dev), + temp_min, temp_max); + if (temp < temp_min) + speed = TDA_FANSPEED_MIN; + else if (temp < temp_max) + speed = TDA_FANSPEED_MIN + (temp - temp_min) * + (TDA_FANSPEED_MAX - TDA_FANSPEED_MIN) / + (temp_max - temp_min); + } else { + /* Translation tables are in Celsius */ + idx = mK_TO_DEGC(temp); + idx += chp->chan_xlate_off; + if (idx >= XLATE_SIZE) + idx = XLATE_SIZE - 1; + if (idx < 0) + idx = 0; + speed = chp->chan_xlate[idx]; + DPRINTF("%s: temperature index (speed): %d (%d)\n", + device_xname(sc->sc_dev), idx, speed); + } + if (speed != chp->chan_fan_speed) { + changed = 1; + DPRINTF("%s: fan speed change: %d > %d\n", + device_xname(sc->sc_dev), + chp->chan_fan_speed, speed); + chp->chan_fan_speed = speed; + } } - aprint_debug_dev(sc->sc_dev, "current temperature: cpu %" PRIu64 - " system %" PRIu64 "\n", - ctemp, stemp); - - if (ctemp < CPU_TEMP_MIN) - cspeed = TDA_FANSPEED_MIN; - else if (ctemp < CPU_TEMP_MAX) - cspeed = TDA_FANSPEED_MIN + - (ctemp - CPU_TEMP_MIN) * - (TDA_FANSPEED_MAX - TDA_FANSPEED_MIN) / - (CPU_TEMP_MAX - CPU_TEMP_MIN); - - if (stemp < SYS_TEMP_MIN) - sspeed = TDA_FANSPEED_MIN; - else if (stemp < SYS_TEMP_MAX) - sspeed = TDA_FANSPEED_MIN + - (stemp - SYS_TEMP_MIN) * - (TDA_FANSPEED_MAX - TDA_FANSPEED_MIN) / - (SYS_TEMP_MAX - SYS_TEMP_MIN); - - if (sspeed == sc->sc_sfan_speed && cspeed == sc->sc_cfan_speed) + if (!changed) return; - sc->sc_sfan_speed = sspeed; - sc->sc_cfan_speed = cspeed; tda_setspeed(sc); } @@ -305,12 +465,9 @@ tda_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) { struct tda_softc *sc = sme->sme_cookie; - u_int16_t speed; + u_int8_t speed; - if (edata->sensor == SENSOR_FAN_CPU) - speed = sc->sc_cfan_speed; - else - speed = sc->sc_sfan_speed; + speed = sc->sc_channels[edata->sensor].chan_fan_speed; if (!speed) edata->state = ENVSYS_SINVALID; else { @@ -318,4 +475,3 @@ edata->state = ENVSYS_SVALID; } } - Index: sys/arch/sparc64/sparc64/autoconf.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/autoconf.c,v retrieving revision 1.227 diff -u -r1.227 autoconf.c --- sys/arch/sparc64/sparc64/autoconf.c 29 Oct 2020 06:47:38 -0000 1.227 +++ sys/arch/sparc64/sparc64/autoconf.c 7 Dec 2020 15:00:25 -0000 @@ -1090,10 +1090,11 @@ } } if (device_is_a(dev, "pcf8574io")) { - if (!strcmp(machine_model, "SUNW,Ultra-250")) { + if (!strcmp(machine_model, "SUNW,Ultra-250")) add_gpio_props_e250(dev, aux); - } - } + if (!strcmp(machine_model, "SUNW,Ultra-4")) + add_gpio_props_e450(dev, aux); + } } else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; Index: sys/arch/sparc64/sparc64/ofw_patch.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/ofw_patch.c,v retrieving revision 1.6 diff -u -r1.6 ofw_patch.c --- sys/arch/sparc64/sparc64/ofw_patch.c 29 Oct 2020 06:47:38 -0000 1.6 +++ sys/arch/sparc64/sparc64/ofw_patch.c 7 Dec 2020 15:00:25 -0000 @@ -134,6 +134,8 @@ prop_array_t pins; switch (ia->ia_addr) { + case 0x38: /* interrupt status */ + break; case 0x39: /* PSU status */ pins = prop_array_create(); add_gpio_pin(pins, "INDICATOR psu0_present", 0, 0, -1); @@ -160,7 +162,7 @@ prop_dictionary_set(dict, "pins", pins); prop_object_release(pins); break; - case 0x3e: /* front panel LEDs */ + case 0x3e: /* front panel LEDs (E250/E450) */ pins = prop_array_create(); add_gpio_pin(pins, "LED disk_fault", 0, 0, -1); add_gpio_pin(pins, "LED psu_fault", 1, 0, -1); @@ -189,6 +191,110 @@ } void +add_gpio_props_e450(device_t dev, void *aux) +{ + struct i2c_attach_args *ia = aux; + prop_dictionary_t dict = device_properties(dev); + prop_array_t pins; + char name[20]; + int i; + + switch (ia->ia_addr) { + case 0x20: /* disk shelf 0 */ + pins = prop_array_create(); + for (i = 0; i < 4; i++) { + snprintf(name, sizeof(name), + "LED disk%d_fault", i); + add_gpio_pin(pins, name, i, 0, -1); + } + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x21: /* disk shelf 1 */ + pins = prop_array_create(); + for (i = 0; i < 8; i++) { + snprintf(name, sizeof(name), + "LED disk%d_fault", i + 4); + add_gpio_pin(pins, name, i, 0, -1); + } + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x22: /* disk shelf 2 */ + pins = prop_array_create(); + for (i = 0; i < 8; i++) { + snprintf(name, sizeof(name), + "LED disk%d_fault", i + 12); + add_gpio_pin(pins, name, i, 0, -1); + } + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x38: /* interrupt status */ + break; + case 0x39: /* PSU 2 status */ + pins = prop_array_create(); + add_gpio_pin(pins, "INDICATOR psu2_present", 0, 0, -1); + add_gpio_pin(pins, "INDICATOR psu2_550W", 1, 0, -1); + add_gpio_pin(pins, "INDICATOR psu2_650W", 2, 0, -1); + add_gpio_pin(pins, "INDICATOR psu2_DC_fault", 3, 0, -1); + add_gpio_pin(pins, "INDICATOR psu2_overload", 4, 0, -1); + add_gpio_pin(pins, "INDICATOR psu2_load_flt", 5, 0, -1); + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x3a: /* PSU 1 status */ + pins = prop_array_create(); + add_gpio_pin(pins, "INDICATOR psu1_present", 0, 0, -1); + add_gpio_pin(pins, "INDICATOR psu1_550W", 1, 0, -1); + add_gpio_pin(pins, "INDICATOR psu1_650W", 2, 0, -1); + add_gpio_pin(pins, "INDICATOR psu1_DC_fault", 3, 0, -1); + add_gpio_pin(pins, "INDICATOR psu1_overload", 4, 0, -1); + add_gpio_pin(pins, "INDICATOR psu1_load_flt", 5, 0, -1); + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x3b: /* PSU 0 status */ + pins = prop_array_create(); + add_gpio_pin(pins, "INDICATOR psu0_present", 0, 0, -1); + add_gpio_pin(pins, "INDICATOR psu0_550W", 1, 0, -1); + add_gpio_pin(pins, "INDICATOR psu0_650W", 2, 0, -1); + add_gpio_pin(pins, "INDICATOR psu0_DC_fault", 3, 0, -1); + add_gpio_pin(pins, "INDICATOR psu0_overload", 4, 0, -1); + add_gpio_pin(pins, "INDICATOR psu0_load_flt", 5, 0, -1); + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x3c: /* fan failure status */ + pins = prop_array_create(); + add_gpio_pin(pins, "INDICATOR psu2_fanfail", 0, 0, -1); + add_gpio_pin(pins, "INDICATOR psu1_fanfail", 1, 0, -1); + add_gpio_pin(pins, "INDICATOR psu0_fanfail", 2, 0, -1); + add_gpio_pin(pins, "INDICATOR cpu0_fanfail", 3, 0, -1); + add_gpio_pin(pins, "INDICATOR cpu1_fanfail", 4, 0, -1); + add_gpio_pin(pins, "INDICATOR cpu2_fanfail", 5, 0, -1); + add_gpio_pin(pins, "INDICATOR afb_fanfail", 6, 0, -1); + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + case 0x3e: /* front panel LEDs (E250/E450) */ + pins = prop_array_create(); + add_gpio_pin(pins, "LED disk_fault", 0, 0, -1); + add_gpio_pin(pins, "LED psu_fault", 1, 0, -1); + add_gpio_pin(pins, "LED overtemp", 2, 0, -1); + add_gpio_pin(pins, "LED fault", 3, 0, -1); + add_gpio_pin(pins, "LED activity", 4, 0, -1); + /* Pin 5 is power LED, but not controllable */ + add_gpio_pin(pins, "INDICATOR key_normal", 6, 0, -1); + add_gpio_pin(pins, "INDICATOR key_diag", 7, 0, -1); + /* If not "normal" or "diag", key is "lock" */ + prop_dictionary_set(dict, "pins", pins); + prop_object_release(pins); + break; + } +} + +void add_drivebay_props(device_t dev, int ofnode, void *aux) { struct scsipibus_attach_args *sa = aux; @@ -275,10 +381,23 @@ add_i2c_props_e450(device_t busdev, uint64_t node) { prop_array_t cfg; + int i; DPRINTF(ACDB_PROBE, ("\nAdding sensors for %s ", machine_model)); cfg = create_i2c_dict(busdev); + /* Disk LED GPIO's */ + for (i = 0x20; i <= 0x22; i++) + add_i2c_device(cfg, "gpio", "i2c-pcf8574", i, node); + + /* TDA8444 fan speed controller */ + add_i2c_device(cfg, "fan-control", "i2c-tda8444", 0x27, node); + + /* Other GPIO's */ + for (i = 0x38; i <= 0x3c; i++) + add_i2c_device(cfg, "gpio", "i2c-pcf8574", i, node); + add_i2c_device(cfg, "gpio", "i2c-pcf8574", 0x3e, node); + /* Power supply 1 temperature. */ add_i2c_device(cfg, "PSU-1", "ecadc", 0x48, node); @@ -294,6 +413,9 @@ /* CPU temperatures. */ add_i2c_device(cfg, "CPU", "ecadc", 0x4f, node); + /* Watchdog. */ + add_i2c_device(cfg, "watchdog", "i2c-pcf8583", 0x50, node); + prop_object_release(cfg); } @@ -306,18 +428,18 @@ DPRINTF(ACDB_PROBE, ("\nAdding sensors for %s ", machine_model)); cfg = create_i2c_dict(busdev); - /* PSU temperature / CPU fan */ - add_i2c_device(cfg, "PSU", "ecadc", 0x4a, node); - - /* CPU & system board temperature */ - add_i2c_device(cfg, "CPU", "ecadc", 0x4f, node); - /* GPIO's */ for (i = 0x38; i <= 0x39; i++) add_i2c_device(cfg, "gpio", "i2c-pcf8574", i, node); for (i = 0x3d; i <= 0x3f; i++) add_i2c_device(cfg, "gpio", "i2c-pcf8574", i, node); + /* PSU temperature / CPU fan */ + add_i2c_device(cfg, "PSU", "ecadc", 0x4a, node); + + /* CPU & system board temperature */ + add_i2c_device(cfg, "CPU", "ecadc", 0x4f, node); + /* NVRAM */ add_i2c_device(cfg, "nvram", "i2c-at24c02", 0x52, node); Index: sys/arch/sparc64/sparc64/ofw_patch.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/ofw_patch.h,v retrieving revision 1.4 diff -u -r1.4 ofw_patch.h --- sys/arch/sparc64/sparc64/ofw_patch.h 29 Oct 2020 06:47:38 -0000 1.4 +++ sys/arch/sparc64/sparc64/ofw_patch.h 7 Dec 2020 15:00:25 -0000 @@ -43,6 +43,7 @@ void add_gpio_props_v210(device_t, void *); void add_gpio_props_e250(device_t, void *); +void add_gpio_props_e450(device_t, void *); void add_drivebay_props(device_t, int, void *); void add_spdmem_props_sparcle(device_t); void add_env_sensors_v210(device_t);