aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1/w1.c
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/w1/w1.c
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/w1/w1.c')
-rw-r--r--drivers/w1/w1.c138
1 files changed, 65 insertions, 73 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