📄 via686a.c
字号:
/* This is called when the module is loaded */static int via686a_attach_adapter(struct i2c_adapter *adapter){ if (!(adapter->class & I2C_CLASS_HWMON)) return 0; return i2c_detect(adapter, &addr_data, via686a_detect);}static int via686a_detect(struct i2c_adapter *adapter, int address, int kind){ struct i2c_client *new_client; struct via686a_data *data; int err = 0; const char client_name[] = "via686a"; u16 val; /* Make sure we are probing the ISA bus!! */ if (!i2c_is_isa_adapter(adapter)) { dev_err(&adapter->dev, "via686a_detect called for an I2C bus adapter?!?\n"); return 0; } /* 8231 requires multiple of 256, we enforce that on 686 as well */ if(force_addr) address = force_addr & 0xFF00; if(force_addr) { dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address); if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge, VIA686A_BASE_REG, address)) return -ENODEV; } if (PCIBIOS_SUCCESSFUL != pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val)) return -ENODEV; if (!(val & 0x0001)) { dev_warn(&adapter->dev,"enabling sensors\n"); if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge, VIA686A_ENABLE_REG, val | 0x0001)) return -ENODEV; } /* Reserve the ISA region */ if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) { dev_err(&adapter->dev,"region 0x%x already in use!\n", address); return -ENODEV; } if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) { err = -ENOMEM; goto ERROR0; } memset(data, 0, sizeof(struct via686a_data)); new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; new_client->driver = &via686a_driver; new_client->flags = 0; new_client->dev.parent = &adapter->dev; /* Fill in the remaining client fields and put into the global list */ snprintf(new_client->name, I2C_NAME_SIZE, client_name); data->valid = 0; init_MUTEX(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) goto ERROR3; /* Initialize the VIA686A chip */ via686a_init_client(new_client); /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_in0_input); device_create_file(&new_client->dev, &dev_attr_in1_input); device_create_file(&new_client->dev, &dev_attr_in2_input); device_create_file(&new_client->dev, &dev_attr_in3_input); device_create_file(&new_client->dev, &dev_attr_in4_input); device_create_file(&new_client->dev, &dev_attr_in0_min); device_create_file(&new_client->dev, &dev_attr_in1_min); device_create_file(&new_client->dev, &dev_attr_in2_min); device_create_file(&new_client->dev, &dev_attr_in3_min); device_create_file(&new_client->dev, &dev_attr_in4_min); device_create_file(&new_client->dev, &dev_attr_in0_max); device_create_file(&new_client->dev, &dev_attr_in1_max); device_create_file(&new_client->dev, &dev_attr_in2_max); device_create_file(&new_client->dev, &dev_attr_in3_max); device_create_file(&new_client->dev, &dev_attr_in4_max); device_create_file(&new_client->dev, &dev_attr_temp1_input); device_create_file(&new_client->dev, &dev_attr_temp2_input); device_create_file(&new_client->dev, &dev_attr_temp3_input); device_create_file(&new_client->dev, &dev_attr_temp1_max); device_create_file(&new_client->dev, &dev_attr_temp2_max); device_create_file(&new_client->dev, &dev_attr_temp3_max); device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst); device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst); device_create_file(&new_client->dev, &dev_attr_fan1_input); device_create_file(&new_client->dev, &dev_attr_fan2_input); device_create_file(&new_client->dev, &dev_attr_fan1_min); device_create_file(&new_client->dev, &dev_attr_fan2_min); device_create_file(&new_client->dev, &dev_attr_fan1_div); device_create_file(&new_client->dev, &dev_attr_fan2_div); device_create_file(&new_client->dev, &dev_attr_alarms); return 0; ERROR3: kfree(data); ERROR0: release_region(address, VIA686A_EXTENT); return err;}static int via686a_detach_client(struct i2c_client *client){ int err; if ((err = i2c_detach_client(client))) { dev_err(&client->dev, "Client deregistration failed, client not detached.\n"); return err; } release_region(client->addr, VIA686A_EXTENT); kfree(i2c_get_clientdata(client)); return 0;}/* Called when we have found a new VIA686A. Set limits, etc. */static void via686a_init_client(struct i2c_client *client){ u8 reg; /* Start monitoring */ reg = via686a_read_value(client, VIA686A_REG_CONFIG); via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F); /* Configure temp interrupt mode for continuous-interrupt operation */ via686a_write_value(client, VIA686A_REG_TEMP_MODE, via686a_read_value(client, VIA686A_REG_TEMP_MODE) & !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));}static struct via686a_data *via686a_update_device(struct device *dev){ struct i2c_client *client = to_i2c_client(dev); struct via686a_data *data = i2c_get_clientdata(client); int i; down(&data->update_lock); if ((jiffies - data->last_updated > HZ + HZ / 2) || (jiffies < data->last_updated) || !data->valid) { for (i = 0; i <= 4; i++) { data->in[i] = via686a_read_value(client, VIA686A_REG_IN(i)); data->in_min[i] = via686a_read_value(client, VIA686A_REG_IN_MIN (i)); data->in_max[i] = via686a_read_value(client, VIA686A_REG_IN_MAX(i)); } for (i = 1; i <= 2; i++) { data->fan[i - 1] = via686a_read_value(client, VIA686A_REG_FAN(i)); data->fan_min[i - 1] = via686a_read_value(client, VIA686A_REG_FAN_MIN(i)); } for (i = 0; i <= 2; i++) { data->temp[i] = via686a_read_value(client, VIA686A_REG_TEMP(i)) << 2; data->temp_over[i] = via686a_read_value(client, VIA686A_REG_TEMP_OVER(i)); data->temp_hyst[i] = via686a_read_value(client, VIA686A_REG_TEMP_HYST(i)); } /* add in lower 2 bits temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1 temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23 temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23 */ data->temp[0] |= (via686a_read_value(client, VIA686A_REG_TEMP_LOW1) & 0xc0) >> 6; data->temp[1] |= (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) & 0x30) >> 4; data->temp[2] |= (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) & 0xc0) >> 6; i = via686a_read_value(client, VIA686A_REG_FANDIV); data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[1] = i >> 6; data->alarms = via686a_read_value(client, VIA686A_REG_ALARM1) | (via686a_read_value(client, VIA686A_REG_ALARM2) << 8); data->last_updated = jiffies; data->valid = 1; } up(&data->update_lock); return data;}static struct pci_device_id via686a_pci_ids[] = { { .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_82C686_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { 0, }};static int __devinit via686a_pci_probe(struct pci_dev *dev, const struct pci_device_id *id){ u16 val; int addr = 0; if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VIA686A_BASE_REG, &val)) return -ENODEV; addr = val & ~(VIA686A_EXTENT - 1); if (addr == 0 && force_addr == 0) { dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; } if (force_addr) addr = force_addr; /* so detect will get called */ if (!addr) { dev_err(&dev->dev,"No Via 686A sensors found.\n"); return -ENODEV; } normal_isa[0] = addr; s_bridge = dev; return i2c_add_driver(&via686a_driver);}static void __devexit via686a_pci_remove(struct pci_dev *dev){ i2c_del_driver(&via686a_driver);}static struct pci_driver via686a_pci_driver = { .name = "via686a", .id_table = via686a_pci_ids, .probe = via686a_pci_probe, .remove = __devexit_p(via686a_pci_remove),};static int __init sm_via686a_init(void){ return pci_module_init(&via686a_pci_driver);}static void __exit sm_via686a_exit(void){ pci_unregister_driver(&via686a_pci_driver);}MODULE_AUTHOR("Ky鰏ti M鋖kki <kmalkki@cc.hut.fi>, " "Mark Studebaker <mdsxyz123@yahoo.com> " "and Bob Dougherty <bobd@stanford.edu>");MODULE_DESCRIPTION("VIA 686A Sensor device");MODULE_LICENSE("GPL");module_init(sm_via686a_init);module_exit(sm_via686a_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -