w1: ds2490 fix and enable hardware search
The hardware search was failing without the COMM_RST flag. Enabled the flag and rewrote the function to handle more than one buffer of results and to continuing where the search left off. Remove hardware search note from the limitations now that it works. The "w1: ds2490 USB setup fixes" change went from 23.16 seconds to about 3 seconds, this takes the time for the search down to .307346 seconds. Signed-off-by: David Fries <David@Fries.net> Acked-by: Evgeniy Polyakov <zbr@ioremap.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
da78b7e74a
commit
d53f0a2c05
@ -21,8 +21,6 @@ Notes and limitations.
|
|||||||
- The weak pullup current is a minimum of 0.9mA and maximum of 6.0mA.
|
- The weak pullup current is a minimum of 0.9mA and maximum of 6.0mA.
|
||||||
- The 5V strong pullup is supported with a minimum of 5.9mA and a
|
- The 5V strong pullup is supported with a minimum of 5.9mA and a
|
||||||
maximum of 30.4 mA. (From DS2490.pdf)
|
maximum of 30.4 mA. (From DS2490.pdf)
|
||||||
- While the ds2490 supports a hardware search the code doesn't take
|
|
||||||
advantage of it (in tested case it only returned first device).
|
|
||||||
- The hardware will detect when devices are attached to the bus on the
|
- The hardware will detect when devices are attached to the bus on the
|
||||||
next bus (reset?) operation, however only a message is printed as
|
next bus (reset?) operation, however only a message is printed as
|
||||||
the core w1 code doesn't make use of the information. Connecting
|
the core w1 code doesn't make use of the information. Connecting
|
||||||
|
@ -698,37 +698,102 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
|
|||||||
return !(err == len);
|
return !(err == len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static void ds9490r_search(void *data, struct w1_master *master,
|
||||||
|
u8 search_type, w1_slave_found_callback callback)
|
||||||
static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
|
|
||||||
{
|
{
|
||||||
|
/* When starting with an existing id, the first id returned will
|
||||||
|
* be that device (if it is still on the bus most likely).
|
||||||
|
*
|
||||||
|
* If the number of devices found is less than or equal to the
|
||||||
|
* search_limit, that number of IDs will be returned. If there are
|
||||||
|
* more, search_limit IDs will be returned followed by a non-zero
|
||||||
|
* discrepency value.
|
||||||
|
*/
|
||||||
|
struct ds_device *dev = data;
|
||||||
int err;
|
int err;
|
||||||
u16 value, index;
|
u16 value, index;
|
||||||
struct ds_status st;
|
struct ds_status st;
|
||||||
|
u8 st_buf[ST_SIZE];
|
||||||
|
int search_limit;
|
||||||
|
int found = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
/* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for
|
||||||
|
* discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time.
|
||||||
|
*/
|
||||||
|
const unsigned long jtime = msecs_to_jiffies(1000*8/75);
|
||||||
|
/* FIFO 128 bytes, bulk packet size 64, read a multiple of the
|
||||||
|
* packet size.
|
||||||
|
*/
|
||||||
|
u64 buf[2*64/8];
|
||||||
|
|
||||||
err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
|
/* address to start searching at */
|
||||||
if (err)
|
if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0)
|
||||||
return err;
|
return;
|
||||||
|
master->search_id = 0;
|
||||||
|
|
||||||
ds_wait_status(ds_dev, &st);
|
value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F |
|
||||||
|
COMM_RTS;
|
||||||
|
search_limit = master->max_slave_count;
|
||||||
|
if (search_limit > 255)
|
||||||
|
search_limit = 0;
|
||||||
|
index = search_type | (search_limit << 8);
|
||||||
|
if (ds_send_control(dev, value, index) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
|
do {
|
||||||
index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
|
schedule_timeout(jtime);
|
||||||
err = ds_send_control(ds_dev, value, index);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
ds_wait_status(ds_dev, &st);
|
if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) <
|
||||||
|
sizeof(st)) {
|
||||||
err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
|
break;
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
return err/8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (st.data_in_buffer_status) {
|
||||||
|
/* Bulk in can receive partial ids, but when it does
|
||||||
|
* they fail crc and will be discarded anyway.
|
||||||
|
* That has only been seen when status in buffer
|
||||||
|
* is 0 and bulk is read anyway, so don't read
|
||||||
|
* bulk without first checking if status says there
|
||||||
|
* is data to read.
|
||||||
|
*/
|
||||||
|
err = ds_recv_data(dev, (u8 *)buf, sizeof(buf));
|
||||||
|
if (err < 0)
|
||||||
|
break;
|
||||||
|
for (i = 0; i < err/8; ++i) {
|
||||||
|
++found;
|
||||||
|
if (found <= search_limit)
|
||||||
|
callback(master, buf[i]);
|
||||||
|
/* can't know if there will be a discrepancy
|
||||||
|
* value after until the next id */
|
||||||
|
if (found == search_limit)
|
||||||
|
master->search_id = buf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(W1_ABORT_SEARCH, &master->flags))
|
||||||
|
break;
|
||||||
|
} while (!(st.status & (ST_IDLE | ST_HALT)));
|
||||||
|
|
||||||
|
/* only continue the search if some weren't found */
|
||||||
|
if (found <= search_limit) {
|
||||||
|
master->search_id = 0;
|
||||||
|
} else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) {
|
||||||
|
/* Only max_slave_count will be scanned in a search,
|
||||||
|
* but it will start where it left off next search
|
||||||
|
* until all ids are identified and then it will start
|
||||||
|
* over. A continued search will report the previous
|
||||||
|
* last id as the first id (provided it is still on the
|
||||||
|
* bus).
|
||||||
|
*/
|
||||||
|
dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, "
|
||||||
|
"will continue next search.\n", __func__,
|
||||||
|
master->max_slave_count);
|
||||||
|
set_bit(W1_WARN_MAX_COUNT, &master->flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int ds_match_access(struct ds_device *dev, u64 init)
|
static int ds_match_access(struct ds_device *dev, u64 init)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@ -902,6 +967,7 @@ static int ds_w1_init(struct ds_device *dev)
|
|||||||
dev->master.write_block = &ds9490r_write_block;
|
dev->master.write_block = &ds9490r_write_block;
|
||||||
dev->master.reset_bus = &ds9490r_reset;
|
dev->master.reset_bus = &ds9490r_reset;
|
||||||
dev->master.set_pullup = &ds9490r_set_pullup;
|
dev->master.set_pullup = &ds9490r_set_pullup;
|
||||||
|
dev->master.search = &ds9490r_search;
|
||||||
|
|
||||||
return w1_add_master_device(&dev->master);
|
return w1_add_master_device(&dev->master);
|
||||||
}
|
}
|
||||||
@ -920,13 +986,11 @@ static int ds_probe(struct usb_interface *intf,
|
|||||||
struct ds_device *dev;
|
struct ds_device *dev;
|
||||||
int i, err, alt;
|
int i, err, alt;
|
||||||
|
|
||||||
dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
|
dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
|
printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
dev->spu_sleep = 0;
|
|
||||||
dev->spu_bit = 0;
|
|
||||||
dev->udev = usb_get_dev(udev);
|
dev->udev = usb_get_dev(udev);
|
||||||
if (!dev->udev) {
|
if (!dev->udev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
Loading…
Reference in New Issue
Block a user