diff options
Diffstat (limited to 'drivers/w1/slaves/w1_ds2413.c')
-rw-r--r-- | drivers/w1/slaves/w1_ds2413.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/drivers/w1/slaves/w1_ds2413.c b/drivers/w1/slaves/w1_ds2413.c index 492e3d010321..3364ad276b15 100644 --- a/drivers/w1/slaves/w1_ds2413.c +++ b/drivers/w1/slaves/w1_ds2413.c @@ -24,12 +24,17 @@ #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5 #define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A #define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA +#define W1_F3A_INVALID_PIO_STATE 0xFF static ssize_t state_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); + unsigned int retries = W1_F3A_RETRIES; + ssize_t bytes_read = -EIO; + u8 state; + dev_dbg(&sl->dev, "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", bin_attr->attr.name, kobj, (unsigned int)off, count, buf); @@ -42,22 +47,37 @@ static ssize_t state_read(struct file *filp, struct kobject *kobj, mutex_lock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex locked"); - if (w1_reset_select_slave(sl)) { - mutex_unlock(&sl->master->bus_mutex); - return -EIO; - } +next: + if (w1_reset_select_slave(sl)) + goto out; + + while (retries--) { + w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ); + + state = w1_read_8(sl->master); + if ((state & 0x0F) == ((~state >> 4) & 0x0F)) { + /* complement is correct */ + *buf = state; + bytes_read = 1; + goto out; + } else if (state == W1_F3A_INVALID_PIO_STATE) { + /* slave didn't respond, try to select it again */ + dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \ + "reselecting, retries left: %d\n", retries); + goto next; + } - w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ); - *buf = w1_read_8(sl->master); + if (w1_reset_resume_command(sl->master)) + goto out; /* unrecoverable error */ - mutex_unlock(&sl->master->bus_mutex); - dev_dbg(&sl->dev, "mutex unlocked"); + dev_warn(&sl->dev, "PIO_ACCESS_READ error, retries left: %d\n", retries); + } - /* check for correct complement */ - if ((*buf & 0x0F) != ((~*buf >> 4) & 0x0F)) - return -EIO; - else - return 1; +out: + mutex_unlock(&sl->master->bus_mutex); + dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n", + (bytes_read > 0) ? "succeeded" : "error", retries); + return bytes_read; } static BIN_ATTR_RO(state, 1); @@ -69,6 +89,7 @@ static ssize_t output_write(struct file *filp, struct kobject *kobj, struct w1_slave *sl = kobj_to_w1_slave(kobj); u8 w1_buf[3]; unsigned int retries = W1_F3A_RETRIES; + ssize_t bytes_written = -EIO; if (count != 1 || off != 0) return -EFAULT; @@ -78,7 +99,7 @@ static ssize_t output_write(struct file *filp, struct kobject *kobj, dev_dbg(&sl->dev, "mutex locked"); if (w1_reset_select_slave(sl)) - goto error; + goto out; /* according to the DS2413 datasheet the most significant 6 bits should be set to "1"s, so do it now */ @@ -91,18 +112,20 @@ static ssize_t output_write(struct file *filp, struct kobject *kobj, w1_write_block(sl->master, w1_buf, 3); if (w1_read_8(sl->master) == W1_F3A_SUCCESS_CONFIRM_BYTE) { - mutex_unlock(&sl->master->bus_mutex); - dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries); - return 1; + bytes_written = 1; + goto out; } if (w1_reset_resume_command(sl->master)) - goto error; + goto out; /* unrecoverable error */ + + dev_warn(&sl->dev, "PIO_ACCESS_WRITE error, retries left: %d\n", retries); } -error: +out: mutex_unlock(&sl->master->bus_mutex); - dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); - return -EIO; + dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n", + (bytes_written > 0) ? "succeeded" : "error", retries); + return bytes_written; } static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1); |