Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
8949d2aa | 2 | * dscore.c |
1da177e4 LT |
3 | * |
4 | * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> | |
8949d2aa | 5 | * |
1da177e4 LT |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
21 | ||
22 | #include <linux/module.h> | |
23 | #include <linux/kernel.h> | |
24 | #include <linux/mod_devicetable.h> | |
25 | #include <linux/usb.h> | |
26 | ||
81f6075e EP |
27 | #include "../w1_int.h" |
28 | #include "../w1.h" | |
29 | ||
30 | /* COMMAND TYPE CODES */ | |
31 | #define CONTROL_CMD 0x00 | |
32 | #define COMM_CMD 0x01 | |
33 | #define MODE_CMD 0x02 | |
34 | ||
35 | /* CONTROL COMMAND CODES */ | |
36 | #define CTL_RESET_DEVICE 0x0000 | |
37 | #define CTL_START_EXE 0x0001 | |
38 | #define CTL_RESUME_EXE 0x0002 | |
39 | #define CTL_HALT_EXE_IDLE 0x0003 | |
40 | #define CTL_HALT_EXE_DONE 0x0004 | |
41 | #define CTL_FLUSH_COMM_CMDS 0x0007 | |
42 | #define CTL_FLUSH_RCV_BUFFER 0x0008 | |
43 | #define CTL_FLUSH_XMT_BUFFER 0x0009 | |
44 | #define CTL_GET_COMM_CMDS 0x000A | |
45 | ||
46 | /* MODE COMMAND CODES */ | |
47 | #define MOD_PULSE_EN 0x0000 | |
48 | #define MOD_SPEED_CHANGE_EN 0x0001 | |
49 | #define MOD_1WIRE_SPEED 0x0002 | |
50 | #define MOD_STRONG_PU_DURATION 0x0003 | |
51 | #define MOD_PULLDOWN_SLEWRATE 0x0004 | |
52 | #define MOD_PROG_PULSE_DURATION 0x0005 | |
53 | #define MOD_WRITE1_LOWTIME 0x0006 | |
54 | #define MOD_DSOW0_TREC 0x0007 | |
55 | ||
56 | /* COMMUNICATION COMMAND CODES */ | |
57 | #define COMM_ERROR_ESCAPE 0x0601 | |
58 | #define COMM_SET_DURATION 0x0012 | |
59 | #define COMM_BIT_IO 0x0020 | |
60 | #define COMM_PULSE 0x0030 | |
61 | #define COMM_1_WIRE_RESET 0x0042 | |
62 | #define COMM_BYTE_IO 0x0052 | |
63 | #define COMM_MATCH_ACCESS 0x0064 | |
64 | #define COMM_BLOCK_IO 0x0074 | |
65 | #define COMM_READ_STRAIGHT 0x0080 | |
66 | #define COMM_DO_RELEASE 0x6092 | |
67 | #define COMM_SET_PATH 0x00A2 | |
68 | #define COMM_WRITE_SRAM_PAGE 0x00B2 | |
69 | #define COMM_WRITE_EPROM 0x00C4 | |
70 | #define COMM_READ_CRC_PROT_PAGE 0x00D4 | |
71 | #define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 | |
72 | #define COMM_SEARCH_ACCESS 0x00F4 | |
73 | ||
74 | /* Communication command bits */ | |
75 | #define COMM_TYPE 0x0008 | |
76 | #define COMM_SE 0x0008 | |
77 | #define COMM_D 0x0008 | |
78 | #define COMM_Z 0x0008 | |
79 | #define COMM_CH 0x0008 | |
80 | #define COMM_SM 0x0008 | |
81 | #define COMM_R 0x0008 | |
82 | #define COMM_IM 0x0001 | |
83 | ||
84 | #define COMM_PS 0x4000 | |
85 | #define COMM_PST 0x4000 | |
86 | #define COMM_CIB 0x4000 | |
87 | #define COMM_RTS 0x4000 | |
88 | #define COMM_DT 0x2000 | |
89 | #define COMM_SPU 0x1000 | |
90 | #define COMM_F 0x0800 | |
91 | #define COMM_NTP 0x0400 | |
92 | #define COMM_ICP 0x0200 | |
93 | #define COMM_RST 0x0100 | |
94 | ||
95 | #define PULSE_PROG 0x01 | |
96 | #define PULSE_SPUE 0x02 | |
97 | ||
98 | #define BRANCH_MAIN 0xCC | |
99 | #define BRANCH_AUX 0x33 | |
100 | ||
81f6075e EP |
101 | /* Status flags */ |
102 | #define ST_SPUA 0x01 /* Strong Pull-up is active */ | |
103 | #define ST_PRGA 0x02 /* 12V programming pulse is being generated */ | |
104 | #define ST_12VP 0x04 /* external 12V programming voltage is present */ | |
105 | #define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ | |
106 | #define ST_HALT 0x10 /* DS2490 is currently halted */ | |
107 | #define ST_IDLE 0x20 /* DS2490 is currently idle */ | |
108 | #define ST_EPOF 0x80 | |
109 | ||
4b9cf1bc DF |
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 | ||
81f6075e EP |
121 | #define SPEED_NORMAL 0x00 |
122 | #define SPEED_FLEXIBLE 0x01 | |
123 | #define SPEED_OVERDRIVE 0x02 | |
124 | ||
125 | #define NUM_EP 4 | |
126 | #define EP_CONTROL 0 | |
127 | #define EP_STATUS 1 | |
128 | #define EP_DATA_OUT 2 | |
129 | #define EP_DATA_IN 3 | |
130 | ||
131 | struct ds_device | |
132 | { | |
133 | struct list_head ds_entry; | |
134 | ||
135 | struct usb_device *udev; | |
136 | struct usb_interface *intf; | |
137 | ||
138 | int ep[NUM_EP]; | |
139 | ||
1f4ec2d7 DF |
140 | /* Strong PullUp |
141 | * 0: pullup not active, else duration in milliseconds | |
142 | */ | |
143 | int spu_sleep; | |
144 | ||
81f6075e EP |
145 | struct w1_bus_master master; |
146 | }; | |
147 | ||
148 | struct ds_status | |
149 | { | |
150 | u8 enable; | |
151 | u8 speed; | |
152 | u8 pullup_dur; | |
153 | u8 ppuls_dur; | |
154 | u8 pulldown_slew; | |
155 | u8 write1_time; | |
156 | u8 write0_time; | |
157 | u8 reserved0; | |
158 | u8 status; | |
159 | u8 command0; | |
160 | u8 command1; | |
161 | u8 command_buffer_status; | |
162 | u8 data_out_buffer_status; | |
163 | u8 data_in_buffer_status; | |
164 | u8 reserved1; | |
165 | u8 reserved2; | |
166 | ||
167 | }; | |
1da177e4 LT |
168 | |
169 | static struct usb_device_id ds_id_table [] = { | |
170 | { USB_DEVICE(0x04fa, 0x2490) }, | |
171 | { }, | |
172 | }; | |
173 | MODULE_DEVICE_TABLE(usb, ds_id_table); | |
174 | ||
8949d2aa EP |
175 | static int ds_probe(struct usb_interface *, const struct usb_device_id *); |
176 | static void ds_disconnect(struct usb_interface *); | |
1da177e4 | 177 | |
1da177e4 | 178 | static int ds_send_control(struct ds_device *, u16, u16); |
1da177e4 LT |
179 | static int ds_send_control_cmd(struct ds_device *, u16, u16); |
180 | ||
81f6075e | 181 | static LIST_HEAD(ds_devices); |
abd52a13 | 182 | static DEFINE_MUTEX(ds_mutex); |
1da177e4 LT |
183 | |
184 | static struct usb_driver ds_driver = { | |
1da177e4 LT |
185 | .name = "DS9490R", |
186 | .probe = ds_probe, | |
187 | .disconnect = ds_disconnect, | |
188 | .id_table = ds_id_table, | |
189 | }; | |
190 | ||
1da177e4 LT |
191 | static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) |
192 | { | |
193 | int err; | |
8949d2aa EP |
194 | |
195 | err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), | |
1da177e4 LT |
196 | CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); |
197 | if (err < 0) { | |
8949d2aa | 198 | printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", |
1da177e4 LT |
199 | value, index, err); |
200 | return err; | |
201 | } | |
202 | ||
203 | return err; | |
204 | } | |
1f4ec2d7 | 205 | |
1da177e4 LT |
206 | static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) |
207 | { | |
208 | int err; | |
8949d2aa EP |
209 | |
210 | err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), | |
1da177e4 LT |
211 | MODE_CMD, 0x40, value, index, NULL, 0, 1000); |
212 | if (err < 0) { | |
8949d2aa | 213 | printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", |
1da177e4 LT |
214 | value, index, err); |
215 | return err; | |
216 | } | |
217 | ||
218 | return err; | |
219 | } | |
1f4ec2d7 | 220 | |
1da177e4 LT |
221 | static int ds_send_control(struct ds_device *dev, u16 value, u16 index) |
222 | { | |
223 | int err; | |
8949d2aa EP |
224 | |
225 | err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), | |
1da177e4 LT |
226 | COMM_CMD, 0x40, value, index, NULL, 0, 1000); |
227 | if (err < 0) { | |
8949d2aa | 228 | printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", |
1da177e4 LT |
229 | value, index, err); |
230 | return err; | |
231 | } | |
232 | ||
233 | return err; | |
234 | } | |
235 | ||
8949d2aa EP |
236 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, |
237 | unsigned char *buf, int size) | |
1da177e4 LT |
238 | { |
239 | int count, err; | |
8949d2aa | 240 | |
e9b5a495 | 241 | memset(st, 0, sizeof(*st)); |
8949d2aa | 242 | |
1da177e4 LT |
243 | count = 0; |
244 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); | |
245 | if (err < 0) { | |
246 | printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); | |
247 | return err; | |
248 | } | |
8949d2aa | 249 | |
1da177e4 LT |
250 | if (count >= sizeof(*st)) |
251 | memcpy(st, buf, sizeof(*st)); | |
252 | ||
253 | return count; | |
254 | } | |
255 | ||
4b9cf1bc | 256 | static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) |
1da177e4 | 257 | { |
4b9cf1bc DF |
258 | printk(KERN_INFO "%45s: %8x\n", str, buf[off]); |
259 | } | |
8949d2aa | 260 | |
4b9cf1bc DF |
261 | static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count) |
262 | { | |
263 | int i; | |
8949d2aa | 264 | |
4b9cf1bc | 265 | printk(KERN_INFO "0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); |
1da177e4 LT |
266 | for (i=0; i<count; ++i) |
267 | printk("%02x ", buf[i]); | |
4b9cf1bc | 268 | printk(KERN_INFO "\n"); |
1da177e4 LT |
269 | |
270 | if (count >= 16) { | |
4b9cf1bc DF |
271 | ds_print_msg(buf, "enable flag", 0); |
272 | ds_print_msg(buf, "1-wire speed", 1); | |
273 | ds_print_msg(buf, "strong pullup duration", 2); | |
274 | ds_print_msg(buf, "programming pulse duration", 3); | |
275 | ds_print_msg(buf, "pulldown slew rate control", 4); | |
276 | ds_print_msg(buf, "write-1 low time", 5); | |
277 | ds_print_msg(buf, "data sample offset/write-0 recovery time", | |
278 | 6); | |
279 | ds_print_msg(buf, "reserved (test register)", 7); | |
280 | ds_print_msg(buf, "device status flags", 8); | |
281 | ds_print_msg(buf, "communication command byte 1", 9); | |
282 | ds_print_msg(buf, "communication command byte 2", 10); | |
283 | ds_print_msg(buf, "communication command buffer status", 11); | |
284 | ds_print_msg(buf, "1-wire data output buffer status", 12); | |
285 | ds_print_msg(buf, "1-wire data input buffer status", 13); | |
286 | ds_print_msg(buf, "reserved", 14); | |
287 | ds_print_msg(buf, "reserved", 15); | |
1da177e4 | 288 | } |
4b9cf1bc DF |
289 | for (i = 16; i < count; ++i) { |
290 | if (buf[i] == RR_DETECT) { | |
291 | ds_print_msg(buf, "new device detect", i); | |
292 | continue; | |
293 | } | |
294 | ds_print_msg(buf, "Result Register Value: ", i); | |
295 | if (buf[i] & RR_NRS) | |
296 | printk(KERN_INFO "NRS: Reset no presence or ...\n"); | |
297 | if (buf[i] & RR_SH) | |
298 | printk(KERN_INFO "SH: short on reset or set path\n"); | |
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"); | |
1da177e4 | 311 | } |
1da177e4 LT |
312 | } |
313 | ||
314 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | |
315 | { | |
316 | int count, err; | |
317 | struct ds_status st; | |
8949d2aa | 318 | |
e464af24 DF |
319 | /* Careful on size. If size is less than what is available in |
320 | * the input buffer, the device fails the bulk transfer and | |
321 | * clears the input buffer. It could read the maximum size of | |
322 | * the data buffer, but then do you return the first, last, or | |
323 | * some set of the middle size bytes? As long as the rest of | |
324 | * the code is correct there will be size bytes waiting. A | |
325 | * call to ds_wait_status will wait until the device is idle | |
326 | * and any data to be received would have been available. | |
327 | */ | |
1da177e4 | 328 | count = 0; |
8949d2aa | 329 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
1da177e4 LT |
330 | buf, size, &count, 1000); |
331 | if (err < 0) { | |
4b9cf1bc DF |
332 | u8 buf[0x20]; |
333 | int count; | |
334 | ||
1da177e4 LT |
335 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); |
336 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); | |
4b9cf1bc DF |
337 | |
338 | count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | |
339 | ds_dump_status(dev, buf, count); | |
1da177e4 LT |
340 | return err; |
341 | } | |
342 | ||
343 | #if 0 | |
344 | { | |
345 | int i; | |
346 | ||
347 | printk("%s: count=%d: ", __func__, count); | |
348 | for (i=0; i<count; ++i) | |
349 | printk("%02x ", buf[i]); | |
350 | printk("\n"); | |
351 | } | |
352 | #endif | |
353 | return count; | |
354 | } | |
355 | ||
356 | static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) | |
357 | { | |
358 | int count, err; | |
8949d2aa | 359 | |
1da177e4 LT |
360 | count = 0; |
361 | err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); | |
362 | if (err < 0) { | |
95cfaebf DF |
363 | printk(KERN_ERR "Failed to write 1-wire data to ep0x%x: " |
364 | "err=%d.\n", dev->ep[EP_DATA_OUT], err); | |
1da177e4 LT |
365 | return err; |
366 | } | |
367 | ||
368 | return err; | |
369 | } | |
370 | ||
8949d2aa EP |
371 | #if 0 |
372 | ||
1da177e4 LT |
373 | int ds_stop_pulse(struct ds_device *dev, int limit) |
374 | { | |
375 | struct ds_status st; | |
376 | int count = 0, err = 0; | |
377 | u8 buf[0x20]; | |
8949d2aa | 378 | |
1da177e4 LT |
379 | do { |
380 | err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); | |
381 | if (err) | |
382 | break; | |
383 | err = ds_send_control(dev, CTL_RESUME_EXE, 0); | |
384 | if (err) | |
385 | break; | |
386 | err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | |
387 | if (err) | |
388 | break; | |
389 | ||
390 | if ((st.status & ST_SPUA) == 0) { | |
391 | err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); | |
392 | if (err) | |
393 | break; | |
394 | } | |
395 | } while(++count < limit); | |
396 | ||
397 | return err; | |
398 | } | |
399 | ||
400 | int ds_detect(struct ds_device *dev, struct ds_status *st) | |
401 | { | |
402 | int err; | |
8949d2aa | 403 | |
1da177e4 LT |
404 | err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); |
405 | if (err) | |
406 | return err; | |
407 | ||
408 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); | |
409 | if (err) | |
410 | return err; | |
8949d2aa | 411 | |
1da177e4 LT |
412 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); |
413 | if (err) | |
414 | return err; | |
8949d2aa | 415 | |
1da177e4 LT |
416 | err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); |
417 | if (err) | |
418 | return err; | |
419 | ||
4b9cf1bc | 420 | err = ds_dump_status(dev, st); |
1da177e4 LT |
421 | |
422 | return err; | |
423 | } | |
424 | ||
8949d2aa EP |
425 | #endif /* 0 */ |
426 | ||
427 | static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | |
1da177e4 LT |
428 | { |
429 | u8 buf[0x20]; | |
430 | int err, count = 0; | |
431 | ||
432 | do { | |
433 | err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | |
434 | #if 0 | |
8949d2aa | 435 | if (err >= 0) { |
1da177e4 LT |
436 | int i; |
437 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); | |
438 | for (i=0; i<err; ++i) | |
439 | printk("%02x ", buf[i]); | |
440 | printk("\n"); | |
441 | } | |
442 | #endif | |
443 | } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); | |
444 | ||
4b9cf1bc DF |
445 | if (err >= 16 && st->status & ST_EPOF) { |
446 | printk(KERN_INFO "Resetting device after ST_EPOF.\n"); | |
447 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | |
448 | /* Always dump the device status. */ | |
449 | count = 101; | |
450 | } | |
1da177e4 | 451 | |
4b9cf1bc DF |
452 | /* Dump the status for errors or if there is extended return data. |
453 | * The extended status includes new device detection (maybe someone | |
454 | * can do something with it). | |
455 | */ | |
456 | if (err > 16 || count >= 100 || err < 0) | |
457 | ds_dump_status(dev, buf, err); | |
458 | ||
459 | /* Extended data isn't an error. Well, a short is, but the dump | |
460 | * would have already told the user that and we can't do anything | |
461 | * about it in software anyway. | |
462 | */ | |
463 | if (count >= 100 || err < 0) | |
1da177e4 | 464 | return -1; |
4b9cf1bc | 465 | else |
1da177e4 | 466 | return 0; |
1da177e4 LT |
467 | } |
468 | ||
7a4b9706 | 469 | static int ds_reset(struct ds_device *dev) |
1da177e4 LT |
470 | { |
471 | int err; | |
472 | ||
473 | //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); | |
474 | err = ds_send_control(dev, 0x43, SPEED_NORMAL); | |
475 | if (err) | |
476 | return err; | |
477 | ||
1da177e4 LT |
478 | return 0; |
479 | } | |
480 | ||
8949d2aa | 481 | #if 0 |
81f6075e | 482 | static int ds_set_speed(struct ds_device *dev, int speed) |
1da177e4 LT |
483 | { |
484 | int err; | |
bd529cfb | 485 | |
1da177e4 LT |
486 | if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) |
487 | return -EINVAL; | |
488 | ||
489 | if (speed != SPEED_OVERDRIVE) | |
490 | speed = SPEED_FLEXIBLE; | |
491 | ||
492 | speed &= 0xff; | |
8949d2aa | 493 | |
1da177e4 LT |
494 | err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); |
495 | if (err) | |
496 | return err; | |
497 | ||
498 | return err; | |
499 | } | |
8949d2aa | 500 | #endif /* 0 */ |
1da177e4 | 501 | |
1f4ec2d7 | 502 | static int ds_set_pullup(struct ds_device *dev, int delay) |
1da177e4 LT |
503 | { |
504 | int err; | |
505 | u8 del = 1 + (u8)(delay >> 4); | |
1da177e4 | 506 | |
1f4ec2d7 DF |
507 | dev->spu_sleep = 0; |
508 | err = ds_send_control_mode(dev, MOD_PULSE_EN, delay ? PULSE_SPUE : 0); | |
1da177e4 LT |
509 | if (err) |
510 | return err; | |
511 | ||
1f4ec2d7 DF |
512 | if (delay) { |
513 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); | |
514 | if (err) | |
515 | return err; | |
1da177e4 | 516 | |
1f4ec2d7 DF |
517 | /* Just storing delay would not get the trunication and |
518 | * roundup. | |
519 | */ | |
520 | dev->spu_sleep = del<<4; | |
521 | } | |
8949d2aa | 522 | |
1da177e4 LT |
523 | return err; |
524 | } | |
525 | ||
81f6075e | 526 | static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) |
1da177e4 | 527 | { |
6e10f654 | 528 | int err; |
1da177e4 | 529 | struct ds_status st; |
8949d2aa | 530 | |
6e10f654 DF |
531 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0), |
532 | 0); | |
1da177e4 LT |
533 | if (err) |
534 | return err; | |
535 | ||
6e10f654 | 536 | ds_wait_status(dev, &st); |
1da177e4 LT |
537 | |
538 | err = ds_recv_data(dev, tbit, sizeof(*tbit)); | |
539 | if (err < 0) | |
540 | return err; | |
541 | ||
542 | return 0; | |
543 | } | |
544 | ||
a08e2d33 | 545 | #if 0 |
81f6075e | 546 | static int ds_write_bit(struct ds_device *dev, u8 bit) |
1da177e4 LT |
547 | { |
548 | int err; | |
549 | struct ds_status st; | |
8949d2aa | 550 | |
e1c86d22 DF |
551 | /* Set COMM_ICP to write without a readback. Note, this will |
552 | * produce one time slot, a down followed by an up with COMM_D | |
553 | * only determing the timing. | |
554 | */ | |
555 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP | | |
556 | (bit ? COMM_D : 0), 0); | |
1da177e4 LT |
557 | if (err) |
558 | return err; | |
559 | ||
560 | ds_wait_status(dev, &st); | |
561 | ||
562 | return 0; | |
563 | } | |
a08e2d33 | 564 | #endif |
1da177e4 | 565 | |
81f6075e | 566 | static int ds_write_byte(struct ds_device *dev, u8 byte) |
1da177e4 LT |
567 | { |
568 | int err; | |
569 | struct ds_status st; | |
570 | u8 rbyte; | |
8949d2aa | 571 | |
1da177e4 LT |
572 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); |
573 | if (err) | |
574 | return err; | |
575 | ||
1f4ec2d7 DF |
576 | if (dev->spu_sleep) |
577 | msleep(dev->spu_sleep); | |
578 | ||
1da177e4 LT |
579 | err = ds_wait_status(dev, &st); |
580 | if (err) | |
581 | return err; | |
8949d2aa | 582 | |
1da177e4 LT |
583 | err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); |
584 | if (err < 0) | |
585 | return err; | |
8949d2aa | 586 | |
1da177e4 LT |
587 | return !(byte == rbyte); |
588 | } | |
589 | ||
81f6075e | 590 | static int ds_read_byte(struct ds_device *dev, u8 *byte) |
1da177e4 LT |
591 | { |
592 | int err; | |
593 | struct ds_status st; | |
594 | ||
595 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); | |
596 | if (err) | |
597 | return err; | |
598 | ||
599 | ds_wait_status(dev, &st); | |
8949d2aa | 600 | |
1da177e4 LT |
601 | err = ds_recv_data(dev, byte, sizeof(*byte)); |
602 | if (err < 0) | |
603 | return err; | |
604 | ||
605 | return 0; | |
606 | } | |
607 | ||
81f6075e | 608 | static int ds_read_block(struct ds_device *dev, u8 *buf, int len) |
1da177e4 LT |
609 | { |
610 | struct ds_status st; | |
611 | int err; | |
612 | ||
613 | if (len > 64*1024) | |
614 | return -E2BIG; | |
615 | ||
616 | memset(buf, 0xFF, len); | |
8949d2aa | 617 | |
1da177e4 LT |
618 | err = ds_send_data(dev, buf, len); |
619 | if (err < 0) | |
620 | return err; | |
8949d2aa | 621 | |
1f4ec2d7 | 622 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len); |
1da177e4 LT |
623 | if (err) |
624 | return err; | |
625 | ||
626 | ds_wait_status(dev, &st); | |
8949d2aa | 627 | |
1da177e4 LT |
628 | memset(buf, 0x00, len); |
629 | err = ds_recv_data(dev, buf, len); | |
630 | ||
631 | return err; | |
632 | } | |
633 | ||
81f6075e | 634 | static int ds_write_block(struct ds_device *dev, u8 *buf, int len) |
1da177e4 LT |
635 | { |
636 | int err; | |
637 | struct ds_status st; | |
8949d2aa | 638 | |
1da177e4 LT |
639 | err = ds_send_data(dev, buf, len); |
640 | if (err < 0) | |
641 | return err; | |
8949d2aa | 642 | |
1da177e4 LT |
643 | ds_wait_status(dev, &st); |
644 | ||
645 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); | |
646 | if (err) | |
647 | return err; | |
648 | ||
1f4ec2d7 DF |
649 | if (dev->spu_sleep) |
650 | msleep(dev->spu_sleep); | |
651 | ||
1da177e4 LT |
652 | ds_wait_status(dev, &st); |
653 | ||
654 | err = ds_recv_data(dev, buf, len); | |
655 | if (err < 0) | |
656 | return err; | |
657 | ||
1da177e4 LT |
658 | return !(err == len); |
659 | } | |
660 | ||
8949d2aa EP |
661 | #if 0 |
662 | ||
81f6075e | 663 | static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) |
1da177e4 LT |
664 | { |
665 | int err; | |
666 | u16 value, index; | |
667 | struct ds_status st; | |
668 | ||
669 | memset(buf, 0, sizeof(buf)); | |
8949d2aa | 670 | |
1da177e4 LT |
671 | err = ds_send_data(ds_dev, (unsigned char *)&init, 8); |
672 | if (err) | |
673 | return err; | |
8949d2aa | 674 | |
1da177e4 LT |
675 | ds_wait_status(ds_dev, &st); |
676 | ||
677 | value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; | |
678 | index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); | |
679 | err = ds_send_control(ds_dev, value, index); | |
680 | if (err) | |
681 | return err; | |
682 | ||
683 | ds_wait_status(ds_dev, &st); | |
684 | ||
685 | err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); | |
686 | if (err < 0) | |
687 | return err; | |
688 | ||
689 | return err/8; | |
690 | } | |
691 | ||
81f6075e | 692 | static int ds_match_access(struct ds_device *dev, u64 init) |
1da177e4 LT |
693 | { |
694 | int err; | |
695 | struct ds_status st; | |
696 | ||
697 | err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); | |
698 | if (err) | |
699 | return err; | |
8949d2aa | 700 | |
1da177e4 LT |
701 | ds_wait_status(dev, &st); |
702 | ||
703 | err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); | |
704 | if (err) | |
705 | return err; | |
706 | ||
707 | ds_wait_status(dev, &st); | |
708 | ||
709 | return 0; | |
710 | } | |
711 | ||
81f6075e | 712 | static int ds_set_path(struct ds_device *dev, u64 init) |
1da177e4 LT |
713 | { |
714 | int err; | |
715 | struct ds_status st; | |
716 | u8 buf[9]; | |
717 | ||
718 | memcpy(buf, &init, 8); | |
719 | buf[8] = BRANCH_MAIN; | |
8949d2aa | 720 | |
1da177e4 LT |
721 | err = ds_send_data(dev, buf, sizeof(buf)); |
722 | if (err) | |
723 | return err; | |
8949d2aa | 724 | |
1da177e4 LT |
725 | ds_wait_status(dev, &st); |
726 | ||
727 | err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); | |
728 | if (err) | |
729 | return err; | |
730 | ||
731 | ds_wait_status(dev, &st); | |
732 | ||
733 | return 0; | |
734 | } | |
735 | ||
8949d2aa EP |
736 | #endif /* 0 */ |
737 | ||
81f6075e EP |
738 | static u8 ds9490r_touch_bit(void *data, u8 bit) |
739 | { | |
740 | u8 ret; | |
741 | struct ds_device *dev = data; | |
742 | ||
743 | if (ds_touch_bit(dev, bit, &ret)) | |
744 | return 0; | |
745 | ||
746 | return ret; | |
747 | } | |
748 | ||
a08e2d33 | 749 | #if 0 |
81f6075e EP |
750 | static void ds9490r_write_bit(void *data, u8 bit) |
751 | { | |
752 | struct ds_device *dev = data; | |
753 | ||
754 | ds_write_bit(dev, bit); | |
755 | } | |
756 | ||
81f6075e EP |
757 | static u8 ds9490r_read_bit(void *data) |
758 | { | |
759 | struct ds_device *dev = data; | |
760 | int err; | |
761 | u8 bit = 0; | |
762 | ||
763 | err = ds_touch_bit(dev, 1, &bit); | |
764 | if (err) | |
765 | return 0; | |
766 | ||
767 | return bit & 1; | |
768 | } | |
a08e2d33 DF |
769 | #endif |
770 | ||
771 | static void ds9490r_write_byte(void *data, u8 byte) | |
772 | { | |
773 | struct ds_device *dev = data; | |
774 | ||
775 | ds_write_byte(dev, byte); | |
776 | } | |
81f6075e EP |
777 | |
778 | static u8 ds9490r_read_byte(void *data) | |
779 | { | |
780 | struct ds_device *dev = data; | |
781 | int err; | |
782 | u8 byte = 0; | |
783 | ||
784 | err = ds_read_byte(dev, &byte); | |
785 | if (err) | |
786 | return 0; | |
787 | ||
788 | return byte; | |
789 | } | |
790 | ||
791 | static void ds9490r_write_block(void *data, const u8 *buf, int len) | |
792 | { | |
793 | struct ds_device *dev = data; | |
794 | ||
795 | ds_write_block(dev, (u8 *)buf, len); | |
796 | } | |
797 | ||
798 | static u8 ds9490r_read_block(void *data, u8 *buf, int len) | |
799 | { | |
800 | struct ds_device *dev = data; | |
801 | int err; | |
802 | ||
803 | err = ds_read_block(dev, buf, len); | |
804 | if (err < 0) | |
805 | return 0; | |
806 | ||
807 | return len; | |
808 | } | |
809 | ||
810 | static u8 ds9490r_reset(void *data) | |
811 | { | |
812 | struct ds_device *dev = data; | |
81f6075e EP |
813 | int err; |
814 | ||
7a4b9706 | 815 | err = ds_reset(dev); |
81f6075e EP |
816 | if (err) |
817 | return 1; | |
818 | ||
819 | return 0; | |
820 | } | |
821 | ||
1f4ec2d7 DF |
822 | static u8 ds9490r_set_pullup(void *data, int delay) |
823 | { | |
824 | struct ds_device *dev = data; | |
825 | ||
826 | if (ds_set_pullup(dev, delay)) | |
827 | return 1; | |
828 | ||
829 | return 0; | |
830 | } | |
831 | ||
81f6075e EP |
832 | static int ds_w1_init(struct ds_device *dev) |
833 | { | |
834 | memset(&dev->master, 0, sizeof(struct w1_bus_master)); | |
835 | ||
e464af24 DF |
836 | /* Reset the device as it can be in a bad state. |
837 | * This is necessary because a block write will wait for data | |
838 | * to be placed in the output buffer and block any later | |
839 | * commands which will keep accumulating and the device will | |
840 | * not be idle. Another case is removing the ds2490 module | |
841 | * while a bus search is in progress, somehow a few commands | |
842 | * get through, but the input transfers fail leaving data in | |
843 | * the input buffer. This will cause the next read to fail | |
844 | * see the note in ds_recv_data. | |
845 | */ | |
846 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | |
847 | ||
81f6075e EP |
848 | dev->master.data = dev; |
849 | dev->master.touch_bit = &ds9490r_touch_bit; | |
a08e2d33 DF |
850 | /* read_bit and write_bit in w1_bus_master are expected to set and |
851 | * sample the line level. For write_bit that means it is expected to | |
852 | * set it to that value and leave it there. ds2490 only supports an | |
853 | * individual time slot at the lowest level. The requirement from | |
854 | * pulling the bus state down to reading the state is 15us, something | |
855 | * that isn't realistic on the USB bus anyway. | |
81f6075e EP |
856 | dev->master.read_bit = &ds9490r_read_bit; |
857 | dev->master.write_bit = &ds9490r_write_bit; | |
a08e2d33 | 858 | */ |
81f6075e EP |
859 | dev->master.read_byte = &ds9490r_read_byte; |
860 | dev->master.write_byte = &ds9490r_write_byte; | |
861 | dev->master.read_block = &ds9490r_read_block; | |
862 | dev->master.write_block = &ds9490r_write_block; | |
863 | dev->master.reset_bus = &ds9490r_reset; | |
1f4ec2d7 | 864 | dev->master.set_pullup = &ds9490r_set_pullup; |
81f6075e EP |
865 | |
866 | return w1_add_master_device(&dev->master); | |
867 | } | |
868 | ||
869 | static void ds_w1_fini(struct ds_device *dev) | |
870 | { | |
871 | w1_remove_master_device(&dev->master); | |
872 | } | |
873 | ||
8949d2aa EP |
874 | static int ds_probe(struct usb_interface *intf, |
875 | const struct usb_device_id *udev_id) | |
1da177e4 LT |
876 | { |
877 | struct usb_device *udev = interface_to_usbdev(intf); | |
878 | struct usb_endpoint_descriptor *endpoint; | |
879 | struct usb_host_interface *iface_desc; | |
81f6075e | 880 | struct ds_device *dev; |
1da177e4 LT |
881 | int i, err; |
882 | ||
81f6075e EP |
883 | dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); |
884 | if (!dev) { | |
1da177e4 LT |
885 | printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); |
886 | return -ENOMEM; | |
887 | } | |
1f4ec2d7 | 888 | dev->spu_sleep = 0; |
81f6075e EP |
889 | dev->udev = usb_get_dev(udev); |
890 | if (!dev->udev) { | |
891 | err = -ENOMEM; | |
892 | goto err_out_free; | |
893 | } | |
894 | memset(dev->ep, 0, sizeof(dev->ep)); | |
1da177e4 | 895 | |
81f6075e | 896 | usb_set_intfdata(intf, dev); |
1da177e4 | 897 | |
81f6075e | 898 | err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); |
1da177e4 LT |
899 | if (err) { |
900 | printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", | |
901 | intf->altsetting[0].desc.bInterfaceNumber, err); | |
81f6075e | 902 | goto err_out_clear; |
1da177e4 LT |
903 | } |
904 | ||
81f6075e | 905 | err = usb_reset_configuration(dev->udev); |
1da177e4 LT |
906 | if (err) { |
907 | printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); | |
81f6075e | 908 | goto err_out_clear; |
1da177e4 | 909 | } |
8949d2aa | 910 | |
1da177e4 LT |
911 | iface_desc = &intf->altsetting[0]; |
912 | if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { | |
913 | printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); | |
81f6075e EP |
914 | err = -EINVAL; |
915 | goto err_out_clear; | |
1da177e4 LT |
916 | } |
917 | ||
1da177e4 | 918 | /* |
8949d2aa | 919 | * This loop doesn'd show control 0 endpoint, |
1da177e4 LT |
920 | * so we will fill only 1-3 endpoints entry. |
921 | */ | |
922 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | |
923 | endpoint = &iface_desc->endpoint[i].desc; | |
924 | ||
81f6075e EP |
925 | dev->ep[i+1] = endpoint->bEndpointAddress; |
926 | #if 0 | |
1da177e4 LT |
927 | printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", |
928 | i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), | |
929 | (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", | |
930 | endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); | |
81f6075e | 931 | #endif |
1da177e4 | 932 | } |
8949d2aa | 933 | |
81f6075e EP |
934 | err = ds_w1_init(dev); |
935 | if (err) | |
936 | goto err_out_clear; | |
8949d2aa | 937 | |
abd52a13 | 938 | mutex_lock(&ds_mutex); |
81f6075e | 939 | list_add_tail(&dev->ds_entry, &ds_devices); |
abd52a13 | 940 | mutex_unlock(&ds_mutex); |
1da177e4 LT |
941 | |
942 | return 0; | |
81f6075e EP |
943 | |
944 | err_out_clear: | |
945 | usb_set_intfdata(intf, NULL); | |
946 | usb_put_dev(dev->udev); | |
947 | err_out_free: | |
948 | kfree(dev); | |
949 | return err; | |
1da177e4 LT |
950 | } |
951 | ||
8949d2aa | 952 | static void ds_disconnect(struct usb_interface *intf) |
1da177e4 LT |
953 | { |
954 | struct ds_device *dev; | |
8949d2aa | 955 | |
1da177e4 | 956 | dev = usb_get_intfdata(intf); |
81f6075e EP |
957 | if (!dev) |
958 | return; | |
1da177e4 | 959 | |
abd52a13 | 960 | mutex_lock(&ds_mutex); |
81f6075e | 961 | list_del(&dev->ds_entry); |
abd52a13 | 962 | mutex_unlock(&ds_mutex); |
1da177e4 | 963 | |
81f6075e EP |
964 | ds_w1_fini(dev); |
965 | ||
966 | usb_set_intfdata(intf, NULL); | |
1da177e4 LT |
967 | |
968 | usb_put_dev(dev->udev); | |
969 | kfree(dev); | |
1da177e4 LT |
970 | } |
971 | ||
8949d2aa | 972 | static int ds_init(void) |
1da177e4 LT |
973 | { |
974 | int err; | |
975 | ||
976 | err = usb_register(&ds_driver); | |
977 | if (err) { | |
978 | printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); | |
979 | return err; | |
980 | } | |
981 | ||
982 | return 0; | |
983 | } | |
984 | ||
8949d2aa | 985 | static void ds_fini(void) |
1da177e4 LT |
986 | { |
987 | usb_deregister(&ds_driver); | |
988 | } | |
989 | ||
990 | module_init(ds_init); | |
991 | module_exit(ds_fini); | |
992 | ||
993 | MODULE_LICENSE("GPL"); | |
994 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | |
81f6075e | 995 | MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); |