Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

w1: ds2438: support for writing to offset register

Added a sysfs entry to support writing to the offset register on page1.
This register is used to calibrate the chip canceling offset errors in the
current ADC. This means that, over time, reading the IAD register will not
return the correct current measurement, it will have an offset. Writing to
the offset register if the two's complement of the current register while
passing zero current to the load will calibrate the measurements. This
change was tested on real hardware and it was able to calibrate the chip
correctly.

Signed-off-by: Luiz Sampaio <sampaio.ime@gmail.com>
Link: https://lore.kernel.org/r/20210519223046.13798-7-sampaio.ime@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Luiz Sampaio and committed by
Greg Kroah-Hartman
c999fbbd fd6ec5d7

+66 -1
+7
Documentation/ABI/stable/sysfs-driver-w1_ds2438
··· 4 4 Description: read the contents of the page1 of the DS2438 5 5 see Documentation/w1/slaves/w1_ds2438.rst for detailed information 6 6 Users: any user space application which wants to communicate with DS2438 7 + 8 + What: /sys/bus/w1/devices/.../offset 9 + Date: April 2021 10 + Contact: Luiz Sampaio <sampaio.ime@gmail.com> 11 + Description: write the contents to the offset register of the DS2438 12 + see Documentation/w1/slaves/w1_ds2438.rst for detailed information 13 + Users: any user space application which wants to communicate with DS2438
+10 -1
Documentation/w1/slaves/w1_ds2438.rst
··· 22 22 wind speed/direction measuring, humidity sensing, etc. 23 23 24 24 Current support is provided through the following sysfs files (all files 25 - except "iad" are readonly): 25 + except "iad" and "offset" are readonly): 26 26 27 27 "iad" 28 28 ----- ··· 51 51 Internally when this file is read, the additional CRC byte is also obtained 52 52 from the slave device. If it is correct, the 8 bytes page data are passed 53 53 to userspace, otherwise an I/O error is returned. 54 + 55 + "offset" 56 + ------- 57 + This file controls the 2-byte Offset Register of the chip. 58 + Writing a 2-byte value will change the Offset Register, which changes the 59 + current measurement done by the chip. Changing this register to the two's complement 60 + of the current register while forcing zero current through the load will calibrate 61 + the chip, canceling offset errors in the current ADC. 62 + 54 63 55 64 "temperature" 56 65 -------------
+49
drivers/w1/slaves/w1_ds2438.c
··· 193 193 return -1; 194 194 } 195 195 196 + static int w1_ds2438_change_offset_register(struct w1_slave *sl, u8 *value) 197 + { 198 + unsigned int retries = W1_DS2438_RETRIES; 199 + u8 w1_buf[9]; 200 + u8 w1_page1_buf[DS2438_PAGE_SIZE + 1 /*for CRC*/]; 201 + 202 + if (w1_ds2438_get_page(sl, 1, w1_page1_buf) == 0) { 203 + memcpy(&w1_buf[2], w1_page1_buf, DS2438_PAGE_SIZE - 1); /* last register reserved */ 204 + w1_buf[7] = value[0]; /* change only offset register */ 205 + w1_buf[8] = value[1]; 206 + while (retries--) { 207 + if (w1_reset_select_slave(sl)) 208 + continue; 209 + w1_buf[0] = W1_DS2438_WRITE_SCRATCH; 210 + w1_buf[1] = 0x01; /* write to page 1 */ 211 + w1_write_block(sl->master, w1_buf, 9); 212 + 213 + if (w1_reset_select_slave(sl)) 214 + continue; 215 + w1_buf[0] = W1_DS2438_COPY_SCRATCH; 216 + w1_buf[1] = 0x01; 217 + w1_write_block(sl->master, w1_buf, 2); 218 + return 0; 219 + } 220 + } 221 + return -1; 222 + } 223 + 196 224 static int w1_ds2438_get_voltage(struct w1_slave *sl, 197 225 int adc_input, uint16_t *voltage) 198 226 { ··· 392 364 return ret; 393 365 } 394 366 367 + static ssize_t offset_write(struct file *filp, struct kobject *kobj, 368 + struct bin_attribute *bin_attr, char *buf, 369 + loff_t off, size_t count) 370 + { 371 + struct w1_slave *sl = kobj_to_w1_slave(kobj); 372 + int ret; 373 + 374 + mutex_lock(&sl->master->bus_mutex); 375 + 376 + if (w1_ds2438_change_offset_register(sl, buf) == 0) 377 + ret = count; 378 + else 379 + ret = -EIO; 380 + 381 + mutex_unlock(&sl->master->bus_mutex); 382 + 383 + return ret; 384 + } 385 + 395 386 static ssize_t temperature_read(struct file *filp, struct kobject *kobj, 396 387 struct bin_attribute *bin_attr, char *buf, 397 388 loff_t off, size_t count) ··· 477 430 static BIN_ATTR_RW(iad, 0); 478 431 static BIN_ATTR_RO(page0, DS2438_PAGE_SIZE); 479 432 static BIN_ATTR_RO(page1, DS2438_PAGE_SIZE); 433 + static BIN_ATTR_WO(offset, 2); 480 434 static BIN_ATTR_RO(temperature, 0/* real length varies */); 481 435 static BIN_ATTR_RO(vad, 0/* real length varies */); 482 436 static BIN_ATTR_RO(vdd, 0/* real length varies */); ··· 486 438 &bin_attr_iad, 487 439 &bin_attr_page0, 488 440 &bin_attr_page1, 441 + &bin_attr_offset, 489 442 &bin_attr_temperature, 490 443 &bin_attr_vad, 491 444 &bin_attr_vdd,