Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / w1 / w1_io.c
index 02796b5..f7f7e8b 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_io.c
+ *     w1_io.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 #include "w1_log.h"
 #include "w1_io.h"
 
-int w1_delay_parm = 1;
+static int w1_delay_parm = 1;
 module_param_named(delay_coef, w1_delay_parm, int, 0);
 
 static u8 w1_crc8_table[] = {
@@ -55,15 +55,29 @@ void w1_delay(unsigned long tm)
        udelay(tm * w1_delay_parm);
 }
 
+static void w1_write_bit(struct w1_master *dev, int bit);
+static u8 w1_read_bit(struct w1_master *dev);
+
+/**
+ * Generates a write-0 or write-1 cycle and samples the level.
+ */
 u8 w1_touch_bit(struct w1_master *dev, int bit)
 {
        if (dev->bus_master->touch_bit)
                return dev->bus_master->touch_bit(dev->bus_master->data, bit);
-       else
+       else if (bit)
                return w1_read_bit(dev);
+       else {
+               w1_write_bit(dev, 0);
+               return(0);
+       }
 }
 
-void w1_write_bit(struct w1_master *dev, int bit)
+/**
+ * Generates a write-0 or write-1 cycle.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static void w1_write_bit(struct w1_master *dev, int bit)
 {
        if (bit) {
                dev->bus_master->write_bit(dev->bus_master->data, 0);
@@ -78,6 +92,12 @@ void w1_write_bit(struct w1_master *dev, int bit)
        }
 }
 
+/**
+ * Writes 8 bits.
+ *
+ * @param dev     the master device
+ * @param byte    the byte to write
+ */
 void w1_write_8(struct w1_master *dev, u8 byte)
 {
        int i;
@@ -86,10 +106,15 @@ void w1_write_8(struct w1_master *dev, u8 byte)
                dev->bus_master->write_byte(dev->bus_master->data, byte);
        else
                for (i = 0; i < 8; ++i)
-                       w1_write_bit(dev, (byte >> i) & 0x1);
+                       w1_touch_bit(dev, (byte >> i) & 0x1);
 }
 
-u8 w1_read_bit(struct w1_master *dev)
+
+/**
+ * Generates a write-1 cycle and samples the level.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static u8 w1_read_bit(struct w1_master *dev)
 {
        int result;
 
@@ -104,6 +129,53 @@ u8 w1_read_bit(struct w1_master *dev)
        return result & 0x1;
 }
 
+/**
+ * Does a triplet - used for searching ROM addresses.
+ * Return bits:
+ *  bit 0 = id_bit
+ *  bit 1 = comp_bit
+ *  bit 2 = dir_taken
+ * If both bits 0 & 1 are set, the search should be restarted.
+ *
+ * @param dev     the master device
+ * @param bdir    the bit to write if both id_bit and comp_bit are 0
+ * @return        bit fields - see above
+ */
+u8 w1_triplet(struct w1_master *dev, int bdir)
+{
+       if ( dev->bus_master->triplet )
+               return(dev->bus_master->triplet(dev->bus_master->data, bdir));
+       else {
+               u8 id_bit   = w1_touch_bit(dev, 1);
+               u8 comp_bit = w1_touch_bit(dev, 1);
+               u8 retval;
+
+               if ( id_bit && comp_bit )
+                       return(0x03);  /* error */
+
+               if ( !id_bit && !comp_bit ) {
+                       /* Both bits are valid, take the direction given */
+                       retval = bdir ? 0x04 : 0;
+               } else {
+                       /* Only one bit is valid, take that direction */
+                       bdir = id_bit;
+                       retval = id_bit ? 0x05 : 0x02;
+               }
+
+               if ( dev->bus_master->touch_bit )
+                       w1_touch_bit(dev, bdir);
+               else
+                       w1_write_bit(dev, bdir);
+               return(retval);
+       }
+}
+
+/**
+ * Reads 8 bits.
+ *
+ * @param dev     the master device
+ * @return        the byte read
+ */
 u8 w1_read_8(struct w1_master * dev)
 {
        int i;
@@ -113,12 +185,20 @@ u8 w1_read_8(struct w1_master * dev)
                res = dev->bus_master->read_byte(dev->bus_master->data);
        else
                for (i = 0; i < 8; ++i)
-                       res |= (w1_read_bit(dev) << i);
+                       res |= (w1_touch_bit(dev,1) << i);
 
        return res;
 }
 
-void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+/**
+ * Writes a series of bytes.
+ *
+ * @param dev     the master device
+ * @param buf     pointer to the data to write
+ * @param len     the number of bytes to write
+ * @return        the byte read
+ */
+void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
 {
        int i;
 
@@ -129,6 +209,14 @@ void w1_write_block(struct w1_master *dev, u8 *buf, int len)
                        w1_write_8(dev, buf[i]);
 }
 
+/**
+ * Reads a series of bytes.
+ *
+ * @param dev     the master device
+ * @param buf     pointer to the buffer to fill
+ * @param len     the number of bytes to read
+ * @return        the number of bytes read
+ */
 u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
 {
        int i;
@@ -145,9 +233,15 @@ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
        return ret;
 }
 
+/**
+ * Issues a reset bus sequence.
+ *
+ * @param  dev The bus master pointer
+ * @return     0=Device present, 1=No device present or error
+ */
 int w1_reset_bus(struct w1_master *dev)
 {
-       int result = 0;
+       int result;
 
        if (dev->bus_master->reset_bus)
                result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
@@ -180,12 +274,34 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
        if (dev->bus_master->search)
                dev->bus_master->search(dev->bus_master->data, cb);
        else
-               w1_search(dev);
+               w1_search(dev, cb);
+}
+
+/**
+ * Resets the bus and then selects the slave by sending either a skip rom
+ * or a rom match.
+ * The w1 master lock must be held.
+ *
+ * @param sl   the slave to select
+ * @return     0=success, anything else=error
+ */
+int w1_reset_select_slave(struct w1_slave *sl)
+{
+       if (w1_reset_bus(sl->master))
+               return -1;
+
+       if (sl->master->slave_count == 1)
+               w1_write_8(sl->master, W1_SKIP_ROM);
+       else {
+               u8 match[9] = {W1_MATCH_ROM, };
+               memcpy(&match[1], (u8 *)&sl->reg_num, 8);
+               w1_write_block(sl->master, match, 9);
+       }
+       return 0;
 }
 
-EXPORT_SYMBOL(w1_write_bit);
+EXPORT_SYMBOL(w1_touch_bit);
 EXPORT_SYMBOL(w1_write_8);
-EXPORT_SYMBOL(w1_read_bit);
 EXPORT_SYMBOL(w1_read_8);
 EXPORT_SYMBOL(w1_reset_bus);
 EXPORT_SYMBOL(w1_calc_crc8);
@@ -193,3 +309,4 @@ EXPORT_SYMBOL(w1_delay);
 EXPORT_SYMBOL(w1_read_block);
 EXPORT_SYMBOL(w1_write_block);
 EXPORT_SYMBOL(w1_search_devices);
+EXPORT_SYMBOL(w1_reset_select_slave);