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 | |
1da177e4 | 319 | count = 0; |
8949d2aa | 320 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
1da177e4 LT |
321 | buf, size, &count, 1000); |
322 | if (err < 0) { | |
4b9cf1bc DF |
323 | u8 buf[0x20]; |
324 | int count; | |
325 | ||
1da177e4 LT |
326 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); |
327 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); | |
4b9cf1bc DF |
328 | |
329 | count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | |
330 | ds_dump_status(dev, buf, count); | |
1da177e4 LT |
331 | return err; |
332 | } | |
333 | ||
334 | #if 0 | |
335 | { | |
336 | int i; | |
337 | ||
338 | printk("%s: count=%d: ", __func__, count); | |
339 | for (i=0; i<count; ++i) | |
340 | printk("%02x ", buf[i]); | |
341 | printk("\n"); | |
342 | } | |
343 | #endif | |
344 | return count; | |
345 | } | |
346 | ||
347 | static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) | |
348 | { | |
349 | int count, err; | |
8949d2aa | 350 | |
1da177e4 LT |
351 | count = 0; |
352 | err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); | |
353 | if (err < 0) { | |
95cfaebf DF |
354 | printk(KERN_ERR "Failed to write 1-wire data to ep0x%x: " |
355 | "err=%d.\n", dev->ep[EP_DATA_OUT], err); | |
1da177e4 LT |
356 | return err; |
357 | } | |
358 | ||
359 | return err; | |
360 | } | |
361 | ||
8949d2aa EP |
362 | #if 0 |
363 | ||
1da177e4 LT |
364 | int ds_stop_pulse(struct ds_device *dev, int limit) |
365 | { | |
366 | struct ds_status st; | |
367 | int count = 0, err = 0; | |
368 | u8 buf[0x20]; | |
8949d2aa | 369 | |
1da177e4 LT |
370 | do { |
371 | err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); | |
372 | if (err) | |
373 | break; | |
374 | err = ds_send_control(dev, CTL_RESUME_EXE, 0); | |
375 | if (err) | |
376 | break; | |
377 | err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | |
378 | if (err) | |
379 | break; | |
380 | ||
381 | if ((st.status & ST_SPUA) == 0) { | |
382 | err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); | |
383 | if (err) | |
384 | break; | |
385 | } | |
386 | } while(++count < limit); | |
387 | ||
388 | return err; | |
389 | } | |
390 | ||
391 | int ds_detect(struct ds_device *dev, struct ds_status *st) | |
392 | { | |
393 | int err; | |
8949d2aa | 394 | |
1da177e4 LT |
395 | err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); |
396 | if (err) | |
397 | return err; | |
398 | ||
399 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); | |
400 | if (err) | |
401 | return err; | |
8949d2aa | 402 | |
1da177e4 LT |
403 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); |
404 | if (err) | |
405 | return err; | |
8949d2aa | 406 | |
1da177e4 LT |
407 | err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); |
408 | if (err) | |
409 | return err; | |
410 | ||
4b9cf1bc | 411 | err = ds_dump_status(dev, st); |
1da177e4 LT |
412 | |
413 | return err; | |
414 | } | |
415 | ||
8949d2aa EP |
416 | #endif /* 0 */ |
417 | ||
418 | static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | |
1da177e4 LT |
419 | { |
420 | u8 buf[0x20]; | |
421 | int err, count = 0; | |
422 | ||
423 | do { | |
424 | err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | |
425 | #if 0 | |
8949d2aa | 426 | if (err >= 0) { |
1da177e4 LT |
427 | int i; |
428 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); | |
429 | for (i=0; i<err; ++i) | |
430 | printk("%02x ", buf[i]); | |
431 | printk("\n"); | |
432 | } | |
433 | #endif | |
434 | } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); | |
435 | ||
4b9cf1bc DF |
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 | } | |
1da177e4 | 442 | |
4b9cf1bc DF |
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); | |
449 | ||
450 | /* Extended data isn't an error. Well, a short is, but the dump | |
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) | |
1da177e4 | 455 | return -1; |
4b9cf1bc | 456 | else |
1da177e4 | 457 | return 0; |
1da177e4 LT |
458 | } |
459 | ||
7a4b9706 | 460 | static int ds_reset(struct ds_device *dev) |
1da177e4 LT |
461 | { |
462 | int err; | |
463 | ||
464 | //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); | |
465 | err = ds_send_control(dev, 0x43, SPEED_NORMAL); | |
466 | if (err) | |
467 | return err; | |
468 | ||
1da177e4 LT |
469 | return 0; |
470 | } | |
471 | ||
8949d2aa | 472 | #if 0 |
81f6075e | 473 | static int ds_set_speed(struct ds_device *dev, int speed) |
1da177e4 LT |
474 | { |
475 | int err; | |
bd529cfb | 476 | |
1da177e4 LT |
477 | if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) |
478 | return -EINVAL; | |
479 | ||
480 | if (speed != SPEED_OVERDRIVE) | |
481 | speed = SPEED_FLEXIBLE; | |
482 | ||
483 | speed &= 0xff; | |
8949d2aa | 484 | |
1da177e4 LT |
485 | err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); |
486 | if (err) | |
487 | return err; | |
488 | ||
489 | return err; | |
490 | } | |
8949d2aa | 491 | #endif /* 0 */ |
1da177e4 | 492 | |
1f4ec2d7 | 493 | static int ds_set_pullup(struct ds_device *dev, int delay) |
1da177e4 LT |
494 | { |
495 | int err; | |
496 | u8 del = 1 + (u8)(delay >> 4); | |
1da177e4 | 497 | |
1f4ec2d7 DF |
498 | dev->spu_sleep = 0; |
499 | err = ds_send_control_mode(dev, MOD_PULSE_EN, delay ? PULSE_SPUE : 0); | |
1da177e4 LT |
500 | if (err) |
501 | return err; | |
502 | ||
1f4ec2d7 DF |
503 | if (delay) { |
504 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); | |
505 | if (err) | |
506 | return err; | |
1da177e4 | 507 | |
1f4ec2d7 DF |
508 | /* Just storing delay would not get the trunication and |
509 | * roundup. | |
510 | */ | |
511 | dev->spu_sleep = del<<4; | |
512 | } | |
8949d2aa | 513 | |
1da177e4 LT |
514 | return err; |
515 | } | |
516 | ||
81f6075e | 517 | static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) |
1da177e4 | 518 | { |
6e10f654 | 519 | int err; |
1da177e4 | 520 | struct ds_status st; |
8949d2aa | 521 | |
6e10f654 DF |
522 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0), |
523 | 0); | |
1da177e4 LT |
524 | if (err) |
525 | return err; | |
526 | ||
6e10f654 | 527 | ds_wait_status(dev, &st); |
1da177e4 LT |
528 | |
529 | err = ds_recv_data(dev, tbit, sizeof(*tbit)); | |
530 | if (err < 0) | |
531 | return err; | |
532 | ||
533 | return 0; | |
534 | } | |
535 | ||
a08e2d33 | 536 | #if 0 |
81f6075e | 537 | static int ds_write_bit(struct ds_device *dev, u8 bit) |
1da177e4 LT |
538 | { |
539 | int err; | |
540 | struct ds_status st; | |
8949d2aa | 541 | |
e1c86d22 DF |
542 | /* Set COMM_ICP to write without a readback. Note, this will |
543 | * produce one time slot, a down followed by an up with COMM_D | |
544 | * only determing the timing. | |
545 | */ | |
546 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP | | |
547 | (bit ? COMM_D : 0), 0); | |
1da177e4 LT |
548 | if (err) |
549 | return err; | |
550 | ||
551 | ds_wait_status(dev, &st); | |
552 | ||
553 | return 0; | |
554 | } | |
a08e2d33 | 555 | #endif |
1da177e4 | 556 | |
81f6075e | 557 | static int ds_write_byte(struct ds_device *dev, u8 byte) |
1da177e4 LT |
558 | { |
559 | int err; | |
560 | struct ds_status st; | |
561 | u8 rbyte; | |
8949d2aa | 562 | |
1da177e4 LT |
563 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); |
564 | if (err) | |
565 | return err; | |
566 | ||
1f4ec2d7 DF |
567 | if (dev->spu_sleep) |
568 | msleep(dev->spu_sleep); | |
569 | ||
1da177e4 LT |
570 | err = ds_wait_status(dev, &st); |
571 | if (err) | |
572 | return err; | |
8949d2aa | 573 | |
1da177e4 LT |
574 | err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); |
575 | if (err < 0) | |
576 | return err; | |
8949d2aa | 577 | |
1da177e4 LT |
578 | return !(byte == rbyte); |
579 | } | |
580 | ||
81f6075e | 581 | static int ds_read_byte(struct ds_device *dev, u8 *byte) |
1da177e4 LT |
582 | { |
583 | int err; | |
584 | struct ds_status st; | |
585 | ||
586 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); | |
587 | if (err) | |
588 | return err; | |
589 | ||
590 | ds_wait_status(dev, &st); | |
8949d2aa | 591 | |
1da177e4 LT |
592 | err = ds_recv_data(dev, byte, sizeof(*byte)); |
593 | if (err < 0) | |
594 | return err; | |
595 | ||
596 | return 0; | |
597 | } | |
598 | ||
81f6075e | 599 | static int ds_read_block(struct ds_device *dev, u8 *buf, int len) |
1da177e4 LT |
600 | { |
601 | struct ds_status st; | |
602 | int err; | |
603 | ||
604 | if (len > 64*1024) | |
605 | return -E2BIG; | |
606 | ||
607 | memset(buf, 0xFF, len); | |
8949d2aa | 608 | |
1da177e4 LT |
609 | err = ds_send_data(dev, buf, len); |
610 | if (err < 0) | |
611 | return err; | |
8949d2aa | 612 | |
1f4ec2d7 | 613 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len); |
1da177e4 LT |
614 | if (err) |
615 | return err; | |
616 | ||
617 | ds_wait_status(dev, &st); | |
8949d2aa | 618 | |
1da177e4 LT |
619 | memset(buf, 0x00, len); |
620 | err = ds_recv_data(dev, buf, len); | |
621 | ||
622 | return err; | |
623 | } | |
624 | ||
81f6075e | 625 | static int ds_write_block(struct ds_device *dev, u8 *buf, int len) |
1da177e4 LT |
626 | { |
627 | int err; | |
628 | struct ds_status st; | |
8949d2aa | 629 | |
1da177e4 LT |
630 | err = ds_send_data(dev, buf, len); |
631 | if (err < 0) | |
632 | return err; | |
8949d2aa | 633 | |
1da177e4 LT |
634 | ds_wait_status(dev, &st); |
635 | ||
636 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); | |
637 | if (err) | |
638 | return err; | |
639 | ||
1f4ec2d7 DF |
640 | if (dev->spu_sleep) |
641 | msleep(dev->spu_sleep); | |
642 | ||
1da177e4 LT |
643 | ds_wait_status(dev, &st); |
644 | ||
645 | err = ds_recv_data(dev, buf, len); | |
646 | if (err < 0) | |
647 | return err; | |
648 | ||
1da177e4 LT |
649 | return !(err == len); |
650 | } | |
651 | ||
8949d2aa EP |
652 | #if 0 |
653 | ||
81f6075e | 654 | static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) |
1da177e4 LT |
655 | { |
656 | int err; | |
657 | u16 value, index; | |
658 | struct ds_status st; | |
659 | ||
660 | memset(buf, 0, sizeof(buf)); | |
8949d2aa | 661 | |
1da177e4 LT |
662 | err = ds_send_data(ds_dev, (unsigned char *)&init, 8); |
663 | if (err) | |
664 | return err; | |
8949d2aa | 665 | |
1da177e4 LT |
666 | ds_wait_status(ds_dev, &st); |
667 | ||
668 | value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; | |
669 | index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); | |
670 | err = ds_send_control(ds_dev, value, index); | |
671 | if (err) | |
672 | return err; | |
673 | ||
674 | ds_wait_status(ds_dev, &st); | |
675 | ||
676 | err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); | |
677 | if (err < 0) | |
678 | return err; | |
679 | ||
680 | return err/8; | |
681 | } | |
682 | ||
81f6075e | 683 | static int ds_match_access(struct ds_device *dev, u64 init) |
1da177e4 LT |
684 | { |
685 | int err; | |
686 | struct ds_status st; | |
687 | ||
688 | err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); | |
689 | if (err) | |
690 | return err; | |
8949d2aa | 691 | |
1da177e4 LT |
692 | ds_wait_status(dev, &st); |
693 | ||
694 | err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); | |
695 | if (err) | |
696 | return err; | |
697 | ||
698 | ds_wait_status(dev, &st); | |
699 | ||
700 | return 0; | |
701 | } | |
702 | ||
81f6075e | 703 | static int ds_set_path(struct ds_device *dev, u64 init) |
1da177e4 LT |
704 | { |
705 | int err; | |
706 | struct ds_status st; | |
707 | u8 buf[9]; | |
708 | ||
709 | memcpy(buf, &init, 8); | |
710 | buf[8] = BRANCH_MAIN; | |
8949d2aa | 711 | |
1da177e4 LT |
712 | err = ds_send_data(dev, buf, sizeof(buf)); |
713 | if (err) | |
714 | return err; | |
8949d2aa | 715 | |
1da177e4 LT |
716 | ds_wait_status(dev, &st); |
717 | ||
718 | err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); | |
719 | if (err) | |
720 | return err; | |
721 | ||
722 | ds_wait_status(dev, &st); | |
723 | ||
724 | return 0; | |
725 | } | |
726 | ||
8949d2aa EP |
727 | #endif /* 0 */ |
728 | ||
81f6075e EP |
729 | static u8 ds9490r_touch_bit(void *data, u8 bit) |
730 | { | |
731 | u8 ret; | |
732 | struct ds_device *dev = data; | |
733 | ||
734 | if (ds_touch_bit(dev, bit, &ret)) | |
735 | return 0; | |
736 | ||
737 | return ret; | |
738 | } | |
739 | ||
a08e2d33 | 740 | #if 0 |
81f6075e EP |
741 | static void ds9490r_write_bit(void *data, u8 bit) |
742 | { | |
743 | struct ds_device *dev = data; | |
744 | ||
745 | ds_write_bit(dev, bit); | |
746 | } | |
747 | ||
81f6075e EP |
748 | static u8 ds9490r_read_bit(void *data) |
749 | { | |
750 | struct ds_device *dev = data; | |
751 | int err; | |
752 | u8 bit = 0; | |
753 | ||
754 | err = ds_touch_bit(dev, 1, &bit); | |
755 | if (err) | |
756 | return 0; | |
757 | ||
758 | return bit & 1; | |
759 | } | |
a08e2d33 DF |
760 | #endif |
761 | ||
762 | static void ds9490r_write_byte(void *data, u8 byte) | |
763 | { | |
764 | struct ds_device *dev = data; | |
765 | ||
766 | ds_write_byte(dev, byte); | |
767 | } | |
81f6075e EP |
768 | |
769 | static u8 ds9490r_read_byte(void *data) | |
770 | { | |
771 | struct ds_device *dev = data; | |
772 | int err; | |
773 | u8 byte = 0; | |
774 | ||
775 | err = ds_read_byte(dev, &byte); | |
776 | if (err) | |
777 | return 0; | |
778 | ||
779 | return byte; | |
780 | } | |
781 | ||
782 | static void ds9490r_write_block(void *data, const u8 *buf, int len) | |
783 | { | |
784 | struct ds_device *dev = data; | |
785 | ||
786 | ds_write_block(dev, (u8 *)buf, len); | |
787 | } | |
788 | ||
789 | static u8 ds9490r_read_block(void *data, u8 *buf, int len) | |
790 | { | |
791 | struct ds_device *dev = data; | |
792 | int err; | |
793 | ||
794 | err = ds_read_block(dev, buf, len); | |
795 | if (err < 0) | |
796 | return 0; | |
797 | ||
798 | return len; | |
799 | } | |
800 | ||
801 | static u8 ds9490r_reset(void *data) | |
802 | { | |
803 | struct ds_device *dev = data; | |
81f6075e EP |
804 | int err; |
805 | ||
7a4b9706 | 806 | err = ds_reset(dev); |
81f6075e EP |
807 | if (err) |
808 | return 1; | |
809 | ||
810 | return 0; | |
811 | } | |
812 | ||
1f4ec2d7 DF |
813 | static u8 ds9490r_set_pullup(void *data, int delay) |
814 | { | |
815 | struct ds_device *dev = data; | |
816 | ||
817 | if (ds_set_pullup(dev, delay)) | |
818 | return 1; | |
819 | ||
820 | return 0; | |
821 | } | |
822 | ||
81f6075e EP |
823 | static int ds_w1_init(struct ds_device *dev) |
824 | { | |
825 | memset(&dev->master, 0, sizeof(struct w1_bus_master)); | |
826 | ||
827 | dev->master.data = dev; | |
828 | dev->master.touch_bit = &ds9490r_touch_bit; | |
a08e2d33 DF |
829 | /* read_bit and write_bit in w1_bus_master are expected to set and |
830 | * sample the line level. For write_bit that means it is expected to | |
831 | * set it to that value and leave it there. ds2490 only supports an | |
832 | * individual time slot at the lowest level. The requirement from | |
833 | * pulling the bus state down to reading the state is 15us, something | |
834 | * that isn't realistic on the USB bus anyway. | |
81f6075e EP |
835 | dev->master.read_bit = &ds9490r_read_bit; |
836 | dev->master.write_bit = &ds9490r_write_bit; | |
a08e2d33 | 837 | */ |
81f6075e EP |
838 | dev->master.read_byte = &ds9490r_read_byte; |
839 | dev->master.write_byte = &ds9490r_write_byte; | |
840 | dev->master.read_block = &ds9490r_read_block; | |
841 | dev->master.write_block = &ds9490r_write_block; | |
842 | dev->master.reset_bus = &ds9490r_reset; | |
1f4ec2d7 | 843 | dev->master.set_pullup = &ds9490r_set_pullup; |
81f6075e EP |
844 | |
845 | return w1_add_master_device(&dev->master); | |
846 | } | |
847 | ||
848 | static void ds_w1_fini(struct ds_device *dev) | |
849 | { | |
850 | w1_remove_master_device(&dev->master); | |
851 | } | |
852 | ||
8949d2aa EP |
853 | static int ds_probe(struct usb_interface *intf, |
854 | const struct usb_device_id *udev_id) | |
1da177e4 LT |
855 | { |
856 | struct usb_device *udev = interface_to_usbdev(intf); | |
857 | struct usb_endpoint_descriptor *endpoint; | |
858 | struct usb_host_interface *iface_desc; | |
81f6075e | 859 | struct ds_device *dev; |
1da177e4 LT |
860 | int i, err; |
861 | ||
81f6075e EP |
862 | dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); |
863 | if (!dev) { | |
1da177e4 LT |
864 | printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); |
865 | return -ENOMEM; | |
866 | } | |
1f4ec2d7 | 867 | dev->spu_sleep = 0; |
81f6075e EP |
868 | dev->udev = usb_get_dev(udev); |
869 | if (!dev->udev) { | |
870 | err = -ENOMEM; | |
871 | goto err_out_free; | |
872 | } | |
873 | memset(dev->ep, 0, sizeof(dev->ep)); | |
1da177e4 | 874 | |
81f6075e | 875 | usb_set_intfdata(intf, dev); |
1da177e4 | 876 | |
81f6075e | 877 | err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); |
1da177e4 LT |
878 | if (err) { |
879 | printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", | |
880 | intf->altsetting[0].desc.bInterfaceNumber, err); | |
81f6075e | 881 | goto err_out_clear; |
1da177e4 LT |
882 | } |
883 | ||
81f6075e | 884 | err = usb_reset_configuration(dev->udev); |
1da177e4 LT |
885 | if (err) { |
886 | printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); | |
81f6075e | 887 | goto err_out_clear; |
1da177e4 | 888 | } |
8949d2aa | 889 | |
1da177e4 LT |
890 | iface_desc = &intf->altsetting[0]; |
891 | if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { | |
892 | printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); | |
81f6075e EP |
893 | err = -EINVAL; |
894 | goto err_out_clear; | |
1da177e4 LT |
895 | } |
896 | ||
1da177e4 | 897 | /* |
8949d2aa | 898 | * This loop doesn'd show control 0 endpoint, |
1da177e4 LT |
899 | * so we will fill only 1-3 endpoints entry. |
900 | */ | |
901 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | |
902 | endpoint = &iface_desc->endpoint[i].desc; | |
903 | ||
81f6075e EP |
904 | dev->ep[i+1] = endpoint->bEndpointAddress; |
905 | #if 0 | |
1da177e4 LT |
906 | printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", |
907 | i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), | |
908 | (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", | |
909 | endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); | |
81f6075e | 910 | #endif |
1da177e4 | 911 | } |
8949d2aa | 912 | |
81f6075e EP |
913 | err = ds_w1_init(dev); |
914 | if (err) | |
915 | goto err_out_clear; | |
8949d2aa | 916 | |
abd52a13 | 917 | mutex_lock(&ds_mutex); |
81f6075e | 918 | list_add_tail(&dev->ds_entry, &ds_devices); |
abd52a13 | 919 | mutex_unlock(&ds_mutex); |
1da177e4 LT |
920 | |
921 | return 0; | |
81f6075e EP |
922 | |
923 | err_out_clear: | |
924 | usb_set_intfdata(intf, NULL); | |
925 | usb_put_dev(dev->udev); | |
926 | err_out_free: | |
927 | kfree(dev); | |
928 | return err; | |
1da177e4 LT |
929 | } |
930 | ||
8949d2aa | 931 | static void ds_disconnect(struct usb_interface *intf) |
1da177e4 LT |
932 | { |
933 | struct ds_device *dev; | |
8949d2aa | 934 | |
1da177e4 | 935 | dev = usb_get_intfdata(intf); |
81f6075e EP |
936 | if (!dev) |
937 | return; | |
1da177e4 | 938 | |
abd52a13 | 939 | mutex_lock(&ds_mutex); |
81f6075e | 940 | list_del(&dev->ds_entry); |
abd52a13 | 941 | mutex_unlock(&ds_mutex); |
1da177e4 | 942 | |
81f6075e EP |
943 | ds_w1_fini(dev); |
944 | ||
945 | usb_set_intfdata(intf, NULL); | |
1da177e4 LT |
946 | |
947 | usb_put_dev(dev->udev); | |
948 | kfree(dev); | |
1da177e4 LT |
949 | } |
950 | ||
8949d2aa | 951 | static int ds_init(void) |
1da177e4 LT |
952 | { |
953 | int err; | |
954 | ||
955 | err = usb_register(&ds_driver); | |
956 | if (err) { | |
957 | printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); | |
958 | return err; | |
959 | } | |
960 | ||
961 | return 0; | |
962 | } | |
963 | ||
8949d2aa | 964 | static void ds_fini(void) |
1da177e4 LT |
965 | { |
966 | usb_deregister(&ds_driver); | |
967 | } | |
968 | ||
969 | module_init(ds_init); | |
970 | module_exit(ds_fini); | |
971 | ||
972 | MODULE_LICENSE("GPL"); | |
973 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | |
81f6075e | 974 | MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); |