📄 it87.c
字号:
&dev_attr_pwm2_freq)) || (err = device_create_file(dev, &dev_attr_pwm3_freq))) goto ERROR4; } if (data->type == it8712 || data->type == it8716 || data->type == it8718) { data->vrm = vid_which_vrm(); /* VID reading from Super-I/O config space if available */ data->vid = sio_data->vid_value; if ((err = device_create_file(dev, &dev_attr_vrm)) || (err = device_create_file(dev, &dev_attr_cpu0_vid))) goto ERROR4; } data->hwmon_dev = hwmon_device_register(dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto ERROR4; } return 0;ERROR4: sysfs_remove_group(&dev->kobj, &it87_group); sysfs_remove_group(&dev->kobj, &it87_group_opt);ERROR2: platform_set_drvdata(pdev, NULL); kfree(data);ERROR1: release_region(res->start, IT87_EC_EXTENT);ERROR0: return err;}static int __devexit it87_remove(struct platform_device *pdev){ struct it87_data *data = platform_get_drvdata(pdev); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &it87_group); sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt); release_region(data->addr, IT87_EC_EXTENT); platform_set_drvdata(pdev, NULL); kfree(data); return 0;}/* Must be called with data->update_lock held, except during initialization. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, would slow down the IT87 access and should not be necessary. */static int it87_read_value(struct it87_data *data, u8 reg){ outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); return inb_p(data->addr + IT87_DATA_REG_OFFSET);}/* Must be called with data->update_lock held, except during initialization. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, would slow down the IT87 access and should not be necessary. */static void it87_write_value(struct it87_data *data, u8 reg, u8 value){ outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); outb_p(value, data->addr + IT87_DATA_REG_OFFSET);}/* Return 1 if and only if the PWM interface is safe to use */static int __devinit it87_check_pwm(struct device *dev){ struct it87_data *data = dev_get_drvdata(dev); /* Some BIOSes fail to correctly configure the IT87 fans. All fans off * and polarity set to active low is sign that this is the case so we * disable pwm control to protect the user. */ int tmp = it87_read_value(data, IT87_REG_FAN_CTL); if ((tmp & 0x87) == 0) { if (fix_pwm_polarity) { /* The user asks us to attempt a chip reconfiguration. * This means switching to active high polarity and * inverting all fan speed values. */ int i; u8 pwm[3]; for (i = 0; i < 3; i++) pwm[i] = it87_read_value(data, IT87_REG_PWM(i)); /* If any fan is in automatic pwm mode, the polarity * might be correct, as suspicious as it seems, so we * better don't change anything (but still disable the * PWM interface). */ if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { dev_info(dev, "Reconfiguring PWM to " "active high polarity\n"); it87_write_value(data, IT87_REG_FAN_CTL, tmp | 0x87); for (i = 0; i < 3; i++) it87_write_value(data, IT87_REG_PWM(i), 0x7f & ~pwm[i]); return 1; } dev_info(dev, "PWM configuration is " "too broken to be fixed\n"); } dev_info(dev, "Detected broken BIOS " "defaults, disabling PWM interface\n"); return 0; } else if (fix_pwm_polarity) { dev_info(dev, "PWM configuration looks " "sane, won't touch\n"); } return 1;}/* Called when we have found a new IT87. */static void __devinit it87_init_device(struct platform_device *pdev){ struct it87_data *data = platform_get_drvdata(pdev); int tmp, i; /* initialize to sane defaults: * - if the chip is in manual pwm mode, this will be overwritten with * the actual settings on the chip (so in this case, initialization * is not needed) * - if in automatic or on/off mode, we could switch to manual mode, * read the registers and set manual_pwm_ctl accordingly, but currently * this is not implemented, so we initialize to something sane */ for (i = 0; i < 3; i++) { data->manual_pwm_ctl[i] = 0xff; } /* Some chips seem to have default value 0xff for all limit * registers. For low voltage limits it makes no sense and triggers * alarms, so change to 0 instead. For high temperature limits, it * means -1 degree C, which surprisingly doesn't trigger an alarm, * but is still confusing, so change to 127 degrees C. */ for (i = 0; i < 8; i++) { tmp = it87_read_value(data, IT87_REG_VIN_MIN(i)); if (tmp == 0xff) it87_write_value(data, IT87_REG_VIN_MIN(i), 0); } for (i = 0; i < 3; i++) { tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); if (tmp == 0xff) it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); } /* Check if temperature channnels are reset manually or by some reason */ tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); if ((tmp & 0x3f) == 0) { /* Temp1,Temp3=thermistor; Temp2=thermal diode */ tmp = (tmp & 0xc0) | 0x2a; it87_write_value(data, IT87_REG_TEMP_ENABLE, tmp); } data->sensor = tmp; /* Check if voltage monitors are reset manually or by some reason */ tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); if ((tmp & 0xff) == 0) { /* Enable all voltage monitors */ it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff); } /* Check if tachometers are reset manually or by some reason */ data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); if ((data->fan_main_ctrl & 0x70) == 0) { /* Enable all fan tachometers */ data->fan_main_ctrl |= 0x70; it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); } data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; /* Set tachometers to 16-bit mode if needed */ if (data->type == it8716 || data->type == it8718) { tmp = it87_read_value(data, IT87_REG_FAN_16BIT); if (~tmp & 0x07 & data->has_fan) { dev_dbg(&pdev->dev, "Setting fan1-3 to 16-bit mode\n"); it87_write_value(data, IT87_REG_FAN_16BIT, tmp | 0x07); } if (tmp & (1 << 4)) data->has_fan |= (1 << 3); /* fan4 enabled */ if (tmp & (1 << 5)) data->has_fan |= (1 << 4); /* fan5 enabled */ } /* Set current fan mode registers and the default settings for the * other mode registers */ for (i = 0; i < 3; i++) { if (data->fan_main_ctrl & (1 << i)) { /* pwm mode */ tmp = it87_read_value(data, IT87_REG_PWM(i)); if (tmp & 0x80) { /* automatic pwm - not yet implemented, but * leave the settings made by the BIOS alone * until a change is requested via the sysfs * interface */ } else { /* manual pwm */ data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp); } } } /* Start monitoring */ it87_write_value(data, IT87_REG_CONFIG, (it87_read_value(data, IT87_REG_CONFIG) & 0x36) | (update_vbat ? 0x41 : 0x01));}static struct it87_data *it87_update_device(struct device *dev){ struct it87_data *data = dev_get_drvdata(dev); int i; mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { if (update_vbat) { /* Cleared after each update, so reenable. Value returned by this read will be previous value */ it87_write_value(data, IT87_REG_CONFIG, it87_read_value(data, IT87_REG_CONFIG) | 0x40); } for (i = 0; i <= 7; i++) { data->in[i] = it87_read_value(data, IT87_REG_VIN(i)); data->in_min[i] = it87_read_value(data, IT87_REG_VIN_MIN(i)); data->in_max[i] = it87_read_value(data, IT87_REG_VIN_MAX(i)); } /* in8 (battery) has no limit registers */ data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); for (i = 0; i < 5; i++) { /* Skip disabled fans */ if (!(data->has_fan & (1 << i))) continue; data->fan_min[i] = it87_read_value(data, IT87_REG_FAN_MIN[i]); data->fan[i] = it87_read_value(data, IT87_REG_FAN[i]); /* Add high byte if in 16-bit mode */ if (data->type == it8716 || data->type == it8718) { data->fan[i] |= it87_read_value(data, IT87_REG_FANX[i]) << 8; data->fan_min[i] |= it87_read_value(data, IT87_REG_FANX_MIN[i]) << 8; } } for (i = 0; i < 3; i++) { data->temp[i] = it87_read_value(data, IT87_REG_TEMP(i)); data->temp_high[i] = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); data->temp_low[i] = it87_read_value(data, IT87_REG_TEMP_LOW(i)); } /* Newer chips don't have clock dividers */ if ((data->has_fan & 0x07) && data->type != it8716 && data->type != it8718) { i = it87_read_value(data, IT87_REG_FAN_DIV); data->fan_div[0] = i & 0x07; data->fan_div[1] = (i >> 3) & 0x07; data->fan_div[2] = (i & 0x40) ? 3 : 1; } data->alarms = it87_read_value(data, IT87_REG_ALARM1) | (it87_read_value(data, IT87_REG_ALARM2) << 8) | (it87_read_value(data, IT87_REG_ALARM3) << 16); data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); /* The 8705 does not have VID capability */ if (data->type == it8712 || data->type == it8716) { data->vid = it87_read_value(data, IT87_REG_VID); /* The older IT8712F revisions had only 5 VID pins, but we assume it is always safe to read 6 bits. */ data->vid &= 0x3f; } data->last_updated = jiffies; data->valid = 1; } mutex_unlock(&data->update_lock); return data;}static int __init it87_device_add(unsigned short address, const struct it87_sio_data *sio_data){ struct resource res = { .start = address + IT87_EC_OFFSET, .end = address + IT87_EC_OFFSET + IT87_EC_EXTENT - 1, .name = DRVNAME, .flags = IORESOURCE_IO, }; int err; pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; printk(KERN_ERR DRVNAME ": Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed " "(%d)\n", err); goto exit_device_put; } err = platform_device_add_data(pdev, sio_data, sizeof(struct it87_sio_data)); if (err) { printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(pdev); if (err) { printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", err); goto exit_device_put; } return 0;exit_device_put: platform_device_put(pdev);exit: return err;}static int __init sm_it87_init(void){ int err; unsigned short isa_address=0; struct it87_sio_data sio_data; err = it87_find(&isa_address, &sio_data); if (err) return err; err = platform_driver_register(&it87_driver); if (err) return err; err = it87_device_add(isa_address, &sio_data); if (err){ platform_driver_unregister(&it87_driver); return err; } return 0;}static void __exit sm_it87_exit(void){ platform_device_unregister(pdev); platform_driver_unregister(&it87_driver);}MODULE_AUTHOR("Chris Gauthron, " "Jean Delvare <khali@linux-fr.org>" "Cark Li <cark.li@ite.com.tw>");MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F/8781F/8782F, SiS950 driver");module_param(update_vbat, bool, 0);MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");module_param(fix_pwm_polarity, bool, 0);MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)");MODULE_LICENSE("GPL");module_init(sm_it87_init);module_exit(sm_it87_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -