]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/w1/masters/ds2490.c
W1: ds2490.c optimize ds_set_pullup
[linux-2.6-omap-h63xx.git] / drivers / w1 / masters / ds2490.c
index 4faf4f9ec068e6b19534b3cd85ea77378bf600d2..59ad6e95af8f0b0dded05413115c45bee2d2276b 100644 (file)
@@ -141,6 +141,10 @@ struct ds_device
         * 0: pullup not active, else duration in milliseconds
         */
        int                     spu_sleep;
+       /* spu_bit contains COMM_SPU or 0 depending on if the strong pullup
+        * should be active or not for writes.
+        */
+       u16                     spu_bit;
 
        struct w1_bus_master    master;
 };
@@ -311,6 +315,25 @@ static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count)
        }
 }
 
+static void ds_reset_device(struct ds_device *dev)
+{
+       ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+       /* Always allow strong pullup which allow individual writes to use
+        * the strong pullup.
+        */
+       if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE))
+               printk(KERN_ERR "ds_reset_device: "
+                       "Error allowing strong pullup\n");
+       /* Chip strong pullup time was cleared. */
+       if (dev->spu_sleep) {
+               /* lower 4 bits are 0, see ds_set_pullup */
+               u8 del = dev->spu_sleep>>4;
+               if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del))
+                       printk(KERN_ERR "ds_reset_device: "
+                               "Error setting duration\n");
+       }
+}
+
 static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
 {
        int count, err;
@@ -444,7 +467,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
 
        if (err >= 16 && st->status & ST_EPOF) {
                printk(KERN_INFO "Resetting device after ST_EPOF.\n");
-               ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+               ds_reset_device(dev);
                /* Always dump the device status. */
                count = 101;
        }
@@ -509,24 +532,26 @@ static int ds_set_speed(struct ds_device *dev, int speed)
 
 static int ds_set_pullup(struct ds_device *dev, int delay)
 {
-       int err;
+       int err = 0;
        u8 del = 1 + (u8)(delay >> 4);
+       /* Just storing delay would not get the trunication and roundup. */
+       int ms = del<<4;
+
+       /* Enable spu_bit if a delay is set. */
+       dev->spu_bit = delay ? COMM_SPU : 0;
+       /* If delay is zero, it has already been disabled, if the time is
+        * the same as the hardware was last programmed to, there is also
+        * nothing more to do.  Compare with the recalculated value ms
+        * rather than del or delay which can have a different value.
+        */
+       if (delay == 0 || ms == dev->spu_sleep)
+               return err;
 
-       dev->spu_sleep = 0;
-       err = ds_send_control_mode(dev, MOD_PULSE_EN, delay ? PULSE_SPUE : 0);
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
        if (err)
                return err;
 
-       if (delay) {
-               err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
-               if (err)
-                       return err;
-
-               /* Just storing delay would not get the trunication and
-                * roundup.
-                */
-               dev->spu_sleep = del<<4;
-       }
+       dev->spu_sleep = ms;
 
        return err;
 }
@@ -577,11 +602,11 @@ static int ds_write_byte(struct ds_device *dev, u8 byte)
        struct ds_status st;
        u8 rbyte;
 
-       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
        if (err)
                return err;
 
-       if (dev->spu_sleep)
+       if (dev->spu_bit)
                msleep(dev->spu_sleep);
 
        err = ds_wait_status(dev, &st);
@@ -648,11 +673,11 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
        if (err < 0)
                return err;
 
-       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len);
        if (err)
                return err;
 
-       if (dev->spu_sleep)
+       if (dev->spu_bit)
                msleep(dev->spu_sleep);
 
        ds_wait_status(dev, &st);
@@ -849,7 +874,7 @@ static int ds_w1_init(struct ds_device *dev)
         * the input buffer.  This will cause the next read to fail
         * see the note in ds_recv_data.
         */
-       ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+       ds_reset_device(dev);
 
        dev->master.data        = dev;
        dev->master.touch_bit   = &ds9490r_touch_bit;
@@ -892,6 +917,7 @@ static int ds_probe(struct usb_interface *intf,
                return -ENOMEM;
        }
        dev->spu_sleep = 0;
+       dev->spu_bit = 0;
        dev->udev = usb_get_dev(udev);
        if (!dev->udev) {
                err = -ENOMEM;