diff options
Diffstat (limited to 'drivers/w1/masters/ds2490.c')
-rw-r--r-- | drivers/w1/masters/ds2490.c | 134 |
1 files changed, 84 insertions, 50 deletions
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index c4ff70b2c7c4..065042db69f7 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c | |||
@@ -107,6 +107,17 @@ | |||
107 | #define ST_IDLE 0x20 /* DS2490 is currently idle */ | 107 | #define ST_IDLE 0x20 /* DS2490 is currently idle */ |
108 | #define ST_EPOF 0x80 | 108 | #define ST_EPOF 0x80 |
109 | 109 | ||
110 | /* Result Register flags */ | ||
111 | #define RR_DETECT 0xA5 /* New device detected */ | ||
112 | #define RR_NRS 0x01 /* Reset no presence or ... */ | ||
113 | #define RR_SH 0x02 /* short on reset or set path */ | ||
114 | #define RR_APP 0x04 /* alarming presence on reset */ | ||
115 | #define RR_VPP 0x08 /* 12V expected not seen */ | ||
116 | #define RR_CMP 0x10 /* compare error */ | ||
117 | #define RR_CRC 0x20 /* CRC error detected */ | ||
118 | #define RR_RDP 0x40 /* redirected page */ | ||
119 | #define RR_EOS 0x80 /* end of search error */ | ||
120 | |||
110 | #define SPEED_NORMAL 0x00 | 121 | #define SPEED_NORMAL 0x00 |
111 | #define SPEED_FLEXIBLE 0x01 | 122 | #define SPEED_FLEXIBLE 0x01 |
112 | #define SPEED_OVERDRIVE 0x02 | 123 | #define SPEED_OVERDRIVE 0x02 |
@@ -164,7 +175,6 @@ MODULE_DEVICE_TABLE(usb, ds_id_table); | |||
164 | static int ds_probe(struct usb_interface *, const struct usb_device_id *); | 175 | static int ds_probe(struct usb_interface *, const struct usb_device_id *); |
165 | static void ds_disconnect(struct usb_interface *); | 176 | static void ds_disconnect(struct usb_interface *); |
166 | 177 | ||
167 | static inline void ds_dump_status(unsigned char *, unsigned char *, int); | ||
168 | static int ds_send_control(struct ds_device *, u16, u16); | 178 | static int ds_send_control(struct ds_device *, u16, u16); |
169 | static int ds_send_control_cmd(struct ds_device *, u16, u16); | 179 | static int ds_send_control_cmd(struct ds_device *, u16, u16); |
170 | 180 | ||
@@ -223,11 +233,6 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index) | |||
223 | return err; | 233 | return err; |
224 | } | 234 | } |
225 | 235 | ||
226 | static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off) | ||
227 | { | ||
228 | printk("%45s: %8x\n", str, buf[off]); | ||
229 | } | ||
230 | |||
231 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, | 236 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, |
232 | unsigned char *buf, int size) | 237 | unsigned char *buf, int size) |
233 | { | 238 | { |
@@ -248,54 +253,62 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, | |||
248 | return count; | 253 | return count; |
249 | } | 254 | } |
250 | 255 | ||
251 | static int ds_recv_status(struct ds_device *dev, struct ds_status *st) | 256 | static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) |
252 | { | 257 | { |
253 | unsigned char buf[64]; | 258 | printk(KERN_INFO "%45s: %8x\n", str, buf[off]); |
254 | int count, err = 0, i; | 259 | } |
255 | |||
256 | memcpy(st, buf, sizeof(*st)); | ||
257 | 260 | ||
258 | count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | 261 | static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count) |
259 | if (count < 0) | 262 | { |
260 | return err; | 263 | int i; |
261 | 264 | ||
262 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); | 265 | printk(KERN_INFO "0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); |
263 | for (i=0; i<count; ++i) | 266 | for (i=0; i<count; ++i) |
264 | printk("%02x ", buf[i]); | 267 | printk("%02x ", buf[i]); |
265 | printk("\n"); | 268 | printk(KERN_INFO "\n"); |
266 | 269 | ||
267 | if (count >= 16) { | 270 | if (count >= 16) { |
268 | ds_dump_status(buf, "enable flag", 0); | 271 | ds_print_msg(buf, "enable flag", 0); |
269 | ds_dump_status(buf, "1-wire speed", 1); | 272 | ds_print_msg(buf, "1-wire speed", 1); |
270 | ds_dump_status(buf, "strong pullup duration", 2); | 273 | ds_print_msg(buf, "strong pullup duration", 2); |
271 | ds_dump_status(buf, "programming pulse duration", 3); | 274 | ds_print_msg(buf, "programming pulse duration", 3); |
272 | ds_dump_status(buf, "pulldown slew rate control", 4); | 275 | ds_print_msg(buf, "pulldown slew rate control", 4); |
273 | ds_dump_status(buf, "write-1 low time", 5); | 276 | ds_print_msg(buf, "write-1 low time", 5); |
274 | ds_dump_status(buf, "data sample offset/write-0 recovery time", 6); | 277 | ds_print_msg(buf, "data sample offset/write-0 recovery time", |
275 | ds_dump_status(buf, "reserved (test register)", 7); | 278 | 6); |
276 | ds_dump_status(buf, "device status flags", 8); | 279 | ds_print_msg(buf, "reserved (test register)", 7); |
277 | ds_dump_status(buf, "communication command byte 1", 9); | 280 | ds_print_msg(buf, "device status flags", 8); |
278 | ds_dump_status(buf, "communication command byte 2", 10); | 281 | ds_print_msg(buf, "communication command byte 1", 9); |
279 | ds_dump_status(buf, "communication command buffer status", 11); | 282 | ds_print_msg(buf, "communication command byte 2", 10); |
280 | ds_dump_status(buf, "1-wire data output buffer status", 12); | 283 | ds_print_msg(buf, "communication command buffer status", 11); |
281 | ds_dump_status(buf, "1-wire data input buffer status", 13); | 284 | ds_print_msg(buf, "1-wire data output buffer status", 12); |
282 | ds_dump_status(buf, "reserved", 14); | 285 | ds_print_msg(buf, "1-wire data input buffer status", 13); |
283 | ds_dump_status(buf, "reserved", 15); | 286 | ds_print_msg(buf, "reserved", 14); |
287 | ds_print_msg(buf, "reserved", 15); | ||
284 | } | 288 | } |
285 | 289 | for (i = 16; i < count; ++i) { | |
286 | memcpy(st, buf, sizeof(*st)); | 290 | if (buf[i] == RR_DETECT) { |
287 | 291 | ds_print_msg(buf, "new device detect", i); | |
288 | if (st->status & ST_EPOF) { | 292 | continue; |
289 | printk(KERN_INFO "Resetting device after ST_EPOF.\n"); | 293 | } |
290 | err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | 294 | ds_print_msg(buf, "Result Register Value: ", i); |
291 | if (err) | 295 | if (buf[i] & RR_NRS) |
292 | return err; | 296 | printk(KERN_INFO "NRS: Reset no presence or ...\n"); |
293 | count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | 297 | if (buf[i] & RR_SH) |
294 | if (count < 0) | 298 | printk(KERN_INFO "SH: short on reset or set path\n"); |
295 | return err; | 299 | if (buf[i] & RR_APP) |
300 | printk(KERN_INFO "APP: alarming presence on reset\n"); | ||
301 | if (buf[i] & RR_VPP) | ||
302 | printk(KERN_INFO "VPP: 12V expected not seen\n"); | ||
303 | if (buf[i] & RR_CMP) | ||
304 | printk(KERN_INFO "CMP: compare error\n"); | ||
305 | if (buf[i] & RR_CRC) | ||
306 | printk(KERN_INFO "CRC: CRC error detected\n"); | ||
307 | if (buf[i] & RR_RDP) | ||
308 | printk(KERN_INFO "RDP: redirected page\n"); | ||
309 | if (buf[i] & RR_EOS) | ||
310 | printk(KERN_INFO "EOS: end of search error\n"); | ||
296 | } | 311 | } |
297 | |||
298 | return err; | ||
299 | } | 312 | } |
300 | 313 | ||
301 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | 314 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) |
@@ -307,9 +320,14 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | |||
307 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), | 320 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
308 | buf, size, &count, 1000); | 321 | buf, size, &count, 1000); |
309 | if (err < 0) { | 322 | if (err < 0) { |
323 | u8 buf[0x20]; | ||
324 | int count; | ||
325 | |||
310 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); | 326 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); |
311 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); | 327 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); |
312 | ds_recv_status(dev, &st); | 328 | |
329 | count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | ||
330 | ds_dump_status(dev, buf, count); | ||
313 | return err; | 331 | return err; |
314 | } | 332 | } |
315 | 333 | ||
@@ -390,7 +408,7 @@ int ds_detect(struct ds_device *dev, struct ds_status *st) | |||
390 | if (err) | 408 | if (err) |
391 | return err; | 409 | return err; |
392 | 410 | ||
393 | err = ds_recv_status(dev, st); | 411 | err = ds_dump_status(dev, st); |
394 | 412 | ||
395 | return err; | 413 | return err; |
396 | } | 414 | } |
@@ -415,11 +433,27 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | |||
415 | #endif | 433 | #endif |
416 | } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); | 434 | } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); |
417 | 435 | ||
436 | if (err >= 16 && st->status & ST_EPOF) { | ||
437 | printk(KERN_INFO "Resetting device after ST_EPOF.\n"); | ||
438 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | ||
439 | /* Always dump the device status. */ | ||
440 | count = 101; | ||
441 | } | ||
442 | |||
443 | /* Dump the status for errors or if there is extended return data. | ||
444 | * The extended status includes new device detection (maybe someone | ||
445 | * can do something with it). | ||
446 | */ | ||
447 | if (err > 16 || count >= 100 || err < 0) | ||
448 | ds_dump_status(dev, buf, err); | ||
418 | 449 | ||
419 | if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) { | 450 | /* Extended data isn't an error. Well, a short is, but the dump |
420 | ds_recv_status(dev, st); | 451 | * would have already told the user that and we can't do anything |
452 | * about it in software anyway. | ||
453 | */ | ||
454 | if (count >= 100 || err < 0) | ||
421 | return -1; | 455 | return -1; |
422 | } else | 456 | else |
423 | return 0; | 457 | return 0; |
424 | } | 458 | } |
425 | 459 | ||