w1: add 1-wire (w1) reset and resume command API support
Jean-Fran├žois Dagenais [Thu, 26 May 2011 23:26:01 +0000 (16:26 -0700)]
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>

drivers/w1/w1.h
drivers/w1/w1_io.c

index d8a9709..f804eba 100644 (file)
@@ -55,6 +55,7 @@ struct w1_reg_num
 #define W1_READ_ROM            0x33
 #define W1_READ_PSUPPLY                0xB4
 #define W1_MATCH_ROM           0x55
+#define W1_RESUME_CMD          0xA5
 
 #define W1_SLAVE_ACTIVE                0
 
@@ -213,6 +214,7 @@ void w1_write_block(struct w1_master *, const u8 *, int);
 void w1_touch_block(struct w1_master *, u8 *, int);
 u8 w1_read_block(struct w1_master *, u8 *, int);
 int w1_reset_select_slave(struct w1_slave *sl);
+int w1_reset_resume_command(struct w1_master *);
 void w1_next_pullup(struct w1_master *, int);
 
 static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
index 3ebe972..8e8b64c 100644 (file)
@@ -390,6 +390,32 @@ int w1_reset_select_slave(struct w1_slave *sl)
 EXPORT_SYMBOL_GPL(w1_reset_select_slave);
 
 /**
+ * When the workflow with a slave amongst many requires several
+ * successive commands a reset between each, this function is similar
+ * to doing a reset then a match ROM for the last matched ROM. The
+ * advantage being that the matched ROM step is skipped in favor of the
+ * resume command. The slave must support the command of course.
+ *
+ * If the bus has only one slave, traditionnaly the match ROM is skipped
+ * and a "SKIP ROM" is done for efficiency. On multi-slave busses, this
+ * doesn't work of course, but the resume command is the next best thing.
+ *
+ * The w1 master lock must be held.
+ *
+ * @param dev     the master device
+ */
+int w1_reset_resume_command(struct w1_master *dev)
+{
+       if (w1_reset_bus(dev))
+               return -1;
+
+       /* This will make only the last matched slave perform a skip ROM. */
+       w1_write_8(dev, W1_RESUME_CMD);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(w1_reset_resume_command);
+
+/**
  * Put out a strong pull-up of the specified duration after the next write
  * operation.  Not all hardware supports strong pullups.  Hardware that
  * doesn't support strong pullups will sleep for the given time after the