aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEvgeniy Polyakov <johnpol@2ka.mipt.ru>2005-06-03 17:30:43 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-22 00:43:11 -0400
commit6b729861831177b270a2932a13e79cb41d673146 (patch)
tree443c86578d04ba42d9b4e483d6ebee91ba30d25e /drivers
parentbe57ce267fd558c52d2389530c15618681b7cfa7 (diff)
[PATCH] w1: Added the triplet w1 master method and changes w1_search() to use it.
Adds the triplet w1 master method and changes w1_search() to use it. Signed-off-by: Ben Gardner <bgardner@wabtec.com> Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/w1/w1.c138
-rw-r--r--drivers/w1/w1.h87
-rw-r--r--drivers/w1/w1_io.c43
-rw-r--r--drivers/w1/w1_io.h1
4 files changed, 175 insertions, 94 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index c85d75ed835a..4fa959f08554 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -135,7 +135,7 @@ struct device w1_device = {
135 135
136static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) 136static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
137{ 137{
138 struct w1_master *md = container_of (dev, struct w1_master, dev); 138 struct w1_master *md = container_of(dev, struct w1_master, dev);
139 ssize_t count; 139 ssize_t count;
140 140
141 if (down_interruptible (&md->mutex)) 141 if (down_interruptible (&md->mutex))
@@ -212,7 +212,6 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
212} 212}
213 213
214static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf) 214static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
215
216{ 215{
217 struct w1_master *md = container_of(dev, struct w1_master, dev); 216 struct w1_master *md = container_of(dev, struct w1_master, dev);
218 int c = PAGE_SIZE; 217 int c = PAGE_SIZE;
@@ -286,13 +285,13 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
286 sl->dev.release = &w1_slave_release; 285 sl->dev.release = &w1_slave_release;
287 286
288 snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id), 287 snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
289 "%02x-%012llx", 288 "%02x-%012llx",
290 (unsigned int) sl->reg_num.family, 289 (unsigned int) sl->reg_num.family,
291 (unsigned long long) sl->reg_num.id); 290 (unsigned long long) sl->reg_num.id);
292 snprintf (&sl->name[0], sizeof(sl->name), 291 snprintf(&sl->name[0], sizeof(sl->name),
293 "%02x-%012llx", 292 "%02x-%012llx",
294 (unsigned int) sl->reg_num.family, 293 (unsigned int) sl->reg_num.family,
295 (unsigned long long) sl->reg_num.id); 294 (unsigned long long) sl->reg_num.id);
296 295
297 dev_dbg(&sl->dev, "%s: registering %s.\n", __func__, 296 dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
298 &sl->dev.bus_id[0]); 297 &sl->dev.bus_id[0]);
@@ -300,8 +299,8 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
300 err = device_register(&sl->dev); 299 err = device_register(&sl->dev);
301 if (err < 0) { 300 if (err < 0) {
302 dev_err(&sl->dev, 301 dev_err(&sl->dev,
303 "Device registration [%s] failed. err=%d\n", 302 "Device registration [%s] failed. err=%d\n",
304 sl->dev.bus_id, err); 303 sl->dev.bus_id, err);
305 return err; 304 return err;
306 } 305 }
307 306
@@ -314,8 +313,8 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
314 err = device_create_file(&sl->dev, &sl->attr_name); 313 err = device_create_file(&sl->dev, &sl->attr_name);
315 if (err < 0) { 314 if (err < 0) {
316 dev_err(&sl->dev, 315 dev_err(&sl->dev,
317 "sysfs file creation for [%s] failed. err=%d\n", 316 "sysfs file creation for [%s] failed. err=%d\n",
318 sl->dev.bus_id, err); 317 sl->dev.bus_id, err);
319 device_unregister(&sl->dev); 318 device_unregister(&sl->dev);
320 return err; 319 return err;
321 } 320 }
@@ -323,8 +322,8 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
323 err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin); 322 err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
324 if (err < 0) { 323 if (err < 0) {
325 dev_err(&sl->dev, 324 dev_err(&sl->dev,
326 "sysfs file creation for [%s] failed. err=%d\n", 325 "sysfs file creation for [%s] failed. err=%d\n",
327 sl->dev.bus_id, err); 326 sl->dev.bus_id, err);
328 device_remove_file(&sl->dev, &sl->attr_name); 327 device_remove_file(&sl->dev, &sl->attr_name);
329 device_unregister(&sl->dev); 328 device_unregister(&sl->dev);
330 return err; 329 return err;
@@ -483,26 +482,39 @@ static void w1_slave_found(unsigned long data, u64 rn)
483 atomic_dec(&dev->refcnt); 482 atomic_dec(&dev->refcnt);
484} 483}
485 484
486void w1_search(struct w1_master *dev) 485/**
486 * Performs a ROM Search & registers any devices found.
487 * The 1-wire search is a simple binary tree search.
488 * For each bit of the address, we read two bits and write one bit.
489 * The bit written will put to sleep all devies that don't match that bit.
490 * When the two reads differ, the direction choice is obvious.
491 * When both bits are 0, we must choose a path to take.
492 * When we can scan all 64 bits without having to choose a path, we are done.
493 *
494 * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
495 *
496 * @dev The master device to search
497 * @cb Function to call when a device is found
498 */
499void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
487{ 500{
488 u64 last, rn, tmp; 501 u64 last_rn, rn, tmp64;
489 int i, count = 0; 502 int i, slave_count = 0;
490 int last_family_desc, last_zero, last_device; 503 int last_zero, last_device;
491 int search_bit, id_bit, comp_bit, desc_bit; 504 int search_bit, desc_bit;
505 u8 triplet_ret = 0;
492 506
493 search_bit = id_bit = comp_bit = 0; 507 search_bit = 0;
494 rn = tmp = last = 0; 508 rn = last_rn = 0;
495 last_device = last_zero = last_family_desc = 0; 509 last_device = 0;
510 last_zero = -1;
496 511
497 desc_bit = 64; 512 desc_bit = 64;
498 513
499 while (!(id_bit && comp_bit) && !last_device && 514 while ( !last_device && (slave_count++ < dev->max_slave_count) ) {
500 count++ < dev->max_slave_count) { 515 last_rn = rn;
501 last = rn;
502 rn = 0; 516 rn = 0;
503 517
504 last_family_desc = 0;
505
506 /* 518 /*
507 * Reset bus and all 1-wire device state machines 519 * Reset bus and all 1-wire device state machines
508 * so they can respond to our requests. 520 * so they can respond to our requests.
@@ -514,59 +526,39 @@ void w1_search(struct w1_master *dev)
514 break; 526 break;
515 } 527 }
516 528
517#if 1 529 /* Start the search */
518 w1_write_8(dev, W1_SEARCH); 530 w1_write_8(dev, W1_SEARCH);
519 for (i = 0; i < 64; ++i) { 531 for (i = 0; i < 64; ++i) {
520 /* 532 /* Determine the direction/search bit */
521 * Read 2 bits from bus. 533 if (i == desc_bit)
522 * All who don't sleep must send ID bit and COMPLEMENT ID bit. 534 search_bit = 1; /* took the 0 path last time, so take the 1 path */
523 * They actually are ANDed between all senders. 535 else if (i > desc_bit)
524 */ 536 search_bit = 0; /* take the 0 path on the next branch */
525 id_bit = w1_touch_bit(dev, 1); 537 else
526 comp_bit = w1_touch_bit(dev, 1); 538 search_bit = ((last_rn >> i) & 0x1);
527
528 if (id_bit && comp_bit)
529 break;
530
531 if (id_bit == 0 && comp_bit == 0) {
532 if (i == desc_bit)
533 search_bit = 1;
534 else if (i > desc_bit)
535 search_bit = 0;
536 else
537 search_bit = ((last >> i) & 0x1);
538
539 if (search_bit == 0) {
540 last_zero = i;
541 if (last_zero < 9)
542 last_family_desc = last_zero;
543 }
544 539
545 } else 540 /** Read two bits and write one bit */
546 search_bit = id_bit; 541 triplet_ret = w1_triplet(dev, search_bit);
547 542
548 tmp = search_bit; 543 /* quit if no device responded */
549 rn |= (tmp << i); 544 if ( (triplet_ret & 0x03) == 0x03 )
545 break;
550 546
551 /* 547 /* If both directions were valid, and we took the 0 path... */
552 * Write 1 bit to bus 548 if (triplet_ret == 0)
553 * and make all who don't have "search_bit" in "i"'th position 549 last_zero = i;
554 * in it's registration number sleep.
555 */
556 if (dev->bus_master->touch_bit)
557 w1_touch_bit(dev, search_bit);
558 else
559 w1_write_bit(dev, search_bit);
560 550
551 /* extract the direction taken & update the device number */
552 tmp64 = (triplet_ret >> 2);
553 rn |= (tmp64 << i);
561 } 554 }
562#endif
563
564 if (desc_bit == last_zero)
565 last_device = 1;
566 555
567 desc_bit = last_zero; 556 if ( (triplet_ret & 0x03) != 0x03 ) {
568 557 if ( (desc_bit == last_zero) || (last_zero < 0))
569 w1_slave_found(dev->bus_master->data, rn); 558 last_device = 1;
559 desc_bit = last_zero;
560 cb(dev->bus_master->data, rn);
561 }
570 } 562 }
571} 563}
572 564
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 44dfb92e55cd..3cfdd08d32fc 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -25,9 +25,9 @@
25struct w1_reg_num 25struct w1_reg_num
26{ 26{
27#if defined(__LITTLE_ENDIAN_BITFIELD) 27#if defined(__LITTLE_ENDIAN_BITFIELD)
28 __u64 family:8, 28 __u64 family:8,
29 id:48, 29 id:48,
30 crc:8; 30 crc:8;
31#elif defined(__BIG_ENDIAN_BITFIELD) 31#elif defined(__BIG_ENDIAN_BITFIELD)
32 __u64 crc:8, 32 __u64 crc:8,
33 id:48, 33 id:48,
@@ -84,24 +84,71 @@ struct w1_slave
84 84
85typedef void (* w1_slave_found_callback)(unsigned long, u64); 85typedef void (* w1_slave_found_callback)(unsigned long, u64);
86 86
87
88/**
89 * Note: read_bit and write_bit are very low level functions and should only
90 * be used with hardware that doesn't really support 1-wire operations,
91 * like a parallel/serial port.
92 * Either define read_bit and write_bit OR define, at minimum, touch_bit and
93 * reset_bus.
94 */
87struct w1_bus_master 95struct w1_bus_master
88{ 96{
89 unsigned long data; 97 /** the first parameter in all the functions below */
90 98 unsigned long data;
91 u8 (*read_bit)(unsigned long); 99
92 void (*write_bit)(unsigned long, u8); 100 /**
93 101 * Sample the line level
94 u8 (*read_byte)(unsigned long); 102 * @return the level read (0 or 1)
95 void (*write_byte)(unsigned long, u8); 103 */
96 104 u8 (*read_bit)(unsigned long);
97 u8 (*read_block)(unsigned long, u8 *, int); 105
98 void (*write_block)(unsigned long, u8 *, int); 106 /** Sets the line level */
99 107 void (*write_bit)(unsigned long, u8);
100 u8 (*touch_bit)(unsigned long, u8); 108
101 109 /**
102 u8 (*reset_bus)(unsigned long); 110 * touch_bit is the lowest-level function for devices that really
103 111 * support the 1-wire protocol.
104 void (*search)(unsigned long, w1_slave_found_callback); 112 * touch_bit(0) = write-0 cycle
113 * touch_bit(1) = write-1 / read cycle
114 * @return the bit read (0 or 1)
115 */
116 u8 (*touch_bit)(unsigned long, u8);
117
118 /**
119 * Reads a bytes. Same as 8 touch_bit(1) calls.
120 * @return the byte read
121 */
122 u8 (*read_byte)(unsigned long);
123
124 /**
125 * Writes a byte. Same as 8 touch_bit(x) calls.
126 */
127 void (*write_byte)(unsigned long, u8);
128
129 /**
130 * Same as a series of read_byte() calls
131 * @return the number of bytes read
132 */
133 u8 (*read_block)(unsigned long, u8 *, int);
134
135 /** Same as a series of write_byte() calls */
136 void (*write_block)(unsigned long, const u8 *, int);
137
138 /**
139 * Combines two reads and a smart write for ROM searches
140 * @return bit0=Id bit1=comp_id bit2=dir_taken
141 */
142 u8 (*triplet)(unsigned long, u8);
143
144 /**
145 * long write-0 with a read for the presence pulse detection
146 * @return -1=Error, 0=Device present, 1=No device present
147 */
148 u8 (*reset_bus)(unsigned long);
149
150 /** Really nice hardware can handles the ROM searches */
151 void (*search)(unsigned long, w1_slave_found_callback);
105}; 152};
106 153
107struct w1_master 154struct w1_master
@@ -137,7 +184,7 @@ struct w1_master
137}; 184};
138 185
139int w1_create_master_attributes(struct w1_master *); 186int w1_create_master_attributes(struct w1_master *);
140void w1_search(struct w1_master *dev); 187void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
141 188
142#endif /* __KERNEL__ */ 189#endif /* __KERNEL__ */
143 190
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 2173336b60a7..00f032220173 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -130,6 +130,47 @@ static u8 w1_read_bit(struct w1_master *dev)
130} 130}
131 131
132/** 132/**
133 * Does a triplet - used for searching ROM addresses.
134 * Return bits:
135 * bit 0 = id_bit
136 * bit 1 = comp_bit
137 * bit 2 = dir_taken
138 * If both bits 0 & 1 are set, the search should be restarted.
139 *
140 * @param dev the master device
141 * @param bdir the bit to write if both id_bit and comp_bit are 0
142 * @return bit fields - see above
143 */
144u8 w1_triplet(struct w1_master *dev, int bdir)
145{
146 if ( dev->bus_master->triplet )
147 return(dev->bus_master->triplet(dev->bus_master->data, bdir));
148 else {
149 u8 id_bit = w1_touch_bit(dev, 1);
150 u8 comp_bit = w1_touch_bit(dev, 1);
151 u8 retval;
152
153 if ( id_bit && comp_bit )
154 return(0x03); /* error */
155
156 if ( !id_bit && !comp_bit ) {
157 /* Both bits are valid, take the direction given */
158 retval = bdir ? 0x04 : 0;
159 } else {
160 /* Only one bit is valid, take that direction */
161 bdir = id_bit;
162 retval = id_bit ? 0x05 : 0x02;
163 }
164
165 if ( dev->bus_master->touch_bit )
166 w1_touch_bit(dev, bdir);
167 else
168 w1_write_bit(dev, bdir);
169 return(retval);
170 }
171}
172
173/**
133 * Reads 8 bits. 174 * Reads 8 bits.
134 * 175 *
135 * @param dev the master device 176 * @param dev the master device
@@ -233,7 +274,7 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
233 if (dev->bus_master->search) 274 if (dev->bus_master->search)
234 dev->bus_master->search(dev->bus_master->data, cb); 275 dev->bus_master->search(dev->bus_master->data, cb);
235 else 276 else
236 w1_search(dev); 277 w1_search(dev, cb);
237} 278}
238 279
239EXPORT_SYMBOL(w1_touch_bit); 280EXPORT_SYMBOL(w1_touch_bit);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index d6daa3189c61..af5829778aaa 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -26,6 +26,7 @@
26 26
27void w1_delay(unsigned long); 27void w1_delay(unsigned long);
28u8 w1_touch_bit(struct w1_master *, int); 28u8 w1_touch_bit(struct w1_master *, int);
29u8 w1_triplet(struct w1_master *dev, int bdir);
29void w1_write_8(struct w1_master *, u8); 30void w1_write_8(struct w1_master *, u8);
30u8 w1_read_8(struct w1_master *); 31u8 w1_read_8(struct w1_master *);
31int w1_reset_bus(struct w1_master *); 32int w1_reset_bus(struct w1_master *);