bcm27xx: import latest patches from the RPi foundation
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0766-w1_therm-adding-code-comments-and-code-reordering.patch
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
5
6 commit 92b8d2724464bc1d2e735a84c0da5741dce33485 upstream.
7
8 Adding code comments to split code in dedicated parts. After the global
9 declarations (defines, macros and function declarations), code is organized
10 as follow :
11 - Device and family dependent structures and functions
12 - Interfaces functions
13 - Helpers functions
14 - Hardware functions
15 - Sysfs interface functions
16
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>
20 ---
21 drivers/w1/slaves/w1_therm.c | 427 +++++++++++++++++++++--------------
22 1 file changed, 259 insertions(+), 168 deletions(-)
23
24 --- a/drivers/w1/slaves/w1_therm.c
25 +++ b/drivers/w1/slaves/w1_therm.c
26 @@ -25,7 +25,8 @@
27 #define W1_THERM_DS1825 0x3B
28 #define W1_THERM_DS28EA00 0x42
29
30 -/* Allow the strong pullup to be disabled, but default to enabled.
31 +/*
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.
36 @@ -41,42 +42,55 @@
37 static int w1_strong_pullup = 1;
38 module_param_named(strong_pullup, w1_strong_pullup, int, 0);
39
40 +/* Helpers Macros */
41 +
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)
45 +
46 +/* Structs definition */
47 +
48 +/**
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
56 + */
57 +struct w1_therm_family_converter {
58 + u8 broken;
59 + u16 reserved;
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);
64 +};
65 +
66 +/**
67 + * struct w1_therm_family_data - device data
68 + * @rom: ROM device id (64bit Lasered ROM code + 1 CRC byte)
69 + * @refcnt: ref count
70 + */
71 struct w1_therm_family_data {
72 uint8_t rom[9];
73 atomic_t refcnt;
74 };
75
76 +/**
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
81 + */
82 struct therm_info {
83 u8 rom[9];
84 u8 crc;
85 u8 verdict;
86 };
87
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)
91 -
92 -static int w1_therm_add_slave(struct w1_slave *sl)
93 -{
94 - sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
95 - GFP_KERNEL);
96 - if (!sl->family_data)
97 - return -ENOMEM;
98 - atomic_set(THERM_REFCNT(sl->family_data), 1);
99 - return 0;
100 -}
101 -
102 -static void w1_therm_remove_slave(struct w1_slave *sl)
103 -{
104 - int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
105 -
106 - while (refcnt) {
107 - msleep(1000);
108 - refcnt = atomic_read(THERM_REFCNT(sl->family_data));
109 - }
110 - kfree(sl->family_data);
111 - sl->family_data = NULL;
112 -}
113 +/* Sysfs interface declaration */
114
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);
120
121 +/* Attributes declarations */
122 +
123 static DEVICE_ATTR_RW(w1_slave);
124 static DEVICE_ATTR_RO(w1_seq);
125
126 +/* Interface Functions declaration */
127 +
128 +/**
129 + * w1_therm_add_slave() - Called when a new slave is discovered
130 + * @sl: slave just discovered by the master.
131 + *
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.
134 + *
135 + * Return: 0 - If success, negative kernel code otherwise
136 + */
137 +static int w1_therm_add_slave(struct w1_slave *sl);
138 +
139 +/**
140 + * w1_therm_remove_slave() - Called when a slave is removed
141 + * @sl: slave to be removed.
142 + *
143 + * Called by the master when the slave is considered not to be on the bus
144 + * anymore. Used to free memory.
145 + */
146 +static void w1_therm_remove_slave(struct w1_slave *sl);
147 +
148 +/* Family attributes */
149 +
150 static struct attribute *w1_therm_attrs[] = {
151 &dev_attr_w1_slave.attr,
152 NULL,
153 @@ -101,6 +141,8 @@ static struct attribute *w1_ds28ea00_att
154 NULL,
155 };
156
157 +/* Attribute groups */
158 +
159 ATTRIBUTE_GROUPS(w1_therm);
160 ATTRIBUTE_GROUPS(w1_ds28ea00);
161
162 @@ -154,6 +196,8 @@ static const struct hwmon_chip_info w1_c
163 #define W1_CHIPINFO NULL
164 #endif
165
166 +/* Family operations */
167 +
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,
173 };
174
175 +/* Family binding operations struct */
176 +
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,
182 };
183
184 -struct w1_therm_family_converter {
185 - u8 broken;
186 - u16 reserved;
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);
191 -};
192 +/* Device dependent func */
193
194 /* write configuration to eeprom */
195 static inline int w1_therm_eeprom(struct device *device);
196
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);
200 -
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]);
204 -
205 -static struct w1_therm_family_converter w1_therm_families[] = {
206 - {
207 - .f = &w1_therm_family_DS18S20,
208 - .convert = w1_DS18S20_convert_temp,
209 - .precision = w1_DS18S20_precision,
210 - .eeprom = w1_therm_eeprom
211 - },
212 - {
213 - .f = &w1_therm_family_DS1822,
214 - .convert = w1_DS18B20_convert_temp,
215 - .precision = w1_DS18S20_precision,
216 - .eeprom = w1_therm_eeprom
217 - },
218 - {
219 - .f = &w1_therm_family_DS18B20,
220 - .convert = w1_DS18B20_convert_temp,
221 - .precision = w1_DS18B20_precision,
222 - .eeprom = w1_therm_eeprom
223 - },
224 - {
225 - .f = &w1_therm_family_DS28EA00,
226 - .convert = w1_DS18B20_convert_temp,
227 - .precision = w1_DS18S20_precision,
228 - .eeprom = w1_therm_eeprom
229 - },
230 - {
231 - .f = &w1_therm_family_DS1825,
232 - .convert = w1_DS18B20_convert_temp,
233 - .precision = w1_DS18S20_precision,
234 - .eeprom = w1_therm_eeprom
235 - }
236 -};
237 -
238 -static inline int w1_therm_eeprom(struct device *device)
239 -{
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;
245 -
246 - if (!sl->family_data) {
247 - ret = -ENODEV;
248 - goto error;
249 - }
250 -
251 - /* prevent the slave from going away in sleep */
252 - atomic_inc(THERM_REFCNT(family_data));
253 -
254 - ret = mutex_lock_interruptible(&dev->bus_mutex);
255 - if (ret != 0)
256 - goto dec_refcnt;
257 -
258 - memset(rom, 0, sizeof(rom));
259 -
260 - while (max_trying--) {
261 - if (!w1_reset_select_slave(sl)) {
262 - unsigned int tm = 10;
263 - unsigned long sleep_rem;
264 -
265 - /* check if in parasite mode */
266 - w1_write_8(dev, W1_READ_PSUPPLY);
267 - external_power = w1_read_8(dev);
268 -
269 - if (w1_reset_select_slave(sl))
270 - continue;
271 -
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);
276 -
277 - w1_write_8(dev, W1_COPY_SCRATCHPAD);
278 -
279 - if (external_power) {
280 - mutex_unlock(&dev->bus_mutex);
281 -
282 - sleep_rem = msleep_interruptible(tm);
283 - if (sleep_rem != 0) {
284 - ret = -EINTR;
285 - goto dec_refcnt;
286 - }
287 -
288 - ret = mutex_lock_interruptible(&dev->bus_mutex);
289 - if (ret != 0)
290 - goto dec_refcnt;
291 - } else if (!w1_strong_pullup) {
292 - sleep_rem = msleep_interruptible(tm);
293 - if (sleep_rem != 0) {
294 - ret = -EINTR;
295 - goto mt_unlock;
296 - }
297 - }
298 -
299 - break;
300 - }
301 - }
302 -
303 -mt_unlock:
304 - mutex_unlock(&dev->bus_mutex);
305 -dec_refcnt:
306 - atomic_dec(THERM_REFCNT(family_data));
307 -error:
308 - return ret;
309 -}
310 -
311 /* DS18S20 does not feature configuration register */
312 static inline int w1_DS18S20_precision(struct device *device, int val)
313 {
314 return 0;
315 }
316
317 +/* Set precision for conversion */
318 static inline int w1_DS18B20_precision(struct device *device, int val)
319 {
320 struct w1_slave *sl = dev_to_w1_slave(device);
321 @@ -407,6 +333,14 @@ error:
322 return ret;
323 }
324
325 +/**
326 + * w1_DS18B20_convert_temp() - temperature computation for DS18B20
327 + * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
328 + *
329 + * Can be called for any DS18B20 compliant device.
330 + *
331 + * Return: value in millidegrees Celsius.
332 + */
333 static inline int w1_DS18B20_convert_temp(u8 rom[9])
334 {
335 s16 t = le16_to_cpup((__le16 *)rom);
336 @@ -414,6 +348,14 @@ static inline int w1_DS18B20_convert_tem
337 return t*1000/16;
338 }
339
340 +/**
341 + * w1_DS18S20_convert_temp() - temperature computation for DS18S20
342 + * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
343 + *
344 + * Can be called for any DS18S20 compliant device.
345 + *
346 + * Return: value in millidegrees Celsius.
347 + */
348 static inline int w1_DS18S20_convert_temp(u8 rom[9])
349 {
350 int t, h;
351 @@ -434,6 +376,53 @@ static inline int w1_DS18S20_convert_tem
352 return t;
353 }
354
355 +/* Device capability description */
356 +
357 +static struct w1_therm_family_converter w1_therm_families[] = {
358 + {
359 + .f = &w1_therm_family_DS18S20,
360 + .convert = w1_DS18S20_convert_temp,
361 + .precision = w1_DS18S20_precision,
362 + .eeprom = w1_therm_eeprom
363 + },
364 + {
365 + .f = &w1_therm_family_DS1822,
366 + .convert = w1_DS18B20_convert_temp,
367 + .precision = w1_DS18S20_precision,
368 + .eeprom = w1_therm_eeprom
369 + },
370 + {
371 + .f = &w1_therm_family_DS18B20,
372 + .convert = w1_DS18B20_convert_temp,
373 + .precision = w1_DS18B20_precision,
374 + .eeprom = w1_therm_eeprom
375 + },
376 + {
377 + .f = &w1_therm_family_DS28EA00,
378 + .convert = w1_DS18B20_convert_temp,
379 + .precision = w1_DS18S20_precision,
380 + .eeprom = w1_therm_eeprom
381 + },
382 + {
383 + .f = &w1_therm_family_DS1825,
384 + .convert = w1_DS18B20_convert_temp,
385 + .precision = w1_DS18S20_precision,
386 + .eeprom = w1_therm_eeprom
387 + }
388 +};
389 +
390 +/* Helpers Functions */
391 +
392 +/**
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
396 + *
397 + * The function call the temperature computation function according to
398 + * device family.
399 + *
400 + * Return: value in millidegrees Celsius.
401 + */
402 static inline int w1_convert_temp(u8 rom[9], u8 fid)
403 {
404 int i;
405 @@ -445,31 +434,32 @@ static inline int w1_convert_temp(u8 rom
406 return 0;
407 }
408
409 -static ssize_t w1_slave_store(struct device *device,
410 - struct device_attribute *attr, const char *buf,
411 - size_t size)
412 +/* Interface Functions */
413 +
414 +static int w1_therm_add_slave(struct w1_slave *sl)
415 {
416 - int val, ret;
417 - struct w1_slave *sl = dev_to_w1_slave(device);
418 - int i;
419 + sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
420 + GFP_KERNEL);
421 + if (!sl->family_data)
422 + return -ENOMEM;
423 + atomic_set(THERM_REFCNT(sl->family_data), 1);
424 + return 0;
425 +}
426
427 - ret = kstrtoint(buf, 0, &val);
428 - if (ret)
429 - return ret;
430 +static void w1_therm_remove_slave(struct w1_slave *sl)
431 +{
432 + int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
433
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 */
437 - if (val == 0)
438 - ret = w1_therm_families[i].eeprom(device);
439 - else
440 - ret = w1_therm_families[i].precision(device, val);
441 - break;
442 - }
443 + while (refcnt) {
444 + msleep(1000);
445 + refcnt = atomic_read(THERM_REFCNT(sl->family_data));
446 }
447 - return ret ? : size;
448 + kfree(sl->family_data);
449 + sl->family_data = NULL;
450 }
451
452 +/* Hardware Functions */
453 +
454 static ssize_t read_therm(struct device *device,
455 struct w1_slave *sl, struct therm_info *info)
456 {
457 @@ -564,6 +554,81 @@ error:
458 return ret;
459 }
460
461 +static inline int w1_therm_eeprom(struct device *device)
462 +{
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;
468 +
469 + if (!sl->family_data) {
470 + ret = -ENODEV;
471 + goto error;
472 + }
473 +
474 + /* prevent the slave from going away in sleep */
475 + atomic_inc(THERM_REFCNT(family_data));
476 +
477 + ret = mutex_lock_interruptible(&dev->bus_mutex);
478 + if (ret != 0)
479 + goto dec_refcnt;
480 +
481 + memset(rom, 0, sizeof(rom));
482 +
483 + while (max_trying--) {
484 + if (!w1_reset_select_slave(sl)) {
485 + unsigned int tm = 10;
486 + unsigned long sleep_rem;
487 +
488 + /* check if in parasite mode */
489 + w1_write_8(dev, W1_READ_PSUPPLY);
490 + external_power = w1_read_8(dev);
491 +
492 + if (w1_reset_select_slave(sl))
493 + continue;
494 +
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);
499 +
500 + w1_write_8(dev, W1_COPY_SCRATCHPAD);
501 +
502 + if (external_power) {
503 + mutex_unlock(&dev->bus_mutex);
504 +
505 + sleep_rem = msleep_interruptible(tm);
506 + if (sleep_rem != 0) {
507 + ret = -EINTR;
508 + goto dec_refcnt;
509 + }
510 +
511 + ret = mutex_lock_interruptible(&dev->bus_mutex);
512 + if (ret != 0)
513 + goto dec_refcnt;
514 + } else if (!w1_strong_pullup) {
515 + sleep_rem = msleep_interruptible(tm);
516 + if (sleep_rem != 0) {
517 + ret = -EINTR;
518 + goto mt_unlock;
519 + }
520 + }
521 +
522 + break;
523 + }
524 + }
525 +
526 +mt_unlock:
527 + mutex_unlock(&dev->bus_mutex);
528 +dec_refcnt:
529 + atomic_dec(THERM_REFCNT(family_data));
530 +error:
531 + return ret;
532 +}
533 +
534 +/* Sysfs Interface definition */
535 +
536 static ssize_t w1_slave_show(struct device *device,
537 struct device_attribute *attr, char *buf)
538 {
539 @@ -597,6 +662,32 @@ static ssize_t w1_slave_show(struct devi
540 return ret;
541 }
542
543 +static ssize_t w1_slave_store(struct device *device,
544 + struct device_attribute *attr, const char *buf,
545 + size_t size)
546 +{
547 + int val, ret;
548 + struct w1_slave *sl = dev_to_w1_slave(device);
549 + int i;
550 +
551 + ret = kstrtoint(buf, 0, &val);
552 + if (ret)
553 + return ret;
554 +
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 */
558 + if (val == 0)
559 + ret = w1_therm_families[i].eeprom(device);
560 + else
561 + ret = w1_therm_families[i].precision(device,
562 + val);
563 + break;
564 + }
565 + }
566 + return ret ? : size;
567 +}
568 +
569 #if IS_REACHABLE(CONFIG_HWMON)
570 static int w1_read_temp(struct device *device, u32 attr, int channel,
571 long *val)
572 @@ -666,7 +757,7 @@ static ssize_t w1_seq_show(struct device
573 if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
574 goto error;
575
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))
580 goto error;