summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/stable/sysfs-driver-w1_ds28ea006
-rw-r--r--Documentation/w1/slaves/w1_therm11
-rw-r--r--drivers/w1/slaves/w1_therm.c102
3 files changed, 117 insertions, 2 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 b/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00
new file mode 100644
index 000000000000..e928def14f28
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00
@@ -0,0 +1,6 @@
1What: /sys/bus/w1/devices/.../w1_seq
2Date: Apr 2015
3Contact: Matt Campbell <mattrcampbell@gmail.com>
4Description: Support for the DS28EA00 chain sequence function
5 see Documentation/w1/slaves/w1_therm for detailed information
6Users: any user space application which wants to communicate with DS28EA00
diff --git a/Documentation/w1/slaves/w1_therm b/Documentation/w1/slaves/w1_therm
index cc62a95e4776..13411fe52f7f 100644
--- a/Documentation/w1/slaves/w1_therm
+++ b/Documentation/w1/slaves/w1_therm
@@ -11,12 +11,14 @@ Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
11Description 11Description
12----------- 12-----------
13 13
14w1_therm provides basic temperature conversion for ds18*20 devices. 14w1_therm provides basic temperature conversion for ds18*20 devices, and the
15ds28ea00 device.
15supported family codes: 16supported family codes:
16W1_THERM_DS18S20 0x10 17W1_THERM_DS18S20 0x10
17W1_THERM_DS1822 0x22 18W1_THERM_DS1822 0x22
18W1_THERM_DS18B20 0x28 19W1_THERM_DS18B20 0x28
19W1_THERM_DS1825 0x3B 20W1_THERM_DS1825 0x3B
21W1_THERM_DS28EA00 0x42
20 22
21Support is provided through the sysfs w1_slave file. Each open and 23Support is provided through the sysfs w1_slave file. Each open and
22read sequence will initiate a temperature conversion then provide two 24read sequence will initiate a temperature conversion then provide two
@@ -48,3 +50,10 @@ resistor). The DS18b20 temperature sensor specification lists a
48maximum current draw of 1.5mA and that a 5k pullup resistor is not 50maximum current draw of 1.5mA and that a 5k pullup resistor is not
49sufficient. The strong pullup is designed to provide the additional 51sufficient. The strong pullup is designed to provide the additional
50current required. 52current required.
53
54The DS28EA00 provides an additional two pins for implementing a sequence
55detection algorithm. This feature allows you to determine the physical
56location of the chip in the 1-wire bus without needing pre-existing
57knowledge of the bus ordering. Support is provided through the sysfs
58w1_seq file. The file will contain a single line with an integer value
59representing the device index in the bus starting at 0.
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 55eb86c9e214..d21e6864b06f 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -92,13 +92,24 @@ static void w1_therm_remove_slave(struct w1_slave *sl)
92static ssize_t w1_slave_show(struct device *device, 92static ssize_t w1_slave_show(struct device *device,
93 struct device_attribute *attr, char *buf); 93 struct device_attribute *attr, char *buf);
94 94
95static ssize_t w1_seq_show(struct device *device,
96 struct device_attribute *attr, char *buf);
97
95static DEVICE_ATTR_RO(w1_slave); 98static DEVICE_ATTR_RO(w1_slave);
99static DEVICE_ATTR_RO(w1_seq);
96 100
97static struct attribute *w1_therm_attrs[] = { 101static struct attribute *w1_therm_attrs[] = {
98 &dev_attr_w1_slave.attr, 102 &dev_attr_w1_slave.attr,
99 NULL, 103 NULL,
100}; 104};
105
106static struct attribute *w1_ds28ea00_attrs[] = {
107 &dev_attr_w1_slave.attr,
108 &dev_attr_w1_seq.attr,
109 NULL,
110};
101ATTRIBUTE_GROUPS(w1_therm); 111ATTRIBUTE_GROUPS(w1_therm);
112ATTRIBUTE_GROUPS(w1_ds28ea00);
102 113
103static struct w1_family_ops w1_therm_fops = { 114static struct w1_family_ops w1_therm_fops = {
104 .add_slave = w1_therm_add_slave, 115 .add_slave = w1_therm_add_slave,
@@ -106,6 +117,12 @@ static struct w1_family_ops w1_therm_fops = {
106 .groups = w1_therm_groups, 117 .groups = w1_therm_groups,
107}; 118};
108 119
120static struct w1_family_ops w1_ds28ea00_fops = {
121 .add_slave = w1_therm_add_slave,
122 .remove_slave = w1_therm_remove_slave,
123 .groups = w1_ds28ea00_groups,
124};
125
109static struct w1_family w1_therm_family_DS18S20 = { 126static struct w1_family w1_therm_family_DS18S20 = {
110 .fid = W1_THERM_DS18S20, 127 .fid = W1_THERM_DS18S20,
111 .fops = &w1_therm_fops, 128 .fops = &w1_therm_fops,
@@ -123,7 +140,7 @@ static struct w1_family w1_therm_family_DS1822 = {
123 140
124static struct w1_family w1_therm_family_DS28EA00 = { 141static struct w1_family w1_therm_family_DS28EA00 = {
125 .fid = W1_THERM_DS28EA00, 142 .fid = W1_THERM_DS28EA00,
126 .fops = &w1_therm_fops, 143 .fops = &w1_ds28ea00_fops,
127}; 144};
128 145
129static struct w1_family w1_therm_family_DS1825 = { 146static struct w1_family w1_therm_family_DS1825 = {
@@ -316,6 +333,89 @@ post_unlock:
316 return ret; 333 return ret;
317} 334}
318 335
336#define W1_42_CHAIN 0x99
337#define W1_42_CHAIN_OFF 0x3C
338#define W1_42_CHAIN_OFF_INV 0xC3
339#define W1_42_CHAIN_ON 0x5A
340#define W1_42_CHAIN_ON_INV 0xA5
341#define W1_42_CHAIN_DONE 0x96
342#define W1_42_CHAIN_DONE_INV 0x69
343#define W1_42_COND_READ 0x0F
344#define W1_42_SUCCESS_CONFIRM_BYTE 0xAA
345#define W1_42_FINISHED_BYTE 0xFF
346static ssize_t w1_seq_show(struct device *device,
347 struct device_attribute *attr, char *buf)
348{
349 struct w1_slave *sl = dev_to_w1_slave(device);
350 ssize_t c = PAGE_SIZE;
351 int rv;
352 int i;
353 u8 ack;
354 u64 rn;
355 struct w1_reg_num *reg_num;
356 int seq = 0;
357
358 mutex_lock(&sl->master->mutex);
359 /* Place all devices in CHAIN state */
360 if (w1_reset_bus(sl->master))
361 goto error;
362 w1_write_8(sl->master, W1_SKIP_ROM);
363 w1_write_8(sl->master, W1_42_CHAIN);
364 w1_write_8(sl->master, W1_42_CHAIN_ON);
365 w1_write_8(sl->master, W1_42_CHAIN_ON_INV);
366 msleep(sl->master->pullup_duration);
367
368 /* check for acknowledgment */
369 ack = w1_read_8(sl->master);
370 if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
371 goto error;
372
373 /* In case the bus fails to send 0xFF, limit*/
374 for (i = 0; i <= 64; i++) {
375 if (w1_reset_bus(sl->master))
376 goto error;
377
378 w1_write_8(sl->master, W1_42_COND_READ);
379 rv = w1_read_block(sl->master, (u8 *)&rn, 8);
380 reg_num = (struct w1_reg_num *) &rn;
381 if ((char)reg_num->family == W1_42_FINISHED_BYTE)
382 break;
383 if (sl->reg_num.id == reg_num->id)
384 seq = i;
385
386 w1_write_8(sl->master, W1_42_CHAIN);
387 w1_write_8(sl->master, W1_42_CHAIN_DONE);
388 w1_write_8(sl->master, W1_42_CHAIN_DONE_INV);
389 w1_read_block(sl->master, &ack, sizeof(ack));
390
391 /* check for acknowledgment */
392 ack = w1_read_8(sl->master);
393 if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
394 goto error;
395
396 }
397
398 /* Exit from CHAIN state */
399 if (w1_reset_bus(sl->master))
400 goto error;
401 w1_write_8(sl->master, W1_SKIP_ROM);
402 w1_write_8(sl->master, W1_42_CHAIN);
403 w1_write_8(sl->master, W1_42_CHAIN_OFF);
404 w1_write_8(sl->master, W1_42_CHAIN_OFF_INV);
405
406 /* check for acknowledgment */
407 ack = w1_read_8(sl->master);
408 if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
409 goto error;
410 mutex_unlock(&sl->master->mutex);
411
412 c -= snprintf(buf + PAGE_SIZE - c, c, "%d\n", seq);
413 return PAGE_SIZE - c;
414error:
415 mutex_unlock(&sl->master->bus_mutex);
416 return -EIO;
417}
418
319static int __init w1_therm_init(void) 419static int __init w1_therm_init(void)
320{ 420{
321 int err, i; 421 int err, i;