| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * w1_ds2408.c - w1 family 29 (DS2408) driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This source code is licensed under the GNU General Public License, |
|---|
| 7 | | - * Version 2. See the file COPYING for more details. |
|---|
| 8 | 6 | */ |
|---|
| 9 | 7 | |
|---|
| 10 | 8 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 138 | 136 | W1_F29_REG_CONTROL_AND_STATUS, buf); |
|---|
| 139 | 137 | } |
|---|
| 140 | 138 | |
|---|
| 139 | +#ifdef CONFIG_W1_SLAVE_DS2408_READBACK |
|---|
| 140 | +static bool optional_read_back_valid(struct w1_slave *sl, u8 expected) |
|---|
| 141 | +{ |
|---|
| 142 | + u8 w1_buf[3]; |
|---|
| 143 | + |
|---|
| 144 | + if (w1_reset_resume_command(sl->master)) |
|---|
| 145 | + return false; |
|---|
| 146 | + |
|---|
| 147 | + w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; |
|---|
| 148 | + w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; |
|---|
| 149 | + w1_buf[2] = 0; |
|---|
| 150 | + |
|---|
| 151 | + w1_write_block(sl->master, w1_buf, 3); |
|---|
| 152 | + |
|---|
| 153 | + return (w1_read_8(sl->master) == expected); |
|---|
| 154 | +} |
|---|
| 155 | +#else |
|---|
| 156 | +static bool optional_read_back_valid(struct w1_slave *sl, u8 expected) |
|---|
| 157 | +{ |
|---|
| 158 | + return true; |
|---|
| 159 | +} |
|---|
| 160 | +#endif |
|---|
| 161 | + |
|---|
| 141 | 162 | static ssize_t output_write(struct file *filp, struct kobject *kobj, |
|---|
| 142 | 163 | struct bin_attribute *bin_attr, char *buf, |
|---|
| 143 | 164 | loff_t off, size_t count) |
|---|
| 144 | 165 | { |
|---|
| 145 | 166 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
|---|
| 146 | 167 | u8 w1_buf[3]; |
|---|
| 147 | | - u8 readBack; |
|---|
| 148 | 168 | unsigned int retries = W1_F29_RETRIES; |
|---|
| 169 | + ssize_t bytes_written = -EIO; |
|---|
| 149 | 170 | |
|---|
| 150 | 171 | if (count != 1 || off != 0) |
|---|
| 151 | 172 | return -EFAULT; |
|---|
| .. | .. |
|---|
| 155 | 176 | dev_dbg(&sl->dev, "mutex locked"); |
|---|
| 156 | 177 | |
|---|
| 157 | 178 | if (w1_reset_select_slave(sl)) |
|---|
| 158 | | - goto error; |
|---|
| 179 | + goto out; |
|---|
| 159 | 180 | |
|---|
| 160 | | - while (retries--) { |
|---|
| 181 | + do { |
|---|
| 161 | 182 | w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE; |
|---|
| 162 | 183 | w1_buf[1] = *buf; |
|---|
| 163 | 184 | w1_buf[2] = ~(*buf); |
|---|
| 185 | + |
|---|
| 164 | 186 | w1_write_block(sl->master, w1_buf, 3); |
|---|
| 165 | 187 | |
|---|
| 166 | | - readBack = w1_read_8(sl->master); |
|---|
| 167 | | - |
|---|
| 168 | | - if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) { |
|---|
| 169 | | - if (w1_reset_resume_command(sl->master)) |
|---|
| 170 | | - goto error; |
|---|
| 171 | | - /* try again, the slave is ready for a command */ |
|---|
| 172 | | - continue; |
|---|
| 188 | + if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE && |
|---|
| 189 | + optional_read_back_valid(sl, *buf)) { |
|---|
| 190 | + bytes_written = 1; |
|---|
| 191 | + goto out; |
|---|
| 173 | 192 | } |
|---|
| 174 | 193 | |
|---|
| 175 | | -#ifdef CONFIG_W1_SLAVE_DS2408_READBACK |
|---|
| 176 | | - /* here the master could read another byte which |
|---|
| 177 | | - would be the PIO reg (the actual pin logic state) |
|---|
| 178 | | - since in this driver we don't know which pins are |
|---|
| 179 | | - in and outs, there's no value to read the state and |
|---|
| 180 | | - compare. with (*buf) so end this command abruptly: */ |
|---|
| 181 | 194 | if (w1_reset_resume_command(sl->master)) |
|---|
| 182 | | - goto error; |
|---|
| 195 | + goto out; /* unrecoverable error */ |
|---|
| 196 | + /* try again, the slave is ready for a command */ |
|---|
| 197 | + } while (--retries); |
|---|
| 183 | 198 | |
|---|
| 184 | | - /* go read back the output latches */ |
|---|
| 185 | | - /* (the direct effect of the write above) */ |
|---|
| 186 | | - w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; |
|---|
| 187 | | - w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; |
|---|
| 188 | | - w1_buf[2] = 0; |
|---|
| 189 | | - w1_write_block(sl->master, w1_buf, 3); |
|---|
| 190 | | - /* read the result of the READ_PIO_REGS command */ |
|---|
| 191 | | - if (w1_read_8(sl->master) == *buf) |
|---|
| 192 | | -#endif |
|---|
| 193 | | - { |
|---|
| 194 | | - /* success! */ |
|---|
| 195 | | - mutex_unlock(&sl->master->bus_mutex); |
|---|
| 196 | | - dev_dbg(&sl->dev, |
|---|
| 197 | | - "mutex unlocked, retries:%d", retries); |
|---|
| 198 | | - return 1; |
|---|
| 199 | | - } |
|---|
| 200 | | - } |
|---|
| 201 | | -error: |
|---|
| 199 | +out: |
|---|
| 202 | 200 | mutex_unlock(&sl->master->bus_mutex); |
|---|
| 203 | | - dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); |
|---|
| 204 | 201 | |
|---|
| 205 | | - return -EIO; |
|---|
| 202 | + dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n", |
|---|
| 203 | + (bytes_written > 0) ? "succeeded" : "error", retries); |
|---|
| 204 | + |
|---|
| 205 | + return bytes_written; |
|---|
| 206 | 206 | } |
|---|
| 207 | 207 | |
|---|
| 208 | 208 | |
|---|
| .. | .. |
|---|
| 336 | 336 | NULL, |
|---|
| 337 | 337 | }; |
|---|
| 338 | 338 | |
|---|
| 339 | | -static struct w1_family_ops w1_f29_fops = { |
|---|
| 339 | +static const struct w1_family_ops w1_f29_fops = { |
|---|
| 340 | 340 | .add_slave = w1_f29_disable_test_mode, |
|---|
| 341 | 341 | .groups = w1_f29_groups, |
|---|
| 342 | 342 | }; |
|---|