xref: /linux/drivers/usb/atm/cxacru.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
1 /******************************************************************************
2  *  cxacru.c  -  driver for USB ADSL modems based on
3  *               Conexant AccessRunner chipset
4  *
5  *  Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan
6  *  Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
7  *
8  *  This program is free software; you can redistribute it and/or modify it
9  *  under the terms of the GNU General Public License as published by the Free
10  *  Software Foundation; either version 2 of the License, or (at your option)
11  *  any later version.
12  *
13  *  This program is distributed in the hope that it will be useful, but WITHOUT
14  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  *  more details.
17  *
18  *  You should have received a copy of the GNU General Public License along with
19  *  this program; if not, write to the Free Software Foundation, Inc., 59
20  *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  ******************************************************************************/
23 
24 /*
25  *  Credit is due for Josep Comas, who created the original patch to speedtch.c
26  *  to support the different padding used by the AccessRunner (now generalized
27  *  into usbatm), and the userspace firmware loading utility.
28  */
29 
30 #include <linux/module.h>
31 #include <linux/moduleparam.h>
32 #include <linux/kernel.h>
33 #include <linux/timer.h>
34 #include <linux/errno.h>
35 #include <linux/slab.h>
36 #include <linux/init.h>
37 #include <linux/device.h>	/* FIXME: linux/firmware.h should include it itself */
38 #include <linux/firmware.h>
39 #include <linux/mutex.h>
40 
41 #include "usbatm.h"
42 
43 #define DRIVER_AUTHOR	"Roman Kagan, David Woodhouse, Duncan Sands"
44 #define DRIVER_VERSION	"0.2"
45 #define DRIVER_DESC	"Conexant AccessRunner ADSL USB modem driver"
46 
47 static const char cxacru_driver_name[] = "cxacru";
48 
49 #define CXACRU_EP_CMD		0x01	/* Bulk/interrupt in/out */
50 #define CXACRU_EP_DATA		0x02	/* Bulk in/out */
51 
52 #define CMD_PACKET_SIZE		64	/* Should be maxpacket(ep)? */
53 
54 /* Addresses */
55 #define PLLFCLK_ADDR	0x00350068
56 #define PLLBCLK_ADDR	0x0035006c
57 #define SDRAMEN_ADDR	0x00350010
58 #define FW_ADDR		0x00801000
59 #define BR_ADDR		0x00180600
60 #define SIG_ADDR	0x00180500
61 #define BR_STACK_ADDR	0x00187f10
62 
63 /* Values */
64 #define SDRAM_ENA	0x1
65 
66 #define CMD_TIMEOUT	2000	/* msecs */
67 #define POLL_INTERVAL	5000	/* msecs */
68 
69 /* commands for interaction with the modem through the control channel before
70  * firmware is loaded  */
71 enum cxacru_fw_request {
72 	FW_CMD_ERR,
73 	FW_GET_VER,
74 	FW_READ_MEM,
75 	FW_WRITE_MEM,
76 	FW_RMW_MEM,
77 	FW_CHECKSUM_MEM,
78 	FW_GOTO_MEM,
79 };
80 
81 /* commands for interaction with the modem through the control channel once
82  * firmware is loaded  */
83 enum cxacru_cm_request {
84 	CM_REQUEST_UNDEFINED = 0x80,
85 	CM_REQUEST_TEST,
86 	CM_REQUEST_CHIP_GET_MAC_ADDRESS,
87 	CM_REQUEST_CHIP_GET_DP_VERSIONS,
88 	CM_REQUEST_CHIP_ADSL_LINE_START,
89 	CM_REQUEST_CHIP_ADSL_LINE_STOP,
90 	CM_REQUEST_CHIP_ADSL_LINE_GET_STATUS,
91 	CM_REQUEST_CHIP_ADSL_LINE_GET_SPEED,
92 	CM_REQUEST_CARD_INFO_GET,
93 	CM_REQUEST_CARD_DATA_GET,
94 	CM_REQUEST_CARD_DATA_SET,
95 	CM_REQUEST_COMMAND_HW_IO,
96 	CM_REQUEST_INTERFACE_HW_IO,
97 	CM_REQUEST_CARD_SERIAL_DATA_PATH_GET,
98 	CM_REQUEST_CARD_SERIAL_DATA_PATH_SET,
99 	CM_REQUEST_CARD_CONTROLLER_VERSION_GET,
100 	CM_REQUEST_CARD_GET_STATUS,
101 	CM_REQUEST_CARD_GET_MAC_ADDRESS,
102 	CM_REQUEST_CARD_GET_DATA_LINK_STATUS,
103 	CM_REQUEST_MAX,
104 };
105 
106 /* reply codes to the commands above */
107 enum cxacru_cm_status {
108 	CM_STATUS_UNDEFINED,
109 	CM_STATUS_SUCCESS,
110 	CM_STATUS_ERROR,
111 	CM_STATUS_UNSUPPORTED,
112 	CM_STATUS_UNIMPLEMENTED,
113 	CM_STATUS_PARAMETER_ERROR,
114 	CM_STATUS_DBG_LOOPBACK,
115 	CM_STATUS_MAX,
116 };
117 
118 /* indices into CARD_INFO_GET return array */
119 enum cxacru_info_idx {
120 	CXINF_DOWNSTREAM_RATE,
121 	CXINF_UPSTREAM_RATE,
122 	CXINF_LINK_STATUS,
123 	CXINF_LINE_STATUS,
124 	CXINF_MAC_ADDRESS_HIGH,
125 	CXINF_MAC_ADDRESS_LOW,
126 	CXINF_UPSTREAM_SNR_MARGIN,
127 	CXINF_DOWNSTREAM_SNR_MARGIN,
128 	CXINF_UPSTREAM_ATTENUATION,
129 	CXINF_DOWNSTREAM_ATTENUATION,
130 	CXINF_TRANSMITTER_POWER,
131 	CXINF_UPSTREAM_BITS_PER_FRAME,
132 	CXINF_DOWNSTREAM_BITS_PER_FRAME,
133 	CXINF_STARTUP_ATTEMPTS,
134 	CXINF_UPSTREAM_CRC_ERRORS,
135 	CXINF_DOWNSTREAM_CRC_ERRORS,
136 	CXINF_UPSTREAM_FEC_ERRORS,
137 	CXINF_DOWNSTREAM_FEC_ERRORS,
138 	CXINF_UPSTREAM_HEC_ERRORS,
139 	CXINF_DOWNSTREAM_HEC_ERRORS,
140 	CXINF_LINE_STARTABLE,
141 	CXINF_MODULATION,
142 	CXINF_ADSL_HEADEND,
143 	CXINF_ADSL_HEADEND_ENVIRONMENT,
144 	CXINF_CONTROLLER_VERSION,
145 	/* dunno what the missing two mean */
146 	CXINF_MAX = 0x1c,
147 };
148 
149 struct cxacru_modem_type {
150 	u32 pll_f_clk;
151 	u32 pll_b_clk;
152 	int boot_rom_patch;
153 };
154 
155 struct cxacru_data {
156 	struct usbatm_data *usbatm;
157 
158 	const struct cxacru_modem_type *modem_type;
159 
160 	int line_status;
161 	struct delayed_work poll_work;
162 
163 	/* contol handles */
164 	struct mutex cm_serialize;
165 	u8 *rcv_buf;
166 	u8 *snd_buf;
167 	struct urb *rcv_urb;
168 	struct urb *snd_urb;
169 	struct completion rcv_done;
170 	struct completion snd_done;
171 };
172 
173 /* the following three functions are stolen from drivers/usb/core/message.c */
174 static void cxacru_blocking_completion(struct urb *urb)
175 {
176 	complete((struct completion *)urb->context);
177 }
178 
179 static void cxacru_timeout_kill(unsigned long data)
180 {
181 	usb_unlink_urb((struct urb *) data);
182 }
183 
184 static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
185 				 int* actual_length)
186 {
187 	struct timer_list timer;
188 	int status;
189 
190 	init_timer(&timer);
191 	timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
192 	timer.data = (unsigned long) urb;
193 	timer.function = cxacru_timeout_kill;
194 	add_timer(&timer);
195 	wait_for_completion(done);
196 	status = urb->status;
197 	if (status == -ECONNRESET)
198 		status = -ETIMEDOUT;
199 	del_timer_sync(&timer);
200 
201 	if (actual_length)
202 		*actual_length = urb->actual_length;
203 	return status;
204 }
205 
206 static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
207 		     u8 *wdata, int wsize, u8 *rdata, int rsize)
208 {
209 	int ret, actlen;
210 	int offb, offd;
211 	const int stride = CMD_PACKET_SIZE - 4;
212 	u8 *wbuf = instance->snd_buf;
213 	u8 *rbuf = instance->rcv_buf;
214 	int wbuflen = ((wsize - 1) / stride + 1) * CMD_PACKET_SIZE;
215 	int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE;
216 
217 	if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) {
218 		dbg("too big transfer requested");
219 		ret = -ENOMEM;
220 		goto fail;
221 	}
222 
223 	mutex_lock(&instance->cm_serialize);
224 
225 	/* submit reading urb before the writing one */
226 	init_completion(&instance->rcv_done);
227 	ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL);
228 	if (ret < 0) {
229 		dbg("submitting read urb for cm %#x failed", cm);
230 		ret = ret;
231 		goto fail;
232 	}
233 
234 	memset(wbuf, 0, wbuflen);
235 	/* handle wsize == 0 */
236 	wbuf[0] = cm;
237 	for (offb = offd = 0; offd < wsize; offd += stride, offb += CMD_PACKET_SIZE) {
238 		wbuf[offb] = cm;
239 		memcpy(wbuf + offb + 4, wdata + offd, min_t(int, stride, wsize - offd));
240 	}
241 
242 	instance->snd_urb->transfer_buffer_length = wbuflen;
243 	init_completion(&instance->snd_done);
244 	ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL);
245 	if (ret < 0) {
246 		dbg("submitting write urb for cm %#x failed", cm);
247 		ret = ret;
248 		goto fail;
249 	}
250 
251 	ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL);
252 	if (ret < 0) {
253 		dbg("sending cm %#x failed", cm);
254 		ret = ret;
255 		goto fail;
256 	}
257 
258 	ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen);
259 	if (ret < 0) {
260 		dbg("receiving cm %#x failed", cm);
261 		ret = ret;
262 		goto fail;
263 	}
264 	if (actlen % CMD_PACKET_SIZE || !actlen) {
265 		dbg("response is not a positive multiple of %d: %#x",
266 				CMD_PACKET_SIZE, actlen);
267 		ret = -EIO;
268 		goto fail;
269 	}
270 
271 	/* check the return status and copy the data to the output buffer, if needed */
272 	for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) {
273 		if (rbuf[offb] != cm) {
274 			dbg("wrong cm %#x in response", rbuf[offb]);
275 			ret = -EIO;
276 			goto fail;
277 		}
278 		if (rbuf[offb + 1] != CM_STATUS_SUCCESS) {
279 			dbg("response failed: %#x", rbuf[offb + 1]);
280 			ret = -EIO;
281 			goto fail;
282 		}
283 		if (offd >= rsize)
284 			break;
285 		memcpy(rdata + offd, rbuf + offb + 4, min_t(int, stride, rsize - offd));
286 		offd += stride;
287 	}
288 
289 	ret = offd;
290 	dbg("cm %#x", cm);
291 fail:
292 	mutex_unlock(&instance->cm_serialize);
293 	return ret;
294 }
295 
296 static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_request cm,
297 			       u32 *data, int size)
298 {
299 	int ret, len;
300 	u32 *buf;
301 	int offb, offd;
302 	const int stride = CMD_PACKET_SIZE / (4 * 2) - 1;
303 	int buflen =  ((size - 1) / stride + 1 + size * 2) * 4;
304 
305 	buf = kmalloc(buflen, GFP_KERNEL);
306 	if (!buf)
307 		return -ENOMEM;
308 
309 	ret = cxacru_cm(instance, cm, NULL, 0, (u8 *) buf, buflen);
310 	if (ret < 0)
311 		goto cleanup;
312 
313 	/* len > 0 && len % 4 == 0 guaranteed by cxacru_cm() */
314 	len = ret / 4;
315 	for (offb = 0; offb < len; ) {
316 		int l = le32_to_cpu(buf[offb++]);
317 		if (l > stride || l > (len - offb) / 2) {
318 			dbg("wrong data length %#x in response", l);
319 			ret = -EIO;
320 			goto cleanup;
321 		}
322 		while (l--) {
323 			offd = le32_to_cpu(buf[offb++]);
324 			if (offd >= size) {
325 				dbg("wrong index %#x in response", offd);
326 				ret = -EIO;
327 				goto cleanup;
328 			}
329 			data[offd] = le32_to_cpu(buf[offb++]);
330 		}
331 	}
332 
333 	ret = 0;
334 
335 cleanup:
336 	kfree(buf);
337 	return ret;
338 }
339 
340 static int cxacru_card_status(struct cxacru_data *instance)
341 {
342 	int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
343 	if (ret < 0) {		/* firmware not loaded */
344 		dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret);
345 		return ret;
346 	}
347 	return 0;
348 }
349 
350 static void cxacru_poll_status(struct work_struct *work);
351 
352 static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
353 		struct atm_dev *atm_dev)
354 {
355 	struct cxacru_data *instance = usbatm_instance->driver_data;
356 	/*
357 	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
358 	*/
359 	int ret;
360 
361 	dbg("cxacru_atm_start");
362 
363 	/* Read MAC address */
364 	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,
365 			atm_dev->esi, sizeof(atm_dev->esi));
366 	if (ret < 0) {
367 		atm_err(usbatm_instance, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
368 		return ret;
369 	}
370 
371 	/* start ADSL */
372 	ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
373 	if (ret < 0) {
374 		atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
375 		return ret;
376 	}
377 
378 	/* Start status polling */
379 	cxacru_poll_status(&instance->poll_work.work);
380 	return 0;
381 }
382 
383 static void cxacru_poll_status(struct work_struct *work)
384 {
385 	struct cxacru_data *instance =
386 		container_of(work, struct cxacru_data, poll_work.work);
387 	u32 buf[CXINF_MAX] = {};
388 	struct usbatm_data *usbatm = instance->usbatm;
389 	struct atm_dev *atm_dev = usbatm->atm_dev;
390 	int ret;
391 
392 	ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX);
393 	if (ret < 0) {
394 		atm_warn(usbatm, "poll status: error %d\n", ret);
395 		goto reschedule;
396 	}
397 
398 	if (instance->line_status == buf[CXINF_LINE_STATUS])
399 		goto reschedule;
400 
401 	instance->line_status = buf[CXINF_LINE_STATUS];
402 	switch (instance->line_status) {
403 	case 0:
404 		atm_dev->signal = ATM_PHY_SIG_LOST;
405 		atm_info(usbatm, "ADSL line: down\n");
406 		break;
407 
408 	case 1:
409 		atm_dev->signal = ATM_PHY_SIG_LOST;
410 		atm_info(usbatm, "ADSL line: attempting to activate\n");
411 		break;
412 
413 	case 2:
414 		atm_dev->signal = ATM_PHY_SIG_LOST;
415 		atm_info(usbatm, "ADSL line: training\n");
416 		break;
417 
418 	case 3:
419 		atm_dev->signal = ATM_PHY_SIG_LOST;
420 		atm_info(usbatm, "ADSL line: channel analysis\n");
421 		break;
422 
423 	case 4:
424 		atm_dev->signal = ATM_PHY_SIG_LOST;
425 		atm_info(usbatm, "ADSL line: exchange\n");
426 		break;
427 
428 	case 5:
429 		atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424;
430 		atm_dev->signal = ATM_PHY_SIG_FOUND;
431 
432 		atm_info(usbatm, "ADSL line: up (%d kb/s down | %d kb/s up)\n",
433 		     buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]);
434 		break;
435 
436 	case 6:
437 		atm_dev->signal = ATM_PHY_SIG_LOST;
438 		atm_info(usbatm, "ADSL line: waiting\n");
439 		break;
440 
441 	case 7:
442 		atm_dev->signal = ATM_PHY_SIG_LOST;
443 		atm_info(usbatm, "ADSL line: initializing\n");
444 		break;
445 
446 	default:
447 		atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
448 		atm_info(usbatm, "Unknown line state %02x\n", instance->line_status);
449 		break;
450 	}
451 reschedule:
452 	schedule_delayed_work(&instance->poll_work, msecs_to_jiffies(POLL_INTERVAL));
453 }
454 
455 static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
456 		     u8 code1, u8 code2, u32 addr, u8 *data, int size)
457 {
458 	int ret;
459 	u8 *buf;
460 	int offd, offb;
461 	const int stride = CMD_PACKET_SIZE - 8;
462 
463 	buf = (u8 *) __get_free_page(GFP_KERNEL);
464 	if (!buf)
465 		return -ENOMEM;
466 
467 	offb = offd = 0;
468 	do {
469 		int l = min_t(int, stride, size - offd);
470 		buf[offb++] = fw;
471 		buf[offb++] = l;
472 		buf[offb++] = code1;
473 		buf[offb++] = code2;
474 		*((u32 *) (buf + offb)) = cpu_to_le32(addr);
475 		offb += 4;
476 		addr += l;
477 		if(l)
478 			memcpy(buf + offb, data + offd, l);
479 		if (l < stride)
480 			memset(buf + offb + l, 0, stride - l);
481 		offb += stride;
482 		offd += stride;
483 		if ((offb >= PAGE_SIZE) || (offd >= size)) {
484 			ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD),
485 					   buf, offb, NULL, CMD_TIMEOUT);
486 			if (ret < 0) {
487 				dbg("sending fw %#x failed", fw);
488 				goto cleanup;
489 			}
490 			offb = 0;
491 		}
492 	} while(offd < size);
493 	dbg("sent fw %#x", fw);
494 
495 	ret = 0;
496 
497 cleanup:
498 	free_page((unsigned long) buf);
499 	return ret;
500 }
501 
502 static void cxacru_upload_firmware(struct cxacru_data *instance,
503 				   const struct firmware *fw,
504 				   const struct firmware *bp,
505 				   const struct firmware *cf)
506 {
507 	int ret;
508 	int off;
509 	struct usbatm_data *usbatm = instance->usbatm;
510 	struct usb_device *usb_dev = usbatm->usb_dev;
511 	u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct };
512 	u32 val;
513 
514 	dbg("cxacru_upload_firmware");
515 
516 	/* FirmwarePllFClkValue */
517 	val = cpu_to_le32(instance->modem_type->pll_f_clk);
518 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
519 	if (ret) {
520 		usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
521 		return;
522 	}
523 
524 	/* FirmwarePllBClkValue */
525 	val = cpu_to_le32(instance->modem_type->pll_b_clk);
526 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
527 	if (ret) {
528 		usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
529 		return;
530 	}
531 
532 	/* Enable SDRAM */
533 	val = cpu_to_le32(SDRAM_ENA);
534 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
535 	if (ret) {
536 		usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
537 		return;
538 	}
539 
540 	/* Firmware */
541 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
542 	if (ret) {
543 		usb_err(usbatm, "Firmware upload failed: %d\n", ret);
544 		return;
545 	}
546 
547 	/* Boot ROM patch */
548 	if (instance->modem_type->boot_rom_patch) {
549 		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
550 		if (ret) {
551 			usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
552 			return;
553 		}
554 	}
555 
556 	/* Signature */
557 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
558 	if (ret) {
559 		usb_err(usbatm, "Signature storing failed: %d\n", ret);
560 		return;
561 	}
562 
563 	if (instance->modem_type->boot_rom_patch) {
564 		val = cpu_to_le32(BR_ADDR);
565 		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
566 	}
567 	else {
568 		ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
569 	}
570 	if (ret) {
571 		usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
572 		return;
573 	}
574 
575 	/* Delay to allow firmware to start up. */
576 	msleep_interruptible(1000);
577 
578 	usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD));
579 	usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD));
580 	usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA));
581 	usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA));
582 
583 	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
584 	if (ret < 0) {
585 		usb_err(usbatm, "modem failed to initialize: %d\n", ret);
586 		return;
587 	}
588 
589 	/* Load config data (le32), doing one packet at a time */
590 	if (cf)
591 		for (off = 0; off < cf->size / 4; ) {
592 			u32 buf[CMD_PACKET_SIZE / 4 - 1];
593 			int i, len = min_t(int, cf->size / 4 - off, CMD_PACKET_SIZE / 4 / 2 - 1);
594 			buf[0] = cpu_to_le32(len);
595 			for (i = 0; i < len; i++, off++) {
596 				buf[i * 2 + 1] = cpu_to_le32(off);
597 				memcpy(buf + i * 2 + 2, cf->data + off * 4, 4);
598 			}
599 			ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
600 					(u8 *) buf, len, NULL, 0);
601 			if (ret < 0) {
602 				usb_err(usbatm, "load config data failed: %d\n", ret);
603 				return;
604 			}
605 		}
606 
607 	msleep_interruptible(4000);
608 }
609 
610 static int cxacru_find_firmware(struct cxacru_data *instance,
611 				char* phase, const struct firmware **fw_p)
612 {
613 	struct usbatm_data *usbatm = instance->usbatm;
614 	struct device *dev = &usbatm->usb_intf->dev;
615 	char buf[16];
616 
617 	sprintf(buf, "cxacru-%s.bin", phase);
618 	dbg("cxacru_find_firmware: looking for %s", buf);
619 
620 	if (request_firmware(fw_p, buf, dev)) {
621 		usb_dbg(usbatm, "no stage %s firmware found\n", phase);
622 		return -ENOENT;
623 	}
624 
625 	usb_info(usbatm, "found firmware %s\n", buf);
626 
627 	return 0;
628 }
629 
630 static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
631 			     struct usb_interface *usb_intf)
632 {
633 	const struct firmware *fw, *bp, *cf;
634 	struct cxacru_data *instance = usbatm_instance->driver_data;
635 
636 	int ret = cxacru_find_firmware(instance, "fw", &fw);
637 	if (ret) {
638 		usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
639 		return ret;
640 	}
641 
642 	if (instance->modem_type->boot_rom_patch) {
643 		ret = cxacru_find_firmware(instance, "bp", &bp);
644 		if (ret) {
645 			usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n");
646 			release_firmware(fw);
647 			return ret;
648 		}
649 	}
650 
651 	if (cxacru_find_firmware(instance, "cf", &cf))		/* optional */
652 		cf = NULL;
653 
654 	cxacru_upload_firmware(instance, fw, bp, cf);
655 
656 	if (cf)
657 		release_firmware(cf);
658 	if (instance->modem_type->boot_rom_patch)
659 		release_firmware(bp);
660 	release_firmware(fw);
661 
662 	ret = cxacru_card_status(instance);
663 	if (ret)
664 		dbg("modem initialisation failed");
665 	else
666 		dbg("done setting up the modem");
667 
668 	return ret;
669 }
670 
671 static int cxacru_bind(struct usbatm_data *usbatm_instance,
672 		       struct usb_interface *intf, const struct usb_device_id *id)
673 {
674 	struct cxacru_data *instance;
675 	struct usb_device *usb_dev = interface_to_usbdev(intf);
676 	int ret;
677 
678 	/* instance init */
679 	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
680 	if (!instance) {
681 		dbg("cxacru_bind: no memory for instance data");
682 		return -ENOMEM;
683 	}
684 
685 	instance->usbatm = usbatm_instance;
686 	instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
687 
688 	instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL);
689 	if (!instance->rcv_buf) {
690 		dbg("cxacru_bind: no memory for rcv_buf");
691 		ret = -ENOMEM;
692 		goto fail;
693 	}
694 	instance->snd_buf = (u8 *) __get_free_page(GFP_KERNEL);
695 	if (!instance->snd_buf) {
696 		dbg("cxacru_bind: no memory for snd_buf");
697 		ret = -ENOMEM;
698 		goto fail;
699 	}
700 	instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL);
701 	if (!instance->rcv_urb) {
702 		dbg("cxacru_bind: no memory for rcv_urb");
703 		ret = -ENOMEM;
704 		goto fail;
705 	}
706 	instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL);
707 	if (!instance->snd_urb) {
708 		dbg("cxacru_bind: no memory for snd_urb");
709 		ret = -ENOMEM;
710 		goto fail;
711 	}
712 
713 	usb_fill_int_urb(instance->rcv_urb,
714 			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
715 			instance->rcv_buf, PAGE_SIZE,
716 			cxacru_blocking_completion, &instance->rcv_done, 1);
717 
718 	usb_fill_int_urb(instance->snd_urb,
719 			usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
720 			instance->snd_buf, PAGE_SIZE,
721 			cxacru_blocking_completion, &instance->snd_done, 4);
722 
723 	mutex_init(&instance->cm_serialize);
724 
725 	INIT_DELAYED_WORK(&instance->poll_work, cxacru_poll_status);
726 
727 	usbatm_instance->driver_data = instance;
728 
729 	usbatm_instance->flags = (cxacru_card_status(instance) ? 0 : UDSL_SKIP_HEAVY_INIT);
730 
731 	return 0;
732 
733  fail:
734 	free_page((unsigned long) instance->snd_buf);
735 	free_page((unsigned long) instance->rcv_buf);
736 	usb_free_urb(instance->snd_urb);
737 	usb_free_urb(instance->rcv_urb);
738 	kfree(instance);
739 
740 	return ret;
741 }
742 
743 static void cxacru_unbind(struct usbatm_data *usbatm_instance,
744 		struct usb_interface *intf)
745 {
746 	struct cxacru_data *instance = usbatm_instance->driver_data;
747 
748 	dbg("cxacru_unbind entered");
749 
750 	if (!instance) {
751 		dbg("cxacru_unbind: NULL instance!");
752 		return;
753 	}
754 
755 	while (!cancel_delayed_work(&instance->poll_work))
756 	       flush_scheduled_work();
757 
758 	usb_kill_urb(instance->snd_urb);
759 	usb_kill_urb(instance->rcv_urb);
760 	usb_free_urb(instance->snd_urb);
761 	usb_free_urb(instance->rcv_urb);
762 
763 	free_page((unsigned long) instance->snd_buf);
764 	free_page((unsigned long) instance->rcv_buf);
765 	kfree(instance);
766 
767 	usbatm_instance->driver_data = NULL;
768 }
769 
770 static const struct cxacru_modem_type cxacru_cafe = {
771 	.pll_f_clk = 0x02d874df,
772 	.pll_b_clk = 0x0196a51a,
773 	.boot_rom_patch = 1,
774 };
775 
776 static const struct cxacru_modem_type cxacru_cb00 = {
777 	.pll_f_clk = 0x5,
778 	.pll_b_clk = 0x3,
779 	.boot_rom_patch = 0,
780 };
781 
782 static const struct usb_device_id cxacru_usb_ids[] = {
783 	{ /* V = Conexant			P = ADSL modem (Euphrates project)	*/
784 		USB_DEVICE(0x0572, 0xcafe),	.driver_info = (unsigned long) &cxacru_cafe
785 	},
786 	{ /* V = Conexant			P = ADSL modem (Hasbani project)	*/
787 		USB_DEVICE(0x0572, 0xcb00),	.driver_info = (unsigned long) &cxacru_cb00
788 	},
789 	{ /* V = Conexant			P = ADSL modem				*/
790 		USB_DEVICE(0x0572, 0xcb01),	.driver_info = (unsigned long) &cxacru_cb00
791 	},
792 	{ /* V = Conexant			P = ADSL modem (Well PTI-800) */
793 		USB_DEVICE(0x0572, 0xcb02),	.driver_info = (unsigned long) &cxacru_cb00
794 	},
795 	{ /* V = Conexant			P = ADSL modem				*/
796 		USB_DEVICE(0x0572, 0xcb06),	.driver_info = (unsigned long) &cxacru_cb00
797 	},
798 	{ /* V = Conexant			P = ADSL modem (ZTE ZXDSL 852)		*/
799 		USB_DEVICE(0x0572, 0xcb07),	.driver_info = (unsigned long) &cxacru_cb00
800 	},
801 	{ /* V = Olitec				P = ADSL modem version 2		*/
802 		USB_DEVICE(0x08e3, 0x0100),	.driver_info = (unsigned long) &cxacru_cafe
803 	},
804 	{ /* V = Olitec				P = ADSL modem version 3		*/
805 		USB_DEVICE(0x08e3, 0x0102),	.driver_info = (unsigned long) &cxacru_cb00
806 	},
807 	{ /* V = Trust/Amigo Technology Co.	P = AMX-CA86U				*/
808 		USB_DEVICE(0x0eb0, 0x3457),	.driver_info = (unsigned long) &cxacru_cafe
809 	},
810 	{ /* V = Zoom				P = 5510				*/
811 		USB_DEVICE(0x1803, 0x5510),	.driver_info = (unsigned long) &cxacru_cb00
812 	},
813 	{ /* V = Draytek			P = Vigor 318				*/
814 		USB_DEVICE(0x0675, 0x0200),	.driver_info = (unsigned long) &cxacru_cb00
815 	},
816 	{ /* V = Zyxel				P = 630-C1 aka OMNI ADSL USB (Annex A)	*/
817 		USB_DEVICE(0x0586, 0x330a),	.driver_info = (unsigned long) &cxacru_cb00
818 	},
819 	{ /* V = Zyxel				P = 630-C3 aka OMNI ADSL USB (Annex B)	*/
820 		USB_DEVICE(0x0586, 0x330b),	.driver_info = (unsigned long) &cxacru_cb00
821 	},
822 	{ /* V = Aethra				P = Starmodem UM1020			*/
823 		USB_DEVICE(0x0659, 0x0020),	.driver_info = (unsigned long) &cxacru_cb00
824 	},
825 	{ /* V = Aztech Systems			P = ? AKA Pirelli AUA-010		*/
826 		USB_DEVICE(0x0509, 0x0812),	.driver_info = (unsigned long) &cxacru_cb00
827 	},
828 	{ /* V = Netopia			P = Cayman 3341(Annex A)/3351(Annex B)	*/
829 		USB_DEVICE(0x100d, 0xcb01),	.driver_info = (unsigned long) &cxacru_cb00
830 	},
831 	{ /* V = Netopia			P = Cayman 3342(Annex A)/3352(Annex B)	*/
832 		USB_DEVICE(0x100d, 0x3342),	.driver_info = (unsigned long) &cxacru_cb00
833 	},
834 	{}
835 };
836 
837 MODULE_DEVICE_TABLE(usb, cxacru_usb_ids);
838 
839 static struct usbatm_driver cxacru_driver = {
840 	.driver_name	= cxacru_driver_name,
841 	.bind		= cxacru_bind,
842 	.heavy_init	= cxacru_heavy_init,
843 	.unbind		= cxacru_unbind,
844 	.atm_start	= cxacru_atm_start,
845 	.bulk_in	= CXACRU_EP_DATA,
846 	.bulk_out	= CXACRU_EP_DATA,
847 	.rx_padding	= 3,
848 	.tx_padding	= 11,
849 };
850 
851 static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
852 {
853 	return usbatm_usb_probe(intf, id, &cxacru_driver);
854 }
855 
856 static struct usb_driver cxacru_usb_driver = {
857 	.name		= cxacru_driver_name,
858 	.probe		= cxacru_usb_probe,
859 	.disconnect	= usbatm_usb_disconnect,
860 	.id_table	= cxacru_usb_ids
861 };
862 
863 static int __init cxacru_init(void)
864 {
865 	return usb_register(&cxacru_usb_driver);
866 }
867 
868 static void __exit cxacru_cleanup(void)
869 {
870 	usb_deregister(&cxacru_usb_driver);
871 }
872 
873 module_init(cxacru_init);
874 module_exit(cxacru_cleanup);
875 
876 MODULE_AUTHOR(DRIVER_AUTHOR);
877 MODULE_DESCRIPTION(DRIVER_DESC);
878 MODULE_LICENSE("GPL");
879 MODULE_VERSION(DRIVER_VERSION);
880