w83627ehf.c
来自「linux 内核源代码」· C语言 代码 · 共 1,579 行 · 第 1/4 页
C
1,579 行
break; case 2: reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV2) & 0x3f) | ((data->fan_div[2] & 0x03) << 6); w83627ehf_write_value(data, W83627EHF_REG_FANDIV2, reg); reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0x7f) | ((data->fan_div[2] & 0x04) << 5); w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); break; case 3: reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0xfc) | (data->fan_div[3] & 0x03); w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg); reg = (w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT) & 0x7f) | ((data->fan_div[3] & 0x04) << 5); w83627ehf_write_value(data, W83627EHF_REG_SMI_OVT, reg); break; case 4: reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0x73) | ((data->fan_div[4] & 0x03) << 2) | ((data->fan_div[4] & 0x04) << 5); w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg); break; }}static void w83627ehf_update_fan_div(struct w83627ehf_data *data){ int i; i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[1] = (i >> 6) & 0x03; i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV2); data->fan_div[2] = (i >> 6) & 0x03; i = w83627ehf_read_value(data, W83627EHF_REG_VBAT); data->fan_div[0] |= (i >> 3) & 0x04; data->fan_div[1] |= (i >> 4) & 0x04; data->fan_div[2] |= (i >> 5) & 0x04; if (data->has_fan & ((1 << 3) | (1 << 4))) { i = w83627ehf_read_value(data, W83627EHF_REG_DIODE); data->fan_div[3] = i & 0x03; data->fan_div[4] = ((i >> 2) & 0x03) | ((i >> 5) & 0x04); } if (data->has_fan & (1 << 3)) { i = w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT); data->fan_div[3] |= (i >> 5) & 0x04; }}static struct w83627ehf_data *w83627ehf_update_device(struct device *dev){ struct w83627ehf_data *data = dev_get_drvdata(dev); int pwmcfg = 0, tolerance = 0; /* shut up the compiler */ int i; mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ/2) || !data->valid) { /* Fan clock dividers */ w83627ehf_update_fan_div(data); /* Measured voltages and limits */ for (i = 0; i < data->in_num; i++) { data->in[i] = w83627ehf_read_value(data, W83627EHF_REG_IN(i)); data->in_min[i] = w83627ehf_read_value(data, W83627EHF_REG_IN_MIN(i)); data->in_max[i] = w83627ehf_read_value(data, W83627EHF_REG_IN_MAX(i)); } /* Measured fan speeds and limits */ for (i = 0; i < 5; i++) { if (!(data->has_fan & (1 << i))) continue; data->fan[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN[i]); data->fan_min[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_MIN[i]); /* If we failed to measure the fan speed and clock divider can be increased, let's try that for next time */ if (data->fan[i] == 0xff && data->fan_div[i] < 0x07) { dev_dbg(dev, "Increasing fan%d " "clock divider from %u to %u\n", i + 1, div_from_reg(data->fan_div[i]), div_from_reg(data->fan_div[i] + 1)); data->fan_div[i]++; w83627ehf_write_fan_div(data, i); /* Preserve min limit if possible */ if (data->fan_min[i] >= 2 && data->fan_min[i] != 255) w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[i], (data->fan_min[i] /= 2)); } } for (i = 0; i < 4; i++) { /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */ if (i != 1) { pwmcfg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[i]); tolerance = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[i]); } data->pwm_mode[i] = ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1; data->pwm_enable[i] = ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i]) & 3) + 1; data->pwm[i] = w83627ehf_read_value(data, W83627EHF_REG_PWM[i]); data->fan_min_output[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_MIN_OUTPUT[i]); data->fan_stop_time[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_STOP_TIME[i]); data->target_temp[i] = w83627ehf_read_value(data, W83627EHF_REG_TARGET[i]) & (data->pwm_mode[i] == 1 ? 0x7f : 0xff); data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) & 0x0f; } /* Measured temperatures and limits */ data->temp1 = w83627ehf_read_value(data, W83627EHF_REG_TEMP1); data->temp1_max = w83627ehf_read_value(data, W83627EHF_REG_TEMP1_OVER); data->temp1_max_hyst = w83627ehf_read_value(data, W83627EHF_REG_TEMP1_HYST); for (i = 0; i < 2; i++) { data->temp[i] = w83627ehf_read_value(data, W83627EHF_REG_TEMP[i]); data->temp_max[i] = w83627ehf_read_value(data, W83627EHF_REG_TEMP_OVER[i]); data->temp_max_hyst[i] = w83627ehf_read_value(data, W83627EHF_REG_TEMP_HYST[i]); } data->alarms = w83627ehf_read_value(data, W83627EHF_REG_ALARM1) | (w83627ehf_read_value(data, W83627EHF_REG_ALARM2) << 8) | (w83627ehf_read_value(data, W83627EHF_REG_ALARM3) << 16); data->last_updated = jiffies; data->valid = 1; } mutex_unlock(&data->update_lock); return data;}/* * Sysfs callback functions */#define show_in_reg(reg) \static ssize_t \show_##reg(struct device *dev, struct device_attribute *attr, \ char *buf) \{ \ struct w83627ehf_data *data = w83627ehf_update_device(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \}show_in_reg(in)show_in_reg(in_min)show_in_reg(in_max)#define store_in_reg(REG, reg) \static ssize_t \store_in_##reg (struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \{ \ struct w83627ehf_data *data = dev_get_drvdata(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ u32 val = simple_strtoul(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->in_##reg[nr] = in_to_reg(val, nr); \ w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ mutex_unlock(&data->update_lock); \ return count; \}store_in_reg(MIN, min)store_in_reg(MAX, max)static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf){ struct w83627ehf_data *data = w83627ehf_update_device(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01);}static struct sensor_device_attribute sda_in_input[] = { SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),};static struct sensor_device_attribute sda_in_alarm[] = { SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19),};static struct sensor_device_attribute sda_in_min[] = { SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),};static struct sensor_device_attribute sda_in_max[] = { SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),};#define show_fan_reg(reg) \static ssize_t \show_##reg(struct device *dev, struct device_attribute *attr, \ char *buf) \{ \ struct w83627ehf_data *data = w83627ehf_update_device(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ return sprintf(buf, "%d\n", \ fan_from_reg(data->reg[nr], \ div_from_reg(data->fan_div[nr]))); \}show_fan_reg(fan);show_fan_reg(fan_min);static ssize_tshow_fan_div(struct device *dev, struct device_attribute *attr, char *buf){ struct w83627ehf_data *data = w83627ehf_update_device(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));}static ssize_tstore_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; unsigned int val = simple_strtoul(buf, NULL, 10); unsigned int reg; u8 new_div; mutex_lock(&data->update_lock); if (!val) { /* No min limit, alarm disabled */ data->fan_min[nr] = 255; new_div = data->fan_div[nr]; /* No change */ dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1); } else if ((reg = 1350000U / val) >= 128 * 255) { /* Speed below this value cannot possibly be represented, even with the highest divider (128) */ data->fan_min[nr] = 254; new_div = 7; /* 128 == (1 << 7) */ dev_warn(dev, "fan%u low limit %u below minimum %u, set to " "minimum\n", nr + 1, val, fan_from_reg(254, 128)); } else if (!reg) { /* Speed above this value cannot possibly be represented, even with the lowest divider (1) */ data->fan_min[nr] = 1; new_div = 0; /* 1 == (1 << 0) */ dev_warn(dev, "fan%u low limit %u above maximum %u, set to " "maximum\n", nr + 1, val, fan_from_reg(1, 1)); } else { /* Automatically pick the best divider, i.e. the one such that the min limit will correspond to a register value in the 96..192 range */ new_div = 0; while (reg > 192 && new_div < 7) { reg >>= 1; new_div++; } data->fan_min[nr] = reg; } /* Write both the fan clock divider (if it changed) and the new fan min (unconditionally) */ if (new_div != data->fan_div[nr]) { /* Preserve the fan speed reading */ if (data->fan[nr] != 0xff) { if (new_div > data->fan_div[nr]) data->fan[nr] >>= new_div - data->fan_div[nr]; else if (data->fan[nr] & 0x80) data->fan[nr] = 0xff; else data->fan[nr] <<= data->fan_div[nr] - new_div; } dev_dbg(dev, "fan%u clock divider changed from %u to %u\n", nr + 1, div_from_reg(data->fan_div[nr]), div_from_reg(new_div)); data->fan_div[nr] = new_div; w83627ehf_write_fan_div(data, nr); /* Give the chip time to sample a new speed value */ data->last_updated = jiffies; } w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count;}static struct sensor_device_attribute sda_fan_input[] = { SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),};static struct sensor_device_attribute sda_fan_alarm[] = { SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10), SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23),};static struct sensor_device_attribute sda_fan_min[] = { SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 0), SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1), SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2), SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3), SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4),};static struct sensor_device_attribute sda_fan_div[] = { SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),};#define show_temp1_reg(reg) \
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?