1 From 7c49e87acd0412ff1fb2490c4ac6fcb5471afd9b Mon Sep 17 00:00:00 2001
2 From: Akira Shimahara <akira215corp@gmail.com>
3 Date: Mon, 11 May 2020 22:35:35 +0200
4 Subject: [PATCH] w1_therm: adding code comments and code reordering
6 commit 92b8d2724464bc1d2e735a84c0da5741dce33485 upstream.
8 Adding code comments to split code in dedicated parts. After the global
9 declarations (defines, macros and function declarations), code is organized
11 - Device and family dependent structures and functions
12 - Interfaces functions
15 - Sysfs interface functions
17 Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
18 Link: https://lore.kernel.org/r/20200511203535.409599-1-akira215corp@gmail.com
19 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
21 drivers/w1/slaves/w1_therm.c | 427 +++++++++++++++++++++--------------
22 1 file changed, 259 insertions(+), 168 deletions(-)
24 --- a/drivers/w1/slaves/w1_therm.c
25 +++ b/drivers/w1/slaves/w1_therm.c
27 #define W1_THERM_DS1825 0x3B
28 #define W1_THERM_DS28EA00 0x42
30 -/* Allow the strong pullup to be disabled, but default to enabled.
32 + * Allow the strong pullup to be disabled, but default to enabled.
33 * If it was disabled a parasite powered device might not get the require
34 * current to do a temperature conversion. If it is enabled parasite powered
35 * devices have a better chance of getting the current required.
37 static int w1_strong_pullup = 1;
38 module_param_named(strong_pullup, w1_strong_pullup, int, 0);
42 +/* return the address of the refcnt in the family data */
43 +#define THERM_REFCNT(family_data) \
44 + (&((struct w1_therm_family_data *)family_data)->refcnt)
46 +/* Structs definition */
49 + * struct w1_therm_family_converter - bind device specific functions
50 + * @broken: flag for non-registred families
51 + * @reserved: not used here
52 + * @f: pointer to the device binding structure
53 + * @convert: pointer to the device conversion function
54 + * @precision: pointer to the device precision function
55 + * @eeprom: pointer to eeprom function
57 +struct w1_therm_family_converter {
60 + struct w1_family *f;
61 + int (*convert)(u8 rom[9]);
62 + int (*precision)(struct device *device, int val);
63 + int (*eeprom)(struct device *device);
67 + * struct w1_therm_family_data - device data
68 + * @rom: ROM device id (64bit Lasered ROM code + 1 CRC byte)
69 + * @refcnt: ref count
71 struct w1_therm_family_data {
77 + * struct therm_info - store temperature reading
78 + * @rom: read device data (8 data bytes + 1 CRC byte)
79 + * @crc: computed crc from rom
80 + * @verdict: 1 crc checked, 0 crc not matching
88 -/* return the address of the refcnt in the family data */
89 -#define THERM_REFCNT(family_data) \
90 - (&((struct w1_therm_family_data *)family_data)->refcnt)
92 -static int w1_therm_add_slave(struct w1_slave *sl)
94 - sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
96 - if (!sl->family_data)
98 - atomic_set(THERM_REFCNT(sl->family_data), 1);
102 -static void w1_therm_remove_slave(struct w1_slave *sl)
104 - int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
108 - refcnt = atomic_read(THERM_REFCNT(sl->family_data));
110 - kfree(sl->family_data);
111 - sl->family_data = NULL;
113 +/* Sysfs interface declaration */
115 static ssize_t w1_slave_show(struct device *device,
116 struct device_attribute *attr, char *buf);
117 @@ -87,9 +101,35 @@ static ssize_t w1_slave_store(struct dev
118 static ssize_t w1_seq_show(struct device *device,
119 struct device_attribute *attr, char *buf);
121 +/* Attributes declarations */
123 static DEVICE_ATTR_RW(w1_slave);
124 static DEVICE_ATTR_RO(w1_seq);
126 +/* Interface Functions declaration */
129 + * w1_therm_add_slave() - Called when a new slave is discovered
130 + * @sl: slave just discovered by the master.
132 + * Called by the master when the slave is discovered on the bus. Used to
133 + * initialize slave state before the beginning of any communication.
135 + * Return: 0 - If success, negative kernel code otherwise
137 +static int w1_therm_add_slave(struct w1_slave *sl);
140 + * w1_therm_remove_slave() - Called when a slave is removed
141 + * @sl: slave to be removed.
143 + * Called by the master when the slave is considered not to be on the bus
144 + * anymore. Used to free memory.
146 +static void w1_therm_remove_slave(struct w1_slave *sl);
148 +/* Family attributes */
150 static struct attribute *w1_therm_attrs[] = {
151 &dev_attr_w1_slave.attr,
153 @@ -101,6 +141,8 @@ static struct attribute *w1_ds28ea00_att
157 +/* Attribute groups */
159 ATTRIBUTE_GROUPS(w1_therm);
160 ATTRIBUTE_GROUPS(w1_ds28ea00);
162 @@ -154,6 +196,8 @@ static const struct hwmon_chip_info w1_c
163 #define W1_CHIPINFO NULL
166 +/* Family operations */
168 static struct w1_family_ops w1_therm_fops = {
169 .add_slave = w1_therm_add_slave,
170 .remove_slave = w1_therm_remove_slave,
171 @@ -168,6 +212,8 @@ static struct w1_family_ops w1_ds28ea00_
172 .chip_info = W1_CHIPINFO,
175 +/* Family binding operations struct */
177 static struct w1_family w1_therm_family_DS18S20 = {
178 .fid = W1_THERM_DS18S20,
179 .fops = &w1_therm_fops,
180 @@ -193,138 +239,18 @@ static struct w1_family w1_therm_family_
181 .fops = &w1_therm_fops,
184 -struct w1_therm_family_converter {
187 - struct w1_family *f;
188 - int (*convert)(u8 rom[9]);
189 - int (*precision)(struct device *device, int val);
190 - int (*eeprom)(struct device *device);
192 +/* Device dependent func */
194 /* write configuration to eeprom */
195 static inline int w1_therm_eeprom(struct device *device);
197 -/* Set precision for conversion */
198 -static inline int w1_DS18B20_precision(struct device *device, int val);
199 -static inline int w1_DS18S20_precision(struct device *device, int val);
201 -/* The return value is millidegrees Centigrade. */
202 -static inline int w1_DS18B20_convert_temp(u8 rom[9]);
203 -static inline int w1_DS18S20_convert_temp(u8 rom[9]);
205 -static struct w1_therm_family_converter w1_therm_families[] = {
207 - .f = &w1_therm_family_DS18S20,
208 - .convert = w1_DS18S20_convert_temp,
209 - .precision = w1_DS18S20_precision,
210 - .eeprom = w1_therm_eeprom
213 - .f = &w1_therm_family_DS1822,
214 - .convert = w1_DS18B20_convert_temp,
215 - .precision = w1_DS18S20_precision,
216 - .eeprom = w1_therm_eeprom
219 - .f = &w1_therm_family_DS18B20,
220 - .convert = w1_DS18B20_convert_temp,
221 - .precision = w1_DS18B20_precision,
222 - .eeprom = w1_therm_eeprom
225 - .f = &w1_therm_family_DS28EA00,
226 - .convert = w1_DS18B20_convert_temp,
227 - .precision = w1_DS18S20_precision,
228 - .eeprom = w1_therm_eeprom
231 - .f = &w1_therm_family_DS1825,
232 - .convert = w1_DS18B20_convert_temp,
233 - .precision = w1_DS18S20_precision,
234 - .eeprom = w1_therm_eeprom
238 -static inline int w1_therm_eeprom(struct device *device)
240 - struct w1_slave *sl = dev_to_w1_slave(device);
241 - struct w1_master *dev = sl->master;
242 - u8 rom[9], external_power;
243 - int ret, max_trying = 10;
244 - u8 *family_data = sl->family_data;
246 - if (!sl->family_data) {
251 - /* prevent the slave from going away in sleep */
252 - atomic_inc(THERM_REFCNT(family_data));
254 - ret = mutex_lock_interruptible(&dev->bus_mutex);
258 - memset(rom, 0, sizeof(rom));
260 - while (max_trying--) {
261 - if (!w1_reset_select_slave(sl)) {
262 - unsigned int tm = 10;
263 - unsigned long sleep_rem;
265 - /* check if in parasite mode */
266 - w1_write_8(dev, W1_READ_PSUPPLY);
267 - external_power = w1_read_8(dev);
269 - if (w1_reset_select_slave(sl))
272 - /* 10ms strong pullup/delay after the copy command */
273 - if (w1_strong_pullup == 2 ||
274 - (!external_power && w1_strong_pullup))
275 - w1_next_pullup(dev, tm);
277 - w1_write_8(dev, W1_COPY_SCRATCHPAD);
279 - if (external_power) {
280 - mutex_unlock(&dev->bus_mutex);
282 - sleep_rem = msleep_interruptible(tm);
283 - if (sleep_rem != 0) {
288 - ret = mutex_lock_interruptible(&dev->bus_mutex);
291 - } else if (!w1_strong_pullup) {
292 - sleep_rem = msleep_interruptible(tm);
293 - if (sleep_rem != 0) {
304 - mutex_unlock(&dev->bus_mutex);
306 - atomic_dec(THERM_REFCNT(family_data));
311 /* DS18S20 does not feature configuration register */
312 static inline int w1_DS18S20_precision(struct device *device, int val)
317 +/* Set precision for conversion */
318 static inline int w1_DS18B20_precision(struct device *device, int val)
320 struct w1_slave *sl = dev_to_w1_slave(device);
321 @@ -407,6 +333,14 @@ error:
326 + * w1_DS18B20_convert_temp() - temperature computation for DS18B20
327 + * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
329 + * Can be called for any DS18B20 compliant device.
331 + * Return: value in millidegrees Celsius.
333 static inline int w1_DS18B20_convert_temp(u8 rom[9])
335 s16 t = le16_to_cpup((__le16 *)rom);
336 @@ -414,6 +348,14 @@ static inline int w1_DS18B20_convert_tem
341 + * w1_DS18S20_convert_temp() - temperature computation for DS18S20
342 + * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
344 + * Can be called for any DS18S20 compliant device.
346 + * Return: value in millidegrees Celsius.
348 static inline int w1_DS18S20_convert_temp(u8 rom[9])
351 @@ -434,6 +376,53 @@ static inline int w1_DS18S20_convert_tem
355 +/* Device capability description */
357 +static struct w1_therm_family_converter w1_therm_families[] = {
359 + .f = &w1_therm_family_DS18S20,
360 + .convert = w1_DS18S20_convert_temp,
361 + .precision = w1_DS18S20_precision,
362 + .eeprom = w1_therm_eeprom
365 + .f = &w1_therm_family_DS1822,
366 + .convert = w1_DS18B20_convert_temp,
367 + .precision = w1_DS18S20_precision,
368 + .eeprom = w1_therm_eeprom
371 + .f = &w1_therm_family_DS18B20,
372 + .convert = w1_DS18B20_convert_temp,
373 + .precision = w1_DS18B20_precision,
374 + .eeprom = w1_therm_eeprom
377 + .f = &w1_therm_family_DS28EA00,
378 + .convert = w1_DS18B20_convert_temp,
379 + .precision = w1_DS18S20_precision,
380 + .eeprom = w1_therm_eeprom
383 + .f = &w1_therm_family_DS1825,
384 + .convert = w1_DS18B20_convert_temp,
385 + .precision = w1_DS18S20_precision,
386 + .eeprom = w1_therm_eeprom
390 +/* Helpers Functions */
393 + * w1_convert_temp() - temperature conversion binding function
394 + * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
395 + * @fid: device family id
397 + * The function call the temperature computation function according to
400 + * Return: value in millidegrees Celsius.
402 static inline int w1_convert_temp(u8 rom[9], u8 fid)
405 @@ -445,31 +434,32 @@ static inline int w1_convert_temp(u8 rom
409 -static ssize_t w1_slave_store(struct device *device,
410 - struct device_attribute *attr, const char *buf,
412 +/* Interface Functions */
414 +static int w1_therm_add_slave(struct w1_slave *sl)
417 - struct w1_slave *sl = dev_to_w1_slave(device);
419 + sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
421 + if (!sl->family_data)
423 + atomic_set(THERM_REFCNT(sl->family_data), 1);
427 - ret = kstrtoint(buf, 0, &val);
430 +static void w1_therm_remove_slave(struct w1_slave *sl)
432 + int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
434 - for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
435 - if (w1_therm_families[i].f->fid == sl->family->fid) {
436 - /* zero value indicates to write current configuration to eeprom */
438 - ret = w1_therm_families[i].eeprom(device);
440 - ret = w1_therm_families[i].precision(device, val);
445 + refcnt = atomic_read(THERM_REFCNT(sl->family_data));
447 - return ret ? : size;
448 + kfree(sl->family_data);
449 + sl->family_data = NULL;
452 +/* Hardware Functions */
454 static ssize_t read_therm(struct device *device,
455 struct w1_slave *sl, struct therm_info *info)
457 @@ -564,6 +554,81 @@ error:
461 +static inline int w1_therm_eeprom(struct device *device)
463 + struct w1_slave *sl = dev_to_w1_slave(device);
464 + struct w1_master *dev = sl->master;
465 + u8 rom[9], external_power;
466 + int ret, max_trying = 10;
467 + u8 *family_data = sl->family_data;
469 + if (!sl->family_data) {
474 + /* prevent the slave from going away in sleep */
475 + atomic_inc(THERM_REFCNT(family_data));
477 + ret = mutex_lock_interruptible(&dev->bus_mutex);
481 + memset(rom, 0, sizeof(rom));
483 + while (max_trying--) {
484 + if (!w1_reset_select_slave(sl)) {
485 + unsigned int tm = 10;
486 + unsigned long sleep_rem;
488 + /* check if in parasite mode */
489 + w1_write_8(dev, W1_READ_PSUPPLY);
490 + external_power = w1_read_8(dev);
492 + if (w1_reset_select_slave(sl))
495 + /* 10ms strong pullup/delay after the copy command */
496 + if (w1_strong_pullup == 2 ||
497 + (!external_power && w1_strong_pullup))
498 + w1_next_pullup(dev, tm);
500 + w1_write_8(dev, W1_COPY_SCRATCHPAD);
502 + if (external_power) {
503 + mutex_unlock(&dev->bus_mutex);
505 + sleep_rem = msleep_interruptible(tm);
506 + if (sleep_rem != 0) {
511 + ret = mutex_lock_interruptible(&dev->bus_mutex);
514 + } else if (!w1_strong_pullup) {
515 + sleep_rem = msleep_interruptible(tm);
516 + if (sleep_rem != 0) {
527 + mutex_unlock(&dev->bus_mutex);
529 + atomic_dec(THERM_REFCNT(family_data));
534 +/* Sysfs Interface definition */
536 static ssize_t w1_slave_show(struct device *device,
537 struct device_attribute *attr, char *buf)
539 @@ -597,6 +662,32 @@ static ssize_t w1_slave_show(struct devi
543 +static ssize_t w1_slave_store(struct device *device,
544 + struct device_attribute *attr, const char *buf,
548 + struct w1_slave *sl = dev_to_w1_slave(device);
551 + ret = kstrtoint(buf, 0, &val);
555 + for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
556 + if (w1_therm_families[i].f->fid == sl->family->fid) {
557 + /* zero value indicates to write current configuration to eeprom */
559 + ret = w1_therm_families[i].eeprom(device);
561 + ret = w1_therm_families[i].precision(device,
566 + return ret ? : size;
569 #if IS_REACHABLE(CONFIG_HWMON)
570 static int w1_read_temp(struct device *device, u32 attr, int channel,
572 @@ -666,7 +757,7 @@ static ssize_t w1_seq_show(struct device
573 if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
576 - /* In case the bus fails to send 0xFF, limit*/
577 + /* In case the bus fails to send 0xFF, limit */
578 for (i = 0; i <= 64; i++) {
579 if (w1_reset_bus(sl->master))