📄 adm1025.c
字号:
struct adm1025_data *data = adm1025_update_device(dev); return sprintf(buf, "%u\n", data->vrm);}static ssize_t set_vrm(struct device *dev, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct adm1025_data *data = i2c_get_clientdata(client); data->vrm = simple_strtoul(buf, NULL, 10); return count;}static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);/* * Real code */static int adm1025_attach_adapter(struct i2c_adapter *adapter){ if (!(adapter->class & I2C_CLASS_HWMON)) return 0; return i2c_detect(adapter, &addr_data, adm1025_detect);}/* * The following function does more than just detection. If detection * succeeds, it also registers the new chip. */static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind){ struct i2c_client *new_client; struct adm1025_data *data; int err = 0; const char *name = ""; u8 config; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) goto exit; if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } memset(data, 0, sizeof(struct adm1025_data)); /* The common I2C client data is placed right before the ADM1025-specific data. */ new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; new_client->driver = &adm1025_driver; new_client->flags = 0; /* * Now we do the remaining detection. A negative kind means that * the driver was loaded with no force parameter (default), so we * must both detect and identify the chip. A zero kind means that * the driver was loaded with the force parameter, the detection * step shall be skipped. A positive kind means that the driver * was loaded with the force parameter and a given kind of chip is * requested, so both the detection and the identification steps * are skipped. */ config = i2c_smbus_read_byte_data(new_client, ADM1025_REG_CONFIG); if (kind < 0) { /* detection */ if ((config & 0x80) != 0x00 || (i2c_smbus_read_byte_data(new_client, ADM1025_REG_STATUS1) & 0xC0) != 0x00 || (i2c_smbus_read_byte_data(new_client, ADM1025_REG_STATUS2) & 0xBC) != 0x00) { dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x.\n", address); goto exit_free; } } if (kind <= 0) { /* identification */ u8 man_id, chip_id; man_id = i2c_smbus_read_byte_data(new_client, ADM1025_REG_MAN_ID); chip_id = i2c_smbus_read_byte_data(new_client, ADM1025_REG_CHIP_ID); if (man_id == 0x41) { /* Analog Devices */ if ((chip_id & 0xF0) == 0x20) { /* ADM1025/ADM1025A */ kind = adm1025; } } else if (man_id == 0xA1) { /* Philips */ if (address != 0x2E && (chip_id & 0xF0) == 0x20) { /* NE1619 */ kind = ne1619; } } if (kind <= 0) { /* identification failed */ dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); goto exit_free; } } if (kind == adm1025) { name = "adm1025"; } else if (kind == ne1619) { name = "ne1619"; } /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); new_client->id = adm1025_id++; 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 exit_free; /* Initialize the ADM1025 chip */ adm1025_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_in5_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_in5_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_in5_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_temp1_min); device_create_file(&new_client->dev, &dev_attr_temp2_min); 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_alarms); device_create_file(&new_client->dev, &dev_attr_in1_ref); device_create_file(&new_client->dev, &dev_attr_vrm); /* Pin 11 is either in4 (+12V) or VID4 */ if (!(config & 0x20)) { device_create_file(&new_client->dev, &dev_attr_in4_input); device_create_file(&new_client->dev, &dev_attr_in4_min); device_create_file(&new_client->dev, &dev_attr_in4_max); } return 0;exit_free: kfree(data);exit: return err;}static void adm1025_init_client(struct i2c_client *client){ u8 reg; struct adm1025_data *data = i2c_get_clientdata(client); int i; data->vrm = 82; /* * Set high limits * Usually we avoid setting limits on driver init, but it happens * that the ADM1025 comes with stupid default limits (all registers * set to 0). In case the chip has not gone through any limit * setting yet, we better set the high limits to the max so that * no alarm triggers. */ for (i=0; i<6; i++) { reg = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MAX(i)); if (reg == 0) i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(i), 0xFF); } for (i=0; i<2; i++) { reg = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_HIGH(i)); if (reg == 0) i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(i), 0x7F); } /* * Start the conversions */ reg = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); if (!(reg & 0x01)) i2c_smbus_write_byte_data(client, ADM1025_REG_CONFIG, (reg&0x7E)|0x01);}static int adm1025_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; } kfree(i2c_get_clientdata(client)); return 0;}static struct adm1025_data *adm1025_update_device(struct device *dev){ struct i2c_client *client = to_i2c_client(dev); struct adm1025_data *data = i2c_get_clientdata(client); down(&data->update_lock); if ((jiffies - data->last_updated > HZ * 2) || (jiffies < data->last_updated) || !data->valid) { int i; dev_dbg(&client->dev, "Updating data.\n"); for (i=0; i<6; i++) { data->in[i] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN(i)); data->in_min[i] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MIN(i)); data->in_max[i] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MAX(i)); } for (i=0; i<2; i++) { data->temp[i] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP(i)); data->temp_min[i] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_LOW(i)); data->temp_max[i] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_HIGH(i)); } data->alarms = i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) | (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) << 8); data->vid = (i2c_smbus_read_byte_data(client, ADM1025_REG_VID) & 0x0f) | ((i2c_smbus_read_byte_data(client, ADM1025_REG_VID4) & 0x01) << 4); data->last_updated = jiffies; data->valid = 1; } up(&data->update_lock); return data;}static int __init sensors_adm1025_init(void){ return i2c_add_driver(&adm1025_driver);}static void __exit sensors_adm1025_exit(void){ i2c_del_driver(&adm1025_driver);}MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");MODULE_DESCRIPTION("ADM1025 driver");MODULE_LICENSE("GPL");module_init(sensors_adm1025_init);module_exit(sensors_adm1025_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -