| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * w1_ds2413.c - w1 family 3a (DS2413) driver |
|---|
| 3 | 4 | * based on w1_ds2408.c by Jean-Francois Dagenais <dagenaisj@sonatest.com> |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Copyright (c) 2013 Mariusz Bialonczyk <manio@skyboo.net> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This source code is licensed under the GNU General Public License, |
|---|
| 8 | | - * Version 2. See the file COPYING for more details. |
|---|
| 9 | 7 | */ |
|---|
| 10 | 8 | |
|---|
| 11 | 9 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 24 | 22 | #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5 |
|---|
| 25 | 23 | #define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A |
|---|
| 26 | 24 | #define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA |
|---|
| 25 | +#define W1_F3A_INVALID_PIO_STATE 0xFF |
|---|
| 27 | 26 | |
|---|
| 28 | 27 | static ssize_t state_read(struct file *filp, struct kobject *kobj, |
|---|
| 29 | 28 | struct bin_attribute *bin_attr, char *buf, loff_t off, |
|---|
| 30 | 29 | size_t count) |
|---|
| 31 | 30 | { |
|---|
| 32 | 31 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
|---|
| 32 | + unsigned int retries = W1_F3A_RETRIES; |
|---|
| 33 | + ssize_t bytes_read = -EIO; |
|---|
| 34 | + u8 state; |
|---|
| 35 | + |
|---|
| 33 | 36 | dev_dbg(&sl->dev, |
|---|
| 34 | 37 | "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", |
|---|
| 35 | 38 | bin_attr->attr.name, kobj, (unsigned int)off, count, buf); |
|---|
| .. | .. |
|---|
| 42 | 45 | mutex_lock(&sl->master->bus_mutex); |
|---|
| 43 | 46 | dev_dbg(&sl->dev, "mutex locked"); |
|---|
| 44 | 47 | |
|---|
| 45 | | - if (w1_reset_select_slave(sl)) { |
|---|
| 46 | | - mutex_unlock(&sl->master->bus_mutex); |
|---|
| 47 | | - return -EIO; |
|---|
| 48 | +next: |
|---|
| 49 | + if (w1_reset_select_slave(sl)) |
|---|
| 50 | + goto out; |
|---|
| 51 | + |
|---|
| 52 | + while (retries--) { |
|---|
| 53 | + w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ); |
|---|
| 54 | + |
|---|
| 55 | + state = w1_read_8(sl->master); |
|---|
| 56 | + if ((state & 0x0F) == ((~state >> 4) & 0x0F)) { |
|---|
| 57 | + /* complement is correct */ |
|---|
| 58 | + *buf = state; |
|---|
| 59 | + bytes_read = 1; |
|---|
| 60 | + goto out; |
|---|
| 61 | + } else if (state == W1_F3A_INVALID_PIO_STATE) { |
|---|
| 62 | + /* slave didn't respond, try to select it again */ |
|---|
| 63 | + dev_warn(&sl->dev, "slave device did not respond to PIO_ACCESS_READ, " \ |
|---|
| 64 | + "reselecting, retries left: %d\n", retries); |
|---|
| 65 | + goto next; |
|---|
| 66 | + } |
|---|
| 67 | + |
|---|
| 68 | + if (w1_reset_resume_command(sl->master)) |
|---|
| 69 | + goto out; /* unrecoverable error */ |
|---|
| 70 | + |
|---|
| 71 | + dev_warn(&sl->dev, "PIO_ACCESS_READ error, retries left: %d\n", retries); |
|---|
| 48 | 72 | } |
|---|
| 49 | 73 | |
|---|
| 50 | | - w1_write_8(sl->master, W1_F3A_FUNC_PIO_ACCESS_READ); |
|---|
| 51 | | - *buf = w1_read_8(sl->master); |
|---|
| 52 | | - |
|---|
| 74 | +out: |
|---|
| 53 | 75 | mutex_unlock(&sl->master->bus_mutex); |
|---|
| 54 | | - dev_dbg(&sl->dev, "mutex unlocked"); |
|---|
| 55 | | - |
|---|
| 56 | | - /* check for correct complement */ |
|---|
| 57 | | - if ((*buf & 0x0F) != ((~*buf >> 4) & 0x0F)) |
|---|
| 58 | | - return -EIO; |
|---|
| 59 | | - else |
|---|
| 60 | | - return 1; |
|---|
| 76 | + dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n", |
|---|
| 77 | + (bytes_read > 0) ? "succeeded" : "error", retries); |
|---|
| 78 | + return bytes_read; |
|---|
| 61 | 79 | } |
|---|
| 62 | 80 | |
|---|
| 63 | 81 | static BIN_ATTR_RO(state, 1); |
|---|
| .. | .. |
|---|
| 69 | 87 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
|---|
| 70 | 88 | u8 w1_buf[3]; |
|---|
| 71 | 89 | unsigned int retries = W1_F3A_RETRIES; |
|---|
| 90 | + ssize_t bytes_written = -EIO; |
|---|
| 72 | 91 | |
|---|
| 73 | 92 | if (count != 1 || off != 0) |
|---|
| 74 | 93 | return -EFAULT; |
|---|
| .. | .. |
|---|
| 78 | 97 | dev_dbg(&sl->dev, "mutex locked"); |
|---|
| 79 | 98 | |
|---|
| 80 | 99 | if (w1_reset_select_slave(sl)) |
|---|
| 81 | | - goto error; |
|---|
| 100 | + goto out; |
|---|
| 82 | 101 | |
|---|
| 83 | 102 | /* according to the DS2413 datasheet the most significant 6 bits |
|---|
| 84 | 103 | should be set to "1"s, so do it now */ |
|---|
| .. | .. |
|---|
| 91 | 110 | w1_write_block(sl->master, w1_buf, 3); |
|---|
| 92 | 111 | |
|---|
| 93 | 112 | if (w1_read_8(sl->master) == W1_F3A_SUCCESS_CONFIRM_BYTE) { |
|---|
| 94 | | - mutex_unlock(&sl->master->bus_mutex); |
|---|
| 95 | | - dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries); |
|---|
| 96 | | - return 1; |
|---|
| 113 | + bytes_written = 1; |
|---|
| 114 | + goto out; |
|---|
| 97 | 115 | } |
|---|
| 98 | 116 | if (w1_reset_resume_command(sl->master)) |
|---|
| 99 | | - goto error; |
|---|
| 117 | + goto out; /* unrecoverable error */ |
|---|
| 118 | + |
|---|
| 119 | + dev_warn(&sl->dev, "PIO_ACCESS_WRITE error, retries left: %d\n", retries); |
|---|
| 100 | 120 | } |
|---|
| 101 | 121 | |
|---|
| 102 | | -error: |
|---|
| 122 | +out: |
|---|
| 103 | 123 | mutex_unlock(&sl->master->bus_mutex); |
|---|
| 104 | | - dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); |
|---|
| 105 | | - return -EIO; |
|---|
| 124 | + dev_dbg(&sl->dev, "%s, mutex unlocked, retries: %d\n", |
|---|
| 125 | + (bytes_written > 0) ? "succeeded" : "error", retries); |
|---|
| 126 | + return bytes_written; |
|---|
| 106 | 127 | } |
|---|
| 107 | 128 | |
|---|
| 108 | 129 | static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1); |
|---|
| .. | .. |
|---|
| 122 | 143 | NULL, |
|---|
| 123 | 144 | }; |
|---|
| 124 | 145 | |
|---|
| 125 | | -static struct w1_family_ops w1_f3a_fops = { |
|---|
| 146 | +static const struct w1_family_ops w1_f3a_fops = { |
|---|
| 126 | 147 | .groups = w1_f3a_groups, |
|---|
| 127 | 148 | }; |
|---|
| 128 | 149 | |
|---|