--- tmp401.c 2008-10-23 22:00:19.000000000 +0200 +++ /home/hans/tmp401.c 2009-05-06 15:41:53.000000000 +0200 @@ -1,6 +1,9 @@ /* tmp401.c * * Copyright (C) 2007,2008 Hans de Goede + * Gabriel Konat + * Sander Leget + * Wouter Willems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +45,6 @@ /* Insmod parameters */ I2C_CLIENT_INSMOD_1(tmp401); - /* * The TMP401 registers, note some registers have different addresses for * reading and writing @@ -56,7 +58,8 @@ #define TMP401_CONSECUTIVE_ALERT 0x22 #define TMP401_MANUFACTURER_ID_REG 0xFE #define TMP401_DEVICE_ID_REG 0xFF - +#define TMP411_N_FACTOR_REG 0x18 + static const u8 TMP401_TEMP_MSB[2] = { 0x00, 0x01 }; static const u8 TMP401_TEMP_LSB[2] = { 0x15, 0x10 }; static const u8 TMP401_TEMP_LOW_LIMIT_MSB_READ[2] = { 0x06, 0x08 }; @@ -67,6 +70,10 @@ static const u8 TMP401_TEMP_HIGH_LIMIT_LSB[2] = { 0x16, 0x13 }; /* These are called the THERM limit / hysteresis / mask in the datasheet */ static const u8 TMP401_TEMP_CRIT_LIMIT[2] = { 0x20, 0x19 }; +static const u8 TMP411_TEMP_LOWEST_MSB[2] = { 0x30, 0x34 }; +static const u8 TMP411_TEMP_LOWEST_LSB[2] = { 0x31, 0x35 }; +static const u8 TMP411_TEMP_HIGHEST_MSB[2] = { 0x32, 0x36 }; +static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 }; /* Flags */ #define TMP401_CONFIG_RANGE 0x04 @@ -80,7 +87,9 @@ #define TMP401_STATUS_LOCAL_HIGH 0x40 /* Manufacturer / Device ID's */ +#define TMP411_MANUFACTURER_ID 0x55 #define TMP401_MANUFACTURER_ID 0x55 +#define TMP411_DEVICE_ID 0x12 #define TMP401_DEVICE_ID 0x11 /* @@ -93,6 +102,7 @@ struct i2c_board_info *info); static int tmp401_remove(struct i2c_client *client); static struct tmp401_data *tmp401_update_device(struct device *dev); +u8 DEVICE_ID; /* * Driver data (common to all clients) @@ -133,13 +143,16 @@ u16 temp_low[2]; u16 temp_high[2]; u8 temp_crit[2]; - u8 temp_crit_hyst; + u8 temp_crit_hyst; + + u16 temp_lowest[2]; + u16 temp_highest[2]; }; /* * Sysfs attr show / store functions */ - + static int tmp401_register_to_temp(u16 reg, u8 config) { int temp = reg; @@ -361,6 +374,26 @@ return count; } +static ssize_t show_temp_highest(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct tmp401_data *data = tmp401_update_device(dev); + + return sprintf(buf, "%d\n", + tmp401_register_to_temp(data->temp_highest[index], data->config)); +} + +static ssize_t show_temp_lowest(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct tmp401_data *data = tmp401_update_device(dev); + + return sprintf(buf, "%d\n", + tmp401_register_to_temp(data->temp_lowest[index], data->config)); +} + static struct sensor_device_attribute tmp401_attr[] = { SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), SENSOR_ATTR(temp1_min, 0644, show_temp_min, store_temp_min, 0), @@ -389,6 +422,13 @@ TMP401_STATUS_REMOTE_CRIT), }; +static struct sensor_device_attribute tmp411_attr[] = { + SENSOR_ATTR(temp1_highest, 0444, show_temp_highest, NULL, 0), + SENSOR_ATTR(temp1_lowest, 0444, show_temp_lowest, NULL, 0), + SENSOR_ATTR(temp2_highest, 0444, show_temp_highest, NULL, 1), + SENSOR_ATTR(temp2_lowest, 0444, show_temp_lowest, NULL, 1), +}; + /* * Begin non sysfs callback code (aka Real code) */ @@ -428,13 +468,15 @@ reg = i2c_smbus_read_byte_data(client, TMP401_MANUFACTURER_ID_REG); - if (reg != TMP401_MANUFACTURER_ID) + if (reg != TMP401_MANUFACTURER_ID && reg != TMP411_MANUFACTURER_ID ) return -ENODEV; reg = i2c_smbus_read_byte_data(client, TMP401_DEVICE_ID_REG); - if (reg != TMP401_DEVICE_ID) + if (reg != TMP401_DEVICE_ID && reg != TMP411_DEVICE_ID ) return -ENODEV; + DEVICE_ID = reg; + reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); if (reg & 0x1b) return -ENODEV; @@ -444,7 +486,11 @@ if (reg > 15) return -ENODEV; } - strlcpy(info->type, "tmp401", I2C_NAME_SIZE); + if(DEVICE_ID == TMP401_DEVICE_ID) + strlcpy(info->type, "tmp401", I2C_NAME_SIZE); + + if(DEVICE_ID == TMP411_DEVICE_ID) + strlcpy(info->type, "tmp411", I2C_NAME_SIZE); return 0; } @@ -473,14 +519,27 @@ goto exit_remove; } + /* Register sysfs hooks */ + if(DEVICE_ID == TMP411_DEVICE_ID) { + for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) { + err = device_create_file(&client->dev, + &tmp411_attr[i].dev_attr); + if (err) + goto exit_remove; + } + } + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); data->hwmon_dev = NULL; goto exit_remove; } - - dev_info(&client->dev, "Detected TI TMP401 chip\n"); + if(DEVICE_ID == TMP401_DEVICE_ID) { + dev_info(&client->dev, "Detected TI TMP401 chip\n"); + } else if(DEVICE_ID == TMP411_DEVICE_ID) { + dev_info(&client->dev, "Detected TI TMP411 chip\n"); + } return 0; @@ -533,6 +592,19 @@ TMP401_TEMP_HIGH_LIMIT_LSB[i]); data->temp_crit[i] = i2c_smbus_read_byte_data(client, TMP401_TEMP_CRIT_LIMIT[i]); + + /* TMP411 */ + if(DEVICE_ID == TMP411_DEVICE_ID) { + data->temp_lowest[i] = i2c_smbus_read_byte_data(client, + TMP411_TEMP_LOWEST_MSB[i]) << 8; + data->temp_lowest[i] |= i2c_smbus_read_byte_data(client, + TMP411_TEMP_LOWEST_LSB[i]); + + data->temp_highest[i] = i2c_smbus_read_byte_data(client, + TMP411_TEMP_HIGHEST_MSB[i]) << 8; + data->temp_highest[i] |= i2c_smbus_read_byte_data(client, + TMP411_TEMP_HIGHEST_LSB[i]); + } } data->temp_crit_hyst = i2c_smbus_read_byte_data(client,