From 5cb27d30fc3a281e830a2099d520b469e2b82008 Mon Sep 17 00:00:00 2001 From: Mariusz Bialonczyk Date: Mon, 4 Mar 2019 12:23:36 +0100 Subject: w1: ds2482: cosmetic fixes after 54865314f5a1 We have a helper function ds2482_calculate_config() which is calculating the config value, so just use it instead of passing the same variable in all calls to this function. Also fixes the placement of module parameters to match with: 50fa2951bd74 (w1: Organize driver source to natural/common order) by Andrew F. Davis Signed-off-by: Mariusz Bialonczyk Cc: Andrew Worsley Cc: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/ds2482.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/w1') diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index 8b5e598ffdb3..8f2b25f1614c 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -37,6 +37,11 @@ module_param_named(active_pullup, ds2482_active_pullup, int, 0644); MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \ "0-disable, 1-enable (default)"); +/* extra configurations - e.g. 1WS */ +static int extra_config; +module_param(extra_config, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS"); + /** * The DS2482 registers - there are 3 registers that are addressed by a read * pointer. The read pointer is set by the last command executed. @@ -70,8 +75,6 @@ MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \ #define DS2482_REG_CFG_PPM 0x02 /* presence pulse masking */ #define DS2482_REG_CFG_APU 0x01 /* active pull-up */ -/* extra configurations - e.g. 1WS */ -static int extra_config; /** * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only). @@ -130,6 +133,8 @@ struct ds2482_data { */ static inline u8 ds2482_calculate_config(u8 conf) { + conf |= extra_config; + if (ds2482_active_pullup) conf |= DS2482_REG_CFG_APU; @@ -405,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data) /* If the chip did reset since detect, re-config it */ if (err & DS2482_REG_STS_RST) ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, - ds2482_calculate_config(extra_config)); + ds2482_calculate_config(0x00)); } mutex_unlock(&pdev->access_lock); @@ -431,7 +436,8 @@ static u8 ds2482_w1_set_pullup(void *data, int delay) ds2482_wait_1wire_idle(pdev); /* note: it seems like both SPU and APU have to be set! */ retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, - ds2482_calculate_config(extra_config|DS2482_REG_CFG_SPU|DS2482_REG_CFG_APU)); + ds2482_calculate_config(DS2482_REG_CFG_SPU | + DS2482_REG_CFG_APU)); ds2482_wait_1wire_idle(pdev); } @@ -484,7 +490,7 @@ static int ds2482_probe(struct i2c_client *client, /* Set all config items to 0 (off) */ ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, - ds2482_calculate_config(extra_config)); + ds2482_calculate_config(0x00)); mutex_init(&data->access_lock); @@ -559,7 +565,5 @@ module_i2c_driver(ds2482_driver); MODULE_AUTHOR("Ben Gardner "); MODULE_DESCRIPTION("DS2482 driver"); -module_param(extra_config, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 49695ac46861180baf2b2b92c62da8619b6bf28f Mon Sep 17 00:00:00 2001 From: Jean-Francois Dagenais Date: Thu, 28 Mar 2019 12:41:11 -0400 Subject: w1: ds2408: reset on output_write retry with readback When we have success in 'Channel Access Write' but reading back latch states fails, a write is retried without doing a proper slave reset. This leads to protocol errors as the slave treats the next 'Channel Access Write' as the continuation of previous command. This commit is fixing this by making sure if the retry loop re-runs, a reset is performed, whatever the failure (CONFIRM_BYTE or the read back). The loop was quite due for a cleanup and this change mandated it. By isolating the CONFIG_W1_SLAVE_DS2408_READBACK case into it's own function, we vastly reduce the visual and branching(runtime and compile-time) noise. Reported-by: Mariusz Bialonczyk Tested-by: Mariusz Bialonczyk Signed-off-by: Jean-Francois Dagenais Signed-off-by: Greg Kroah-Hartman --- drivers/w1/slaves/w1_ds2408.c | 76 ++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'drivers/w1') diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index b535d5ec35b6..92e8f0755b9a 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c @@ -138,14 +138,37 @@ static ssize_t status_control_read(struct file *filp, struct kobject *kobj, W1_F29_REG_CONTROL_AND_STATUS, buf); } +#ifdef fCONFIG_W1_SLAVE_DS2408_READBACK +static bool optional_read_back_valid(struct w1_slave *sl, u8 expected) +{ + u8 w1_buf[3]; + + if (w1_reset_resume_command(sl->master)) + return false; + + w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; + w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; + w1_buf[2] = 0; + + w1_write_block(sl->master, w1_buf, 3); + + return (w1_read_8(sl->master) == expected); +} +#else +static bool optional_read_back_valid(struct w1_slave *sl, u8 expected) +{ + return true; +} +#endif + static ssize_t output_write(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); u8 w1_buf[3]; - u8 readBack; unsigned int retries = W1_F29_RETRIES; + ssize_t bytes_written = -EIO; if (count != 1 || off != 0) return -EFAULT; @@ -155,54 +178,33 @@ 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; - while (retries--) { + do { w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE; w1_buf[1] = *buf; w1_buf[2] = ~(*buf); - w1_write_block(sl->master, w1_buf, 3); - readBack = w1_read_8(sl->master); + w1_write_block(sl->master, w1_buf, 3); - if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) { - if (w1_reset_resume_command(sl->master)) - goto error; - /* try again, the slave is ready for a command */ - continue; + if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE && + optional_read_back_valid(sl, *buf)) { + bytes_written = 1; + goto out; } -#ifdef CONFIG_W1_SLAVE_DS2408_READBACK - /* here the master could read another byte which - would be the PIO reg (the actual pin logic state) - since in this driver we don't know which pins are - in and outs, there's no value to read the state and - compare. with (*buf) so end this command abruptly: */ if (w1_reset_resume_command(sl->master)) - goto error; + goto out; /* unrecoverable error */ + /* try again, the slave is ready for a command */ + } while (--retries); - /* go read back the output latches */ - /* (the direct effect of the write above) */ - w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; - w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; - w1_buf[2] = 0; - w1_write_block(sl->master, w1_buf, 3); - /* read the result of the READ_PIO_REGS command */ - if (w1_read_8(sl->master) == *buf) -#endif - { - /* success! */ - mutex_unlock(&sl->master->bus_mutex); - dev_dbg(&sl->dev, - "mutex unlocked, retries:%d", retries); - return 1; - } - } -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; } -- cgit v1.2.3 From 62909da8aca048ecf9fbd7e484e5100608f40a63 Mon Sep 17 00:00:00 2001 From: Mariusz Bialonczyk Date: Thu, 21 Mar 2019 11:52:55 +0100 Subject: w1: fix the resume command API >From the DS2408 datasheet [1]: "Resume Command function checks the status of the RC flag and, if it is set, directly transfers control to the control functions, similar to a Skip ROM command. The only way to set the RC flag is through successfully executing the Match ROM, Search ROM, Conditional Search ROM, or Overdrive-Match ROM command" The function currently works perfectly fine in a multidrop bus, but when we have only a single slave connected, then only a Skip ROM is used and Match ROM is not called at all. This is leading to problems e.g. with single one DS2408 connected, as the Resume Command is not working properly and the device is responding with failing results after the Resume Command. This commit is fixing this by using a Skip ROM instead in those cases. The bandwidth / performance advantage is exactly the same. Refs: [1] https://datasheets.maximintegrated.com/en/ds/DS2408.pdf Signed-off-by: Mariusz Bialonczyk Reviewed-by: Jean-Francois Dagenais Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1_io.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/w1') diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 0364d3329c52..3516ce6718d9 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -432,8 +432,7 @@ int w1_reset_resume_command(struct w1_master *dev) if (w1_reset_bus(dev)) return -1; - /* This will make only the last matched slave perform a skip ROM. */ - w1_write_8(dev, W1_RESUME_CMD); + w1_write_8(dev, dev->slave_count > 1 ? W1_RESUME_CMD : W1_SKIP_ROM); return 0; } EXPORT_SYMBOL_GPL(w1_reset_resume_command); -- cgit v1.2.3