Commit 06ad1312 authored by Jean Delvare's avatar Jean Delvare Committed by Deepak Saxena

[PATCH] I2C: Rewrite temperature conversions in via686a driver

The following patch rewrites the temperature conversion macros and
functions found in the via686a chip driver. Contrary to the voltage
conversions a few weeks ago, temperature conversions were numerically
correct, but artificially complex. The new ones are cleaner. It also
fixes a highly improbable array overflow (would take one of the measured
temperatures to be over 145 degrees C).

Successfully tested by Mark D. Studebaker and I, and already applied to
our CVS repository.
parent 888c8b6b
......@@ -268,52 +268,31 @@ static const u8 viaLUT[] =
239, 240
};
/* Converting temps to (8-bit) hyst and over registers
No interpolation here. Just check the limits and go.
The +5 effectively rounds off properly and the +50 is because
the temps start at -50 */
/* Converting temps to (8-bit) hyst and over registers
No interpolation here.
The +50 is because the temps start at -50 */
static inline u8 TEMP_TO_REG(long val)
{
return (u8)
SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 :
((val + 5) / 10 + 50))], 0, 255);
return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
(val < 0 ? val - 500 : val + 500) / 1000 + 50];
}
/* for 8-bit temperature hyst and over registers
The temp values are already *10, so we don't need to do that.
But we _will_ round these off to the nearest degree with (...*10+5)/10 */
#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10)
/* for 8-bit temperature hyst and over registers */
#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
/* for 10-bit temperature readings
You might _think_ this is too long to inline, but's it's really only
called once... */
/* for 10-bit temperature readings */
static inline long TEMP_FROM_REG10(u16 val)
{
/* the temp values are already *10, so we don't need to do that. */
long temp;
u16 eightBits = val >> 2;
u16 twoBits = val & 3;
/* handle the extremes first (they won't interpolate well! ;-) */
if (val == 0)
return (long) tempLUT[0];
if (val == 1023)
return (long) tempLUT[255];
if (twoBits == 0)
return (long) tempLUT[eightBits];
else {
/* do some interpolation by multipying the lower and upper
bounds by 25, 50 or 75, then /100. */
temp = ((25 * (4 - twoBits)) * tempLUT[eightBits]
+ (25 * twoBits) * tempLUT[eightBits + 1]);
/* increase the magnitude by 50 to achieve rounding. */
if (temp > 0)
temp += 50;
else
temp -= 50;
return (temp / 100);
}
/* no interpolation for these */
if (twoBits == 0 || eightBits == 255)
return TEMP_FROM_REG(eightBits);
/* do some linear interpolation */
return (tempLUT[eightBits] * (4 - twoBits) +
tempLUT[eightBits + 1] * twoBits) * 25;
}
#define ALARMS_FROM_REG(val) (val)
......@@ -441,21 +420,21 @@ show_in_offset(4);
/* 3 temperatures */
static ssize_t show_temp(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])*100 );
return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));
}
static ssize_t show_temp_over(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])*100);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));
}
static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])*100);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
}
static ssize_t set_temp_over(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10)/100;
int val = simple_strtol(buf, NULL, 10);
data->temp_over[nr] = TEMP_TO_REG(val);
via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);
return count;
......@@ -464,7 +443,7 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10)/100;
int val = simple_strtol(buf, NULL, 10);
data->temp_hyst[nr] = TEMP_TO_REG(val);
via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
return count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment