? src/sys/arch/sparc64/sparc64/autoconf.c.u45 ? src/sys/arch/sparc64/sparc64/cpu.c.sysctl ? src/sys/dev/i2c/adm1021.c.dist ? src/sys/dev/i2c/lm87.c.limits Index: src/sys/arch/sparc64/dev/pcf8591_envctrl.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc64/dev/pcf8591_envctrl.c,v retrieving revision 1.11 diff -u -r1.11 pcf8591_envctrl.c --- src/sys/arch/sparc64/dev/pcf8591_envctrl.c 31 Oct 2020 13:17:34 -0000 1.11 +++ src/sys/arch/sparc64/dev/pcf8591_envctrl.c 23 Nov 2020 08:10:07 -0000 @@ -99,10 +99,28 @@ ecadc_match(device_t parent, cfdata_t cf, void *aux) { struct i2c_attach_args *ia = aux; + struct ecadc_softc sc; int match_result; + u_int8_t junk; - if (iic_use_direct_match(ia, cf, compat_data, &match_result)) - return match_result; + if (!iic_use_direct_match(ia, cf, compat_data, &match_result)) + return 0; + + /* Try a read so that we don't match on optional components */ + if (match_result) { + sc.sc_tag = ia->ia_tag; + sc.sc_addr = ia->ia_addr; + + iic_acquire_bus(sc.sc_tag, 0); + if (iic_exec(sc.sc_tag, I2C_OP_READ_WITH_STOP, sc.sc_addr, + NULL, 0, &junk, 1, 0)) { + iic_release_bus(sc.sc_tag, 0); + return 0; + } else { + iic_release_bus(sc.sc_tag, 0); + return 1; + } + } /* This driver is direct-config only. */ Index: src/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 --- src/sys/arch/sparc64/dev/tda.c 31 Oct 2020 13:17:34 -0000 1.14 +++ src/sys/arch/sparc64/dev/tda.c 23 Nov 2020 08:10:07 -0000 @@ -33,10 +33,26 @@ #include -/* fan control registers */ -#define TDA_SYSFAN_REG 0xf0 -#define TDA_CPUFAN_REG 0xf2 -#define TDA_PSFAN_REG 0xf4 +#define TDA_DEBUG 1 + +#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,31 +60,49 @@ #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 */ + +/* Magic E450 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; }; @@ -92,8 +126,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 +147,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 +156,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[0].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, + "SYSFAN",sizeof("SYSFAN")); + 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 +263,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,14 +272,18 @@ 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; + for (i = 0; i < sc->sc_num_fans; i++) + sc->sc_channels[i].chan_fan_speed = TDA_FANSPEED_MAX; tda_setspeed(sc); return 0; } @@ -199,105 +300,154 @@ void tda_setspeed(struct tda_softc *sc) { +/* XXX u_int8_t cmd[2]; +XXX */ + int i; - 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; + +/* XXX + iic_acquire_bus(sc->sc_tag, 0); + cmd[0] = sc->sc_channels[i].chan_reg_num | TDA_REG_NO_INC; + cmd[1] = sc->sc_channels[i].chan_fan_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"); + iic_release_bus(sc->sc_tag, 0); + return; + } iic_release_bus(sc->sc_tag, 0); - return; - } +XXX */ - 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); } 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 "\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: %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 +455,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 +465,3 @@ edata->state = ENVSYS_SVALID; } } - Index: src/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 --- src/sys/arch/sparc64/sparc64/autoconf.c 29 Oct 2020 06:47:38 -0000 1.227 +++ src/sys/arch/sparc64/sparc64/autoconf.c 23 Nov 2020 08:10:07 -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: src/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 --- src/sys/arch/sparc64/sparc64/ofw_patch.c 29 Oct 2020 06:47:38 -0000 1.6 +++ src/sys/arch/sparc64/sparc64/ofw_patch.c 23 Nov 2020 08:10:07 -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,96 @@ } 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); + } + 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); + } + 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); + } + 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); + 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); + 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); + 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); + 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 +367,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 +399,9 @@ /* CPU temperatures. */ add_i2c_device(cfg, "CPU", "ecadc", 0x4f, node); + /* Watchdog. */ + add_i2c_device(cfg, "CPU", "watchdog", 0x50, node); + prop_object_release(cfg); } @@ -306,18 +414,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: src/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 --- src/sys/arch/sparc64/sparc64/ofw_patch.h 29 Oct 2020 06:47:38 -0000 1.4 +++ src/sys/arch/sparc64/sparc64/ofw_patch.h 23 Nov 2020 08:10:07 -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); Index: src/sys/dev/i2c/adm1021.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/adm1021.c,v retrieving revision 1.20 diff -u -r1.20 adm1021.c --- src/sys/dev/i2c/adm1021.c 21 Aug 2020 20:44:38 -0000 1.20 +++ src/sys/dev/i2c/adm1021.c 23 Nov 2020 08:10:07 -0000 @@ -124,7 +124,13 @@ uint8_t sc_thermlim[ADMTEMP_NUM_SENSORS]; }; +static int admtemp_ident(struct admtemp_softc *); int admtemp_match(device_t, cfdata_t, void *); +static int admtemp_exec(struct admtemp_softc *, i2c_op_t, + uint8_t *, uint8_t *); +static void admtemp_setflags(struct admtemp_softc *, + struct i2c_attach_args *, uint8_t *, + uint8_t *, char* ); void admtemp_attach(device_t, device_t, void *); void admtemp_refresh(struct sysmon_envsys *, envsys_data_t *); void admtemp_getlim_1021(struct sysmon_envsys *, envsys_data_t *, @@ -151,12 +157,34 @@ { NULL, 0 } }; +/* Check company ID for possible matches */ +static int +admtemp_ident(struct admtemp_softc *sc) +{ + uint8_t cmd, comp; + int err; + + comp = 0; + cmd = ADM1021_COMPANY; + err = admtemp_exec(sc, I2C_OP_READ_WITH_STOP, &cmd, &comp); + if (err) + return 0; + if (comp == 0 || comp == ADM1021_COMPANY_MAXIM || + comp == ADM1021_COMPANY_GMT || comp == ADM1021_COMPANY_ADM) + return 1; + return 0; +} + int admtemp_match(device_t parent, cfdata_t match, void *aux) { struct i2c_attach_args *ia = aux; + struct admtemp_softc sc; /* For chip ident */ int match_result; + sc.sc_tag = ia->ia_tag; + sc.sc_addr = ia->ia_addr; + if (iic_use_direct_match(ia, match, compat_data, &match_result)) return match_result; @@ -164,10 +192,11 @@ * Indirect config - not much we can do! * Check typical addresses. */ - if (((ia->ia_addr >= 0x18) && (ia->ia_addr <= 0x1a)) || + if ((((ia->ia_addr >= 0x18) && (ia->ia_addr <= 0x1a)) || ((ia->ia_addr >= 0x29) && (ia->ia_addr <= 0x2b)) || - ((ia->ia_addr >= 0x48) && (ia->ia_addr <= 0x4e))) - return I2C_MATCH_ADDRESS_ONLY; + ((ia->ia_addr >= 0x48) && (ia->ia_addr <= 0x4e))) && + admtemp_ident(&sc)) + return I2C_MATCH_ADDRESS_AND_PROBE; return 0; } @@ -200,7 +229,7 @@ */ static void admtemp_setflags(struct admtemp_softc *sc, struct i2c_attach_args *ia, - uint8_t* comp, uint8_t *rev, char* name) + uint8_t *comp, uint8_t *rev, char* name) { uint8_t cmd, data, tmp; int i; Index: src/sys/dev/i2c/hytp14.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/hytp14.c,v retrieving revision 1.9 diff -u -r1.9 hytp14.c --- src/sys/dev/i2c/hytp14.c 8 Oct 2019 21:16:11 -0000 1.9 +++ src/sys/dev/i2c/hytp14.c 23 Nov 2020 08:10:07 -0000 @@ -189,6 +189,7 @@ aprint_error_dev(sc->sc_dev, "unable to attach sensor\n"); sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; return; } } Index: src/sys/dev/i2c/pcf8574.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/pcf8574.c,v retrieving revision 1.2 diff -u -r1.2 pcf8574.c --- src/sys/dev/i2c/pcf8574.c 31 Oct 2020 14:39:31 -0000 1.2 +++ src/sys/dev/i2c/pcf8574.c 23 Nov 2020 08:10:07 -0000 @@ -1,3 +1,5 @@ +/* $NetBSD$ */ + /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. * All rights reserved. @@ -106,10 +108,21 @@ pcf8574_match(device_t parent, cfdata_t cf, void *aux) { struct i2c_attach_args *ia = aux; + struct pcf8574_softc sc; int match_result; - if (iic_use_direct_match(ia, cf, compat_data, &match_result)) - return match_result; + if (!iic_use_direct_match(ia, cf, compat_data, &match_result)) + return 0; + + /* Try a read so that we don't match on optional components */ + if (match_result) { + sc.sc_tag = ia->ia_tag; + sc.sc_addr = ia->ia_addr; + if (pcf8574_read(&sc, &sc.sc_state)) + return 0; + else + return 1; + } /* We don't support indirect matches */ return 0; @@ -190,6 +203,7 @@ if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) { sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; aprint_error_dev(self, "unable to attach pin %d at sysmon\n", i); return; @@ -208,6 +222,7 @@ aprint_error_dev(self, "unable to register with sysmon\n"); sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; return; } } @@ -219,8 +234,10 @@ struct pcf8574_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; + } for (i = 0; i < sc->sc_nleds; i++) led_detach(sc->sc_leds[i].led); Index: src/sys/dev/i2c/si70xx.c =================================================================== RCS file: /cvsroot/src/sys/dev/i2c/si70xx.c,v retrieving revision 1.5 diff -u -r1.5 si70xx.c --- src/sys/dev/i2c/si70xx.c 3 Feb 2019 12:18:21 -0000 1.5 +++ src/sys/dev/i2c/si70xx.c 23 Nov 2020 08:10:07 -0000 @@ -718,6 +718,7 @@ if (error) { aprint_error_dev(self, "Unable to attach sensor %d: %d\n", i, error); + sc->sc_sme = NULL; goto out; } }