diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c index c54233f0369b2..cefb954efcc4f 100644 --- a/drivers/hwmon/nct6775-core.c +++ b/drivers/hwmon/nct6775-core.c @@ -33,6 +33,7 @@ * (0xd451) * nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3 * (0xd429) + * nct6799d 14 7 7 2+6 0xd802 0xc1 0x5ca3 * * #temp lists the number of monitored temperature sources (first value) plus * the number of directly connectable temperature sensors (second value). @@ -40,6 +41,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -73,6 +75,7 @@ static const char * const nct6775_device_names[] = { "nct6796", "nct6797", "nct6798", + "nct6799", }; /* Common and NCT6775 specific data */ @@ -381,7 +384,7 @@ static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = { 0x39, 0x155 }; static const u16 NCT6779_REG_TEMP_OFFSET[] = { - 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c }; + 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c, 0x44d, 0x449 }; static const char *const nct6779_temp_label[] = { "", @@ -654,6 +657,44 @@ static const char *const nct6798_temp_label[] = { #define NCT6798_TEMP_MASK 0xbfff0ffe #define NCT6798_VIRT_TEMP_MASK 0x80000c00 +static const char *const nct6799_temp_label[] = { + "", + "SYSTIN", + "CPUTIN", + "AUXTIN0", + "AUXTIN1", + "AUXTIN2", + "AUXTIN3", + "AUXTIN4", + "SMBUSMASTER 0", + "SMBUSMASTER 1", + "Virtual_TEMP", + "Virtual_TEMP", + "", + "AUXTIN5", + "", + "", + "PECI Agent 0", + "PECI Agent 1", + "PCH_CHIP_CPU_MAX_TEMP", + "PCH_CHIP_TEMP", + "PCH_CPU_TEMP", + "PCH_MCH_TEMP", + "Agent0 Dimm0", + "Agent0 Dimm1", + "Agent1 Dimm0", + "Agent1 Dimm1", + "BYTE_TEMP0", + "BYTE_TEMP1", + "PECI Agent 0 Calibration", /* undocumented */ + "PECI Agent 1 Calibration", /* undocumented */ + "", + "Virtual_TEMP" +}; + +#define NCT6799_TEMP_MASK 0xbfff2ffe +#define NCT6799_VIRT_TEMP_MASK 0x80000c00 + /* NCT6102D/NCT6106D specific data */ #define NCT6106_REG_VBAT 0x318 @@ -1109,6 +1150,7 @@ bool nct6775_reg_is_word_sized(struct nct6775_data *data, u16 reg) case nct6796: case nct6797: case nct6798: + case nct6799: return reg == 0x150 || reg == 0x153 || reg == 0x155 || (reg & 0xfff0) == 0x4c0 || reg == 0x402 || @@ -1462,6 +1504,7 @@ static int nct6775_update_pwm_limits(struct device *dev) case nct6796: case nct6797: case nct6798: + case nct6799: err = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[i], ®); if (err) return err; @@ -1480,13 +1523,27 @@ static int nct6775_update_pwm_limits(struct device *dev) return 0; } +static int nct6775_lock(struct nct6775_data *data) +{ + mutex_lock(&data->update_lock); + + return 0; +} + +static void nct6775_unlock(struct nct6775_data *data, struct device *dev) +{ + mutex_unlock(&data->update_lock); +} + struct nct6775_data *nct6775_update_device(struct device *dev) { struct nct6775_data *data = dev_get_drvdata(dev); - int i, j, err = 0; + int i, j, err; u16 reg; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return data; if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1612,7 +1669,7 @@ struct nct6775_data *nct6775_update_device(struct device *dev) data->valid = true; } out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? ERR_PTR(err) : data; } EXPORT_SYMBOL_GPL(nct6775_update_device); @@ -1648,10 +1705,14 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf, err = kstrtoul(buf, 10, &val); if (err < 0) return err; - mutex_lock(&data->update_lock); + + err = data->lock(data); + if (err) + return err; + data->in[nr][index] = in_to_reg(val, nr); err = nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], data->in[nr][index]); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -1745,14 +1806,17 @@ nct6775_store_beep(struct device *dev, struct device_attribute *attr, const char if (val > 1) return -EINVAL; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + if (val) data->beeps |= (1ULL << nr); else data->beeps &= ~(1ULL << nr); err = nct6775_write_value(data, data->REG_BEEP[regindex], (data->beeps >> (regindex << 3)) & 0xff); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } EXPORT_SYMBOL_GPL(nct6775_store_beep); @@ -1805,14 +1869,17 @@ store_temp_beep(struct device *dev, struct device_attribute *attr, bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE]; regindex = bit >> 3; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + if (val) data->beeps |= (1ULL << bit); else data->beeps &= ~(1ULL << bit); err = nct6775_write_value(data, data->REG_BEEP[regindex], (data->beeps >> (regindex << 3)) & 0xff); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -1912,7 +1979,10 @@ store_fan_min(struct device *dev, struct device_attribute *attr, if (err < 0) return err; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + if (!data->has_fan_div) { /* NCT6776F or NCT6779D; we know this is a 13 bit register */ if (!val) { @@ -1987,7 +2057,7 @@ store_fan_min(struct device *dev, struct device_attribute *attr, write_min: err = nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2024,7 +2094,10 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr, if (val > 4) return -EINVAL; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->fan_pulses[nr] = val & 3; err = nct6775_read_value(data, data->REG_FAN_PULSES[nr], ®); if (err) @@ -2033,7 +2106,7 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr, reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr]; err = nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg); out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2134,10 +2207,13 @@ store_temp(struct device *dev, struct device_attribute *attr, const char *buf, if (err < 0) return err; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->temp[index][nr] = LM75_TEMP_TO_REG(val); err = nct6775_write_temp(data, data->reg_temp[index][nr], data->temp[index][nr]); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2169,10 +2245,13 @@ store_temp_offset(struct device *dev, struct device_attribute *attr, val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->temp_offset[nr] = val; err = nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2212,7 +2291,9 @@ store_temp_type(struct device *dev, struct device_attribute *attr, if (val != 1 && val != 3 && val != 4) return -EINVAL; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; data->temp_type[nr] = val; vbit = 0x02 << nr; @@ -2244,7 +2325,7 @@ store_temp_type(struct device *dev, struct device_attribute *attr, goto out; err = nct6775_write_value(data, data->REG_DIODE, diode); out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2401,7 +2482,10 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, return count; } - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->pwm_mode[nr] = val; err = nct6775_read_value(data, data->REG_PWM_MODE[nr], ®); if (err) @@ -2411,7 +2495,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, reg |= data->PWM_MODE_MASK[nr]; err = nct6775_write_value(data, data->REG_PWM_MODE[nr], reg); out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2463,7 +2547,10 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, return err; val = clamp_val(val, minval[index], maxval[index]); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->pwm[index][nr] = val; err = nct6775_write_value(data, data->REG_PWM[index][nr], val); if (err) @@ -2478,7 +2565,7 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, err = nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); } out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2595,7 +2682,10 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, return -EINVAL; } - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->pwm_enable[nr] = val; if (val == off) { /* @@ -2616,7 +2706,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, reg |= pwm_enable_to_reg(val) << 4; err = nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2672,7 +2762,10 @@ store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, if (!(data->have_temp & BIT(val - 1)) || !data->temp_src[val - 1]) return -EINVAL; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + src = data->temp_src[val - 1]; data->pwm_temp_sel[nr] = src; err = nct6775_read_value(data, data->REG_TEMP_SEL[nr], ®); @@ -2682,7 +2775,7 @@ store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, reg |= src; err = nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2726,7 +2819,10 @@ store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, !data->temp_src[val - 1])) return -EINVAL; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + if (val) { src = data->temp_src[val - 1]; data->pwm_weight_temp_sel[nr] = src; @@ -2745,7 +2841,7 @@ store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, err = nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); } out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2779,10 +2875,13 @@ store_target_temp(struct device *dev, struct device_attribute *attr, val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->target_temp_mask); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->target_temp[nr] = val; err = pwm_update_registers(data, nr); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2819,10 +2918,13 @@ store_target_speed(struct device *dev, struct device_attribute *attr, val = clamp_val(val, 0, 1350000U); speed = fan_to_reg(val, data->fan_div[nr]); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->target_speed[nr] = speed; err = pwm_update_registers(data, nr); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2859,13 +2961,16 @@ store_temp_tolerance(struct device *dev, struct device_attribute *attr, /* Limit tolerance as needed */ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->temp_tolerance[index][nr] = val; if (index) err = pwm_update_registers(data, nr); else err = nct6775_write_value(data, data->REG_CRITICAL_TEMP_TOLERANCE[nr], val); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2936,10 +3041,13 @@ store_speed_tolerance(struct device *dev, struct device_attribute *attr, /* Limit tolerance as needed */ val = clamp_val(val, 0, data->speed_tolerance_limit); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->target_speed_tolerance[nr] = val; err = pwm_update_registers(data, nr); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -2985,10 +3093,13 @@ store_weight_temp(struct device *dev, struct device_attribute *attr, val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->weight_temp[index][nr] = val; err = nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -3035,10 +3146,13 @@ store_fan_time(struct device *dev, struct device_attribute *attr, return err; val = step_time_to_reg(val, data->pwm_mode[nr]); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->fan_time[index][nr] = val; err = nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val); - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -3079,7 +3193,10 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, val = 0xff; } - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->auto_pwm[nr][point] = val; if (point < data->auto_pwm_num) { err = nct6775_write_value(data, NCT6775_AUTO_PWM(data, nr, point), @@ -3109,6 +3226,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, case nct6796: case nct6797: case nct6798: + case nct6799: err = nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], val); if (err) break; @@ -3123,7 +3241,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, break; } } - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -3162,7 +3280,10 @@ store_auto_temp(struct device *dev, struct device_attribute *attr, if (val > 255000) return -EINVAL; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000); if (point < data->auto_pwm_num) { err = nct6775_write_value(data, NCT6775_AUTO_TEMP(data, nr, point), @@ -3171,7 +3292,7 @@ store_auto_temp(struct device *dev, struct device_attribute *attr, err = nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr], data->auto_temp[nr][point]); } - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err ? : count; } @@ -3399,6 +3520,29 @@ static int add_temp_sensors(struct nct6775_data *data, const u16 *regp, return 0; } +/* Wait for up to 0.5 s to acquire the lock */ +#define ASUSWMI_LOCK_TIMEOUT_MS 500 + +static int nct6775_wmi_lock(struct nct6775_data *data) +{ + acpi_status status; + + status = acpi_acquire_mutex(data->acpi_wmi_mutex, NULL, ASUSWMI_LOCK_TIMEOUT_MS); + if (ACPI_FAILURE(status)) + return -EIO; + + return 0; +} + +static void nct6775_wmi_unlock(struct nct6775_data *data, struct device *dev) +{ + acpi_status status; + + status = acpi_release_mutex(data->acpi_wmi_mutex, NULL); + if (ACPI_FAILURE(status)) + dev_err(dev, "Failed to release mutex."); +} + int nct6775_probe(struct device *dev, struct nct6775_data *data, const struct regmap_config *regmapcfg) { @@ -3416,7 +3560,15 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); - mutex_init(&data->update_lock); + if (data->acpi_wmi_mutex) { + data->lock = nct6775_wmi_lock; + data->unlock = nct6775_wmi_unlock; + } else { + mutex_init(&data->update_lock); + data->lock = nct6775_lock; + data->unlock = nct6775_unlock; + } + data->name = nct6775_device_names[data->kind]; data->bank = 0xff; /* Force initial bank selection */ @@ -3807,10 +3959,12 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, case nct6796: case nct6797: case nct6798: + case nct6799: data->in_num = 15; data->pwm_num = (data->kind == nct6796 || data->kind == nct6797 || - data->kind == nct6798) ? 7 : 6; + data->kind == nct6798 || + data->kind == nct6799) ? 7 : 6; data->auto_pwm_num = 4; data->has_fan_div = false; data->temp_fixed_num = 6; @@ -3859,6 +4013,11 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, data->temp_mask = NCT6798_TEMP_MASK; data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK; break; + case nct6799: + data->temp_label = nct6799_temp_label; + data->temp_mask = NCT6799_TEMP_MASK; + data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK; + break; } data->REG_CONFIG = NCT6775_REG_CONFIG; @@ -3918,6 +4077,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, case nct6796: case nct6797: case nct6798: + case nct6799: data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP; num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP); break; diff --git a/drivers/hwmon/nct6775-i2c.c b/drivers/hwmon/nct6775-i2c.c index e1bcd11461913..779ce65db1a15 100644 --- a/drivers/hwmon/nct6775-i2c.c +++ b/drivers/hwmon/nct6775-i2c.c @@ -87,6 +87,7 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = { { .compatible = "nuvoton,nct6796", .data = (void *)nct6796, }, { .compatible = "nuvoton,nct6797", .data = (void *)nct6797, }, { .compatible = "nuvoton,nct6798", .data = (void *)nct6798, }, + { .compatible = "nuvoton,nct6799", .data = (void *)nct6799, }, { }, }; MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match); @@ -104,6 +105,7 @@ static const struct i2c_device_id nct6775_i2c_id[] = { { "nct6796", nct6796 }, { "nct6797", nct6797 }, { "nct6798", nct6798 }, + { "nct6799", nct6799 }, { } }; MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id); diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c index 76c6b564d7fc4..975701242a9d0 100644 --- a/drivers/hwmon/nct6775-platform.c +++ b/drivers/hwmon/nct6775-platform.c @@ -35,6 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = { "NCT6796D", "NCT6797D", "NCT6798D", + "NCT6799D", }; static unsigned short force_id; @@ -85,6 +86,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define SIO_NCT6796_ID 0xd420 #define SIO_NCT6797_ID 0xd450 #define SIO_NCT6798_ID 0xd428 +#define SIO_NCT6799_ID 0xd800 #define SIO_ID_MASK 0xFFF8 /* @@ -97,6 +99,7 @@ struct nct6775_sio_data { int ld; enum kinds kind; enum sensor_access access; + acpi_handle acpi_wmi_mutex; /* superio_() callbacks */ void (*sio_outb)(struct nct6775_sio_data *sio_data, int reg, int val); @@ -149,7 +152,7 @@ static int nct6775_asuswmi_evaluate_method(u32 method_id, u8 bank, u8 reg, u8 va return -EIO; if (retval) - *retval = (u32)result & 0xFFFFFFFF; + *retval = result; return 0; #else @@ -374,7 +377,10 @@ static int nct6775_suspend(struct device *dev) if (IS_ERR(data)) return PTR_ERR(data); - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + err = nct6775_read_value(data, data->REG_VBAT, &tmp); if (err) goto out; @@ -391,7 +397,7 @@ static int nct6775_suspend(struct device *dev) data->fandiv2 = tmp; } out: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err; } @@ -403,7 +409,10 @@ static int nct6775_resume(struct device *dev) int i, j, err = 0; u8 reg; - mutex_lock(&data->update_lock); + err = data->lock(data); + if (err) + return err; + data->bank = 0xff; /* Force initial bank selection */ err = sio_data->sio_enter(sio_data); @@ -418,7 +427,7 @@ static int nct6775_resume(struct device *dev) if (data->kind == nct6791 || data->kind == nct6792 || data->kind == nct6793 || data->kind == nct6795 || data->kind == nct6796 || data->kind == nct6797 || - data->kind == nct6798) + data->kind == nct6798 || data->kind == nct6799) nct6791_enable_io_mapping(sio_data); sio_data->sio_exit(sio_data); @@ -472,7 +481,7 @@ static int nct6775_resume(struct device *dev) abort: /* Force re-reading all values */ data->valid = false; - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return err; } @@ -565,7 +574,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio } else { /* * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D, - * NCT6797D, NCT6798D + * NCT6797D, NCT6798D, NCT6799D */ int cr1a = sio_data->sio_inb(sio_data, 0x1a); int cr1b = sio_data->sio_inb(sio_data, 0x1b); @@ -575,12 +584,17 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio int cr2b = sio_data->sio_inb(sio_data, 0x2b); int cr2d = sio_data->sio_inb(sio_data, 0x2d); int cr2f = sio_data->sio_inb(sio_data, 0x2f); + bool vsb_ctl_en = cr2f & BIT(0); bool dsw_en = cr2f & BIT(3); bool ddr4_en = cr2f & BIT(4); + bool as_seq1_en = cr2f & BIT(7); int cre0; + int cre6; int creb; int cred; + cre6 = sio_data->sio_inb(sio_data, 0xe0); + sio_data->sio_select(sio_data, NCT6775_LD_12); cre0 = sio_data->sio_inb(sio_data, 0xe0); creb = sio_data->sio_inb(sio_data, 0xeb); @@ -683,6 +697,29 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio pwm7pin = !(cr1d & (BIT(2) | BIT(3))); pwm7pin |= cr2d & BIT(7); pwm7pin |= creb & BIT(2); + break; + case nct6799: + fan4pin = cr1c & BIT(6); + fan5pin = cr1c & BIT(7); + + fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3)); + fan6pin |= cre6 & BIT(5); + fan6pin |= creb & BIT(5); + fan6pin |= !as_seq1_en && (cr2a & BIT(4)); + + fan7pin = cr1b & BIT(5); + fan7pin |= !vsb_ctl_en && !(cr2b & BIT(2)); + fan7pin |= creb & BIT(3); + + pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4)); + pwm6pin |= !as_seq1_en && !(cred & BIT(2)) && (cr2a & BIT(3)); + pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0)); + pwm6pin |= cre6 & BIT(3); + + pwm7pin = !vsb_ctl_en && !(cr1d & (BIT(2) | BIT(3))); + pwm7pin |= creb & BIT(2); + pwm7pin |= cr2d & BIT(7); + break; default: /* NCT6779D */ break; @@ -729,7 +766,9 @@ clear_caseopen(struct device *dev, struct device_attribute *attr, if (kstrtoul(buf, 10, &val) || val != 0) return -EINVAL; - mutex_lock(&data->update_lock); + ret = data->lock(data); + if (ret) + return ret; /* * Use CR registers to clear caseopen status. @@ -752,7 +791,7 @@ clear_caseopen(struct device *dev, struct device_attribute *attr, data->valid = false; /* Force cache refresh */ error: - mutex_unlock(&data->update_lock); + data->unlock(data, dev); return count; } @@ -838,6 +877,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data) case nct6796: case nct6797: case nct6798: + case nct6799: break; } @@ -876,6 +916,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data) case nct6796: case nct6797: case nct6798: + case nct6799: tmp |= 0x7e; break; } @@ -923,6 +964,7 @@ static int nct6775_platform_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + data->acpi_wmi_mutex = sio_data->acpi_wmi_mutex; data->kind = sio_data->kind; data->sioreg = sio_data->sioreg; @@ -1005,6 +1047,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) case SIO_NCT6798_ID: sio_data->kind = nct6798; break; + case SIO_NCT6799_ID: + sio_data->kind = nct6799; + break; default: if (val != 0xffff) pr_debug("unsupported chip ID: 0x%04x\n", val); @@ -1033,7 +1078,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) if (sio_data->kind == nct6791 || sio_data->kind == nct6792 || sio_data->kind == nct6793 || sio_data->kind == nct6795 || sio_data->kind == nct6796 || sio_data->kind == nct6797 || - sio_data->kind == nct6798) + sio_data->kind == nct6798 || sio_data->kind == nct6799) nct6791_enable_io_mapping(sio_data); sio_data->sio_exit(sio_data); @@ -1052,33 +1097,106 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) static struct platform_device *pdev[2]; static const char * const asus_wmi_boards[] = { - "PRO H410T", - "ProArt B550-CREATOR", - "ProArt X570-CREATOR WIFI", - "ProArt Z490-CREATOR 10G", - "Pro B550M-C", - "Pro WS X570-ACE", + "B360M-BASALT", + "B360M-D3H", + "CROSSHAIR VI HERO", // use custom port definition + "EX-B360M-V", + "EX-B360M-V3", + "EX-B360M-V5", + "EX-B460M-V5", + "EX-H410M-V3", + "PRIME A520M-A", + "PRIME A520M-A II", + "PRIME A520M-E", + "PRIME A520M-K", "PRIME B360-PLUS", + "PRIME B360M-A", + "PRIME B360M-C", + "PRIME B360M-D", + "PRIME B360M-K", "PRIME B460-PLUS", + "PRIME B460I-PLUS", + "PRIME B460M-A", + "PRIME B460M-A R2.0", + "PRIME B460M-K", "PRIME B550-PLUS", + "PRIME B550-PLUS AC-HES", "PRIME B550M-A", "PRIME B550M-A (WI-FI)", + "PRIME B550M-A AC", + "PRIME B550M-A WIFI II", + "PRIME B550M-K", + "PRIME H310T", // No feedback + "PRIME H410I-PLUS", + "PRIME H410M-A", + "PRIME H410M-D", + "PRIME H410M-E", + "PRIME H410M-F", + "PRIME H410M-K", + "PRIME H410M-K R2.0", "PRIME H410M-R", + "PRIME H510M-K R2.0", "PRIME X570-P", "PRIME X570-PRO", + "PRIME Z390-A", + "PRIME Z390-A/H10", + "PRIME Z390-P", + "PRIME Z390M-PLUS", + "PRIME Z490-A", + "PRIME Z490-P", + "PRIME Z490-V", + "PRIME Z490M-PLUS", + "PRO B460M-C", + "PRO H410M-C", + "PRO H410T", + "Pro A520M-C", + "Pro A520M-C II", + "Pro B550M-C", + "Pro WS X570-ACE", + "ProArt B550-CREATOR", + "ProArt X570-CREATOR WIFI", + "ProArt Z490-CREATOR 10G", + "ROG CROSSHAIR VI EXTREME", // use custom port definition + "ROG CROSSHAIR VI HERO (WI-FI AC)", // use custom port definition + "ROG CROSSHAIR VII HERO", // use custom port definition + "ROG CROSSHAIR VII HERO (WI-FI)", // use custom port definition "ROG CROSSHAIR VIII DARK HERO", "ROG CROSSHAIR VIII EXTREME", "ROG CROSSHAIR VIII FORMULA", "ROG CROSSHAIR VIII HERO", "ROG CROSSHAIR VIII HERO (WI-FI)", "ROG CROSSHAIR VIII IMPACT", + "ROG MAXIMUS XI APEX", + "ROG MAXIMUS XI CODE", + "ROG MAXIMUS XI EXTREME", + "ROG MAXIMUS XI FORMULA", + "ROG MAXIMUS XI GENE", + "ROG MAXIMUS XI HERO", + "ROG MAXIMUS XI HERO (WI-FI)", + "ROG MAXIMUS XII APEX", + "ROG MAXIMUS XII EXTREME", + "ROG MAXIMUS XII FORMULA", + "ROG MAXIMUS XII HERO (WI-FI)", + "ROG STRIX B360-F GAMING", + "ROG STRIX B360-G GAMING", + "ROG STRIX B360-H GAMING", + "ROG STRIX B360-H GAMING/OPTANE", + "ROG STRIX B360-I GAMING", + "ROG STRIX B450-E GAMING", // use custom port definition + "ROG STRIX B450-I GAMING", // use custom port definition + "ROG STRIX B460-F GAMING", + "ROG STRIX B460-G GAMING", + "ROG STRIX B460-H GAMING", + "ROG STRIX B460-I GAMING", "ROG STRIX B550-A GAMING", "ROG STRIX B550-E GAMING", "ROG STRIX B550-F GAMING", "ROG STRIX B550-F GAMING (WI-FI)", "ROG STRIX B550-F GAMING WIFI II", "ROG STRIX B550-I GAMING", - "ROG STRIX B550-XE GAMING (WI-FI)", + "ROG STRIX B550-XE GAMING WIFI", + "ROG STRIX X370-I GAMING", // use custom port definition + "ROG STRIX X470-I GAMING", // use custom port definition "ROG STRIX X570-E GAMING", "ROG STRIX X570-E GAMING WIFI II", "ROG STRIX X570-F GAMING", @@ -1094,65 +1212,231 @@ static const char * const asus_wmi_boards[] = { "ROG STRIX Z490-G GAMING (WI-FI)", "ROG STRIX Z490-H GAMING", "ROG STRIX Z490-I GAMING", + "TUF B360-PLUS GAMING", + "TUF B360-PRO GAMING", + "TUF B360-PRO GAMING (WI-FI)", + "TUF B360M-E GAMING", + "TUF B360M-PLUS GAMING", + "TUF B360M-PLUS GAMING S", + "TUF B360M-PLUS GAMING/BR", + "TUF GAMING A520M-PLUS", + "TUF GAMING A520M-PLUS II", + "TUF GAMING A520M-PLUS WIFI", + "TUF GAMING B460-PLUS", + "TUF GAMING B460-PRO (WI-FI)", + "TUF GAMING B460M-PLUS", + "TUF GAMING B460M-PLUS (WI-FI)", + "TUF GAMING B460M-PRO", + "TUF GAMING B550-PLUS", + "TUF GAMING B550-PLUS (WI-FI)", + "TUF GAMING B550-PLUS WIFI II", + "TUF GAMING B550-PRO", + "TUF GAMING B550M ZAKU (WI-FI)", "TUF GAMING B550M-E", - "TUF GAMING B550M-E (WI-FI)", + "TUF GAMING B550M-E WIFI", "TUF GAMING B550M-PLUS", "TUF GAMING B550M-PLUS (WI-FI)", "TUF GAMING B550M-PLUS WIFI II", - "TUF GAMING B550-PLUS", - "TUF GAMING B550-PLUS WIFI II", - "TUF GAMING B550-PRO", "TUF GAMING X570-PLUS", "TUF GAMING X570-PLUS (WI-FI)", + "TUF GAMING X570-PLUS_BR", "TUF GAMING X570-PRO (WI-FI)", + "TUF GAMING X570-PRO WIFI II", "TUF GAMING Z490-PLUS", "TUF GAMING Z490-PLUS (WI-FI)", + "TUF Z390-PLUS GAMING", + "TUF Z390-PLUS GAMING (WI-FI)", + "TUF Z390-PRO GAMING", + "TUF Z390M-PRO GAMING", + "TUF Z390M-PRO GAMING (WI-FI)", + "WS Z390 PRO", + "Z490-GUNDAM (WI-FI)", }; static const char * const asus_msi_boards[] = { + "B560M-P", + "EX-B560M-V5", + "EX-B660M-V5 D4", "EX-B660M-V5 PRO D4", + "EX-B760M-V5 D4", + "EX-H510M-V3", + "EX-H610M-V3 D4", + "PRIME A620M-A", + "PRIME B560-PLUS", + "PRIME B560-PLUS AC-HES", + "PRIME B560M-A", + "PRIME B560M-A AC", + "PRIME B560M-K", "PRIME B650-PLUS", "PRIME B650M-A", "PRIME B650M-A AX", + "PRIME B650M-A AX II", "PRIME B650M-A II", "PRIME B650M-A WIFI", "PRIME B650M-A WIFI II", + "PRIME B660-PLUS D4", + "PRIME B660M-A AC D4", "PRIME B660M-A D4", "PRIME B660M-A WIFI D4", + "PRIME B760-PLUS", + "PRIME B760-PLUS D4", + "PRIME B760M-A", + "PRIME B760M-A AX D4", + "PRIME B760M-A D4", + "PRIME B760M-A WIFI", + "PRIME B760M-A WIFI D4", + "PRIME B760M-AJ D4", + "PRIME B760M-K D4", + "PRIME H510M-A", + "PRIME H510M-A WIFI", + "PRIME H510M-D", + "PRIME H510M-E", + "PRIME H510M-F", + "PRIME H510M-K", + "PRIME H510M-R", + "PRIME H510T2/CSM", + "PRIME H610I-PLUS D4", + "PRIME H610M-A D4", + "PRIME H610M-A WIFI D4", + "PRIME H610M-D D4", + "PRIME H610M-E D4", + "PRIME H610M-F D4", + "PRIME H610M-K D4", + "PRIME H610M-R D4", "PRIME X670-P", "PRIME X670-P WIFI", "PRIME X670E-PRO WIFI", - "Pro B660M-C-D4", + "PRIME Z590-A", + "PRIME Z590-P", + "PRIME Z590-P WIFI", + "PRIME Z590-V", + "PRIME Z590M-PLUS", + "PRIME Z690-A", + "PRIME Z690-P", + "PRIME Z690-P D4", + "PRIME Z690-P WIFI", + "PRIME Z690-P WIFI D4", + "PRIME Z690M-PLUS D4", + "PRIME Z790-A WIFI", + "PRIME Z790-P", + "PRIME Z790-P D4", + "PRIME Z790-P WIFI", + "PRIME Z790-P WIFI D4", + "PRIME Z790M-PLUS", + "PRIME Z790M-PLUS D4", + "Pro B560M-C", + "Pro B560M-CT", + "Pro B660M-C", + "Pro B660M-C D4", + "Pro B760M-C", + "Pro B760M-CT", + "Pro H510M-C", + "Pro H510M-CT", + "Pro H610M-C", + "Pro H610M-C D4", + "Pro H610M-CT D4", + "Pro H610T D4", + "Pro WS W680-ACE", + "Pro WS W680-ACE IPMI", + "Pro WS W790-ACE", // No feedback + "Pro WS W790E-SAGE SE", // No feedback + "ProArt B650-CREATOR", "ProArt B660-CREATOR D4", + "ProArt B760-CREATOR D4", "ProArt X670E-CREATOR WIFI", + "ProArt Z690-CREATOR WIFI", + "ProArt Z790-CREATOR WIFI", "ROG CROSSHAIR X670E EXTREME", "ROG CROSSHAIR X670E GENE", "ROG CROSSHAIR X670E HERO", + "ROG MAXIMUS XIII APEX", + "ROG MAXIMUS XIII EXTREME", "ROG MAXIMUS XIII EXTREME GLACIAL", + "ROG MAXIMUS XIII HERO", + "ROG MAXIMUS Z690 APEX", "ROG MAXIMUS Z690 EXTREME", "ROG MAXIMUS Z690 EXTREME GLACIAL", + "ROG MAXIMUS Z690 FORMULA", + "ROG MAXIMUS Z690 HERO", + "ROG MAXIMUS Z690 HERO EVA", + "ROG MAXIMUS Z790 APEX", + "ROG MAXIMUS Z790 EXTREME", + "ROG MAXIMUS Z790 HERO", + "ROG STRIX B560-A GAMING WIFI", + "ROG STRIX B560-E GAMING WIFI", + "ROG STRIX B560-F GAMING WIFI", + "ROG STRIX B560-G GAMING WIFI", + "ROG STRIX B560-I GAMING WIFI", "ROG STRIX B650-A GAMING WIFI", "ROG STRIX B650E-E GAMING WIFI", "ROG STRIX B650E-F GAMING WIFI", "ROG STRIX B650E-I GAMING WIFI", + "ROG STRIX B660-A GAMING WIFI", "ROG STRIX B660-A GAMING WIFI D4", "ROG STRIX B660-F GAMING WIFI", "ROG STRIX B660-G GAMING WIFI", "ROG STRIX B660-I GAMING WIFI", + "ROG STRIX B760-A GAMING WIFI", + "ROG STRIX B760-A GAMING WIFI D4", + "ROG STRIX B760-F GAMING WIFI", + "ROG STRIX B760-G GAMING WIFI", + "ROG STRIX B760-G GAMING WIFI D4", + "ROG STRIX B760-I GAMING WIFI", "ROG STRIX X670E-A GAMING WIFI", "ROG STRIX X670E-E GAMING WIFI", "ROG STRIX X670E-F GAMING WIFI", "ROG STRIX X670E-I GAMING WIFI", + "ROG STRIX Z590-A GAMING WIFI", "ROG STRIX Z590-A GAMING WIFI II", + "ROG STRIX Z590-E GAMING WIFI", + "ROG STRIX Z590-F GAMING WIFI", + "ROG STRIX Z590-I GAMING WIFI", + "ROG STRIX Z690-A GAMING WIFI", "ROG STRIX Z690-A GAMING WIFI D4", + "ROG STRIX Z690-E GAMING WIFI", + "ROG STRIX Z690-F GAMING WIFI", + "ROG STRIX Z690-G GAMING WIFI", + "ROG STRIX Z690-I GAMING WIFI", + "ROG STRIX Z790-A GAMING WIFI", + "ROG STRIX Z790-A GAMING WIFI D4", + "ROG STRIX Z790-E GAMING WIFI", + "ROG STRIX Z790-F GAMING WIFI", + "ROG STRIX Z790-H GAMING WIFI", + "ROG STRIX Z790-I GAMING WIFI", + "TUF GAMING A620M-PLUS WIFI", + "TUF GAMING B560-PLUS WIFI", + "TUF GAMING B560M-E", + "TUF GAMING B560M-PLUS", + "TUF GAMING B560M-PLUS WIFI", "TUF GAMING B650-PLUS", "TUF GAMING B650-PLUS WIFI", "TUF GAMING B650M-PLUS", "TUF GAMING B650M-PLUS WIFI", + "TUF GAMING B660-PLUS WIFI D4", + "TUF GAMING B660M-E D4", + "TUF GAMING B660M-PLUS D4", "TUF GAMING B660M-PLUS WIFI", + "TUF GAMING B660M-PLUS WIFI D4", + "TUF GAMING B760-PLUS WIFI", + "TUF GAMING B760-PLUS WIFI D4", + "TUF GAMING B760M-BTF WIFI D4", + "TUF GAMING B760M-E D4", + "TUF GAMING B760M-PLUS", + "TUF GAMING B760M-PLUS D4", + "TUF GAMING B760M-PLUS WIFI", + "TUF GAMING B760M-PLUS WIFI D4", "TUF GAMING X670E-PLUS", "TUF GAMING X670E-PLUS WIFI", + "TUF GAMING Z590-PLUS", "TUF GAMING Z590-PLUS WIFI", + "TUF GAMING Z690-PLUS", + "TUF GAMING Z690-PLUS D4", + "TUF GAMING Z690-PLUS WIFI", + "TUF GAMING Z690-PLUS WIFI D4", + "TUF GAMING Z790-PLUS D4", + "TUF GAMING Z790-PLUS WIFI", + "TUF GAMING Z790-PLUS WIFI D4", + "Z590 WIFI GUNDAM EDITION", }; #if IS_ENABLED(CONFIG_ACPI) @@ -1194,6 +1478,117 @@ static enum sensor_access nct6775_determine_access(const char *device_uid) return access_direct; } +struct acpi_board_info { + char *acpi_mutex_path; +}; + +#define DMI_ASUS_BOARD_INFO(name, mutex_path) \ +static struct acpi_board_info name = { \ + .acpi_mutex_path = mutex_path, \ +} + +DMI_ASUS_BOARD_INFO(acpi_board_ILPC_MUTEX, "\\_SB.PCI0.LPCB.SIO1.MUT0"); +DMI_ASUS_BOARD_INFO(acpi_board_SBRG_MUTEX, "\\_SB.PCI0.SBRG.SIO1.MUT0"); +DMI_ASUS_BOARD_INFO(acpi_board_LPC0_MUTEX, "\\_SB_.PCI0.LPC0.SIO1.MUT0"); + +#define DMI_MATCH_ASUS_WMI_BOARD(name, info) { \ + .matches = { \ + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), \ + DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \ + }, \ + .driver_data = info, \ +} + +#define DMI_MATCH_ASUS_NONWMI_BOARD(name, info) { \ + .matches = { \ + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), \ + DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \ + }, \ + .driver_data = info, \ +} + +#define DMI_MATCH_ASROCK_WMI_BOARD(name, info) { \ + .matches = { \ + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ASRock"), \ + DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \ + }, \ + .driver_data = info, \ +} + +static const struct dmi_system_id asus_wmi_info_table[] = { + DMI_MATCH_ASUS_WMI_BOARD("B150 PRO GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("B150 PRO GAMING D3", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("B150M PRO GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("B250M-C PRO", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("B365M Pro4-F", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("B450M Pro4", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("B650E PG Riptide WiFi", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("CROSSHAIR VI HERO", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("EX-B365M-V", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("EX-B365M-V5", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("H81M-R", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("K30AD_M31AD_M51AD_M32AD", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS IX APEX", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS IX CODE", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS IX EXTREME", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS IX FORMULA", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS IX HERO", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS VII HERO", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("MAXIMUS VIII FORMULA", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("P8H61-M LX R2.0", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("P8H67", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_NONWMI_BOARD("P8Z68-V LX", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME B250M-C", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME B250M-J", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME B365-PLUS", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME B365M-A", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME B365M-C", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME B365M-K", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME X399-A", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("PRIME Z270-A", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG CROSSHAIR VI EXTREME", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG CROSSHAIR VI HERO (WI-FI AC)", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG CROSSHAIR VII HERO", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG CROSSHAIR VII HERO (WI-FI)", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG MAXIMUS X HERO", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX B365-F GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX B365-G GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX B450-E GAMING", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX B450-I GAMING", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX TRX40-E GAMING", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX TRX40-XE GAMING", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX X370-I GAMING", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX X470-I GAMING", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG STRIX Z370-H GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG ZENITH II EXTREME", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("ROG ZENITH II EXTREME ALPHA", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("STRIX Z270E GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("STRIX Z270F GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("STRIX Z270G GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("STRIX Z270H GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("TUF B365-PLUS GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("TUF B365M-PLUS GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("TUF Z270 MARK 1", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("X370 Gaming X", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("X399 Taichi", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("X570 Steel Legend", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("X570 Taichi", &acpi_board_SBRG_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("X99-E WS/USB 3.1", &acpi_board_LPC0_MUTEX), + DMI_MATCH_ASROCK_WMI_BOARD("Z170 Extreme4", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("Z170 PRO GAMING", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("Z170 PRO GAMING/AURA", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("Z170-A", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("Z170-DELUXE", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("Z170M-PLUS", &acpi_board_ILPC_MUTEX), + DMI_MATCH_ASUS_WMI_BOARD("Z270-WS", &acpi_board_ILPC_MUTEX), + {} +}; +MODULE_DEVICE_TABLE(dmi, asus_wmi_info_table); + +static const char * const asus_nonconflict_boards[] = { + "H97-PRO GAMER", +}; + static int __init sensors_nct6775_platform_init(void) { int i, err; @@ -1204,6 +1599,10 @@ static int __init sensors_nct6775_platform_init(void) int sioaddr[2] = { 0x2e, 0x4e }; enum sensor_access access = access_direct; const char *board_vendor, *board_name; + const struct dmi_system_id *dmi_id; + struct acpi_board_info *board_info; + acpi_handle acpi_wmi_mutex = NULL; + acpi_status status; err = platform_driver_register(&nct6775_driver); if (err) @@ -1225,6 +1624,30 @@ static int __init sensors_nct6775_platform_init(void) access = nct6775_determine_access(ASUSMSI_DEVICE_UID); } + if (access == access_direct) { + /* Mutext access check */ + dmi_id = dmi_first_match(asus_wmi_info_table); + if (dmi_id && dmi_id->driver_data) { + board_info = dmi_id->driver_data; + if (board_info->acpi_mutex_path) { + status = acpi_get_handle(NULL, board_info->acpi_mutex_path, + &acpi_wmi_mutex); + if (!ACPI_FAILURE(status)) { + pr_info("Using Asus WMI mutex: %s\n", + board_info->acpi_mutex_path); + access = access_direct; + } else { + pr_info("No such ASUS mutex: %s\n", + board_info->acpi_mutex_path); + } + } else { + pr_info("No mutex path\n"); + } + } else { + pr_info("No dmi definition `%s`:`%s`\n", board_name, board_vendor); + } + } + /* * initialize sio_data->kind and sio_data->sioreg. * @@ -1246,6 +1669,7 @@ static int __init sensors_nct6775_platform_init(void) found = true; sio_data.access = access; + sio_data.acpi_wmi_mutex = acpi_wmi_mutex; if (access == access_asuswmi) { sio_data.sio_outb = superio_wmi_outb; @@ -1273,11 +1697,15 @@ static int __init sensors_nct6775_platform_init(void) res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; res.flags = IORESOURCE_IO; - err = acpi_check_resource_conflict(&res); - if (err) { - platform_device_put(pdev[i]); - pdev[i] = NULL; - continue; + err = match_string(asus_nonconflict_boards, ARRAY_SIZE(asus_nonconflict_boards), + board_name); + if (!acpi_wmi_mutex && err < 0) { + err = acpi_check_resource_conflict(&res); + if (err) { + platform_device_put(pdev[i]); + pdev[i] = NULL; + continue; + } } err = platform_device_add_resources(pdev[i], &res, 1); diff --git a/drivers/hwmon/nct6775.h b/drivers/hwmon/nct6775.h index be41848c3cd29..c58ea93a54286 100644 --- a/drivers/hwmon/nct6775.h +++ b/drivers/hwmon/nct6775.h @@ -5,7 +5,7 @@ #include enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792, - nct6793, nct6795, nct6796, nct6797, nct6798 }; + nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 }; enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; #define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ @@ -90,10 +90,15 @@ struct nct6775_data { unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg); unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg); - struct mutex update_lock; + struct mutex update_lock; /* non ACPI lock */ + acpi_handle acpi_wmi_mutex; /* ACPI lock */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ + int (*lock)(struct nct6775_data *data); + void (*unlock)(struct nct6775_data *data, struct device *dev); + /* Register values */ u8 bank; /* current register bank */ u8 in_num; /* number of in inputs we have */