📄 it87.c
字号:
show_temp_##offset##_min (struct device *dev, char *buf) \{ \ return show_temp_min(dev, buf, offset - 1); \} \static ssize_t set_temp_##offset##_max (struct device *dev, \ const char *buf, size_t count) \{ \ return set_temp_max(dev, buf, count, offset - 1); \} \static ssize_t set_temp_##offset##_min (struct device *dev, \ const char *buf, size_t count) \{ \ return set_temp_min(dev, buf, count, offset - 1); \} \static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ show_temp_##offset##_max, set_temp_##offset##_max); \static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ show_temp_##offset##_min, set_temp_##offset##_min); show_temp_offset(1);show_temp_offset(2);show_temp_offset(3);static ssize_t show_sensor(struct device *dev, char *buf, int nr){ struct it87_data *data = it87_update_device(dev); if (data->sensor & (1 << nr)) return sprintf(buf, "3\n"); /* thermal diode */ if (data->sensor & (8 << nr)) return sprintf(buf, "2\n"); /* thermistor */ return sprintf(buf, "0\n"); /* disabled */}static ssize_t set_sensor(struct device *dev, const char *buf, size_t count, int nr){ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); data->sensor &= ~(1 << nr); data->sensor &= ~(8 << nr); /* 3 = thermal diode; 2 = thermistor; 0 = disabled */ if (val == 3) data->sensor |= 1 << nr; else if (val == 2) data->sensor |= 8 << nr; else if (val != 0) return -EINVAL; it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); return count;}#define show_sensor_offset(offset) \static ssize_t show_sensor_##offset (struct device *dev, char *buf) \{ \ return show_sensor(dev, buf, offset - 1); \} \static ssize_t set_sensor_##offset (struct device *dev, \ const char *buf, size_t count) \{ \ return set_sensor(dev, buf, count, offset - 1); \} \static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ show_sensor_##offset, set_sensor_##offset);show_sensor_offset(1);show_sensor_offset(2);show_sensor_offset(3);/* 3 Fans */static ssize_t show_fan(struct device *dev, char *buf, int nr){ struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr])));}static ssize_t show_fan_min(struct device *dev, char *buf, int nr){ struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));}static ssize_t show_fan_div(struct device *dev, char *buf, int nr){ struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));}static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr){ struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);}static ssize_t show_pwm(struct device *dev, char *buf, int nr){ struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);}static ssize_t set_fan_min(struct device *dev, const char *buf, size_t count, int nr){ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); return count;}static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr){ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); int i, min[3]; u8 old = it87_read_value(client, IT87_REG_FAN_DIV); for (i = 0; i < 3; i++) min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i])); switch (nr) { case 0: case 1: data->fan_div[nr] = DIV_TO_REG(val); break; case 2: if (val < 8) data->fan_div[nr] = 1; else data->fan_div[nr] = 3; } val = old & 0x80; val |= (data->fan_div[0] & 0x07); val |= (data->fan_div[1] & 0x07) << 3; if (data->fan_div[2] == 3) val |= 0x1 << 6; it87_write_value(client, IT87_REG_FAN_DIV, val); for (i = 0; i < 3; i++) { data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); } return count;}static ssize_t set_pwm_enable(struct device *dev, const char *buf, size_t count, int nr){ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); if (val == 0) { int tmp; /* make sure the fan is on when in on/off mode */ tmp = it87_read_value(client, IT87_REG_FAN_CTL); it87_write_value(client, IT87_REG_FAN_CTL, tmp | (1 << nr)); /* set on/off mode */ data->fan_main_ctrl &= ~(1 << nr); it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); } else if (val == 1) { /* set SmartGuardian mode */ data->fan_main_ctrl |= (1 << nr); it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); /* set saved pwm value, clear FAN_CTLX PWM mode bit */ it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); } else return -EINVAL; return count;}static ssize_t set_pwm(struct device *dev, const char *buf, size_t count, int nr){ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); if (val < 0 || val > 255) return -EINVAL; data->manual_pwm_ctl[nr] = val; if (data->fan_main_ctrl & (1 << nr)) it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); return count;}#define show_fan_offset(offset) \static ssize_t show_fan_##offset (struct device *dev, char *buf) \{ \ return show_fan(dev, buf, offset - 1); \} \static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \{ \ return show_fan_min(dev, buf, offset - 1); \} \static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \{ \ return show_fan_div(dev, buf, offset - 1); \} \static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \{ \ return set_fan_min(dev, buf, count, offset - 1); \} \static ssize_t set_fan_##offset##_div (struct device *dev, \ const char *buf, size_t count) \{ \ return set_fan_div(dev, buf, count, offset - 1); \} \static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_fan_##offset##_min, set_fan_##offset##_min); \static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ show_fan_##offset##_div, set_fan_##offset##_div);show_fan_offset(1);show_fan_offset(2);show_fan_offset(3);#define show_pwm_offset(offset) \static ssize_t show_pwm##offset##_enable (struct device *dev, \ char *buf) \{ \ return show_pwm_enable(dev, buf, offset - 1); \} \static ssize_t show_pwm##offset (struct device *dev, char *buf) \{ \ return show_pwm(dev, buf, offset - 1); \} \static ssize_t set_pwm##offset##_enable (struct device *dev, \ const char *buf, size_t count) \{ \ return set_pwm_enable(dev, buf, count, offset - 1); \} \static ssize_t set_pwm##offset (struct device *dev, \ const char *buf, size_t count) \{ \ return set_pwm(dev, buf, count, offset - 1); \} \static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ show_pwm##offset##_enable, \ set_pwm##offset##_enable); \static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ show_pwm##offset , set_pwm##offset );show_pwm_offset(1);show_pwm_offset(2);show_pwm_offset(3);/* Alarms */static ssize_t show_alarms(struct device *dev, char *buf){ struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));}static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);static ssize_tshow_vrm_reg(struct device *dev, char *buf){ struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%ld\n", (long) data->vrm);}static ssize_tstore_vrm_reg(struct device *dev, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); u32 val; val = simple_strtoul(buf, NULL, 10); data->vrm = val; return count;}static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);#define device_create_file_vrm(client) \device_create_file(&client->dev, &dev_attr_vrm)static ssize_tshow_vid_reg(struct device *dev, char *buf){ struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));}static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);#define device_create_file_vid(client) \device_create_file(&client->dev, &dev_attr_cpu0_vid)/* This function is called when: * it87_driver is inserted (when this module is loaded), for each available adapter * when a new adapter is inserted (and it87_driver is still present) */static int it87_attach_adapter(struct i2c_adapter *adapter){ if (!(adapter->class & I2C_CLASS_HWMON)) return 0; return i2c_detect(adapter, &addr_data, it87_detect);}/* SuperIO detection - will change normal_isa[0] if a chip is found */static int it87_find(int *address){ int err = -ENODEV; superio_enter(); chip_type = superio_inw(DEVID); if (chip_type != IT8712F_DEVID && chip_type != IT8705F_DEVID) goto exit; superio_select(); if (!(superio_inb(IT87_ACT_REG) & 0x01)) { pr_info("it87: Device not activated, skipping\n"); goto exit; } *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); if (*address == 0) { pr_info("it87: Base address not set, skipping\n"); goto exit; } err = 0; pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", chip_type, *address, superio_inb(DEVREV) & 0x0f);exit: superio_exit(); return err;}/* This function is called by i2c_detect */int it87_detect(struct i2c_adapter *adapter, int address, int kind){ int i; struct i2c_client *new_client; struct it87_data *data; int err = 0; const char *name = ""; int is_isa = i2c_is_isa_adapter(adapter); int enable_pwm_interface; int tmp; if (!is_isa && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) goto ERROR0; /* Reserve the ISA region */ if (is_isa) if (!request_region(address, IT87_EXTENT, it87_driver.name)) goto ERROR0; /* Probe whether there is anything available on this address. Already done for SMBus clients */ if (kind < 0) { if (is_isa) {#define REALLY_SLOW_IO /* We need the timeouts for at least some IT87-like chips. But only if we read 'undefined' registers. */ i = inb_p(address + 1); if (inb_p(address + 2) != i || inb_p(address + 3) != i || inb_p(address + 7) != i) { err = -ENODEV; goto ERROR1; }#undef REALLY_SLOW_IO /* Let's just hope nothing breaks here */ i = inb_p(address + 5) & 0x7f; outb_p(~i & 0x7f, address + 5); if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { outb_p(i, address + 5); err = -ENODEV; goto ERROR1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -