Commit 7cd9ad69 authored by Evgeniy Polyakov's avatar Evgeniy Polyakov Committed by Greg Kroah-Hartman

[PATCH] w1_therm: more precise temperature calculation

This patch will introduce new temperature calculation mechanism which
allows to use up to 9bit resolution(currently 3 digits after point).
Fixed timeout issues with multiple repeated reading.
Signed-off-by: default avatarEvgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 83e9c6b3
...@@ -59,19 +59,28 @@ static ssize_t w1_therm_read_name(struct device *dev, char *buf) ...@@ -59,19 +59,28 @@ static ssize_t w1_therm_read_name(struct device *dev, char *buf)
return sprintf(buf, "%s\n", sl->name); return sprintf(buf, "%s\n", sl->name);
} }
static inline int w1_convert_temp(u8 rom[9])
{
int t, h;
if (rom[1] == 0)
t = ((s32)rom[0] >> 1)*1000;
else
t = 1000*(-1*(s32)(0x100-rom[0]) >> 1);
t -= 250;
h = 1000*((s32)rom[7] - (s32)rom[6]);
h /= (s32)rom[7];
t += h;
return t;
}
static ssize_t w1_therm_read_temp(struct device *dev, char *buf) static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
{ {
struct w1_slave *sl = container_of(dev, struct w1_slave, dev); struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
s16 temp;
/* return sprintf(buf, "%d\n", w1_convert_temp(sl->rom));
* Must be more precise.
*/
temp = 0;
temp <<= sl->rom[1] / 2;
temp |= sl->rom[0] / 2;
return sprintf(buf, "%d\n", temp * 1000);
} }
static int w1_therm_check_rom(u8 rom[9]) static int w1_therm_check_rom(u8 rom[9])
...@@ -92,7 +101,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -92,7 +101,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
struct w1_master *dev = sl->master; struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict; u8 rom[9], crc, verdict;
int i, max_trying = 10; int i, max_trying = 10;
u16 temp;
atomic_inc(&sl->refcnt); atomic_inc(&sl->refcnt);
if (down_interruptible(&sl->master->mutex)) { if (down_interruptible(&sl->master->mutex)) {
...@@ -120,6 +128,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -120,6 +128,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
if (!w1_reset_bus (dev)) { if (!w1_reset_bus (dev)) {
int count = 0; int count = 0;
u8 match[9] = {W1_MATCH_ROM, }; u8 match[9] = {W1_MATCH_ROM, };
unsigned long tm;
memcpy(&match[1], (u64 *) & sl->reg_num, 8); memcpy(&match[1], (u64 *) & sl->reg_num, 8);
...@@ -127,24 +136,29 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -127,24 +136,29 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
w1_write_8(dev, W1_CONVERT_TEMP); w1_write_8(dev, W1_CONVERT_TEMP);
if (count < 10) { tm = jiffies + msecs_to_jiffies(750);
if (!w1_reset_bus(dev)) { while(time_before(jiffies, tm)) {
w1_write_block(dev, match, 9); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(tm-jiffies);
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
}
crc = w1_calc_crc8(rom, 8); if (signal_pending(current))
flush_signals(current);
}
if (rom[8] == crc && rom[0]) if (!w1_reset_bus (dev)) {
verdict = 1; w1_write_block(dev, match, 9);
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
} }
crc = w1_calc_crc8(rom, 8);
if (rom[8] == crc && rom[0])
verdict = 1;
} }
else
dev_warn(&dev->dev,
"18S20 doesn't respond to CONVERT_TEMP.\n");
} }
if (!w1_therm_check_rom(rom)) if (!w1_therm_check_rom(rom))
...@@ -157,12 +171,13 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -157,12 +171,13 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
crc, (verdict) ? "YES" : "NO"); crc, (verdict) ? "YES" : "NO");
if (verdict) if (verdict)
memcpy(sl->rom, rom, sizeof(sl->rom)); memcpy(sl->rom, rom, sizeof(sl->rom));
else
dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
for (i = 0; i < 9; ++i) for (i = 0; i < 9; ++i)
count += sprintf(buf + count, "%02x ", sl->rom[i]); count += sprintf(buf + count, "%02x ", sl->rom[i]);
temp = 0;
temp <<= sl->rom[1] / 2; count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
temp |= sl->rom[0] / 2;
count += sprintf(buf + count, "t=%u\n", temp);
out: out:
up(&dev->mutex); up(&dev->mutex);
out_dec: out_dec:
......
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