aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1')
-rw-r--r--drivers/w1/slaves/w1_therm.c102
1 files changed, 101 insertions, 1 deletions
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;