diff options
author | Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 2005-06-03 17:30:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-22 00:43:11 -0400 |
commit | 6b729861831177b270a2932a13e79cb41d673146 (patch) | |
tree | 443c86578d04ba42d9b4e483d6ebee91ba30d25e /drivers/w1/w1.c | |
parent | be57ce267fd558c52d2389530c15618681b7cfa7 (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.c | 138 |
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 | ||
136 | static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) | 136 | static 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 | ||
214 | static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf) | 214 | static 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 | ||
486 | void 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 | */ | ||
499 | void 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 | ||