diff options
author | Jean-François Dagenais <dagenaisj@sonatest.com> | 2011-05-26 19:26:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-26 20:12:38 -0400 |
commit | 67dfd54c2d83a76a5756760f7fee0c8cfac52b1c (patch) | |
tree | 67f60d8bf1fcfd64106e419c1de3cd6e5618dd1d /drivers/w1 | |
parent | 6f7bd76f05eb2bfbb48d58c0408a50a7e16b2423 (diff) |
w1: add 1-wire (w1) reset and resume command API support
The first patch adds generic functionnality to w1_io for Resume Command
[A5h] lots of slaves support. I found it useful for multi-commands/reset
workflows with the same slave on a multi-slave bus.
This DS2408 w1 slave driver is not complete for all the features of the
chip, but its sufficient if you use it as a simple IO expander. Enjoy!
The ds1wm had Kconfig dependencies towards ARM && HAVE_CLK. I took them
out since I was using the ds1wm on an x86_64 platform (ds1wm in a FPGA
through pcie) and found them irrelevant.
The clock freq/divisors at the top of ds1wm.c did not have the MSB set to
1. This bit is CLK_EN which turns the whole prescaler and dividers on.
The driver never mentionned this bit either, so I just included this bit
right in the table entries. I also took the liberty to add a couple of
entries to the table. The spec doesn't explicitely mentions these
possibilities but the description and examination of the core shows the
prescalers & dividers can be used for more than the table explicitely
shows. The table I enlarged still doesn't cover all possibilities, but
it's a good start.
I also made a few tweaks to a couple of the read and write algorithms
which made sense while I had my head very deep in the ds1wm documentation.
We stressed it a lot with 10+ slaves on the bus, many ds2408, ds2431 and
ds2433 at the same time doing extensive interaction. It proved quite
stable in our production environment.
This patch:
Add generic functionnality to w1_io for Resume Command [A5h] lots of
slaves support.
Signed-off-by: Jean-François Dagenais <dagenaisj@sonatest.com>
Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Cc: Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
Cc: Matt Reimer <mreimer@vpop.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/w1')
-rw-r--r-- | drivers/w1/w1.h | 2 | ||||
-rw-r--r-- | drivers/w1/w1_io.c | 26 |
2 files changed, 28 insertions, 0 deletions
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index d8a9709f3449..f804eba89b7b 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
@@ -55,6 +55,7 @@ struct w1_reg_num | |||
55 | #define W1_READ_ROM 0x33 | 55 | #define W1_READ_ROM 0x33 |
56 | #define W1_READ_PSUPPLY 0xB4 | 56 | #define W1_READ_PSUPPLY 0xB4 |
57 | #define W1_MATCH_ROM 0x55 | 57 | #define W1_MATCH_ROM 0x55 |
58 | #define W1_RESUME_CMD 0xA5 | ||
58 | 59 | ||
59 | #define W1_SLAVE_ACTIVE 0 | 60 | #define W1_SLAVE_ACTIVE 0 |
60 | 61 | ||
@@ -213,6 +214,7 @@ void w1_write_block(struct w1_master *, const u8 *, int); | |||
213 | void w1_touch_block(struct w1_master *, u8 *, int); | 214 | void w1_touch_block(struct w1_master *, u8 *, int); |
214 | u8 w1_read_block(struct w1_master *, u8 *, int); | 215 | u8 w1_read_block(struct w1_master *, u8 *, int); |
215 | int w1_reset_select_slave(struct w1_slave *sl); | 216 | int w1_reset_select_slave(struct w1_slave *sl); |
217 | int w1_reset_resume_command(struct w1_master *); | ||
216 | void w1_next_pullup(struct w1_master *, int); | 218 | void w1_next_pullup(struct w1_master *, int); |
217 | 219 | ||
218 | static inline struct w1_slave* dev_to_w1_slave(struct device *dev) | 220 | static inline struct w1_slave* dev_to_w1_slave(struct device *dev) |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 3ebe9726a9e5..8e8b64cfafb6 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -390,6 +390,32 @@ int w1_reset_select_slave(struct w1_slave *sl) | |||
390 | EXPORT_SYMBOL_GPL(w1_reset_select_slave); | 390 | EXPORT_SYMBOL_GPL(w1_reset_select_slave); |
391 | 391 | ||
392 | /** | 392 | /** |
393 | * When the workflow with a slave amongst many requires several | ||
394 | * successive commands a reset between each, this function is similar | ||
395 | * to doing a reset then a match ROM for the last matched ROM. The | ||
396 | * advantage being that the matched ROM step is skipped in favor of the | ||
397 | * resume command. The slave must support the command of course. | ||
398 | * | ||
399 | * If the bus has only one slave, traditionnaly the match ROM is skipped | ||
400 | * and a "SKIP ROM" is done for efficiency. On multi-slave busses, this | ||
401 | * doesn't work of course, but the resume command is the next best thing. | ||
402 | * | ||
403 | * The w1 master lock must be held. | ||
404 | * | ||
405 | * @param dev the master device | ||
406 | */ | ||
407 | int w1_reset_resume_command(struct w1_master *dev) | ||
408 | { | ||
409 | if (w1_reset_bus(dev)) | ||
410 | return -1; | ||
411 | |||
412 | /* This will make only the last matched slave perform a skip ROM. */ | ||
413 | w1_write_8(dev, W1_RESUME_CMD); | ||
414 | return 0; | ||
415 | } | ||
416 | EXPORT_SYMBOL_GPL(w1_reset_resume_command); | ||
417 | |||
418 | /** | ||
393 | * Put out a strong pull-up of the specified duration after the next write | 419 | * Put out a strong pull-up of the specified duration after the next write |
394 | * operation. Not all hardware supports strong pullups. Hardware that | 420 | * operation. Not all hardware supports strong pullups. Hardware that |
395 | * doesn't support strong pullups will sleep for the given time after the | 421 | * doesn't support strong pullups will sleep for the given time after the |