Skip to content

Commit 79bbb18

Browse files
yc-hou-0919jamess-huang
authored andcommitted
Add resolution attribute w1_res for ds18b20
The values: 00 : 9bit, conversion time 93.75ms 01 : 10bit, conversion time 187.5ms 10 : 11bit, conversion time 375ms 11 : 12bit, conversion time 750ms Ex: # change resolution to 10 bit echo 1 > /sys/bus/w1/devices/28-04167526d7ff/w1_res Change-Id: I141cec8ed9ecbac7eb766579f5c28baa0ccbfd03 Reviewed-on: https://tp-biosrd-v02/gerrit/82969 Reviewed-by: Jamess Huang(黃以民) <Jamess_Huang@asus.com> Tested-by: Jamess Huang(黃以民) <Jamess_Huang@asus.com>
1 parent 257dc8f commit 79bbb18

2 files changed

Lines changed: 151 additions & 0 deletions

File tree

drivers/w1/slaves/w1_therm.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/types.h>
3030
#include <linux/slab.h>
3131
#include <linux/delay.h>
32+
#include <linux/uaccess.h>
3233

3334
#include "../w1.h"
3435
#include "../w1_int.h"
@@ -59,6 +60,9 @@ MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00));
5960
static int w1_strong_pullup = 1;
6061
module_param_named(strong_pullup, w1_strong_pullup, int, 0);
6162

63+
/* resolution of ds18b20, use for temperture convert */
64+
static int w1_ds18b20_res = 3;
65+
6266
struct w1_therm_family_data {
6367
uint8_t rom[9];
6468
atomic_t refcnt;
@@ -95,11 +99,19 @@ static ssize_t w1_slave_show(struct device *device,
9599
static ssize_t w1_seq_show(struct device *device,
96100
struct device_attribute *attr, char *buf);
97101

102+
static ssize_t w1_res_show(struct device *device,
103+
struct device_attribute *attr, char *buf);
104+
105+
static ssize_t w1_res_store(struct device *device,
106+
struct device_attribute *attr, const char *buf, size_t count);
107+
98108
static DEVICE_ATTR_RO(w1_slave);
99109
static DEVICE_ATTR_RO(w1_seq);
110+
static DEVICE_ATTR_RW(w1_res);
100111

101112
static struct attribute *w1_therm_attrs[] = {
102113
&dev_attr_w1_slave.attr,
114+
&dev_attr_w1_res.attr,
103115
NULL,
104116
};
105117

@@ -416,6 +428,144 @@ static ssize_t w1_seq_show(struct device *device,
416428
return -EIO;
417429
}
418430

431+
static ssize_t w1_res_show(struct device *device,
432+
struct device_attribute *attr, char *buf)
433+
{
434+
struct w1_slave *sl = dev_to_w1_slave(device);
435+
struct w1_master *dev = sl->master;
436+
u8 rom[9], crc, verdict;
437+
int res, ret, max_trying = 10, count = 0;
438+
u8 *family_data = sl->family_data;
439+
440+
ret = mutex_lock_interruptible(&dev->bus_mutex);
441+
if (ret != 0)
442+
goto post_unlock;
443+
444+
if(!sl->family_data)
445+
{
446+
ret = -ENODEV;
447+
goto pre_unlock;
448+
}
449+
450+
/* prevent the slave from going away in sleep */
451+
atomic_inc(THERM_REFCNT(family_data));
452+
memset(rom, 0, sizeof(rom));
453+
454+
while (max_trying--) {
455+
verdict = 0;
456+
crc = 0 ;
457+
458+
if (!w1_reset_select_slave(sl)) {
459+
w1_write_8(dev, W1_READ_SCRATCHPAD);
460+
if ((count = w1_read_block(dev, rom, 9)) != 9) {
461+
dev_warn(device, "w1_read_block() "
462+
"returned %u instead of 9.\n",
463+
count);
464+
}
465+
466+
crc = w1_calc_crc8(rom, 8);
467+
468+
if (rom[8] == crc)
469+
verdict = 1;
470+
}
471+
472+
if (verdict)
473+
break;
474+
}
475+
476+
res = (rom[4] & 0x60) >> 5;
477+
ret = sprintf(buf, "Resolution is %d\n", res);
478+
479+
pre_unlock:
480+
mutex_unlock(&dev->bus_mutex);
481+
482+
post_unlock:
483+
atomic_dec(THERM_REFCNT(family_data));
484+
return ret;
485+
}
486+
487+
static ssize_t w1_res_store(struct device *device,
488+
struct device_attribute *attr, const char *buf, size_t count)
489+
{
490+
struct w1_slave *sl = dev_to_w1_slave(device);
491+
struct w1_master *dev = sl->master;
492+
u8 rom[9], crc, verdict;
493+
int ret, max_trying = 10, val, res;
494+
u8 *family_data = sl->family_data;
495+
496+
ret = mutex_lock_interruptible(&dev->bus_mutex);
497+
if (ret != 0)
498+
goto post_unlock;
499+
500+
if(!sl->family_data)
501+
{
502+
ret = -ENODEV;
503+
goto pre_unlock;
504+
}
505+
506+
/* prevent the slave from going away in sleep */
507+
atomic_inc(THERM_REFCNT(family_data));
508+
memset(rom, 0, sizeof(rom));
509+
510+
while (max_trying--) {
511+
verdict = 0;
512+
crc = 0;
513+
514+
if (!w1_reset_select_slave(sl)) {
515+
w1_write_8(dev, W1_READ_SCRATCHPAD);
516+
if ((count = w1_read_block(dev, rom, 9)) != 9) {
517+
dev_warn(device, "w1_read_block() "
518+
"returned %u instead of 9.\n",
519+
count);
520+
}
521+
522+
crc = w1_calc_crc8(rom, 8);
523+
524+
if (rom[8] == crc)
525+
verdict = 1;
526+
}
527+
528+
if (verdict)
529+
break;
530+
}
531+
532+
res = (rom[4] & 0x60) >> 5;
533+
534+
ret = kstrtoint(buf, 10, &val);
535+
if (ret)
536+
{
537+
ret = -EINVAL;
538+
goto pre_unlock;
539+
}
540+
541+
if (val == res)
542+
{
543+
dev_warn(device, "w1_res_store() "
544+
"the same resolution setting! ignore\n");
545+
goto pre_unlock;
546+
}
547+
else
548+
res = val;
549+
550+
rom[4] &= 0x9f;
551+
rom[4] |= (res << 5);
552+
553+
if (!w1_reset_select_slave(sl)) {
554+
w1_write_8(dev, W1_WRITE_SCRATCHPAD);
555+
w1_write_block(dev, rom+2, 3);
556+
}
557+
558+
w1_ds18b20_res = res;
559+
560+
pre_unlock:
561+
mutex_unlock(&dev->bus_mutex);
562+
563+
post_unlock:
564+
atomic_dec(THERM_REFCNT(family_data));
565+
566+
return sizeof(w1_ds18b20_res);
567+
}
568+
419569
static int __init w1_therm_init(void)
420570
{
421571
int err, i;

drivers/w1/w1.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct w1_reg_num
6363
#define W1_READ_PSUPPLY 0xB4
6464
#define W1_MATCH_ROM 0x55
6565
#define W1_RESUME_CMD 0xA5
66+
#define W1_WRITE_SCRATCHPAD 0x4E
6667

6768
#define W1_SLAVE_ACTIVE 0
6869
#define W1_SLAVE_DETACH 1

0 commit comments

Comments
 (0)