1 From e6585a1d299375740f95f30027b8b3f4b34e7548 Mon Sep 17 00:00:00 2001
2 From: Akira Shimahara <akira215corp@gmail.com>
3 Date: Mon, 11 May 2020 22:38:20 +0200
4 Subject: [PATCH] w1_therm: adding bulk read support to trigger
5 multiple conversion on bus
7 commit 57c76221d5af648c8355a55c09b050c5d8d38189 upstream.
9 Adding bulk read support:
10 Sending a 'trigger' command in the dedicated sysfs entry of bus master
11 device send a conversion command for all the slaves on the bus. The sysfs
12 entry is added as soon as at least one device supporting this feature
13 is detected on the bus.
15 The behavior of the sysfs reading temperature on the device is as follow:
16 * If no bulk read pending, trigger a conversion on the device, wait for
17 the conversion to be done, read the temperature in device RAM
18 * If a bulk read has been trigger, access directly the device RAM
19 This behavior is the same on the 2 sysfs entries ('temperature' and
22 Reading the therm_bulk_read sysfs give the status of bulk operations:
23 * '-1': conversion in progress on at least 1 sensor
24 * '1': conversion complete but at least one sensor has not been read yet
25 * '0': no bulk operation. Reading temperature on ecah device will trigger
28 As not all devices support bulk read feature, it has been added in device
31 The attribute is set at master level as soon as a supporting device is
32 discover. It is removed when the last supported device leave the bus.
33 The count of supported device is kept with the static counter
34 bulk_read_device_counter.
36 A strong pull up is apply on the line if at least one device required it.
37 The duration of the pull up is the max time required by a device on the
38 line, which depends on the resolution settings of each device. The strong
39 pull up could be adjust with the a module parameter.
41 Updating documentation in Documentation/ABI/testing/sysfs-driver-w1_therm
42 and Documentation/w1/slaves/w1_therm.rst accordingly.
44 Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
45 Link: https://lore.kernel.org/r/20200511203820.411483-1-akira215corp@gmail.com
46 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
48 .../ABI/testing/sysfs-driver-w1_therm | 36 ++-
49 Documentation/w1/slaves/w1_therm.rst | 50 +++-
50 drivers/w1/slaves/w1_therm.c | 251 +++++++++++++++++-
51 3 files changed, 322 insertions(+), 15 deletions(-)
53 --- a/Documentation/ABI/testing/sysfs-driver-w1_therm
54 +++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
55 @@ -62,9 +62,16 @@ Date: May 2020
56 Contact: Akira Shimahara <akira215corp@gmail.com>
58 (RO) return the temperature in 1/1000 degC.
59 - Note that the conversion duration depend on the resolution (if
60 - device support this feature). It takes 94ms in 9bits
61 - resolution, 750ms for 12bits.
62 + * If a bulk read has been triggered, it will directly
63 + return the temperature computed when the bulk read
64 + occurred, if available. If not yet available, nothing
65 + is returned (a debug kernel message is sent), you
66 + should retry later on.
67 + * If no bulk read has been triggered, it will trigger
68 + a conversion and send the result. Note that the
69 + conversion duration depend on the resolution (if
70 + device support this feature). It takes 94ms in 9bits
71 + resolution, 750ms for 12bits.
72 Users: any user space application which wants to communicate with
75 @@ -85,4 +92,25 @@ Description:
76 refer to Documentation/w1/slaves/w1_therm.rst for detailed
78 Users: any user space application which wants to communicate with
80 \ No newline at end of file
84 +What: /sys/bus/w1/devices/w1_bus_masterXX/therm_bulk_read
86 +Contact: Akira Shimahara <akira215corp@gmail.com>
88 + (RW) trigger a bulk read conversion. read the status
90 + * '-1': conversion in progress on at least 1 sensor
91 + * '1' : conversion complete but at least one sensor
92 + value has not been read yet
93 + * '0' : no bulk operation. Reading temperature will
94 + trigger a conversion on each device
95 + *write*: 'trigger': trigger a bulk read on all supporting
97 + Note that if a bulk read is sent but one sensor is not read
98 + immediately, the next access to temperature on this device
99 + will return the temperature measured at the time of issue
100 + of the bulk read command (not the current temperature).
101 +Users: any user space application which wants to communicate with
103 --- a/Documentation/w1/slaves/w1_therm.rst
104 +++ b/Documentation/w1/slaves/w1_therm.rst
105 @@ -26,20 +26,31 @@ W1_THERM_DS1825 0x3B
106 W1_THERM_DS28EA00 0x42
107 ==================== ====
109 -Support is provided through the sysfs w1_slave file. Each open and
110 +Support is provided through the sysfs w1_slave file. Each open and
111 read sequence will initiate a temperature conversion then provide two
112 -lines of ASCII output. The first line contains the nine hex bytes
113 +lines of ASCII output. The first line contains the nine hex bytes
114 read along with a calculated crc value and YES or NO if it matched.
115 -If the crc matched the returned values are retained. The second line
116 +If the crc matched the returned values are retained. The second line
117 displays the retained values along with a temperature in millidegrees
120 -Parasite powered devices are limited to one slave performing a
121 -temperature conversion at a time. If none of the devices are parasite
122 -powered it would be possible to convert all the devices at the same
123 -time and then go back to read individual sensors. That isn't
124 -currently supported. The driver also doesn't support reduced
125 -precision (which would also reduce the conversion time) when reading values.
126 +Alternatively, temperature can be read using temperature sysfs, it
127 +return only temperature in millidegrees Centigrade.
129 +A bulk read of all devices on the bus could be done writing 'trigger'
130 +in the therm_bulk_read sysfs entry at w1_bus_master level. This will
131 +sent the convert command on all devices on the bus, and if parasite
132 +powered devices are detected on the bus (and strong pullup is enable
133 +in the module), it will drive the line high during the longer conversion
134 +time required by parasited powered device on the line. Reading
135 +therm_bulk_read will return 0 if no bulk conversion pending,
136 +-1 if at least one sensor still in conversion, 1 if conversion is complete
137 +but at least one sensor value has not been read yet. Result temperature is
138 +then accessed by reading the temperature sysfs entry of each device, which
139 +may return empty if conversion is still in progress. Note that if a bulk
140 +read is sent but one sensor is not read immediately, the next access to
141 +temperature on this device will return the temperature measured at the
142 +time of issue of the bulk read command (not the current temperature).
144 Writing a value between 9 and 12 to the sysfs w1_slave file will change the
145 precision of the sensor for the next readings. This value is in (volatile)
146 @@ -49,6 +60,27 @@ To store the current precision configura
147 has to be written to the sysfs w1_slave file. Since the EEPROM has a limited
148 amount of writes (>50k), this command should be used wisely.
150 +Alternatively, resolution can be set or read (value from 9 to 12) using the
151 +dedicated resolution sysfs entry on each device. This sysfs entry is not
152 +present for devices not supporting this feature. Driver will adjust the
153 +correct conversion time for each device regarding to its resolution setting.
154 +In particular, strong pullup will be applied if required during the conversion
157 +The write-only sysfs entry eeprom is an alternative for EEPROM operations:
158 + * 'save': will save device RAM to EEPROM
159 + * 'restore': will restore EEPROM data in device RAM.
161 +ext_power syfs entry allow tho check the power status of each device.
162 + * '0': device parasite powered
163 + * '1': device externally powered
165 +sysfs alarms allow read or write TH and TL (Temperature High an Low) alarms.
166 +Values shall be space separated and in the device range (typical -55 degC
167 +to 125 degC). Values are integer as they are store in a 8bit register in
168 +the device. Lowest value is automatically put to TL.Once set, alarms could
169 +be search at master level.
171 The module parameter strong_pullup can be set to 0 to disable the
172 strong pullup, 1 to enable autodetection or 2 to force strong pullup.
173 In case of autodetection, the driver will use the "READ POWER SUPPLY"
174 --- a/drivers/w1/slaves/w1_therm.c
175 +++ b/drivers/w1/slaves/w1_therm.c
177 static int w1_strong_pullup = 1;
178 module_param_named(strong_pullup, w1_strong_pullup, int, 0);
180 +/* Counter for devices supporting bulk reading */
181 +static u16 bulk_read_device_counter; /* =0 as per C standard */
183 /* This command should be in public header w1.h but is not */
184 #define W1_RECALL_EEPROM 0xB8
186 @@ -57,6 +60,7 @@ module_param_named(strong_pullup, w1_str
188 #define EEPROM_CMD_WRITE "save" /* cmd for write eeprom sysfs */
189 #define EEPROM_CMD_READ "restore" /* cmd for read eeprom sysfs */
190 +#define BULK_TRIGGER_CMD "trigger" /* cmd to trigger a bulk read */
192 #define MIN_TEMP -55 /* min temperature that can be mesured */
193 #define MAX_TEMP 125 /* max temperature that can be mesured */
194 @@ -84,6 +88,15 @@ module_param_named(strong_pullup, w1_str
195 #define SLAVE_RESOLUTION(sl) \
196 (((struct w1_therm_family_data *)(sl->family_data))->resolution)
199 + * return whether or not a converT command has been issued to the slave
200 + * * 0: no bulk read is pending
201 + * * -1: conversion is in progress
202 + * * 1: conversion done, result to be read
204 +#define SLAVE_CONVERT_TRIGGERED(sl) \
205 + (((struct w1_therm_family_data *)(sl->family_data))->convert_triggered)
207 /* return the address of the refcnt in the family data */
208 #define THERM_REFCNT(family_data) \
209 (&((struct w1_therm_family_data *)family_data)->refcnt)
210 @@ -100,6 +113,7 @@ module_param_named(strong_pullup, w1_str
211 * @set_resolution: pointer to the device set_resolution function
212 * @get_resolution: pointer to the device get_resolution function
213 * @write_data: pointer to the device writing function (2 or 3 bytes)
214 + * @bulk_read: true if device family support bulk read, false otherwise
216 struct w1_therm_family_converter {
218 @@ -110,6 +124,7 @@ struct w1_therm_family_converter {
219 int (*set_resolution)(struct w1_slave *sl, int val);
220 int (*get_resolution)(struct w1_slave *sl);
221 int (*write_data)(struct w1_slave *sl, const u8 *data);
226 @@ -120,6 +135,7 @@ struct w1_therm_family_converter {
227 * 0 device parasite powered,
228 * -x error or undefined
229 * @resolution: current device resolution
230 + * @convert_triggered: conversion state of the device
231 * @specific_functions: pointer to struct of device specific function
233 struct w1_therm_family_data {
234 @@ -127,6 +143,7 @@ struct w1_therm_family_data {
236 int external_powered;
238 + int convert_triggered;
239 struct w1_therm_family_converter *specific_functions;
242 @@ -218,6 +235,18 @@ static int recall_eeprom(struct w1_slave
244 static int read_powermode(struct w1_slave *sl);
247 + * trigger_bulk_read() - function to trigger a bulk read on the bus
248 + * @dev_master: the device master of the bus
250 + * Send a SKIP ROM follow by a CONVERT T commmand on the bus.
251 + * It also set the status flag in each slave &struct w1_therm_family_data
252 + * to signal that a conversion is in progress.
254 + * Return: 0 if success, -kernel error code otherwise
256 +static int trigger_bulk_read(struct w1_master *dev_master);
258 /* Sysfs interface declaration */
260 static ssize_t w1_slave_show(struct device *device,
261 @@ -250,6 +279,12 @@ static ssize_t alarms_store(struct devic
262 static ssize_t alarms_show(struct device *device,
263 struct device_attribute *attr, char *buf);
265 +static ssize_t therm_bulk_read_store(struct device *device,
266 + struct device_attribute *attr, const char *buf, size_t size);
268 +static ssize_t therm_bulk_read_show(struct device *device,
269 + struct device_attribute *attr, char *buf);
271 /* Attributes declarations */
273 static DEVICE_ATTR_RW(w1_slave);
274 @@ -260,6 +295,8 @@ static DEVICE_ATTR_RW(resolution);
275 static DEVICE_ATTR_WO(eeprom);
276 static DEVICE_ATTR_RW(alarms);
278 +static DEVICE_ATTR_RW(therm_bulk_read); /* attribut at master level */
280 /* Interface Functions declaration */
283 @@ -572,6 +609,7 @@ static struct w1_therm_family_converter
284 .set_resolution = NULL, /* no config register */
285 .get_resolution = NULL, /* no config register */
286 .write_data = w1_DS18S20_write_data,
290 .f = &w1_therm_family_DS1822,
291 @@ -580,6 +618,7 @@ static struct w1_therm_family_converter
292 .set_resolution = w1_DS18B20_set_resolution,
293 .get_resolution = w1_DS18B20_get_resolution,
294 .write_data = w1_DS18B20_write_data,
298 .f = &w1_therm_family_DS18B20,
299 @@ -588,6 +627,7 @@ static struct w1_therm_family_converter
300 .set_resolution = w1_DS18B20_set_resolution,
301 .get_resolution = w1_DS18B20_get_resolution,
302 .write_data = w1_DS18B20_write_data,
306 .f = &w1_therm_family_DS28EA00,
307 @@ -596,6 +636,7 @@ static struct w1_therm_family_converter
308 .set_resolution = w1_DS18B20_set_resolution,
309 .get_resolution = w1_DS18B20_get_resolution,
310 .write_data = w1_DS18B20_write_data,
314 .f = &w1_therm_family_DS1825,
315 @@ -604,6 +645,7 @@ static struct w1_therm_family_converter
316 .set_resolution = w1_DS18B20_set_resolution,
317 .get_resolution = w1_DS18B20_get_resolution,
318 .write_data = w1_DS18B20_write_data,
323 @@ -658,6 +700,23 @@ static inline bool bus_mutex_lock(struct
327 + * support_bulk_read() - check if slave support bulk read
328 + * @sl: device to check the ability
330 + * Return: true if bulk read is supported, false if not or error
332 +static inline bool bulk_read_support(struct w1_slave *sl)
334 + if (SLAVE_SPECIFIC_FUNC(sl))
335 + return SLAVE_SPECIFIC_FUNC(sl)->bulk_read;
338 + "%s: Device not supported by the driver\n", __func__);
340 + return false; /* No device family */
344 * conversion_time() - get the Tconv for the slave
345 * @sl: device to get the conversion time
347 @@ -741,6 +800,24 @@ static int w1_therm_add_slave(struct w1_
348 /* save this pointer to the device structure */
349 SLAVE_SPECIFIC_FUNC(sl) = sl_family_conv;
351 + if (bulk_read_support(sl)) {
353 + * add the sys entry to trigger bulk_read
354 + * at master level only the 1st time
356 + if (!bulk_read_device_counter) {
357 + int err = device_create_file(&sl->master->dev,
358 + &dev_attr_therm_bulk_read);
362 + "%s: Device has been added, but bulk read is unavailable. err=%d\n",
365 + /* Increment the counter */
366 + bulk_read_device_counter++;
369 /* Getting the power mode of the device {external, parasite} */
370 SLAVE_POWERMODE(sl) = read_powermode(sl);
372 @@ -763,6 +840,9 @@ static int w1_therm_add_slave(struct w1_
376 + /* Finally initialize convert_triggered flag */
377 + SLAVE_CONVERT_TRIGGERED(sl) = 0;
382 @@ -770,6 +850,14 @@ static void w1_therm_remove_slave(struct
384 int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
386 + if (bulk_read_support(sl)) {
387 + bulk_read_device_counter--;
388 + /* Delete the entry if no more device support the feature */
389 + if (!bulk_read_device_counter)
390 + device_remove_file(&sl->master->dev,
391 + &dev_attr_therm_bulk_read);
396 refcnt = atomic_read(THERM_REFCNT(sl->family_data));
397 @@ -1084,6 +1172,96 @@ error:
401 +static int trigger_bulk_read(struct w1_master *dev_master)
403 + struct w1_slave *sl = NULL; /* used to iterate through slaves */
404 + int max_trying = W1_THERM_MAX_TRY;
407 + bool strong_pullup = false;
410 + * Check whether there are parasite powered device on the bus,
411 + * and compute duration of conversion for these devices
412 + * so we can apply a strong pullup if required
414 + list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
415 + if (!sl->family_data)
417 + if (bulk_read_support(sl)) {
418 + int t_cur = conversion_time(sl);
420 + t_conv = t_cur > t_conv ? t_cur : t_conv;
421 + strong_pullup = strong_pullup ||
422 + (w1_strong_pullup == 2 ||
423 + (!SLAVE_POWERMODE(sl) &&
424 + w1_strong_pullup));
429 + * t_conv is the max conversion time required on the bus
430 + * If its 0, no device support the bulk read feature
435 + if (!bus_mutex_lock(&dev_master->bus_mutex)) {
436 + ret = -EAGAIN; /* Didn't acquire the mutex */
440 + while ((max_trying--) && (ret < 0)) { /* ret should be either 0 */
442 + if (!w1_reset_bus(dev_master)) { /* Just reset the bus */
443 + unsigned long sleep_rem;
445 + w1_write_8(dev_master, W1_SKIP_ROM);
447 + if (strong_pullup) /* Apply pullup if required */
448 + w1_next_pullup(dev_master, t_conv);
450 + w1_write_8(dev_master, W1_CONVERT_TEMP);
452 + /* set a flag to instruct that converT pending */
453 + list_for_each_entry(sl,
454 + &dev_master->slist, w1_slave_entry) {
455 + if (bulk_read_support(sl))
456 + SLAVE_CONVERT_TRIGGERED(sl) = -1;
459 + if (strong_pullup) { /* some device need pullup */
460 + sleep_rem = msleep_interruptible(t_conv);
461 + if (sleep_rem != 0) {
465 + mutex_unlock(&dev_master->bus_mutex);
467 + mutex_unlock(&dev_master->bus_mutex);
468 + sleep_rem = msleep_interruptible(t_conv);
469 + if (sleep_rem != 0) {
480 + mutex_unlock(&dev_master->bus_mutex);
482 + /* set a flag to register convsersion is done */
483 + list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
484 + if (bulk_read_support(sl))
485 + SLAVE_CONVERT_TRIGGERED(sl) = 1;
491 /* Sysfs Interface definition */
493 static ssize_t w1_slave_show(struct device *device,
494 @@ -1095,7 +1273,20 @@ static ssize_t w1_slave_show(struct devi
496 ssize_t c = PAGE_SIZE;
498 - ret = convert_t(sl, &info);
499 + if (bulk_read_support(sl)) {
500 + if (SLAVE_CONVERT_TRIGGERED(sl) < 0) {
502 + "%s: Conversion in progress, retry later\n",
505 + } else if (SLAVE_CONVERT_TRIGGERED(sl) > 0) {
506 + /* A bulk read has been issued, read the device RAM */
507 + ret = read_scratchpad(sl, &info);
508 + SLAVE_CONVERT_TRIGGERED(sl) = 0;
510 + ret = convert_t(sl, &info);
512 + ret = convert_t(sl, &info);
516 @@ -1176,7 +1367,20 @@ static ssize_t temperature_show(struct d
517 return 0; /* No device family */
520 - ret = convert_t(sl, &info);
521 + if (bulk_read_support(sl)) {
522 + if (SLAVE_CONVERT_TRIGGERED(sl) < 0) {
524 + "%s: Conversion in progress, retry later\n",
527 + } else if (SLAVE_CONVERT_TRIGGERED(sl) > 0) {
528 + /* A bulk read has been issued, read the device RAM */
529 + ret = read_scratchpad(sl, &info);
530 + SLAVE_CONVERT_TRIGGERED(sl) = 0;
532 + ret = convert_t(sl, &info);
534 + ret = convert_t(sl, &info);
538 @@ -1412,6 +1616,49 @@ free_m:
542 +static ssize_t therm_bulk_read_store(struct device *device,
543 + struct device_attribute *attr, const char *buf, size_t size)
545 + struct w1_master *dev_master = dev_to_w1_master(device);
546 + int ret = -EINVAL; /* Invalid argument */
548 + if (size == sizeof(BULK_TRIGGER_CMD))
549 + if (!strncmp(buf, BULK_TRIGGER_CMD,
550 + sizeof(BULK_TRIGGER_CMD)-1))
551 + ret = trigger_bulk_read(dev_master);
555 + "%s: unable to trigger a bulk read on the bus. err=%d\n",
561 +static ssize_t therm_bulk_read_show(struct device *device,
562 + struct device_attribute *attr, char *buf)
564 + struct w1_master *dev_master = dev_to_w1_master(device);
565 + struct w1_slave *sl = NULL;
568 + list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
569 + if (sl->family_data) {
570 + if (bulk_read_support(sl)) {
571 + if (SLAVE_CONVERT_TRIGGERED(sl) == -1) {
575 + if (SLAVE_CONVERT_TRIGGERED(sl) == 1)
576 + /* continue to check other slaves */
582 + return sprintf(buf, "%d\n", ret);
585 #if IS_REACHABLE(CONFIG_HWMON)
586 static int w1_read_temp(struct device *device, u32 attr, int channel,