it87.c
来自「linux 内核源代码」· C语言 代码 · 共 1,502 行 · 第 1/3 页
C
1,502 行
int nr = sensor_attr->index; 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, struct device_attribute *attr, char *buf){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; 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, struct device_attribute *attr, char *buf){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; 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, struct device_attribute *attr, char *buf){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; 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, struct device_attribute *attr, char *buf){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);}static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf){ struct it87_data *data = it87_update_device(dev); int index = (data->fan_ctl >> 4) & 0x07; return sprintf(buf, "%u\n", pwm_freq[index]);}static ssize_t set_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); int nr = sensor_attr->index; struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); u8 reg; mutex_lock(&data->update_lock); reg = it87_read_value(data, IT87_REG_FAN_DIV); switch (nr) { case 0: data->fan_div[nr] = reg & 0x07; break; case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break; } data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count;}static ssize_t set_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); int nr = sensor_attr->index; struct it87_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); int min; u8 old; mutex_lock(&data->update_lock); old = it87_read_value(data, IT87_REG_FAN_DIV); /* Save fan min limit */ min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); 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(data, IT87_REG_FAN_DIV, val); /* Restore fan min limit */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count;}static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); if (val == 0) { int tmp; /* make sure the fan is on when in on/off mode */ tmp = it87_read_value(data, IT87_REG_FAN_CTL); it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); /* set on/off mode */ data->fan_main_ctrl &= ~(1 << nr); it87_write_value(data, 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(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); /* set saved pwm value, clear FAN_CTLX PWM mode bit */ it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); } else { mutex_unlock(&data->update_lock); return -EINVAL; } mutex_unlock(&data->update_lock); return count;}static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); if (val < 0 || val > 255) return -EINVAL; mutex_lock(&data->update_lock); data->manual_pwm_ctl[nr] = val; if (data->fan_main_ctrl & (1 << nr)) it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); mutex_unlock(&data->update_lock); return count;}static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct it87_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); int i; /* Search for the nearest available frequency */ for (i = 0; i < 7; i++) { if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) break; } mutex_lock(&data->update_lock); data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f; data->fan_ctl |= i << 4; it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl); mutex_unlock(&data->update_lock); return count;}#define show_fan_offset(offset) \static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ show_fan, NULL, offset - 1); \static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_fan_min, set_fan_min, offset - 1); \static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ show_fan_div, set_fan_div, offset - 1);show_fan_offset(1);show_fan_offset(2);show_fan_offset(3);#define show_pwm_offset(offset) \static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ show_pwm_enable, set_pwm_enable, offset - 1); \static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ show_pwm, set_pwm, offset - 1); \static DEVICE_ATTR(pwm##offset##_freq, \ (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));show_pwm_offset(1);show_pwm_offset(2);show_pwm_offset(3);/* A different set of callbacks for 16-bit fans */static ssize_t show_fan16(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 it87_data *data = it87_update_device(dev); return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr]));}static ssize_t show_fan16_min(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 it87_data *data = it87_update_device(dev); return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr]));}static ssize_t set_fan16_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); int nr = sensor_attr->index; struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN16_TO_REG(val); it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr] & 0xff); it87_write_value(data, IT87_REG_FANX_MIN[nr], data->fan_min[nr] >> 8); mutex_unlock(&data->update_lock); return count;}/* We want to use the same sysfs file names as 8-bit fans, but we need different variable names, so we have to use SENSOR_ATTR instead of SENSOR_DEVICE_ATTR. */#define show_fan16_offset(offset) \static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \ = SENSOR_ATTR(fan##offset##_input, S_IRUGO, \ show_fan16, NULL, offset - 1); \static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \ = SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_fan16_min, set_fan16_min, offset - 1)show_fan16_offset(1);show_fan16_offset(2);show_fan16_offset(3);show_fan16_offset(4);show_fan16_offset(5);/* Alarms */static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf){ struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%u\n", data->alarms);}static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);static ssize_tshow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf){ struct it87_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->vrm);}static ssize_tstore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct it87_data *data = dev_get_drvdata(dev); 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);static ssize_tshow_vid_reg(struct device *dev, struct device_attribute *attr, 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);static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf){ struct it87_data *data = dev_get_drvdata(dev); return sprintf(buf, "%s\n", data->name);}static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);static struct attribute *it87_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, &sensor_dev_attr_in8_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in5_min.dev_attr.attr, &sensor_dev_attr_in6_min.dev_attr.attr, &sensor_dev_attr_in7_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, &sensor_dev_attr_in6_max.dev_attr.attr, &sensor_dev_attr_in7_max.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp1_type.dev_attr.attr, &sensor_dev_attr_temp2_type.dev_attr.attr, &sensor_dev_attr_temp3_type.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_name.attr, NULL};static const struct attribute_group it87_group = { .attrs = it87_attributes,};static struct attribute *it87_attributes_opt[] = { &sensor_dev_attr_fan1_input16.dev_attr.attr, &sensor_dev_attr_fan1_min16.dev_attr.attr, &sensor_dev_attr_fan2_input16.dev_attr.attr, &sensor_dev_attr_fan2_min16.dev_attr.attr, &sensor_dev_attr_fan3_input16.dev_attr.attr, &sensor_dev_attr_fan3_min16.dev_attr.attr, &sensor_dev_attr_fan4_input16.dev_attr.attr, &sensor_dev_attr_fan4_min16.dev_attr.attr, &sensor_dev_attr_fan5_input16.dev_attr.attr, &sensor_dev_attr_fan5_min16.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan3_div.dev_attr.attr, &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm2_enable.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, &dev_attr_vrm.attr, &dev_attr_cpu0_vid.attr, NULL};static const struct attribute_group it87_group_opt = { .attrs = it87_attributes_opt,};/* SuperIO detection - will change isa_address if a chip is found */static int __init it87_find(unsigned short *address, struct it87_sio_data *sio_data){ int err = -ENODEV; u16 chip_type; superio_enter(); chip_type = superio_inw(DEVID); switch (chip_type) { case IT8705F_DEVID: sio_data->type = it87; break; case IT8712F_DEVID: sio_data->type = it8712; break; case IT8716F_DEVID: case IT8726F_DEVID: sio_data->type = it8716; break; case IT8718F_DEVID: sio_data->type = it8718; break; case 0xffff: /* No device at all */ goto exit; default: pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", chip_type); goto exit; } superio_select(PME); 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); /* Read GPIO config and VID value from LDN 7 (GPIO) */ if (chip_type != IT8705F_DEVID) { int reg; superio_select(GPIO); if (chip_type == it8718) sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); reg = superio_inb(IT87_SIO_PINX2_REG); if (reg & (1 << 0)) pr_info("it87: in3 is VCC (+5V)\n"); if (reg & (1 << 1)) pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); }exit: superio_exit(); return err;}static int __devinit it87_probe(struct platform_device *pdev){ struct it87_data *data; struct resource *res; struct device *dev = &pdev->dev; struct it87_sio_data *sio_data = dev->platform_data; int err = 0; int enable_pwm_interface; static const char *names[] = { "it87", "it8712", "it8716", "it8718", }; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!request_region(res->start, IT87_EC_EXTENT, DRVNAME)) { dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", (unsigned long)res->start, (unsigned long)(res->start + IT87_EC_EXTENT - 1)); err = -EBUSY; goto ERROR0; } if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) { err = -ENOMEM; goto ERROR1; } data->addr = res->start; data->type = sio_data->type; data->name = names[sio_data->type]; /* Now, we do the remaining detection. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?