📄 w83791d.c
字号:
static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ char *buf) \{ \ struct sensor_device_attribute *sensor_attr = \ to_sensor_dev_attr(attr); \ struct w83791d_data *data = w83791d_update_device(dev); \ 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_t store_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); int nr = sensor_attr->index; mutex_lock(&data->update_lock); data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr])); w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count;}static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, char *buf){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct w83791d_data *data = w83791d_update_device(dev); return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));}/* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of least suprise; the user doesn't expect the fan minimum to change just because the divisor changed. */static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); int nr = sensor_attr->index; unsigned long min; u8 tmp_fan_div; u8 fan_div_reg; int indx = 0; u8 keep_mask = 0; u8 new_shift = 0; /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); mutex_lock(&data->update_lock); data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10)); switch (nr) { case 0: indx = 0; keep_mask = 0xcf; new_shift = 4; break; case 1: indx = 0; keep_mask = 0x3f; new_shift = 6; break; case 2: indx = 1; keep_mask = 0x3f; new_shift = 6; break; case 3: indx = 2; keep_mask = 0xf8; new_shift = 0; break; case 4: indx = 2; keep_mask = 0x8f; new_shift = 4; break;#ifdef DEBUG default: dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr); count = -EINVAL; goto err_exit;#endif } fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx]) & keep_mask; tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; w83791d_write(client, W83791D_REG_FAN_DIV[indx], fan_div_reg | tmp_fan_div); /* Restore fan_min */ data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr])); w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);#ifdef DEBUGerr_exit:#endif 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_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_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 0), SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1), SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2), SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3), SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4),};static struct sensor_device_attribute sda_fan_beep[] = { SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6), SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7), SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11), SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21), SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22),};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, 21), SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22),};/* read/write the temperature1, includes measured value and limits */static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, char *buf){ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct w83791d_data *data = w83791d_update_device(dev); return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index]));}static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count){ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); int nr = attr->index; mutex_lock(&data->update_lock); data->temp1[nr] = TEMP1_TO_REG(val); w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]); mutex_unlock(&data->update_lock); return count;}/* read/write temperature2-3, includes measured value and limits */static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr, char *buf){ struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); struct w83791d_data *data = w83791d_update_device(dev); int nr = attr->nr; int index = attr->index; return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index]));}static ssize_t store_temp23(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count){ struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); int nr = attr->nr; int index = attr->index; mutex_lock(&data->update_lock); data->temp_add[nr][index] = TEMP23_TO_REG(val); w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2], data->temp_add[nr][index] >> 8); w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1], data->temp_add[nr][index] & 0x80); mutex_unlock(&data->update_lock); return count;}static struct sensor_device_attribute_2 sda_temp_input[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),};static struct sensor_device_attribute_2 sda_temp_max[] = { SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1), SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 1), SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 1),};static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2), SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2), SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2),};/* Note: The bitmask for the beep enable/disable is different than the bitmask for the alarm. */static struct sensor_device_attribute sda_temp_beep[] = { SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4), SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5), SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1),};static struct sensor_device_attribute sda_temp_alarm[] = { SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),};/* get reatime status of all sensors items: voltage, temp, fan */static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf){ struct w83791d_data *data = w83791d_update_device(dev); return sprintf(buf, "%u\n", data->alarms);}static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);/* Beep control */#define GLOBAL_BEEP_ENABLE_SHIFT 15#define GLOBAL_BEEP_ENABLE_MASK (1 << GLOBAL_BEEP_ENABLE_SHIFT)static ssize_t show_beep_enable(struct device *dev, struct device_attribute *attr, char *buf){ struct w83791d_data *data = w83791d_update_device(dev); return sprintf(buf, "%d\n", data->beep_enable);}static ssize_t show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf){ struct w83791d_data *data = w83791d_update_device(dev); return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask));}static ssize_t store_beep_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); int i; mutex_lock(&data->update_lock); /* The beep_enable state overrides any enabling request from the masks */ data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK; data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); val = data->beep_mask; for (i = 0; i < 3; i++) { w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff)); val >>= 8; } mutex_unlock(&data->update_lock); return count;}static ssize_t store_beep_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->beep_enable = val ? 1 : 0; /* Keep the full mask value in sync with the current enable */ data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK; data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); /* The global control is in the second beep control register so only need to update that register */ val = (data->beep_mask >> 8) & 0xff; w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val); mutex_unlock(&data->update_lock); return count;}static struct sensor_device_attribute sda_beep_ctrl[] = { SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR, show_beep_enable, store_beep_enable, 0), SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR, show_beep_mask, store_beep_mask, 1)};/* cpu voltage regulation information */static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf){ struct w83791d_data *data = w83791d_update_device(dev); return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));}static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf){ struct w83791d_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm);}static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); /* No lock needed as vrm is internal to the driver (not read from a chip register) and so is not updated in w83791d_update_device() */ data->vrm = val; return count;}static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);#define IN_UNIT_ATTRS(X) \ &sda_in_input[X].dev_attr.attr, \ &sda_in_min[X].dev_attr.attr, \ &sda_in_max[X].dev_attr.attr, \ &sda_in_beep[X].dev_attr.attr, \ &sda_in_alarm[X].dev_attr.attr#define FAN_UNIT_ATTRS(X) \ &sda_fan_input[X].dev_attr.attr, \ &sda_fan_min[X].dev_attr.attr, \ &sda_fan_div[X].dev_attr.attr, \ &sda_fan_beep[X].dev_attr.attr, \ &sda_fan_alarm[X].dev_attr.attr#define TEMP_UNIT_ATTRS(X) \ &sda_temp_input[X].dev_attr.attr, \ &sda_temp_max[X].dev_attr.attr, \ &sda_temp_max_hyst[X].dev_attr.attr, \ &sda_temp_beep[X].dev_attr.attr, \ &sda_temp_alarm[X].dev_attr.attrstatic struct attribute *w83791d_attributes[] = { IN_UNIT_ATTRS(0), IN_UNIT_ATTRS(1), IN_UNIT_ATTRS(2), IN_UNIT_ATTRS(3), IN_UNIT_ATTRS(4), IN_UNIT_ATTRS(5), IN_UNIT_ATTRS(6), IN_UNIT_ATTRS(7), IN_UNIT_ATTRS(8), IN_UNIT_ATTRS(9), FAN_UNIT_ATTRS(0), FAN_UNIT_ATTRS(1), FAN_UNIT_ATTRS(2), FAN_UNIT_ATTRS(3), FAN_UNIT_ATTRS(4), TEMP_UNIT_ATTRS(0), TEMP_UNIT_ATTRS(1), TEMP_UNIT_ATTRS(2), &dev_attr_alarms.attr, &sda_beep_ctrl[0].dev_attr.attr, &sda_beep_ctrl[1].dev_attr.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, NULL};static const struct attribute_group w83791d_group = { .attrs = w83791d_attributes,};/* This function is called when: * w83791d_driver is inserted (when this module is loaded), for each available adapter * when a new adapter is inserted (and w83791d_driver is still present) */static int w83791d_attach_adapter(struct i2c_adapter *adapter){ if (!(adapter->class & I2C_CLASS_HWMON)) return 0; return i2c_probe(adapter, &addr_data, w83791d_detect);}static int w83791d_create_subclient(struct i2c_adapter *adapter, struct i2c_client *client, int addr, struct i2c_client **sub_cli){ int err; struct i2c_client *sub_client; (*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (!(sub_client)) { return -ENOMEM; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -