xref: /OK3568_Linux_fs/kernel/drivers/usb/misc/ftdi-elan.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * USB FTDI client driver for Elan Digital Systems's Uxxx adapters
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright(C) 2006 Elan Digital Systems Limited
6*4882a593Smuzhiyun  * http://www.elandigitalsystems.com
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Author and Maintainer - Tony Olech - Elan Digital Systems
9*4882a593Smuzhiyun  * tony.olech@elandigitalsystems.com
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
12*4882a593Smuzhiyun  * based on various USB client drivers in the 2.6.15 linux kernel
13*4882a593Smuzhiyun  * with constant reference to the 3rd Edition of Linux Device Drivers
14*4882a593Smuzhiyun  * published by O'Reilly
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * The U132 adapter is a USB to CardBus adapter specifically designed
17*4882a593Smuzhiyun  * for PC cards that contain an OHCI host controller. Typical PC cards
18*4882a593Smuzhiyun  * are the Orange Mobile 3G Option GlobeTrotter Fusion card.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  * The U132 adapter will *NOT *work with PC cards that do not contain
21*4882a593Smuzhiyun  * an OHCI controller. A simple way to test whether a PC card has an
22*4882a593Smuzhiyun  * OHCI controller as an interface is to insert the PC card directly
23*4882a593Smuzhiyun  * into a laptop(or desktop) with a CardBus slot and if "lspci" shows
24*4882a593Smuzhiyun  * a new USB controller and "lsusb -v" shows a new OHCI Host Controller
25*4882a593Smuzhiyun  * then there is a good chance that the U132 adapter will support the
26*4882a593Smuzhiyun  * PC card.(you also need the specific client driver for the PC card)
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * Please inform the Author and Maintainer about any PC cards that
29*4882a593Smuzhiyun  * contain OHCI Host Controller and work when directly connected to
30*4882a593Smuzhiyun  * an embedded CardBus slot but do not work when they are connected
31*4882a593Smuzhiyun  * via an ELAN U132 adapter.
32*4882a593Smuzhiyun  *
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include <linux/kernel.h>
38*4882a593Smuzhiyun #include <linux/errno.h>
39*4882a593Smuzhiyun #include <linux/init.h>
40*4882a593Smuzhiyun #include <linux/list.h>
41*4882a593Smuzhiyun #include <linux/ioctl.h>
42*4882a593Smuzhiyun #include <linux/pci_ids.h>
43*4882a593Smuzhiyun #include <linux/slab.h>
44*4882a593Smuzhiyun #include <linux/module.h>
45*4882a593Smuzhiyun #include <linux/kref.h>
46*4882a593Smuzhiyun #include <linux/mutex.h>
47*4882a593Smuzhiyun #include <linux/uaccess.h>
48*4882a593Smuzhiyun #include <linux/usb.h>
49*4882a593Smuzhiyun #include <linux/workqueue.h>
50*4882a593Smuzhiyun #include <linux/platform_device.h>
51*4882a593Smuzhiyun MODULE_AUTHOR("Tony Olech");
52*4882a593Smuzhiyun MODULE_DESCRIPTION("FTDI ELAN driver");
53*4882a593Smuzhiyun MODULE_LICENSE("GPL");
54*4882a593Smuzhiyun #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
55*4882a593Smuzhiyun static bool distrust_firmware = 1;
56*4882a593Smuzhiyun module_param(distrust_firmware, bool, 0);
57*4882a593Smuzhiyun MODULE_PARM_DESC(distrust_firmware,
58*4882a593Smuzhiyun 		 "true to distrust firmware power/overcurrent setup");
59*4882a593Smuzhiyun extern struct platform_driver u132_platform_driver;
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun  * ftdi_module_lock exists to protect access to global variables
62*4882a593Smuzhiyun  *
63*4882a593Smuzhiyun  */
64*4882a593Smuzhiyun static struct mutex ftdi_module_lock;
65*4882a593Smuzhiyun static int ftdi_instances = 0;
66*4882a593Smuzhiyun static struct list_head ftdi_static_list;
67*4882a593Smuzhiyun /*
68*4882a593Smuzhiyun  * end of the global variables protected by ftdi_module_lock
69*4882a593Smuzhiyun  */
70*4882a593Smuzhiyun #include "usb_u132.h"
71*4882a593Smuzhiyun #include <asm/io.h>
72*4882a593Smuzhiyun #include <linux/usb/hcd.h>
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* FIXME ohci.h is ONLY for internal use by the OHCI driver.
75*4882a593Smuzhiyun  * If you're going to try stuff like this, you need to split
76*4882a593Smuzhiyun  * out shareable stuff (register declarations?) into its own
77*4882a593Smuzhiyun  * file, maybe name <linux/usb/ohci.h>
78*4882a593Smuzhiyun  */
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #include "../host/ohci.h"
81*4882a593Smuzhiyun /* Define these values to match your devices*/
82*4882a593Smuzhiyun #define USB_FTDI_ELAN_VENDOR_ID 0x0403
83*4882a593Smuzhiyun #define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
84*4882a593Smuzhiyun /* table of devices that work with this driver*/
85*4882a593Smuzhiyun static const struct usb_device_id ftdi_elan_table[] = {
86*4882a593Smuzhiyun 	{USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)},
87*4882a593Smuzhiyun 	{ /* Terminating entry */ }
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, ftdi_elan_table);
91*4882a593Smuzhiyun /* only the jtag(firmware upgrade device) interface requires
92*4882a593Smuzhiyun  * a device file and corresponding minor number, but the
93*4882a593Smuzhiyun  * interface is created unconditionally - I suppose it could
94*4882a593Smuzhiyun  * be configured or not according to a module parameter.
95*4882a593Smuzhiyun  * But since we(now) require one interface per device,
96*4882a593Smuzhiyun  * and since it unlikely that a normal installation would
97*4882a593Smuzhiyun  * require more than a couple of elan-ftdi devices, 8 seems
98*4882a593Smuzhiyun  * like a reasonable limit to have here, and if someone
99*4882a593Smuzhiyun  * really requires more than 8 devices, then they can frig the
100*4882a593Smuzhiyun  * code and recompile
101*4882a593Smuzhiyun  */
102*4882a593Smuzhiyun #define USB_FTDI_ELAN_MINOR_BASE 192
103*4882a593Smuzhiyun #define COMMAND_BITS 5
104*4882a593Smuzhiyun #define COMMAND_SIZE (1<<COMMAND_BITS)
105*4882a593Smuzhiyun #define COMMAND_MASK (COMMAND_SIZE-1)
106*4882a593Smuzhiyun struct u132_command {
107*4882a593Smuzhiyun 	u8 header;
108*4882a593Smuzhiyun 	u16 length;
109*4882a593Smuzhiyun 	u8 address;
110*4882a593Smuzhiyun 	u8 width;
111*4882a593Smuzhiyun 	u32 value;
112*4882a593Smuzhiyun 	int follows;
113*4882a593Smuzhiyun 	void *buffer;
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun #define RESPOND_BITS 5
116*4882a593Smuzhiyun #define RESPOND_SIZE (1<<RESPOND_BITS)
117*4882a593Smuzhiyun #define RESPOND_MASK (RESPOND_SIZE-1)
118*4882a593Smuzhiyun struct u132_respond {
119*4882a593Smuzhiyun 	u8 header;
120*4882a593Smuzhiyun 	u8 address;
121*4882a593Smuzhiyun 	u32 *value;
122*4882a593Smuzhiyun 	int *result;
123*4882a593Smuzhiyun 	struct completion wait_completion;
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun struct u132_target {
126*4882a593Smuzhiyun 	void *endp;
127*4882a593Smuzhiyun 	struct urb *urb;
128*4882a593Smuzhiyun 	int toggle_bits;
129*4882a593Smuzhiyun 	int error_count;
130*4882a593Smuzhiyun 	int condition_code;
131*4882a593Smuzhiyun 	int repeat_number;
132*4882a593Smuzhiyun 	int halted;
133*4882a593Smuzhiyun 	int skipped;
134*4882a593Smuzhiyun 	int actual;
135*4882a593Smuzhiyun 	int non_null;
136*4882a593Smuzhiyun 	int active;
137*4882a593Smuzhiyun 	int abandoning;
138*4882a593Smuzhiyun 	void (*callback)(void *endp, struct urb *urb, u8 *buf, int len,
139*4882a593Smuzhiyun 			 int toggle_bits, int error_count, int condition_code,
140*4882a593Smuzhiyun 			 int repeat_number, int halted, int skipped, int actual,
141*4882a593Smuzhiyun 			 int non_null);
142*4882a593Smuzhiyun };
143*4882a593Smuzhiyun /* Structure to hold all of our device specific stuff*/
144*4882a593Smuzhiyun struct usb_ftdi {
145*4882a593Smuzhiyun 	struct list_head ftdi_list;
146*4882a593Smuzhiyun 	struct mutex u132_lock;
147*4882a593Smuzhiyun 	int command_next;
148*4882a593Smuzhiyun 	int command_head;
149*4882a593Smuzhiyun 	struct u132_command command[COMMAND_SIZE];
150*4882a593Smuzhiyun 	int respond_next;
151*4882a593Smuzhiyun 	int respond_head;
152*4882a593Smuzhiyun 	struct u132_respond respond[RESPOND_SIZE];
153*4882a593Smuzhiyun 	struct u132_target target[4];
154*4882a593Smuzhiyun 	char device_name[16];
155*4882a593Smuzhiyun 	unsigned synchronized:1;
156*4882a593Smuzhiyun 	unsigned enumerated:1;
157*4882a593Smuzhiyun 	unsigned registered:1;
158*4882a593Smuzhiyun 	unsigned initialized:1;
159*4882a593Smuzhiyun 	unsigned card_ejected:1;
160*4882a593Smuzhiyun 	int function;
161*4882a593Smuzhiyun 	int sequence_num;
162*4882a593Smuzhiyun 	int disconnected;
163*4882a593Smuzhiyun 	int gone_away;
164*4882a593Smuzhiyun 	int stuck_status;
165*4882a593Smuzhiyun 	int status_queue_delay;
166*4882a593Smuzhiyun 	struct semaphore sw_lock;
167*4882a593Smuzhiyun 	struct usb_device *udev;
168*4882a593Smuzhiyun 	struct usb_interface *interface;
169*4882a593Smuzhiyun 	struct usb_class_driver *class;
170*4882a593Smuzhiyun 	struct delayed_work status_work;
171*4882a593Smuzhiyun 	struct delayed_work command_work;
172*4882a593Smuzhiyun 	struct delayed_work respond_work;
173*4882a593Smuzhiyun 	struct u132_platform_data platform_data;
174*4882a593Smuzhiyun 	struct resource resources[0];
175*4882a593Smuzhiyun 	struct platform_device platform_dev;
176*4882a593Smuzhiyun 	unsigned char *bulk_in_buffer;
177*4882a593Smuzhiyun 	size_t bulk_in_size;
178*4882a593Smuzhiyun 	size_t bulk_in_last;
179*4882a593Smuzhiyun 	size_t bulk_in_left;
180*4882a593Smuzhiyun 	__u8 bulk_in_endpointAddr;
181*4882a593Smuzhiyun 	__u8 bulk_out_endpointAddr;
182*4882a593Smuzhiyun 	struct kref kref;
183*4882a593Smuzhiyun 	u32 controlreg;
184*4882a593Smuzhiyun 	u8 response[4 + 1024];
185*4882a593Smuzhiyun 	int expected;
186*4882a593Smuzhiyun 	int received;
187*4882a593Smuzhiyun 	int ed_found;
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun #define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref)
190*4882a593Smuzhiyun #define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \
191*4882a593Smuzhiyun 						    platform_dev)
192*4882a593Smuzhiyun static struct usb_driver ftdi_elan_driver;
ftdi_elan_delete(struct kref * kref)193*4882a593Smuzhiyun static void ftdi_elan_delete(struct kref *kref)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref);
196*4882a593Smuzhiyun 	dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi);
197*4882a593Smuzhiyun 	usb_put_dev(ftdi->udev);
198*4882a593Smuzhiyun 	ftdi->disconnected += 1;
199*4882a593Smuzhiyun 	mutex_lock(&ftdi_module_lock);
200*4882a593Smuzhiyun 	list_del_init(&ftdi->ftdi_list);
201*4882a593Smuzhiyun 	ftdi_instances -= 1;
202*4882a593Smuzhiyun 	mutex_unlock(&ftdi_module_lock);
203*4882a593Smuzhiyun 	kfree(ftdi->bulk_in_buffer);
204*4882a593Smuzhiyun 	ftdi->bulk_in_buffer = NULL;
205*4882a593Smuzhiyun 	kfree(ftdi);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
ftdi_elan_put_kref(struct usb_ftdi * ftdi)208*4882a593Smuzhiyun static void ftdi_elan_put_kref(struct usb_ftdi *ftdi)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	kref_put(&ftdi->kref, ftdi_elan_delete);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
ftdi_elan_get_kref(struct usb_ftdi * ftdi)213*4882a593Smuzhiyun static void ftdi_elan_get_kref(struct usb_ftdi *ftdi)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	kref_get(&ftdi->kref);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
ftdi_elan_init_kref(struct usb_ftdi * ftdi)218*4882a593Smuzhiyun static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	kref_init(&ftdi->kref);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
ftdi_status_requeue_work(struct usb_ftdi * ftdi,unsigned int delta)223*4882a593Smuzhiyun static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun 	if (!schedule_delayed_work(&ftdi->status_work, delta))
226*4882a593Smuzhiyun 		kref_put(&ftdi->kref, ftdi_elan_delete);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
ftdi_status_queue_work(struct usb_ftdi * ftdi,unsigned int delta)229*4882a593Smuzhiyun static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	if (schedule_delayed_work(&ftdi->status_work, delta))
232*4882a593Smuzhiyun 		kref_get(&ftdi->kref);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
ftdi_status_cancel_work(struct usb_ftdi * ftdi)235*4882a593Smuzhiyun static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	if (cancel_delayed_work_sync(&ftdi->status_work))
238*4882a593Smuzhiyun 		kref_put(&ftdi->kref, ftdi_elan_delete);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
ftdi_command_requeue_work(struct usb_ftdi * ftdi,unsigned int delta)241*4882a593Smuzhiyun static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	if (!schedule_delayed_work(&ftdi->command_work, delta))
244*4882a593Smuzhiyun 		kref_put(&ftdi->kref, ftdi_elan_delete);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
ftdi_command_queue_work(struct usb_ftdi * ftdi,unsigned int delta)247*4882a593Smuzhiyun static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	if (schedule_delayed_work(&ftdi->command_work, delta))
250*4882a593Smuzhiyun 		kref_get(&ftdi->kref);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
ftdi_command_cancel_work(struct usb_ftdi * ftdi)253*4882a593Smuzhiyun static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	if (cancel_delayed_work_sync(&ftdi->command_work))
256*4882a593Smuzhiyun 		kref_put(&ftdi->kref, ftdi_elan_delete);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
ftdi_response_requeue_work(struct usb_ftdi * ftdi,unsigned int delta)259*4882a593Smuzhiyun static void ftdi_response_requeue_work(struct usb_ftdi *ftdi,
260*4882a593Smuzhiyun 				       unsigned int delta)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	if (!schedule_delayed_work(&ftdi->respond_work, delta))
263*4882a593Smuzhiyun 		kref_put(&ftdi->kref, ftdi_elan_delete);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
ftdi_respond_queue_work(struct usb_ftdi * ftdi,unsigned int delta)266*4882a593Smuzhiyun static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	if (schedule_delayed_work(&ftdi->respond_work, delta))
269*4882a593Smuzhiyun 		kref_get(&ftdi->kref);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
ftdi_response_cancel_work(struct usb_ftdi * ftdi)272*4882a593Smuzhiyun static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	if (cancel_delayed_work_sync(&ftdi->respond_work))
275*4882a593Smuzhiyun 		kref_put(&ftdi->kref, ftdi_elan_delete);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
ftdi_elan_gone_away(struct platform_device * pdev)278*4882a593Smuzhiyun void ftdi_elan_gone_away(struct platform_device *pdev)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
281*4882a593Smuzhiyun 	ftdi->gone_away += 1;
282*4882a593Smuzhiyun 	ftdi_elan_put_kref(ftdi);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
ftdi_release_platform_dev(struct device * dev)287*4882a593Smuzhiyun static void ftdi_release_platform_dev(struct device *dev)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	dev->parent = NULL;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
293*4882a593Smuzhiyun 				  struct u132_target *target, u8 *buffer, int length);
294*4882a593Smuzhiyun static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi);
295*4882a593Smuzhiyun static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi);
296*4882a593Smuzhiyun static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi);
297*4882a593Smuzhiyun static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi);
298*4882a593Smuzhiyun static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi);
299*4882a593Smuzhiyun static int ftdi_elan_synchronize(struct usb_ftdi *ftdi);
300*4882a593Smuzhiyun static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi);
301*4882a593Smuzhiyun static int ftdi_elan_command_engine(struct usb_ftdi *ftdi);
302*4882a593Smuzhiyun static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi);
ftdi_elan_hcd_init(struct usb_ftdi * ftdi)303*4882a593Smuzhiyun static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	if (ftdi->platform_dev.dev.parent)
306*4882a593Smuzhiyun 		return -EBUSY;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	ftdi_elan_get_kref(ftdi);
309*4882a593Smuzhiyun 	ftdi->platform_data.potpg = 100;
310*4882a593Smuzhiyun 	ftdi->platform_data.reset = NULL;
311*4882a593Smuzhiyun 	ftdi->platform_dev.id = ftdi->sequence_num;
312*4882a593Smuzhiyun 	ftdi->platform_dev.resource = ftdi->resources;
313*4882a593Smuzhiyun 	ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources);
314*4882a593Smuzhiyun 	ftdi->platform_dev.dev.platform_data = &ftdi->platform_data;
315*4882a593Smuzhiyun 	ftdi->platform_dev.dev.parent = NULL;
316*4882a593Smuzhiyun 	ftdi->platform_dev.dev.release = ftdi_release_platform_dev;
317*4882a593Smuzhiyun 	ftdi->platform_dev.dev.dma_mask = NULL;
318*4882a593Smuzhiyun 	snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd");
319*4882a593Smuzhiyun 	ftdi->platform_dev.name = ftdi->device_name;
320*4882a593Smuzhiyun 	dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd");
321*4882a593Smuzhiyun 	request_module("u132_hcd");
322*4882a593Smuzhiyun 	dev_info(&ftdi->udev->dev, "registering '%s'\n",
323*4882a593Smuzhiyun 		 ftdi->platform_dev.name);
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	return platform_device_register(&ftdi->platform_dev);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
ftdi_elan_abandon_completions(struct usb_ftdi * ftdi)328*4882a593Smuzhiyun static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun 	mutex_lock(&ftdi->u132_lock);
331*4882a593Smuzhiyun 	while (ftdi->respond_next > ftdi->respond_head) {
332*4882a593Smuzhiyun 		struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &
333*4882a593Smuzhiyun 							      ftdi->respond_head++];
334*4882a593Smuzhiyun 		*respond->result = -ESHUTDOWN;
335*4882a593Smuzhiyun 		*respond->value = 0;
336*4882a593Smuzhiyun 		complete(&respond->wait_completion);
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun 	mutex_unlock(&ftdi->u132_lock);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
ftdi_elan_abandon_targets(struct usb_ftdi * ftdi)341*4882a593Smuzhiyun static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	int ed_number = 4;
344*4882a593Smuzhiyun 	mutex_lock(&ftdi->u132_lock);
345*4882a593Smuzhiyun 	while (ed_number-- > 0) {
346*4882a593Smuzhiyun 		struct u132_target *target = &ftdi->target[ed_number];
347*4882a593Smuzhiyun 		if (target->active == 1) {
348*4882a593Smuzhiyun 			target->condition_code = TD_DEVNOTRESP;
349*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
350*4882a593Smuzhiyun 			ftdi_elan_do_callback(ftdi, target, NULL, 0);
351*4882a593Smuzhiyun 			mutex_lock(&ftdi->u132_lock);
352*4882a593Smuzhiyun 		}
353*4882a593Smuzhiyun 	}
354*4882a593Smuzhiyun 	ftdi->received = 0;
355*4882a593Smuzhiyun 	ftdi->expected = 4;
356*4882a593Smuzhiyun 	ftdi->ed_found = 0;
357*4882a593Smuzhiyun 	mutex_unlock(&ftdi->u132_lock);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
ftdi_elan_flush_targets(struct usb_ftdi * ftdi)360*4882a593Smuzhiyun static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	int ed_number = 4;
363*4882a593Smuzhiyun 	mutex_lock(&ftdi->u132_lock);
364*4882a593Smuzhiyun 	while (ed_number-- > 0) {
365*4882a593Smuzhiyun 		struct u132_target *target = &ftdi->target[ed_number];
366*4882a593Smuzhiyun 		target->abandoning = 1;
367*4882a593Smuzhiyun 	wait_1:if (target->active == 1) {
368*4882a593Smuzhiyun 			int command_size = ftdi->command_next -
369*4882a593Smuzhiyun 				ftdi->command_head;
370*4882a593Smuzhiyun 			if (command_size < COMMAND_SIZE) {
371*4882a593Smuzhiyun 				struct u132_command *command = &ftdi->command[
372*4882a593Smuzhiyun 					COMMAND_MASK & ftdi->command_next];
373*4882a593Smuzhiyun 				command->header = 0x80 | (ed_number << 5) | 0x4;
374*4882a593Smuzhiyun 				command->length = 0x00;
375*4882a593Smuzhiyun 				command->address = 0x00;
376*4882a593Smuzhiyun 				command->width = 0x00;
377*4882a593Smuzhiyun 				command->follows = 0;
378*4882a593Smuzhiyun 				command->value = 0;
379*4882a593Smuzhiyun 				command->buffer = &command->value;
380*4882a593Smuzhiyun 				ftdi->command_next += 1;
381*4882a593Smuzhiyun 				ftdi_elan_kick_command_queue(ftdi);
382*4882a593Smuzhiyun 			} else {
383*4882a593Smuzhiyun 				mutex_unlock(&ftdi->u132_lock);
384*4882a593Smuzhiyun 				msleep(100);
385*4882a593Smuzhiyun 				mutex_lock(&ftdi->u132_lock);
386*4882a593Smuzhiyun 				goto wait_1;
387*4882a593Smuzhiyun 			}
388*4882a593Smuzhiyun 		}
389*4882a593Smuzhiyun 	wait_2:if (target->active == 1) {
390*4882a593Smuzhiyun 			int command_size = ftdi->command_next -
391*4882a593Smuzhiyun 				ftdi->command_head;
392*4882a593Smuzhiyun 			if (command_size < COMMAND_SIZE) {
393*4882a593Smuzhiyun 				struct u132_command *command = &ftdi->command[
394*4882a593Smuzhiyun 					COMMAND_MASK & ftdi->command_next];
395*4882a593Smuzhiyun 				command->header = 0x90 | (ed_number << 5);
396*4882a593Smuzhiyun 				command->length = 0x00;
397*4882a593Smuzhiyun 				command->address = 0x00;
398*4882a593Smuzhiyun 				command->width = 0x00;
399*4882a593Smuzhiyun 				command->follows = 0;
400*4882a593Smuzhiyun 				command->value = 0;
401*4882a593Smuzhiyun 				command->buffer = &command->value;
402*4882a593Smuzhiyun 				ftdi->command_next += 1;
403*4882a593Smuzhiyun 				ftdi_elan_kick_command_queue(ftdi);
404*4882a593Smuzhiyun 			} else {
405*4882a593Smuzhiyun 				mutex_unlock(&ftdi->u132_lock);
406*4882a593Smuzhiyun 				msleep(100);
407*4882a593Smuzhiyun 				mutex_lock(&ftdi->u132_lock);
408*4882a593Smuzhiyun 				goto wait_2;
409*4882a593Smuzhiyun 			}
410*4882a593Smuzhiyun 		}
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun 	ftdi->received = 0;
413*4882a593Smuzhiyun 	ftdi->expected = 4;
414*4882a593Smuzhiyun 	ftdi->ed_found = 0;
415*4882a593Smuzhiyun 	mutex_unlock(&ftdi->u132_lock);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
ftdi_elan_cancel_targets(struct usb_ftdi * ftdi)418*4882a593Smuzhiyun static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	int ed_number = 4;
421*4882a593Smuzhiyun 	mutex_lock(&ftdi->u132_lock);
422*4882a593Smuzhiyun 	while (ed_number-- > 0) {
423*4882a593Smuzhiyun 		struct u132_target *target = &ftdi->target[ed_number];
424*4882a593Smuzhiyun 		target->abandoning = 1;
425*4882a593Smuzhiyun 	wait:if (target->active == 1) {
426*4882a593Smuzhiyun 			int command_size = ftdi->command_next -
427*4882a593Smuzhiyun 				ftdi->command_head;
428*4882a593Smuzhiyun 			if (command_size < COMMAND_SIZE) {
429*4882a593Smuzhiyun 				struct u132_command *command = &ftdi->command[
430*4882a593Smuzhiyun 					COMMAND_MASK & ftdi->command_next];
431*4882a593Smuzhiyun 				command->header = 0x80 | (ed_number << 5) | 0x4;
432*4882a593Smuzhiyun 				command->length = 0x00;
433*4882a593Smuzhiyun 				command->address = 0x00;
434*4882a593Smuzhiyun 				command->width = 0x00;
435*4882a593Smuzhiyun 				command->follows = 0;
436*4882a593Smuzhiyun 				command->value = 0;
437*4882a593Smuzhiyun 				command->buffer = &command->value;
438*4882a593Smuzhiyun 				ftdi->command_next += 1;
439*4882a593Smuzhiyun 				ftdi_elan_kick_command_queue(ftdi);
440*4882a593Smuzhiyun 			} else {
441*4882a593Smuzhiyun 				mutex_unlock(&ftdi->u132_lock);
442*4882a593Smuzhiyun 				msleep(100);
443*4882a593Smuzhiyun 				mutex_lock(&ftdi->u132_lock);
444*4882a593Smuzhiyun 				goto wait;
445*4882a593Smuzhiyun 			}
446*4882a593Smuzhiyun 		}
447*4882a593Smuzhiyun 	}
448*4882a593Smuzhiyun 	ftdi->received = 0;
449*4882a593Smuzhiyun 	ftdi->expected = 4;
450*4882a593Smuzhiyun 	ftdi->ed_found = 0;
451*4882a593Smuzhiyun 	mutex_unlock(&ftdi->u132_lock);
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun 
ftdi_elan_kick_command_queue(struct usb_ftdi * ftdi)454*4882a593Smuzhiyun static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	ftdi_command_queue_work(ftdi, 0);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
ftdi_elan_command_work(struct work_struct * work)459*4882a593Smuzhiyun static void ftdi_elan_command_work(struct work_struct *work)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	struct usb_ftdi *ftdi =
462*4882a593Smuzhiyun 		container_of(work, struct usb_ftdi, command_work.work);
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
465*4882a593Smuzhiyun 		ftdi_elan_put_kref(ftdi);
466*4882a593Smuzhiyun 		return;
467*4882a593Smuzhiyun 	} else {
468*4882a593Smuzhiyun 		int retval = ftdi_elan_command_engine(ftdi);
469*4882a593Smuzhiyun 		if (retval == -ESHUTDOWN) {
470*4882a593Smuzhiyun 			ftdi->disconnected += 1;
471*4882a593Smuzhiyun 		} else if (retval == -ENODEV) {
472*4882a593Smuzhiyun 			ftdi->disconnected += 1;
473*4882a593Smuzhiyun 		} else if (retval)
474*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "command error %d\n", retval);
475*4882a593Smuzhiyun 		ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10));
476*4882a593Smuzhiyun 		return;
477*4882a593Smuzhiyun 	}
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
ftdi_elan_kick_respond_queue(struct usb_ftdi * ftdi)480*4882a593Smuzhiyun static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	ftdi_respond_queue_work(ftdi, 0);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun 
ftdi_elan_respond_work(struct work_struct * work)485*4882a593Smuzhiyun static void ftdi_elan_respond_work(struct work_struct *work)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun 	struct usb_ftdi *ftdi =
488*4882a593Smuzhiyun 		container_of(work, struct usb_ftdi, respond_work.work);
489*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
490*4882a593Smuzhiyun 		ftdi_elan_put_kref(ftdi);
491*4882a593Smuzhiyun 		return;
492*4882a593Smuzhiyun 	} else {
493*4882a593Smuzhiyun 		int retval = ftdi_elan_respond_engine(ftdi);
494*4882a593Smuzhiyun 		if (retval == 0) {
495*4882a593Smuzhiyun 		} else if (retval == -ESHUTDOWN) {
496*4882a593Smuzhiyun 			ftdi->disconnected += 1;
497*4882a593Smuzhiyun 		} else if (retval == -ENODEV) {
498*4882a593Smuzhiyun 			ftdi->disconnected += 1;
499*4882a593Smuzhiyun 		} else if (retval == -EILSEQ) {
500*4882a593Smuzhiyun 			ftdi->disconnected += 1;
501*4882a593Smuzhiyun 		} else {
502*4882a593Smuzhiyun 			ftdi->disconnected += 1;
503*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "respond error %d\n", retval);
504*4882a593Smuzhiyun 		}
505*4882a593Smuzhiyun 		if (ftdi->disconnected > 0) {
506*4882a593Smuzhiyun 			ftdi_elan_abandon_completions(ftdi);
507*4882a593Smuzhiyun 			ftdi_elan_abandon_targets(ftdi);
508*4882a593Smuzhiyun 		}
509*4882a593Smuzhiyun 		ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10));
510*4882a593Smuzhiyun 		return;
511*4882a593Smuzhiyun 	}
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun /*
516*4882a593Smuzhiyun  * the sw_lock is initially held and will be freed
517*4882a593Smuzhiyun  * after the FTDI has been synchronized
518*4882a593Smuzhiyun  *
519*4882a593Smuzhiyun  */
ftdi_elan_status_work(struct work_struct * work)520*4882a593Smuzhiyun static void ftdi_elan_status_work(struct work_struct *work)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun 	struct usb_ftdi *ftdi =
523*4882a593Smuzhiyun 		container_of(work, struct usb_ftdi, status_work.work);
524*4882a593Smuzhiyun 	int work_delay_in_msec = 0;
525*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
526*4882a593Smuzhiyun 		ftdi_elan_put_kref(ftdi);
527*4882a593Smuzhiyun 		return;
528*4882a593Smuzhiyun 	} else if (ftdi->synchronized == 0) {
529*4882a593Smuzhiyun 		down(&ftdi->sw_lock);
530*4882a593Smuzhiyun 		if (ftdi_elan_synchronize(ftdi) == 0) {
531*4882a593Smuzhiyun 			ftdi->synchronized = 1;
532*4882a593Smuzhiyun 			ftdi_command_queue_work(ftdi, 1);
533*4882a593Smuzhiyun 			ftdi_respond_queue_work(ftdi, 1);
534*4882a593Smuzhiyun 			up(&ftdi->sw_lock);
535*4882a593Smuzhiyun 			work_delay_in_msec = 100;
536*4882a593Smuzhiyun 		} else {
537*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "synchronize failed\n");
538*4882a593Smuzhiyun 			up(&ftdi->sw_lock);
539*4882a593Smuzhiyun 			work_delay_in_msec = 10 *1000;
540*4882a593Smuzhiyun 		}
541*4882a593Smuzhiyun 	} else if (ftdi->stuck_status > 0) {
542*4882a593Smuzhiyun 		if (ftdi_elan_stuck_waiting(ftdi) == 0) {
543*4882a593Smuzhiyun 			ftdi->stuck_status = 0;
544*4882a593Smuzhiyun 			ftdi->synchronized = 0;
545*4882a593Smuzhiyun 		} else if ((ftdi->stuck_status++ % 60) == 1) {
546*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "WRONG type of card inserted - please remove\n");
547*4882a593Smuzhiyun 		} else
548*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "WRONG type of card inserted - checked %d times\n",
549*4882a593Smuzhiyun 				ftdi->stuck_status);
550*4882a593Smuzhiyun 		work_delay_in_msec = 100;
551*4882a593Smuzhiyun 	} else if (ftdi->enumerated == 0) {
552*4882a593Smuzhiyun 		if (ftdi_elan_enumeratePCI(ftdi) == 0) {
553*4882a593Smuzhiyun 			ftdi->enumerated = 1;
554*4882a593Smuzhiyun 			work_delay_in_msec = 250;
555*4882a593Smuzhiyun 		} else
556*4882a593Smuzhiyun 			work_delay_in_msec = 1000;
557*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
558*4882a593Smuzhiyun 		if (ftdi_elan_setupOHCI(ftdi) == 0) {
559*4882a593Smuzhiyun 			ftdi->initialized = 1;
560*4882a593Smuzhiyun 			work_delay_in_msec = 500;
561*4882a593Smuzhiyun 		} else {
562*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "initialized failed - trying again in 10 seconds\n");
563*4882a593Smuzhiyun 			work_delay_in_msec = 1 *1000;
564*4882a593Smuzhiyun 		}
565*4882a593Smuzhiyun 	} else if (ftdi->registered == 0) {
566*4882a593Smuzhiyun 		work_delay_in_msec = 10;
567*4882a593Smuzhiyun 		if (ftdi_elan_hcd_init(ftdi) == 0) {
568*4882a593Smuzhiyun 			ftdi->registered = 1;
569*4882a593Smuzhiyun 		} else
570*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "register failed\n");
571*4882a593Smuzhiyun 		work_delay_in_msec = 250;
572*4882a593Smuzhiyun 	} else {
573*4882a593Smuzhiyun 		if (ftdi_elan_checkingPCI(ftdi) == 0) {
574*4882a593Smuzhiyun 			work_delay_in_msec = 250;
575*4882a593Smuzhiyun 		} else if (ftdi->controlreg & 0x00400000) {
576*4882a593Smuzhiyun 			if (ftdi->gone_away > 0) {
577*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "PCI device eject confirmed platform_dev.dev.parent=%p platform_dev.dev=%p\n",
578*4882a593Smuzhiyun 					ftdi->platform_dev.dev.parent,
579*4882a593Smuzhiyun 					&ftdi->platform_dev.dev);
580*4882a593Smuzhiyun 				platform_device_unregister(&ftdi->platform_dev);
581*4882a593Smuzhiyun 				ftdi->platform_dev.dev.parent = NULL;
582*4882a593Smuzhiyun 				ftdi->registered = 0;
583*4882a593Smuzhiyun 				ftdi->enumerated = 0;
584*4882a593Smuzhiyun 				ftdi->card_ejected = 0;
585*4882a593Smuzhiyun 				ftdi->initialized = 0;
586*4882a593Smuzhiyun 				ftdi->gone_away = 0;
587*4882a593Smuzhiyun 			} else
588*4882a593Smuzhiyun 				ftdi_elan_flush_targets(ftdi);
589*4882a593Smuzhiyun 			work_delay_in_msec = 250;
590*4882a593Smuzhiyun 		} else {
591*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "PCI device has disappeared\n");
592*4882a593Smuzhiyun 			ftdi_elan_cancel_targets(ftdi);
593*4882a593Smuzhiyun 			work_delay_in_msec = 500;
594*4882a593Smuzhiyun 			ftdi->enumerated = 0;
595*4882a593Smuzhiyun 			ftdi->initialized = 0;
596*4882a593Smuzhiyun 		}
597*4882a593Smuzhiyun 	}
598*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
599*4882a593Smuzhiyun 		ftdi_elan_put_kref(ftdi);
600*4882a593Smuzhiyun 		return;
601*4882a593Smuzhiyun 	} else {
602*4882a593Smuzhiyun 		ftdi_status_requeue_work(ftdi,
603*4882a593Smuzhiyun 					 msecs_to_jiffies(work_delay_in_msec));
604*4882a593Smuzhiyun 		return;
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun /*
610*4882a593Smuzhiyun  * file_operations for the jtag interface
611*4882a593Smuzhiyun  *
612*4882a593Smuzhiyun  * the usage count for the device is incremented on open()
613*4882a593Smuzhiyun  * and decremented on release()
614*4882a593Smuzhiyun  */
ftdi_elan_open(struct inode * inode,struct file * file)615*4882a593Smuzhiyun static int ftdi_elan_open(struct inode *inode, struct file *file)
616*4882a593Smuzhiyun {
617*4882a593Smuzhiyun 	int subminor;
618*4882a593Smuzhiyun 	struct usb_interface *interface;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	subminor = iminor(inode);
621*4882a593Smuzhiyun 	interface = usb_find_interface(&ftdi_elan_driver, subminor);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (!interface) {
624*4882a593Smuzhiyun 		pr_err("can't find device for minor %d\n", subminor);
625*4882a593Smuzhiyun 		return -ENODEV;
626*4882a593Smuzhiyun 	} else {
627*4882a593Smuzhiyun 		struct usb_ftdi *ftdi = usb_get_intfdata(interface);
628*4882a593Smuzhiyun 		if (!ftdi) {
629*4882a593Smuzhiyun 			return -ENODEV;
630*4882a593Smuzhiyun 		} else {
631*4882a593Smuzhiyun 			if (down_interruptible(&ftdi->sw_lock)) {
632*4882a593Smuzhiyun 				return -EINTR;
633*4882a593Smuzhiyun 			} else {
634*4882a593Smuzhiyun 				ftdi_elan_get_kref(ftdi);
635*4882a593Smuzhiyun 				file->private_data = ftdi;
636*4882a593Smuzhiyun 				return 0;
637*4882a593Smuzhiyun 			}
638*4882a593Smuzhiyun 		}
639*4882a593Smuzhiyun 	}
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
ftdi_elan_release(struct inode * inode,struct file * file)642*4882a593Smuzhiyun static int ftdi_elan_release(struct inode *inode, struct file *file)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = file->private_data;
645*4882a593Smuzhiyun 	if (ftdi == NULL)
646*4882a593Smuzhiyun 		return -ENODEV;
647*4882a593Smuzhiyun 	up(&ftdi->sw_lock);        /* decrement the count on our device */
648*4882a593Smuzhiyun 	ftdi_elan_put_kref(ftdi);
649*4882a593Smuzhiyun 	return 0;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun /*
654*4882a593Smuzhiyun  *
655*4882a593Smuzhiyun  * blocking bulk reads are used to get data from the device
656*4882a593Smuzhiyun  *
657*4882a593Smuzhiyun  */
ftdi_elan_read(struct file * file,char __user * buffer,size_t count,loff_t * ppos)658*4882a593Smuzhiyun static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
659*4882a593Smuzhiyun 			      size_t count, loff_t *ppos)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun 	char data[30 *3 + 4];
662*4882a593Smuzhiyun 	char *d = data;
663*4882a593Smuzhiyun 	int m = (sizeof(data) - 1) / 3 - 1;
664*4882a593Smuzhiyun 	int bytes_read = 0;
665*4882a593Smuzhiyun 	int retry_on_empty = 10;
666*4882a593Smuzhiyun 	int retry_on_timeout = 5;
667*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = file->private_data;
668*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
669*4882a593Smuzhiyun 		return -ENODEV;
670*4882a593Smuzhiyun 	}
671*4882a593Smuzhiyun 	data[0] = 0;
672*4882a593Smuzhiyun have:if (ftdi->bulk_in_left > 0) {
673*4882a593Smuzhiyun 		if (count-- > 0) {
674*4882a593Smuzhiyun 			char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer;
675*4882a593Smuzhiyun 			ftdi->bulk_in_left -= 1;
676*4882a593Smuzhiyun 			if (bytes_read < m) {
677*4882a593Smuzhiyun 				d += sprintf(d, " %02X", 0x000000FF & *p);
678*4882a593Smuzhiyun 			} else if (bytes_read > m) {
679*4882a593Smuzhiyun 			} else
680*4882a593Smuzhiyun 				d += sprintf(d, " ..");
681*4882a593Smuzhiyun 			if (copy_to_user(buffer++, p, 1)) {
682*4882a593Smuzhiyun 				return -EFAULT;
683*4882a593Smuzhiyun 			} else {
684*4882a593Smuzhiyun 				bytes_read += 1;
685*4882a593Smuzhiyun 				goto have;
686*4882a593Smuzhiyun 			}
687*4882a593Smuzhiyun 		} else
688*4882a593Smuzhiyun 			return bytes_read;
689*4882a593Smuzhiyun 	}
690*4882a593Smuzhiyun more:if (count > 0) {
691*4882a593Smuzhiyun 		int packet_bytes = 0;
692*4882a593Smuzhiyun 		int retval = usb_bulk_msg(ftdi->udev,
693*4882a593Smuzhiyun 					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
694*4882a593Smuzhiyun 					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
695*4882a593Smuzhiyun 					  &packet_bytes, 50);
696*4882a593Smuzhiyun 		if (packet_bytes > 2) {
697*4882a593Smuzhiyun 			ftdi->bulk_in_left = packet_bytes - 2;
698*4882a593Smuzhiyun 			ftdi->bulk_in_last = 1;
699*4882a593Smuzhiyun 			goto have;
700*4882a593Smuzhiyun 		} else if (retval == -ETIMEDOUT) {
701*4882a593Smuzhiyun 			if (retry_on_timeout-- > 0) {
702*4882a593Smuzhiyun 				goto more;
703*4882a593Smuzhiyun 			} else if (bytes_read > 0) {
704*4882a593Smuzhiyun 				return bytes_read;
705*4882a593Smuzhiyun 			} else
706*4882a593Smuzhiyun 				return retval;
707*4882a593Smuzhiyun 		} else if (retval == 0) {
708*4882a593Smuzhiyun 			if (retry_on_empty-- > 0) {
709*4882a593Smuzhiyun 				goto more;
710*4882a593Smuzhiyun 			} else
711*4882a593Smuzhiyun 				return bytes_read;
712*4882a593Smuzhiyun 		} else
713*4882a593Smuzhiyun 			return retval;
714*4882a593Smuzhiyun 	} else
715*4882a593Smuzhiyun 		return bytes_read;
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun 
ftdi_elan_write_bulk_callback(struct urb * urb)718*4882a593Smuzhiyun static void ftdi_elan_write_bulk_callback(struct urb *urb)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = urb->context;
721*4882a593Smuzhiyun 	int status = urb->status;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	if (status && !(status == -ENOENT || status == -ECONNRESET ||
724*4882a593Smuzhiyun 			status == -ESHUTDOWN)) {
725*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev,
726*4882a593Smuzhiyun 			"urb=%p write bulk status received: %d\n", urb, status);
727*4882a593Smuzhiyun 	}
728*4882a593Smuzhiyun 	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
729*4882a593Smuzhiyun 			  urb->transfer_buffer, urb->transfer_dma);
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun 
fill_buffer_with_all_queued_commands(struct usb_ftdi * ftdi,char * buf,int command_size,int total_size)732*4882a593Smuzhiyun static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi,
733*4882a593Smuzhiyun 						char *buf, int command_size, int total_size)
734*4882a593Smuzhiyun {
735*4882a593Smuzhiyun 	int ed_commands = 0;
736*4882a593Smuzhiyun 	int b = 0;
737*4882a593Smuzhiyun 	int I = command_size;
738*4882a593Smuzhiyun 	int i = ftdi->command_head;
739*4882a593Smuzhiyun 	while (I-- > 0) {
740*4882a593Smuzhiyun 		struct u132_command *command = &ftdi->command[COMMAND_MASK &
741*4882a593Smuzhiyun 							      i++];
742*4882a593Smuzhiyun 		int F = command->follows;
743*4882a593Smuzhiyun 		u8 *f = command->buffer;
744*4882a593Smuzhiyun 		if (command->header & 0x80) {
745*4882a593Smuzhiyun 			ed_commands |= 1 << (0x3 & (command->header >> 5));
746*4882a593Smuzhiyun 		}
747*4882a593Smuzhiyun 		buf[b++] = command->header;
748*4882a593Smuzhiyun 		buf[b++] = (command->length >> 0) & 0x00FF;
749*4882a593Smuzhiyun 		buf[b++] = (command->length >> 8) & 0x00FF;
750*4882a593Smuzhiyun 		buf[b++] = command->address;
751*4882a593Smuzhiyun 		buf[b++] = command->width;
752*4882a593Smuzhiyun 		while (F-- > 0) {
753*4882a593Smuzhiyun 			buf[b++] = *f++;
754*4882a593Smuzhiyun 		}
755*4882a593Smuzhiyun 	}
756*4882a593Smuzhiyun 	return ed_commands;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun 
ftdi_elan_total_command_size(struct usb_ftdi * ftdi,int command_size)759*4882a593Smuzhiyun static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	int total_size = 0;
762*4882a593Smuzhiyun 	int I = command_size;
763*4882a593Smuzhiyun 	int i = ftdi->command_head;
764*4882a593Smuzhiyun 	while (I-- > 0) {
765*4882a593Smuzhiyun 		struct u132_command *command = &ftdi->command[COMMAND_MASK &
766*4882a593Smuzhiyun 							      i++];
767*4882a593Smuzhiyun 		total_size += 5 + command->follows;
768*4882a593Smuzhiyun 	}
769*4882a593Smuzhiyun 	return total_size;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun 
ftdi_elan_command_engine(struct usb_ftdi * ftdi)772*4882a593Smuzhiyun static int ftdi_elan_command_engine(struct usb_ftdi *ftdi)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun 	int retval;
775*4882a593Smuzhiyun 	char *buf;
776*4882a593Smuzhiyun 	int ed_commands;
777*4882a593Smuzhiyun 	int total_size;
778*4882a593Smuzhiyun 	struct urb *urb;
779*4882a593Smuzhiyun 	int command_size = ftdi->command_next - ftdi->command_head;
780*4882a593Smuzhiyun 	if (command_size == 0)
781*4882a593Smuzhiyun 		return 0;
782*4882a593Smuzhiyun 	total_size = ftdi_elan_total_command_size(ftdi, command_size);
783*4882a593Smuzhiyun 	urb = usb_alloc_urb(0, GFP_KERNEL);
784*4882a593Smuzhiyun 	if (!urb)
785*4882a593Smuzhiyun 		return -ENOMEM;
786*4882a593Smuzhiyun 	buf = usb_alloc_coherent(ftdi->udev, total_size, GFP_KERNEL,
787*4882a593Smuzhiyun 				 &urb->transfer_dma);
788*4882a593Smuzhiyun 	if (!buf) {
789*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "could not get a buffer to write %d commands totaling %d bytes to the Uxxx\n",
790*4882a593Smuzhiyun 			command_size, total_size);
791*4882a593Smuzhiyun 		usb_free_urb(urb);
792*4882a593Smuzhiyun 		return -ENOMEM;
793*4882a593Smuzhiyun 	}
794*4882a593Smuzhiyun 	ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf,
795*4882a593Smuzhiyun 							   command_size, total_size);
796*4882a593Smuzhiyun 	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
797*4882a593Smuzhiyun 							   ftdi->bulk_out_endpointAddr), buf, total_size,
798*4882a593Smuzhiyun 			  ftdi_elan_write_bulk_callback, ftdi);
799*4882a593Smuzhiyun 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
800*4882a593Smuzhiyun 	if (ed_commands) {
801*4882a593Smuzhiyun 		char diag[40 *3 + 4];
802*4882a593Smuzhiyun 		char *d = diag;
803*4882a593Smuzhiyun 		int m = total_size;
804*4882a593Smuzhiyun 		u8 *c = buf;
805*4882a593Smuzhiyun 		int s = (sizeof(diag) - 1) / 3;
806*4882a593Smuzhiyun 		diag[0] = 0;
807*4882a593Smuzhiyun 		while (s-- > 0 && m-- > 0) {
808*4882a593Smuzhiyun 			if (s > 0 || m == 0) {
809*4882a593Smuzhiyun 				d += sprintf(d, " %02X", *c++);
810*4882a593Smuzhiyun 			} else
811*4882a593Smuzhiyun 				d += sprintf(d, " ..");
812*4882a593Smuzhiyun 		}
813*4882a593Smuzhiyun 	}
814*4882a593Smuzhiyun 	retval = usb_submit_urb(urb, GFP_KERNEL);
815*4882a593Smuzhiyun 	if (retval) {
816*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write %d commands totaling %d bytes to the Uxxx\n",
817*4882a593Smuzhiyun 			retval, urb, command_size, total_size);
818*4882a593Smuzhiyun 		usb_free_coherent(ftdi->udev, total_size, buf, urb->transfer_dma);
819*4882a593Smuzhiyun 		usb_free_urb(urb);
820*4882a593Smuzhiyun 		return retval;
821*4882a593Smuzhiyun 	}
822*4882a593Smuzhiyun 	usb_free_urb(urb);        /* release our reference to this urb,
823*4882a593Smuzhiyun 				     the USB core will eventually free it entirely */
824*4882a593Smuzhiyun 	ftdi->command_head += command_size;
825*4882a593Smuzhiyun 	ftdi_elan_kick_respond_queue(ftdi);
826*4882a593Smuzhiyun 	return 0;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun 
ftdi_elan_do_callback(struct usb_ftdi * ftdi,struct u132_target * target,u8 * buffer,int length)829*4882a593Smuzhiyun static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
830*4882a593Smuzhiyun 				  struct u132_target *target, u8 *buffer, int length)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun 	struct urb *urb = target->urb;
833*4882a593Smuzhiyun 	int halted = target->halted;
834*4882a593Smuzhiyun 	int skipped = target->skipped;
835*4882a593Smuzhiyun 	int actual = target->actual;
836*4882a593Smuzhiyun 	int non_null = target->non_null;
837*4882a593Smuzhiyun 	int toggle_bits = target->toggle_bits;
838*4882a593Smuzhiyun 	int error_count = target->error_count;
839*4882a593Smuzhiyun 	int condition_code = target->condition_code;
840*4882a593Smuzhiyun 	int repeat_number = target->repeat_number;
841*4882a593Smuzhiyun 	void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int,
842*4882a593Smuzhiyun 			  int, int, int, int) = target->callback;
843*4882a593Smuzhiyun 	target->active -= 1;
844*4882a593Smuzhiyun 	target->callback = NULL;
845*4882a593Smuzhiyun 	(*callback) (target->endp, urb, buffer, length, toggle_bits,
846*4882a593Smuzhiyun 		     error_count, condition_code, repeat_number, halted, skipped,
847*4882a593Smuzhiyun 		     actual, non_null);
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun 
have_ed_set_response(struct usb_ftdi * ftdi,struct u132_target * target,u16 ed_length,int ed_number,int ed_type,char * b)850*4882a593Smuzhiyun static char *have_ed_set_response(struct usb_ftdi *ftdi,
851*4882a593Smuzhiyun 				  struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
852*4882a593Smuzhiyun 				  char *b)
853*4882a593Smuzhiyun {
854*4882a593Smuzhiyun 	int payload = (ed_length >> 0) & 0x07FF;
855*4882a593Smuzhiyun 	mutex_lock(&ftdi->u132_lock);
856*4882a593Smuzhiyun 	target->actual = 0;
857*4882a593Smuzhiyun 	target->non_null = (ed_length >> 15) & 0x0001;
858*4882a593Smuzhiyun 	target->repeat_number = (ed_length >> 11) & 0x000F;
859*4882a593Smuzhiyun 	if (ed_type == 0x02 || ed_type == 0x03) {
860*4882a593Smuzhiyun 		if (payload == 0 || target->abandoning > 0) {
861*4882a593Smuzhiyun 			target->abandoning = 0;
862*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
863*4882a593Smuzhiyun 			ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
864*4882a593Smuzhiyun 					      payload);
865*4882a593Smuzhiyun 			ftdi->received = 0;
866*4882a593Smuzhiyun 			ftdi->expected = 4;
867*4882a593Smuzhiyun 			ftdi->ed_found = 0;
868*4882a593Smuzhiyun 			return ftdi->response;
869*4882a593Smuzhiyun 		} else {
870*4882a593Smuzhiyun 			ftdi->expected = 4 + payload;
871*4882a593Smuzhiyun 			ftdi->ed_found = 1;
872*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
873*4882a593Smuzhiyun 			return b;
874*4882a593Smuzhiyun 		}
875*4882a593Smuzhiyun 	} else {
876*4882a593Smuzhiyun 		target->abandoning = 0;
877*4882a593Smuzhiyun 		mutex_unlock(&ftdi->u132_lock);
878*4882a593Smuzhiyun 		ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
879*4882a593Smuzhiyun 				      payload);
880*4882a593Smuzhiyun 		ftdi->received = 0;
881*4882a593Smuzhiyun 		ftdi->expected = 4;
882*4882a593Smuzhiyun 		ftdi->ed_found = 0;
883*4882a593Smuzhiyun 		return ftdi->response;
884*4882a593Smuzhiyun 	}
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun 
have_ed_get_response(struct usb_ftdi * ftdi,struct u132_target * target,u16 ed_length,int ed_number,int ed_type,char * b)887*4882a593Smuzhiyun static char *have_ed_get_response(struct usb_ftdi *ftdi,
888*4882a593Smuzhiyun 				  struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
889*4882a593Smuzhiyun 				  char *b)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun 	mutex_lock(&ftdi->u132_lock);
892*4882a593Smuzhiyun 	target->condition_code = TD_DEVNOTRESP;
893*4882a593Smuzhiyun 	target->actual = (ed_length >> 0) & 0x01FF;
894*4882a593Smuzhiyun 	target->non_null = (ed_length >> 15) & 0x0001;
895*4882a593Smuzhiyun 	target->repeat_number = (ed_length >> 11) & 0x000F;
896*4882a593Smuzhiyun 	mutex_unlock(&ftdi->u132_lock);
897*4882a593Smuzhiyun 	if (target->active)
898*4882a593Smuzhiyun 		ftdi_elan_do_callback(ftdi, target, NULL, 0);
899*4882a593Smuzhiyun 	target->abandoning = 0;
900*4882a593Smuzhiyun 	ftdi->received = 0;
901*4882a593Smuzhiyun 	ftdi->expected = 4;
902*4882a593Smuzhiyun 	ftdi->ed_found = 0;
903*4882a593Smuzhiyun 	return ftdi->response;
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun /*
908*4882a593Smuzhiyun  * The engine tries to empty the FTDI fifo
909*4882a593Smuzhiyun  *
910*4882a593Smuzhiyun  * all responses found in the fifo data are dispatched thus
911*4882a593Smuzhiyun  * the response buffer can only ever hold a maximum sized
912*4882a593Smuzhiyun  * response from the Uxxx.
913*4882a593Smuzhiyun  *
914*4882a593Smuzhiyun  */
ftdi_elan_respond_engine(struct usb_ftdi * ftdi)915*4882a593Smuzhiyun static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun 	u8 *b = ftdi->response + ftdi->received;
918*4882a593Smuzhiyun 	int bytes_read = 0;
919*4882a593Smuzhiyun 	int retry_on_empty = 1;
920*4882a593Smuzhiyun 	int retry_on_timeout = 3;
921*4882a593Smuzhiyun read:{
922*4882a593Smuzhiyun 		int packet_bytes = 0;
923*4882a593Smuzhiyun 		int retval = usb_bulk_msg(ftdi->udev,
924*4882a593Smuzhiyun 					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
925*4882a593Smuzhiyun 					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
926*4882a593Smuzhiyun 					  &packet_bytes, 500);
927*4882a593Smuzhiyun 		char diag[30 *3 + 4];
928*4882a593Smuzhiyun 		char *d = diag;
929*4882a593Smuzhiyun 		int m = packet_bytes;
930*4882a593Smuzhiyun 		u8 *c = ftdi->bulk_in_buffer;
931*4882a593Smuzhiyun 		int s = (sizeof(diag) - 1) / 3;
932*4882a593Smuzhiyun 		diag[0] = 0;
933*4882a593Smuzhiyun 		while (s-- > 0 && m-- > 0) {
934*4882a593Smuzhiyun 			if (s > 0 || m == 0) {
935*4882a593Smuzhiyun 				d += sprintf(d, " %02X", *c++);
936*4882a593Smuzhiyun 			} else
937*4882a593Smuzhiyun 				d += sprintf(d, " ..");
938*4882a593Smuzhiyun 		}
939*4882a593Smuzhiyun 		if (packet_bytes > 2) {
940*4882a593Smuzhiyun 			ftdi->bulk_in_left = packet_bytes - 2;
941*4882a593Smuzhiyun 			ftdi->bulk_in_last = 1;
942*4882a593Smuzhiyun 			goto have;
943*4882a593Smuzhiyun 		} else if (retval == -ETIMEDOUT) {
944*4882a593Smuzhiyun 			if (retry_on_timeout-- > 0) {
945*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "TIMED OUT with packet_bytes = %d with total %d bytes%s\n",
946*4882a593Smuzhiyun 					packet_bytes, bytes_read, diag);
947*4882a593Smuzhiyun 				goto more;
948*4882a593Smuzhiyun 			} else if (bytes_read > 0) {
949*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n",
950*4882a593Smuzhiyun 					bytes_read, diag);
951*4882a593Smuzhiyun 				return -ENOMEM;
952*4882a593Smuzhiyun 			} else {
953*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "TIMED OUT with packet_bytes = %d with total %d bytes%s\n",
954*4882a593Smuzhiyun 					packet_bytes, bytes_read, diag);
955*4882a593Smuzhiyun 				return -ENOMEM;
956*4882a593Smuzhiyun 			}
957*4882a593Smuzhiyun 		} else if (retval == -EILSEQ) {
958*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n",
959*4882a593Smuzhiyun 				retval, packet_bytes, bytes_read, diag);
960*4882a593Smuzhiyun 			return retval;
961*4882a593Smuzhiyun 		} else if (retval) {
962*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n",
963*4882a593Smuzhiyun 				retval, packet_bytes, bytes_read, diag);
964*4882a593Smuzhiyun 			return retval;
965*4882a593Smuzhiyun 		} else {
966*4882a593Smuzhiyun 			if (retry_on_empty-- > 0) {
967*4882a593Smuzhiyun 				goto more;
968*4882a593Smuzhiyun 			} else
969*4882a593Smuzhiyun 				return 0;
970*4882a593Smuzhiyun 		}
971*4882a593Smuzhiyun 	}
972*4882a593Smuzhiyun more:{
973*4882a593Smuzhiyun 		goto read;
974*4882a593Smuzhiyun 	}
975*4882a593Smuzhiyun have:if (ftdi->bulk_in_left > 0) {
976*4882a593Smuzhiyun 		u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last];
977*4882a593Smuzhiyun 		bytes_read += 1;
978*4882a593Smuzhiyun 		ftdi->bulk_in_left -= 1;
979*4882a593Smuzhiyun 		if (ftdi->received == 0 && c == 0xFF) {
980*4882a593Smuzhiyun 			goto have;
981*4882a593Smuzhiyun 		} else
982*4882a593Smuzhiyun 			*b++ = c;
983*4882a593Smuzhiyun 		if (++ftdi->received < ftdi->expected) {
984*4882a593Smuzhiyun 			goto have;
985*4882a593Smuzhiyun 		} else if (ftdi->ed_found) {
986*4882a593Smuzhiyun 			int ed_number = (ftdi->response[0] >> 5) & 0x03;
987*4882a593Smuzhiyun 			u16 ed_length = (ftdi->response[2] << 8) |
988*4882a593Smuzhiyun 				ftdi->response[1];
989*4882a593Smuzhiyun 			struct u132_target *target = &ftdi->target[ed_number];
990*4882a593Smuzhiyun 			int payload = (ed_length >> 0) & 0x07FF;
991*4882a593Smuzhiyun 			char diag[30 *3 + 4];
992*4882a593Smuzhiyun 			char *d = diag;
993*4882a593Smuzhiyun 			int m = payload;
994*4882a593Smuzhiyun 			u8 *c = 4 + ftdi->response;
995*4882a593Smuzhiyun 			int s = (sizeof(diag) - 1) / 3;
996*4882a593Smuzhiyun 			diag[0] = 0;
997*4882a593Smuzhiyun 			while (s-- > 0 && m-- > 0) {
998*4882a593Smuzhiyun 				if (s > 0 || m == 0) {
999*4882a593Smuzhiyun 					d += sprintf(d, " %02X", *c++);
1000*4882a593Smuzhiyun 				} else
1001*4882a593Smuzhiyun 					d += sprintf(d, " ..");
1002*4882a593Smuzhiyun 			}
1003*4882a593Smuzhiyun 			ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
1004*4882a593Smuzhiyun 					      payload);
1005*4882a593Smuzhiyun 			ftdi->received = 0;
1006*4882a593Smuzhiyun 			ftdi->expected = 4;
1007*4882a593Smuzhiyun 			ftdi->ed_found = 0;
1008*4882a593Smuzhiyun 			b = ftdi->response;
1009*4882a593Smuzhiyun 			goto have;
1010*4882a593Smuzhiyun 		} else if (ftdi->expected == 8) {
1011*4882a593Smuzhiyun 			u8 buscmd;
1012*4882a593Smuzhiyun 			int respond_head = ftdi->respond_head++;
1013*4882a593Smuzhiyun 			struct u132_respond *respond = &ftdi->respond[
1014*4882a593Smuzhiyun 				RESPOND_MASK & respond_head];
1015*4882a593Smuzhiyun 			u32 data = ftdi->response[7];
1016*4882a593Smuzhiyun 			data <<= 8;
1017*4882a593Smuzhiyun 			data |= ftdi->response[6];
1018*4882a593Smuzhiyun 			data <<= 8;
1019*4882a593Smuzhiyun 			data |= ftdi->response[5];
1020*4882a593Smuzhiyun 			data <<= 8;
1021*4882a593Smuzhiyun 			data |= ftdi->response[4];
1022*4882a593Smuzhiyun 			*respond->value = data;
1023*4882a593Smuzhiyun 			*respond->result = 0;
1024*4882a593Smuzhiyun 			complete(&respond->wait_completion);
1025*4882a593Smuzhiyun 			ftdi->received = 0;
1026*4882a593Smuzhiyun 			ftdi->expected = 4;
1027*4882a593Smuzhiyun 			ftdi->ed_found = 0;
1028*4882a593Smuzhiyun 			b = ftdi->response;
1029*4882a593Smuzhiyun 			buscmd = (ftdi->response[0] >> 0) & 0x0F;
1030*4882a593Smuzhiyun 			if (buscmd == 0x00) {
1031*4882a593Smuzhiyun 			} else if (buscmd == 0x02) {
1032*4882a593Smuzhiyun 			} else if (buscmd == 0x06) {
1033*4882a593Smuzhiyun 			} else if (buscmd == 0x0A) {
1034*4882a593Smuzhiyun 			} else
1035*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) value = %08X\n",
1036*4882a593Smuzhiyun 					buscmd, data);
1037*4882a593Smuzhiyun 			goto have;
1038*4882a593Smuzhiyun 		} else {
1039*4882a593Smuzhiyun 			if ((ftdi->response[0] & 0x80) == 0x00) {
1040*4882a593Smuzhiyun 				ftdi->expected = 8;
1041*4882a593Smuzhiyun 				goto have;
1042*4882a593Smuzhiyun 			} else {
1043*4882a593Smuzhiyun 				int ed_number = (ftdi->response[0] >> 5) & 0x03;
1044*4882a593Smuzhiyun 				int ed_type = (ftdi->response[0] >> 0) & 0x03;
1045*4882a593Smuzhiyun 				u16 ed_length = (ftdi->response[2] << 8) |
1046*4882a593Smuzhiyun 					ftdi->response[1];
1047*4882a593Smuzhiyun 				struct u132_target *target = &ftdi->target[
1048*4882a593Smuzhiyun 					ed_number];
1049*4882a593Smuzhiyun 				target->halted = (ftdi->response[0] >> 3) &
1050*4882a593Smuzhiyun 					0x01;
1051*4882a593Smuzhiyun 				target->skipped = (ftdi->response[0] >> 2) &
1052*4882a593Smuzhiyun 					0x01;
1053*4882a593Smuzhiyun 				target->toggle_bits = (ftdi->response[3] >> 6)
1054*4882a593Smuzhiyun 					& 0x03;
1055*4882a593Smuzhiyun 				target->error_count = (ftdi->response[3] >> 4)
1056*4882a593Smuzhiyun 					& 0x03;
1057*4882a593Smuzhiyun 				target->condition_code = (ftdi->response[
1058*4882a593Smuzhiyun 								  3] >> 0) & 0x0F;
1059*4882a593Smuzhiyun 				if ((ftdi->response[0] & 0x10) == 0x00) {
1060*4882a593Smuzhiyun 					b = have_ed_set_response(ftdi, target,
1061*4882a593Smuzhiyun 								 ed_length, ed_number, ed_type,
1062*4882a593Smuzhiyun 								 b);
1063*4882a593Smuzhiyun 					goto have;
1064*4882a593Smuzhiyun 				} else {
1065*4882a593Smuzhiyun 					b = have_ed_get_response(ftdi, target,
1066*4882a593Smuzhiyun 								 ed_length, ed_number, ed_type,
1067*4882a593Smuzhiyun 								 b);
1068*4882a593Smuzhiyun 					goto have;
1069*4882a593Smuzhiyun 				}
1070*4882a593Smuzhiyun 			}
1071*4882a593Smuzhiyun 		}
1072*4882a593Smuzhiyun 	} else
1073*4882a593Smuzhiyun 		goto more;
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun /*
1078*4882a593Smuzhiyun  * create a urb, and a buffer for it, and copy the data to the urb
1079*4882a593Smuzhiyun  *
1080*4882a593Smuzhiyun  */
ftdi_elan_write(struct file * file,const char __user * user_buffer,size_t count,loff_t * ppos)1081*4882a593Smuzhiyun static ssize_t ftdi_elan_write(struct file *file,
1082*4882a593Smuzhiyun 			       const char __user *user_buffer, size_t count,
1083*4882a593Smuzhiyun 			       loff_t *ppos)
1084*4882a593Smuzhiyun {
1085*4882a593Smuzhiyun 	int retval = 0;
1086*4882a593Smuzhiyun 	struct urb *urb;
1087*4882a593Smuzhiyun 	char *buf;
1088*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = file->private_data;
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
1091*4882a593Smuzhiyun 		return -ENODEV;
1092*4882a593Smuzhiyun 	}
1093*4882a593Smuzhiyun 	if (count == 0) {
1094*4882a593Smuzhiyun 		goto exit;
1095*4882a593Smuzhiyun 	}
1096*4882a593Smuzhiyun 	urb = usb_alloc_urb(0, GFP_KERNEL);
1097*4882a593Smuzhiyun 	if (!urb) {
1098*4882a593Smuzhiyun 		retval = -ENOMEM;
1099*4882a593Smuzhiyun 		goto error_1;
1100*4882a593Smuzhiyun 	}
1101*4882a593Smuzhiyun 	buf = usb_alloc_coherent(ftdi->udev, count, GFP_KERNEL,
1102*4882a593Smuzhiyun 				 &urb->transfer_dma);
1103*4882a593Smuzhiyun 	if (!buf) {
1104*4882a593Smuzhiyun 		retval = -ENOMEM;
1105*4882a593Smuzhiyun 		goto error_2;
1106*4882a593Smuzhiyun 	}
1107*4882a593Smuzhiyun 	if (copy_from_user(buf, user_buffer, count)) {
1108*4882a593Smuzhiyun 		retval = -EFAULT;
1109*4882a593Smuzhiyun 		goto error_3;
1110*4882a593Smuzhiyun 	}
1111*4882a593Smuzhiyun 	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
1112*4882a593Smuzhiyun 							   ftdi->bulk_out_endpointAddr), buf, count,
1113*4882a593Smuzhiyun 			  ftdi_elan_write_bulk_callback, ftdi);
1114*4882a593Smuzhiyun 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1115*4882a593Smuzhiyun 	retval = usb_submit_urb(urb, GFP_KERNEL);
1116*4882a593Smuzhiyun 	if (retval) {
1117*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev,
1118*4882a593Smuzhiyun 			"failed submitting write urb, error %d\n", retval);
1119*4882a593Smuzhiyun 		goto error_3;
1120*4882a593Smuzhiyun 	}
1121*4882a593Smuzhiyun 	usb_free_urb(urb);
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun exit:
1124*4882a593Smuzhiyun 	return count;
1125*4882a593Smuzhiyun error_3:
1126*4882a593Smuzhiyun 	usb_free_coherent(ftdi->udev, count, buf, urb->transfer_dma);
1127*4882a593Smuzhiyun error_2:
1128*4882a593Smuzhiyun 	usb_free_urb(urb);
1129*4882a593Smuzhiyun error_1:
1130*4882a593Smuzhiyun 	return retval;
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun 
1133*4882a593Smuzhiyun static const struct file_operations ftdi_elan_fops = {
1134*4882a593Smuzhiyun 	.owner = THIS_MODULE,
1135*4882a593Smuzhiyun 	.llseek = no_llseek,
1136*4882a593Smuzhiyun 	.read = ftdi_elan_read,
1137*4882a593Smuzhiyun 	.write = ftdi_elan_write,
1138*4882a593Smuzhiyun 	.open = ftdi_elan_open,
1139*4882a593Smuzhiyun 	.release = ftdi_elan_release,
1140*4882a593Smuzhiyun };
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun /*
1143*4882a593Smuzhiyun  * usb class driver info in order to get a minor number from the usb core,
1144*4882a593Smuzhiyun  * and to have the device registered with the driver core
1145*4882a593Smuzhiyun  */
1146*4882a593Smuzhiyun static struct usb_class_driver ftdi_elan_jtag_class = {
1147*4882a593Smuzhiyun 	.name = "ftdi-%d-jtag",
1148*4882a593Smuzhiyun 	.fops = &ftdi_elan_fops,
1149*4882a593Smuzhiyun 	.minor_base = USB_FTDI_ELAN_MINOR_BASE,
1150*4882a593Smuzhiyun };
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun /*
1153*4882a593Smuzhiyun  * the following definitions are for the
1154*4882a593Smuzhiyun  * ELAN FPGA state machgine processor that
1155*4882a593Smuzhiyun  * lies on the other side of the FTDI chip
1156*4882a593Smuzhiyun  */
1157*4882a593Smuzhiyun #define cPCIu132rd 0x0
1158*4882a593Smuzhiyun #define cPCIu132wr 0x1
1159*4882a593Smuzhiyun #define cPCIiord 0x2
1160*4882a593Smuzhiyun #define cPCIiowr 0x3
1161*4882a593Smuzhiyun #define cPCImemrd 0x6
1162*4882a593Smuzhiyun #define cPCImemwr 0x7
1163*4882a593Smuzhiyun #define cPCIcfgrd 0xA
1164*4882a593Smuzhiyun #define cPCIcfgwr 0xB
1165*4882a593Smuzhiyun #define cPCInull 0xF
1166*4882a593Smuzhiyun #define cU132cmd_status 0x0
1167*4882a593Smuzhiyun #define cU132flash 0x1
1168*4882a593Smuzhiyun #define cPIDsetup 0x0
1169*4882a593Smuzhiyun #define cPIDout 0x1
1170*4882a593Smuzhiyun #define cPIDin 0x2
1171*4882a593Smuzhiyun #define cPIDinonce 0x3
1172*4882a593Smuzhiyun #define cCCnoerror 0x0
1173*4882a593Smuzhiyun #define cCCcrc 0x1
1174*4882a593Smuzhiyun #define cCCbitstuff 0x2
1175*4882a593Smuzhiyun #define cCCtoggle 0x3
1176*4882a593Smuzhiyun #define cCCstall 0x4
1177*4882a593Smuzhiyun #define cCCnoresp 0x5
1178*4882a593Smuzhiyun #define cCCbadpid1 0x6
1179*4882a593Smuzhiyun #define cCCbadpid2 0x7
1180*4882a593Smuzhiyun #define cCCdataoverrun 0x8
1181*4882a593Smuzhiyun #define cCCdataunderrun 0x9
1182*4882a593Smuzhiyun #define cCCbuffoverrun 0xC
1183*4882a593Smuzhiyun #define cCCbuffunderrun 0xD
1184*4882a593Smuzhiyun #define cCCnotaccessed 0xF
ftdi_elan_write_reg(struct usb_ftdi * ftdi,u32 data)1185*4882a593Smuzhiyun static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
1186*4882a593Smuzhiyun {
1187*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1188*4882a593Smuzhiyun 		return -ENODEV;
1189*4882a593Smuzhiyun 	} else {
1190*4882a593Smuzhiyun 		int command_size;
1191*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1192*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1193*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1194*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1195*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1196*4882a593Smuzhiyun 			command->header = 0x00 | cPCIu132wr;
1197*4882a593Smuzhiyun 			command->length = 0x04;
1198*4882a593Smuzhiyun 			command->address = 0x00;
1199*4882a593Smuzhiyun 			command->width = 0x00;
1200*4882a593Smuzhiyun 			command->follows = 4;
1201*4882a593Smuzhiyun 			command->value = data;
1202*4882a593Smuzhiyun 			command->buffer = &command->value;
1203*4882a593Smuzhiyun 			ftdi->command_next += 1;
1204*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1205*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1206*4882a593Smuzhiyun 			return 0;
1207*4882a593Smuzhiyun 		} else {
1208*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1209*4882a593Smuzhiyun 			msleep(100);
1210*4882a593Smuzhiyun 			goto wait;
1211*4882a593Smuzhiyun 		}
1212*4882a593Smuzhiyun 	}
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun 
ftdi_elan_write_config(struct usb_ftdi * ftdi,int config_offset,u8 width,u32 data)1215*4882a593Smuzhiyun static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
1216*4882a593Smuzhiyun 				  u8 width, u32 data)
1217*4882a593Smuzhiyun {
1218*4882a593Smuzhiyun 	u8 addressofs = config_offset / 4;
1219*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1220*4882a593Smuzhiyun 		return -ENODEV;
1221*4882a593Smuzhiyun 	} else {
1222*4882a593Smuzhiyun 		int command_size;
1223*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1224*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1225*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1226*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1227*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1228*4882a593Smuzhiyun 			command->header = 0x00 | (cPCIcfgwr & 0x0F);
1229*4882a593Smuzhiyun 			command->length = 0x04;
1230*4882a593Smuzhiyun 			command->address = addressofs;
1231*4882a593Smuzhiyun 			command->width = 0x00 | (width & 0x0F);
1232*4882a593Smuzhiyun 			command->follows = 4;
1233*4882a593Smuzhiyun 			command->value = data;
1234*4882a593Smuzhiyun 			command->buffer = &command->value;
1235*4882a593Smuzhiyun 			ftdi->command_next += 1;
1236*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1237*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1238*4882a593Smuzhiyun 			return 0;
1239*4882a593Smuzhiyun 		} else {
1240*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1241*4882a593Smuzhiyun 			msleep(100);
1242*4882a593Smuzhiyun 			goto wait;
1243*4882a593Smuzhiyun 		}
1244*4882a593Smuzhiyun 	}
1245*4882a593Smuzhiyun }
1246*4882a593Smuzhiyun 
ftdi_elan_write_pcimem(struct usb_ftdi * ftdi,int mem_offset,u8 width,u32 data)1247*4882a593Smuzhiyun static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
1248*4882a593Smuzhiyun 				  u8 width, u32 data)
1249*4882a593Smuzhiyun {
1250*4882a593Smuzhiyun 	u8 addressofs = mem_offset / 4;
1251*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1252*4882a593Smuzhiyun 		return -ENODEV;
1253*4882a593Smuzhiyun 	} else {
1254*4882a593Smuzhiyun 		int command_size;
1255*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1256*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1257*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1258*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1259*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1260*4882a593Smuzhiyun 			command->header = 0x00 | (cPCImemwr & 0x0F);
1261*4882a593Smuzhiyun 			command->length = 0x04;
1262*4882a593Smuzhiyun 			command->address = addressofs;
1263*4882a593Smuzhiyun 			command->width = 0x00 | (width & 0x0F);
1264*4882a593Smuzhiyun 			command->follows = 4;
1265*4882a593Smuzhiyun 			command->value = data;
1266*4882a593Smuzhiyun 			command->buffer = &command->value;
1267*4882a593Smuzhiyun 			ftdi->command_next += 1;
1268*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1269*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1270*4882a593Smuzhiyun 			return 0;
1271*4882a593Smuzhiyun 		} else {
1272*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1273*4882a593Smuzhiyun 			msleep(100);
1274*4882a593Smuzhiyun 			goto wait;
1275*4882a593Smuzhiyun 		}
1276*4882a593Smuzhiyun 	}
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun 
usb_ftdi_elan_write_pcimem(struct platform_device * pdev,int mem_offset,u8 width,u32 data)1279*4882a593Smuzhiyun int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
1280*4882a593Smuzhiyun 			       u8 width, u32 data)
1281*4882a593Smuzhiyun {
1282*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1283*4882a593Smuzhiyun 	return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data);
1284*4882a593Smuzhiyun }
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 
1287*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem);
ftdi_elan_read_reg(struct usb_ftdi * ftdi,u32 * data)1288*4882a593Smuzhiyun static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
1289*4882a593Smuzhiyun {
1290*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1291*4882a593Smuzhiyun 		return -ENODEV;
1292*4882a593Smuzhiyun 	} else {
1293*4882a593Smuzhiyun 		int command_size;
1294*4882a593Smuzhiyun 		int respond_size;
1295*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1296*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1297*4882a593Smuzhiyun 		respond_size = ftdi->respond_next - ftdi->respond_head;
1298*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
1299*4882a593Smuzhiyun 		{
1300*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1301*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1302*4882a593Smuzhiyun 			struct u132_respond *respond = &ftdi->respond[
1303*4882a593Smuzhiyun 				RESPOND_MASK & ftdi->respond_next];
1304*4882a593Smuzhiyun 			int result = -ENODEV;
1305*4882a593Smuzhiyun 			respond->result = &result;
1306*4882a593Smuzhiyun 			respond->header = command->header = 0x00 | cPCIu132rd;
1307*4882a593Smuzhiyun 			command->length = 0x04;
1308*4882a593Smuzhiyun 			respond->address = command->address = cU132cmd_status;
1309*4882a593Smuzhiyun 			command->width = 0x00;
1310*4882a593Smuzhiyun 			command->follows = 0;
1311*4882a593Smuzhiyun 			command->value = 0;
1312*4882a593Smuzhiyun 			command->buffer = NULL;
1313*4882a593Smuzhiyun 			respond->value = data;
1314*4882a593Smuzhiyun 			init_completion(&respond->wait_completion);
1315*4882a593Smuzhiyun 			ftdi->command_next += 1;
1316*4882a593Smuzhiyun 			ftdi->respond_next += 1;
1317*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1318*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1319*4882a593Smuzhiyun 			wait_for_completion(&respond->wait_completion);
1320*4882a593Smuzhiyun 			return result;
1321*4882a593Smuzhiyun 		} else {
1322*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1323*4882a593Smuzhiyun 			msleep(100);
1324*4882a593Smuzhiyun 			goto wait;
1325*4882a593Smuzhiyun 		}
1326*4882a593Smuzhiyun 	}
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun 
ftdi_elan_read_config(struct usb_ftdi * ftdi,int config_offset,u8 width,u32 * data)1329*4882a593Smuzhiyun static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
1330*4882a593Smuzhiyun 				 u8 width, u32 *data)
1331*4882a593Smuzhiyun {
1332*4882a593Smuzhiyun 	u8 addressofs = config_offset / 4;
1333*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1334*4882a593Smuzhiyun 		return -ENODEV;
1335*4882a593Smuzhiyun 	} else {
1336*4882a593Smuzhiyun 		int command_size;
1337*4882a593Smuzhiyun 		int respond_size;
1338*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1339*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1340*4882a593Smuzhiyun 		respond_size = ftdi->respond_next - ftdi->respond_head;
1341*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
1342*4882a593Smuzhiyun 		{
1343*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1344*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1345*4882a593Smuzhiyun 			struct u132_respond *respond = &ftdi->respond[
1346*4882a593Smuzhiyun 				RESPOND_MASK & ftdi->respond_next];
1347*4882a593Smuzhiyun 			int result = -ENODEV;
1348*4882a593Smuzhiyun 			respond->result = &result;
1349*4882a593Smuzhiyun 			respond->header = command->header = 0x00 | (cPCIcfgrd &
1350*4882a593Smuzhiyun 								    0x0F);
1351*4882a593Smuzhiyun 			command->length = 0x04;
1352*4882a593Smuzhiyun 			respond->address = command->address = addressofs;
1353*4882a593Smuzhiyun 			command->width = 0x00 | (width & 0x0F);
1354*4882a593Smuzhiyun 			command->follows = 0;
1355*4882a593Smuzhiyun 			command->value = 0;
1356*4882a593Smuzhiyun 			command->buffer = NULL;
1357*4882a593Smuzhiyun 			respond->value = data;
1358*4882a593Smuzhiyun 			init_completion(&respond->wait_completion);
1359*4882a593Smuzhiyun 			ftdi->command_next += 1;
1360*4882a593Smuzhiyun 			ftdi->respond_next += 1;
1361*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1362*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1363*4882a593Smuzhiyun 			wait_for_completion(&respond->wait_completion);
1364*4882a593Smuzhiyun 			return result;
1365*4882a593Smuzhiyun 		} else {
1366*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1367*4882a593Smuzhiyun 			msleep(100);
1368*4882a593Smuzhiyun 			goto wait;
1369*4882a593Smuzhiyun 		}
1370*4882a593Smuzhiyun 	}
1371*4882a593Smuzhiyun }
1372*4882a593Smuzhiyun 
ftdi_elan_read_pcimem(struct usb_ftdi * ftdi,int mem_offset,u8 width,u32 * data)1373*4882a593Smuzhiyun static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
1374*4882a593Smuzhiyun 				 u8 width, u32 *data)
1375*4882a593Smuzhiyun {
1376*4882a593Smuzhiyun 	u8 addressofs = mem_offset / 4;
1377*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1378*4882a593Smuzhiyun 		return -ENODEV;
1379*4882a593Smuzhiyun 	} else {
1380*4882a593Smuzhiyun 		int command_size;
1381*4882a593Smuzhiyun 		int respond_size;
1382*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1383*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1384*4882a593Smuzhiyun 		respond_size = ftdi->respond_next - ftdi->respond_head;
1385*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
1386*4882a593Smuzhiyun 		{
1387*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1388*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1389*4882a593Smuzhiyun 			struct u132_respond *respond = &ftdi->respond[
1390*4882a593Smuzhiyun 				RESPOND_MASK & ftdi->respond_next];
1391*4882a593Smuzhiyun 			int result = -ENODEV;
1392*4882a593Smuzhiyun 			respond->result = &result;
1393*4882a593Smuzhiyun 			respond->header = command->header = 0x00 | (cPCImemrd &
1394*4882a593Smuzhiyun 								    0x0F);
1395*4882a593Smuzhiyun 			command->length = 0x04;
1396*4882a593Smuzhiyun 			respond->address = command->address = addressofs;
1397*4882a593Smuzhiyun 			command->width = 0x00 | (width & 0x0F);
1398*4882a593Smuzhiyun 			command->follows = 0;
1399*4882a593Smuzhiyun 			command->value = 0;
1400*4882a593Smuzhiyun 			command->buffer = NULL;
1401*4882a593Smuzhiyun 			respond->value = data;
1402*4882a593Smuzhiyun 			init_completion(&respond->wait_completion);
1403*4882a593Smuzhiyun 			ftdi->command_next += 1;
1404*4882a593Smuzhiyun 			ftdi->respond_next += 1;
1405*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1406*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1407*4882a593Smuzhiyun 			wait_for_completion(&respond->wait_completion);
1408*4882a593Smuzhiyun 			return result;
1409*4882a593Smuzhiyun 		} else {
1410*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1411*4882a593Smuzhiyun 			msleep(100);
1412*4882a593Smuzhiyun 			goto wait;
1413*4882a593Smuzhiyun 		}
1414*4882a593Smuzhiyun 	}
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun 
usb_ftdi_elan_read_pcimem(struct platform_device * pdev,int mem_offset,u8 width,u32 * data)1417*4882a593Smuzhiyun int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
1418*4882a593Smuzhiyun 			      u8 width, u32 *data)
1419*4882a593Smuzhiyun {
1420*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1421*4882a593Smuzhiyun 	if (ftdi->initialized == 0) {
1422*4882a593Smuzhiyun 		return -ENODEV;
1423*4882a593Smuzhiyun 	} else
1424*4882a593Smuzhiyun 		return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data);
1425*4882a593Smuzhiyun }
1426*4882a593Smuzhiyun 
1427*4882a593Smuzhiyun 
1428*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem);
ftdi_elan_edset_setup(struct usb_ftdi * ftdi,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1429*4882a593Smuzhiyun static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
1430*4882a593Smuzhiyun 				 void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1431*4882a593Smuzhiyun 				 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1432*4882a593Smuzhiyun 						   int toggle_bits, int error_count, int condition_code, int repeat_number,
1433*4882a593Smuzhiyun 						   int halted, int skipped, int actual, int non_null))
1434*4882a593Smuzhiyun {
1435*4882a593Smuzhiyun 	u8 ed = ed_number - 1;
1436*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1437*4882a593Smuzhiyun 		return -ENODEV;
1438*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
1439*4882a593Smuzhiyun 		return -ENODEV;
1440*4882a593Smuzhiyun 	} else {
1441*4882a593Smuzhiyun 		int command_size;
1442*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1443*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1444*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1445*4882a593Smuzhiyun 			struct u132_target *target = &ftdi->target[ed];
1446*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1447*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1448*4882a593Smuzhiyun 			command->header = 0x80 | (ed << 5);
1449*4882a593Smuzhiyun 			command->length = 0x8007;
1450*4882a593Smuzhiyun 			command->address = (toggle_bits << 6) | (ep_number << 2)
1451*4882a593Smuzhiyun 				| (address << 0);
1452*4882a593Smuzhiyun 			command->width = usb_maxpacket(urb->dev, urb->pipe,
1453*4882a593Smuzhiyun 						       usb_pipeout(urb->pipe));
1454*4882a593Smuzhiyun 			command->follows = 8;
1455*4882a593Smuzhiyun 			command->value = 0;
1456*4882a593Smuzhiyun 			command->buffer = urb->setup_packet;
1457*4882a593Smuzhiyun 			target->callback = callback;
1458*4882a593Smuzhiyun 			target->endp = endp;
1459*4882a593Smuzhiyun 			target->urb = urb;
1460*4882a593Smuzhiyun 			target->active = 1;
1461*4882a593Smuzhiyun 			ftdi->command_next += 1;
1462*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1463*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1464*4882a593Smuzhiyun 			return 0;
1465*4882a593Smuzhiyun 		} else {
1466*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1467*4882a593Smuzhiyun 			msleep(100);
1468*4882a593Smuzhiyun 			goto wait;
1469*4882a593Smuzhiyun 		}
1470*4882a593Smuzhiyun 	}
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun 
usb_ftdi_elan_edset_setup(struct platform_device * pdev,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1473*4882a593Smuzhiyun int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
1474*4882a593Smuzhiyun 			      void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1475*4882a593Smuzhiyun 			      void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1476*4882a593Smuzhiyun 						int toggle_bits, int error_count, int condition_code, int repeat_number,
1477*4882a593Smuzhiyun 						int halted, int skipped, int actual, int non_null))
1478*4882a593Smuzhiyun {
1479*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1480*4882a593Smuzhiyun 	return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address,
1481*4882a593Smuzhiyun 				     ep_number, toggle_bits, callback);
1482*4882a593Smuzhiyun }
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun 
1485*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup);
ftdi_elan_edset_input(struct usb_ftdi * ftdi,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1486*4882a593Smuzhiyun static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
1487*4882a593Smuzhiyun 				 void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1488*4882a593Smuzhiyun 				 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1489*4882a593Smuzhiyun 						   int toggle_bits, int error_count, int condition_code, int repeat_number,
1490*4882a593Smuzhiyun 						   int halted, int skipped, int actual, int non_null))
1491*4882a593Smuzhiyun {
1492*4882a593Smuzhiyun 	u8 ed = ed_number - 1;
1493*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1494*4882a593Smuzhiyun 		return -ENODEV;
1495*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
1496*4882a593Smuzhiyun 		return -ENODEV;
1497*4882a593Smuzhiyun 	} else {
1498*4882a593Smuzhiyun 		int command_size;
1499*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1500*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1501*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1502*4882a593Smuzhiyun 			struct u132_target *target = &ftdi->target[ed];
1503*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1504*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1505*4882a593Smuzhiyun 			u32 remaining_length = urb->transfer_buffer_length -
1506*4882a593Smuzhiyun 				urb->actual_length;
1507*4882a593Smuzhiyun 			command->header = 0x82 | (ed << 5);
1508*4882a593Smuzhiyun 			if (remaining_length == 0) {
1509*4882a593Smuzhiyun 				command->length = 0x0000;
1510*4882a593Smuzhiyun 			} else if (remaining_length > 1024) {
1511*4882a593Smuzhiyun 				command->length = 0x8000 | 1023;
1512*4882a593Smuzhiyun 			} else
1513*4882a593Smuzhiyun 				command->length = 0x8000 | (remaining_length -
1514*4882a593Smuzhiyun 							    1);
1515*4882a593Smuzhiyun 			command->address = (toggle_bits << 6) | (ep_number << 2)
1516*4882a593Smuzhiyun 				| (address << 0);
1517*4882a593Smuzhiyun 			command->width = usb_maxpacket(urb->dev, urb->pipe,
1518*4882a593Smuzhiyun 						       usb_pipeout(urb->pipe));
1519*4882a593Smuzhiyun 			command->follows = 0;
1520*4882a593Smuzhiyun 			command->value = 0;
1521*4882a593Smuzhiyun 			command->buffer = NULL;
1522*4882a593Smuzhiyun 			target->callback = callback;
1523*4882a593Smuzhiyun 			target->endp = endp;
1524*4882a593Smuzhiyun 			target->urb = urb;
1525*4882a593Smuzhiyun 			target->active = 1;
1526*4882a593Smuzhiyun 			ftdi->command_next += 1;
1527*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1528*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1529*4882a593Smuzhiyun 			return 0;
1530*4882a593Smuzhiyun 		} else {
1531*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1532*4882a593Smuzhiyun 			msleep(100);
1533*4882a593Smuzhiyun 			goto wait;
1534*4882a593Smuzhiyun 		}
1535*4882a593Smuzhiyun 	}
1536*4882a593Smuzhiyun }
1537*4882a593Smuzhiyun 
usb_ftdi_elan_edset_input(struct platform_device * pdev,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1538*4882a593Smuzhiyun int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
1539*4882a593Smuzhiyun 			      void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1540*4882a593Smuzhiyun 			      void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1541*4882a593Smuzhiyun 						int toggle_bits, int error_count, int condition_code, int repeat_number,
1542*4882a593Smuzhiyun 						int halted, int skipped, int actual, int non_null))
1543*4882a593Smuzhiyun {
1544*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1545*4882a593Smuzhiyun 	return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address,
1546*4882a593Smuzhiyun 				     ep_number, toggle_bits, callback);
1547*4882a593Smuzhiyun }
1548*4882a593Smuzhiyun 
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input);
ftdi_elan_edset_empty(struct usb_ftdi * ftdi,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1551*4882a593Smuzhiyun static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
1552*4882a593Smuzhiyun 				 void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1553*4882a593Smuzhiyun 				 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1554*4882a593Smuzhiyun 						   int toggle_bits, int error_count, int condition_code, int repeat_number,
1555*4882a593Smuzhiyun 						   int halted, int skipped, int actual, int non_null))
1556*4882a593Smuzhiyun {
1557*4882a593Smuzhiyun 	u8 ed = ed_number - 1;
1558*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1559*4882a593Smuzhiyun 		return -ENODEV;
1560*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
1561*4882a593Smuzhiyun 		return -ENODEV;
1562*4882a593Smuzhiyun 	} else {
1563*4882a593Smuzhiyun 		int command_size;
1564*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1565*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1566*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1567*4882a593Smuzhiyun 			struct u132_target *target = &ftdi->target[ed];
1568*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1569*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1570*4882a593Smuzhiyun 			command->header = 0x81 | (ed << 5);
1571*4882a593Smuzhiyun 			command->length = 0x0000;
1572*4882a593Smuzhiyun 			command->address = (toggle_bits << 6) | (ep_number << 2)
1573*4882a593Smuzhiyun 				| (address << 0);
1574*4882a593Smuzhiyun 			command->width = usb_maxpacket(urb->dev, urb->pipe,
1575*4882a593Smuzhiyun 						       usb_pipeout(urb->pipe));
1576*4882a593Smuzhiyun 			command->follows = 0;
1577*4882a593Smuzhiyun 			command->value = 0;
1578*4882a593Smuzhiyun 			command->buffer = NULL;
1579*4882a593Smuzhiyun 			target->callback = callback;
1580*4882a593Smuzhiyun 			target->endp = endp;
1581*4882a593Smuzhiyun 			target->urb = urb;
1582*4882a593Smuzhiyun 			target->active = 1;
1583*4882a593Smuzhiyun 			ftdi->command_next += 1;
1584*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1585*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1586*4882a593Smuzhiyun 			return 0;
1587*4882a593Smuzhiyun 		} else {
1588*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1589*4882a593Smuzhiyun 			msleep(100);
1590*4882a593Smuzhiyun 			goto wait;
1591*4882a593Smuzhiyun 		}
1592*4882a593Smuzhiyun 	}
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun 
usb_ftdi_elan_edset_empty(struct platform_device * pdev,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1595*4882a593Smuzhiyun int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
1596*4882a593Smuzhiyun 			      void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1597*4882a593Smuzhiyun 			      void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1598*4882a593Smuzhiyun 						int toggle_bits, int error_count, int condition_code, int repeat_number,
1599*4882a593Smuzhiyun 						int halted, int skipped, int actual, int non_null))
1600*4882a593Smuzhiyun {
1601*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1602*4882a593Smuzhiyun 	return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address,
1603*4882a593Smuzhiyun 				     ep_number, toggle_bits, callback);
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun 
1607*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty);
ftdi_elan_edset_output(struct usb_ftdi * ftdi,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1608*4882a593Smuzhiyun static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
1609*4882a593Smuzhiyun 				  void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1610*4882a593Smuzhiyun 				  void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1611*4882a593Smuzhiyun 						    int toggle_bits, int error_count, int condition_code, int repeat_number,
1612*4882a593Smuzhiyun 						    int halted, int skipped, int actual, int non_null))
1613*4882a593Smuzhiyun {
1614*4882a593Smuzhiyun 	u8 ed = ed_number - 1;
1615*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1616*4882a593Smuzhiyun 		return -ENODEV;
1617*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
1618*4882a593Smuzhiyun 		return -ENODEV;
1619*4882a593Smuzhiyun 	} else {
1620*4882a593Smuzhiyun 		int command_size;
1621*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1622*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1623*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1624*4882a593Smuzhiyun 			u8 *b;
1625*4882a593Smuzhiyun 			u16 urb_size;
1626*4882a593Smuzhiyun 			int i = 0;
1627*4882a593Smuzhiyun 			char data[30 *3 + 4];
1628*4882a593Smuzhiyun 			char *d = data;
1629*4882a593Smuzhiyun 			int m = (sizeof(data) - 1) / 3 - 1;
1630*4882a593Smuzhiyun 			int l = 0;
1631*4882a593Smuzhiyun 			struct u132_target *target = &ftdi->target[ed];
1632*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1633*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1634*4882a593Smuzhiyun 			command->header = 0x81 | (ed << 5);
1635*4882a593Smuzhiyun 			command->address = (toggle_bits << 6) | (ep_number << 2)
1636*4882a593Smuzhiyun 				| (address << 0);
1637*4882a593Smuzhiyun 			command->width = usb_maxpacket(urb->dev, urb->pipe,
1638*4882a593Smuzhiyun 						       usb_pipeout(urb->pipe));
1639*4882a593Smuzhiyun 			command->follows = min_t(u32, 1024,
1640*4882a593Smuzhiyun 						 urb->transfer_buffer_length -
1641*4882a593Smuzhiyun 						 urb->actual_length);
1642*4882a593Smuzhiyun 			command->value = 0;
1643*4882a593Smuzhiyun 			command->buffer = urb->transfer_buffer +
1644*4882a593Smuzhiyun 				urb->actual_length;
1645*4882a593Smuzhiyun 			command->length = 0x8000 | (command->follows - 1);
1646*4882a593Smuzhiyun 			b = command->buffer;
1647*4882a593Smuzhiyun 			urb_size = command->follows;
1648*4882a593Smuzhiyun 			data[0] = 0;
1649*4882a593Smuzhiyun 			while (urb_size-- > 0) {
1650*4882a593Smuzhiyun 				if (i > m) {
1651*4882a593Smuzhiyun 				} else if (i++ < m) {
1652*4882a593Smuzhiyun 					int w = sprintf(d, " %02X", *b++);
1653*4882a593Smuzhiyun 					d += w;
1654*4882a593Smuzhiyun 					l += w;
1655*4882a593Smuzhiyun 				} else
1656*4882a593Smuzhiyun 					d += sprintf(d, " ..");
1657*4882a593Smuzhiyun 			}
1658*4882a593Smuzhiyun 			target->callback = callback;
1659*4882a593Smuzhiyun 			target->endp = endp;
1660*4882a593Smuzhiyun 			target->urb = urb;
1661*4882a593Smuzhiyun 			target->active = 1;
1662*4882a593Smuzhiyun 			ftdi->command_next += 1;
1663*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1664*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1665*4882a593Smuzhiyun 			return 0;
1666*4882a593Smuzhiyun 		} else {
1667*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1668*4882a593Smuzhiyun 			msleep(100);
1669*4882a593Smuzhiyun 			goto wait;
1670*4882a593Smuzhiyun 		}
1671*4882a593Smuzhiyun 	}
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun 
usb_ftdi_elan_edset_output(struct platform_device * pdev,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1674*4882a593Smuzhiyun int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
1675*4882a593Smuzhiyun 			       void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1676*4882a593Smuzhiyun 			       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1677*4882a593Smuzhiyun 						 int toggle_bits, int error_count, int condition_code, int repeat_number,
1678*4882a593Smuzhiyun 						 int halted, int skipped, int actual, int non_null))
1679*4882a593Smuzhiyun {
1680*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1681*4882a593Smuzhiyun 	return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address,
1682*4882a593Smuzhiyun 				      ep_number, toggle_bits, callback);
1683*4882a593Smuzhiyun }
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output);
ftdi_elan_edset_single(struct usb_ftdi * ftdi,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1687*4882a593Smuzhiyun static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
1688*4882a593Smuzhiyun 				  void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1689*4882a593Smuzhiyun 				  void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1690*4882a593Smuzhiyun 						    int toggle_bits, int error_count, int condition_code, int repeat_number,
1691*4882a593Smuzhiyun 						    int halted, int skipped, int actual, int non_null))
1692*4882a593Smuzhiyun {
1693*4882a593Smuzhiyun 	u8 ed = ed_number - 1;
1694*4882a593Smuzhiyun wait:if (ftdi->disconnected > 0) {
1695*4882a593Smuzhiyun 		return -ENODEV;
1696*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
1697*4882a593Smuzhiyun 		return -ENODEV;
1698*4882a593Smuzhiyun 	} else {
1699*4882a593Smuzhiyun 		int command_size;
1700*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1701*4882a593Smuzhiyun 		command_size = ftdi->command_next - ftdi->command_head;
1702*4882a593Smuzhiyun 		if (command_size < COMMAND_SIZE) {
1703*4882a593Smuzhiyun 			u32 remaining_length = urb->transfer_buffer_length -
1704*4882a593Smuzhiyun 				urb->actual_length;
1705*4882a593Smuzhiyun 			struct u132_target *target = &ftdi->target[ed];
1706*4882a593Smuzhiyun 			struct u132_command *command = &ftdi->command[
1707*4882a593Smuzhiyun 				COMMAND_MASK & ftdi->command_next];
1708*4882a593Smuzhiyun 			command->header = 0x83 | (ed << 5);
1709*4882a593Smuzhiyun 			if (remaining_length == 0) {
1710*4882a593Smuzhiyun 				command->length = 0x0000;
1711*4882a593Smuzhiyun 			} else if (remaining_length > 1024) {
1712*4882a593Smuzhiyun 				command->length = 0x8000 | 1023;
1713*4882a593Smuzhiyun 			} else
1714*4882a593Smuzhiyun 				command->length = 0x8000 | (remaining_length -
1715*4882a593Smuzhiyun 							    1);
1716*4882a593Smuzhiyun 			command->address = (toggle_bits << 6) | (ep_number << 2)
1717*4882a593Smuzhiyun 				| (address << 0);
1718*4882a593Smuzhiyun 			command->width = usb_maxpacket(urb->dev, urb->pipe,
1719*4882a593Smuzhiyun 						       usb_pipeout(urb->pipe));
1720*4882a593Smuzhiyun 			command->follows = 0;
1721*4882a593Smuzhiyun 			command->value = 0;
1722*4882a593Smuzhiyun 			command->buffer = NULL;
1723*4882a593Smuzhiyun 			target->callback = callback;
1724*4882a593Smuzhiyun 			target->endp = endp;
1725*4882a593Smuzhiyun 			target->urb = urb;
1726*4882a593Smuzhiyun 			target->active = 1;
1727*4882a593Smuzhiyun 			ftdi->command_next += 1;
1728*4882a593Smuzhiyun 			ftdi_elan_kick_command_queue(ftdi);
1729*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1730*4882a593Smuzhiyun 			return 0;
1731*4882a593Smuzhiyun 		} else {
1732*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1733*4882a593Smuzhiyun 			msleep(100);
1734*4882a593Smuzhiyun 			goto wait;
1735*4882a593Smuzhiyun 		}
1736*4882a593Smuzhiyun 	}
1737*4882a593Smuzhiyun }
1738*4882a593Smuzhiyun 
usb_ftdi_elan_edset_single(struct platform_device * pdev,u8 ed_number,void * endp,struct urb * urb,u8 address,u8 ep_number,u8 toggle_bits,void (* callback)(void * endp,struct urb * urb,u8 * buf,int len,int toggle_bits,int error_count,int condition_code,int repeat_number,int halted,int skipped,int actual,int non_null))1739*4882a593Smuzhiyun int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
1740*4882a593Smuzhiyun 			       void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
1741*4882a593Smuzhiyun 			       void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
1742*4882a593Smuzhiyun 						 int toggle_bits, int error_count, int condition_code, int repeat_number,
1743*4882a593Smuzhiyun 						 int halted, int skipped, int actual, int non_null))
1744*4882a593Smuzhiyun {
1745*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1746*4882a593Smuzhiyun 	return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address,
1747*4882a593Smuzhiyun 				      ep_number, toggle_bits, callback);
1748*4882a593Smuzhiyun }
1749*4882a593Smuzhiyun 
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single);
ftdi_elan_edset_flush(struct usb_ftdi * ftdi,u8 ed_number,void * endp)1752*4882a593Smuzhiyun static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
1753*4882a593Smuzhiyun 				 void *endp)
1754*4882a593Smuzhiyun {
1755*4882a593Smuzhiyun 	u8 ed = ed_number - 1;
1756*4882a593Smuzhiyun 	if (ftdi->disconnected > 0) {
1757*4882a593Smuzhiyun 		return -ENODEV;
1758*4882a593Smuzhiyun 	} else if (ftdi->initialized == 0) {
1759*4882a593Smuzhiyun 		return -ENODEV;
1760*4882a593Smuzhiyun 	} else {
1761*4882a593Smuzhiyun 		struct u132_target *target = &ftdi->target[ed];
1762*4882a593Smuzhiyun 		mutex_lock(&ftdi->u132_lock);
1763*4882a593Smuzhiyun 		if (target->abandoning > 0) {
1764*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1765*4882a593Smuzhiyun 			return 0;
1766*4882a593Smuzhiyun 		} else {
1767*4882a593Smuzhiyun 			target->abandoning = 1;
1768*4882a593Smuzhiyun 		wait_1:if (target->active == 1) {
1769*4882a593Smuzhiyun 				int command_size = ftdi->command_next -
1770*4882a593Smuzhiyun 					ftdi->command_head;
1771*4882a593Smuzhiyun 				if (command_size < COMMAND_SIZE) {
1772*4882a593Smuzhiyun 					struct u132_command *command =
1773*4882a593Smuzhiyun 						&ftdi->command[COMMAND_MASK &
1774*4882a593Smuzhiyun 							       ftdi->command_next];
1775*4882a593Smuzhiyun 					command->header = 0x80 | (ed << 5) |
1776*4882a593Smuzhiyun 						0x4;
1777*4882a593Smuzhiyun 					command->length = 0x00;
1778*4882a593Smuzhiyun 					command->address = 0x00;
1779*4882a593Smuzhiyun 					command->width = 0x00;
1780*4882a593Smuzhiyun 					command->follows = 0;
1781*4882a593Smuzhiyun 					command->value = 0;
1782*4882a593Smuzhiyun 					command->buffer = &command->value;
1783*4882a593Smuzhiyun 					ftdi->command_next += 1;
1784*4882a593Smuzhiyun 					ftdi_elan_kick_command_queue(ftdi);
1785*4882a593Smuzhiyun 				} else {
1786*4882a593Smuzhiyun 					mutex_unlock(&ftdi->u132_lock);
1787*4882a593Smuzhiyun 					msleep(100);
1788*4882a593Smuzhiyun 					mutex_lock(&ftdi->u132_lock);
1789*4882a593Smuzhiyun 					goto wait_1;
1790*4882a593Smuzhiyun 				}
1791*4882a593Smuzhiyun 			}
1792*4882a593Smuzhiyun 			mutex_unlock(&ftdi->u132_lock);
1793*4882a593Smuzhiyun 			return 0;
1794*4882a593Smuzhiyun 		}
1795*4882a593Smuzhiyun 	}
1796*4882a593Smuzhiyun }
1797*4882a593Smuzhiyun 
usb_ftdi_elan_edset_flush(struct platform_device * pdev,u8 ed_number,void * endp)1798*4882a593Smuzhiyun int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
1799*4882a593Smuzhiyun 			      void *endp)
1800*4882a593Smuzhiyun {
1801*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
1802*4882a593Smuzhiyun 	return ftdi_elan_edset_flush(ftdi, ed_number, endp);
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun 
1805*4882a593Smuzhiyun 
1806*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush);
ftdi_elan_flush_input_fifo(struct usb_ftdi * ftdi)1807*4882a593Smuzhiyun static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi)
1808*4882a593Smuzhiyun {
1809*4882a593Smuzhiyun 	int retry_on_empty = 10;
1810*4882a593Smuzhiyun 	int retry_on_timeout = 5;
1811*4882a593Smuzhiyun 	int retry_on_status = 20;
1812*4882a593Smuzhiyun more:{
1813*4882a593Smuzhiyun 		int packet_bytes = 0;
1814*4882a593Smuzhiyun 		int retval = usb_bulk_msg(ftdi->udev,
1815*4882a593Smuzhiyun 					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
1816*4882a593Smuzhiyun 					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
1817*4882a593Smuzhiyun 					  &packet_bytes, 100);
1818*4882a593Smuzhiyun 		if (packet_bytes > 2) {
1819*4882a593Smuzhiyun 			char diag[30 *3 + 4];
1820*4882a593Smuzhiyun 			char *d = diag;
1821*4882a593Smuzhiyun 			int m = (sizeof(diag) - 1) / 3 - 1;
1822*4882a593Smuzhiyun 			char *b = ftdi->bulk_in_buffer;
1823*4882a593Smuzhiyun 			int bytes_read = 0;
1824*4882a593Smuzhiyun 			diag[0] = 0;
1825*4882a593Smuzhiyun 			while (packet_bytes-- > 0) {
1826*4882a593Smuzhiyun 				char c = *b++;
1827*4882a593Smuzhiyun 				if (bytes_read < m) {
1828*4882a593Smuzhiyun 					d += sprintf(d, " %02X",
1829*4882a593Smuzhiyun 						     0x000000FF & c);
1830*4882a593Smuzhiyun 				} else if (bytes_read > m) {
1831*4882a593Smuzhiyun 				} else
1832*4882a593Smuzhiyun 					d += sprintf(d, " ..");
1833*4882a593Smuzhiyun 				bytes_read += 1;
1834*4882a593Smuzhiyun 				continue;
1835*4882a593Smuzhiyun 			}
1836*4882a593Smuzhiyun 			goto more;
1837*4882a593Smuzhiyun 		} else if (packet_bytes > 1) {
1838*4882a593Smuzhiyun 			char s1 = ftdi->bulk_in_buffer[0];
1839*4882a593Smuzhiyun 			char s2 = ftdi->bulk_in_buffer[1];
1840*4882a593Smuzhiyun 			if (s1 == 0x31 && s2 == 0x60) {
1841*4882a593Smuzhiyun 				return 0;
1842*4882a593Smuzhiyun 			} else if (retry_on_status-- > 0) {
1843*4882a593Smuzhiyun 				goto more;
1844*4882a593Smuzhiyun 			} else {
1845*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n");
1846*4882a593Smuzhiyun 				return -EFAULT;
1847*4882a593Smuzhiyun 			}
1848*4882a593Smuzhiyun 		} else if (packet_bytes > 0) {
1849*4882a593Smuzhiyun 			char b1 = ftdi->bulk_in_buffer[0];
1850*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "only one byte flushed from FTDI = %02X\n",
1851*4882a593Smuzhiyun 				b1);
1852*4882a593Smuzhiyun 			if (retry_on_status-- > 0) {
1853*4882a593Smuzhiyun 				goto more;
1854*4882a593Smuzhiyun 			} else {
1855*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n");
1856*4882a593Smuzhiyun 				return -EFAULT;
1857*4882a593Smuzhiyun 			}
1858*4882a593Smuzhiyun 		} else if (retval == -ETIMEDOUT) {
1859*4882a593Smuzhiyun 			if (retry_on_timeout-- > 0) {
1860*4882a593Smuzhiyun 				goto more;
1861*4882a593Smuzhiyun 			} else {
1862*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n");
1863*4882a593Smuzhiyun 				return -ENOMEM;
1864*4882a593Smuzhiyun 			}
1865*4882a593Smuzhiyun 		} else if (retval == 0) {
1866*4882a593Smuzhiyun 			if (retry_on_empty-- > 0) {
1867*4882a593Smuzhiyun 				goto more;
1868*4882a593Smuzhiyun 			} else {
1869*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n");
1870*4882a593Smuzhiyun 				return -ENOMEM;
1871*4882a593Smuzhiyun 			}
1872*4882a593Smuzhiyun 		} else {
1873*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "error = %d\n", retval);
1874*4882a593Smuzhiyun 			return retval;
1875*4882a593Smuzhiyun 		}
1876*4882a593Smuzhiyun 	}
1877*4882a593Smuzhiyun 	return -1;
1878*4882a593Smuzhiyun }
1879*4882a593Smuzhiyun 
1880*4882a593Smuzhiyun 
1881*4882a593Smuzhiyun /*
1882*4882a593Smuzhiyun  * send the long flush sequence
1883*4882a593Smuzhiyun  *
1884*4882a593Smuzhiyun  */
ftdi_elan_synchronize_flush(struct usb_ftdi * ftdi)1885*4882a593Smuzhiyun static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi)
1886*4882a593Smuzhiyun {
1887*4882a593Smuzhiyun 	int retval;
1888*4882a593Smuzhiyun 	struct urb *urb;
1889*4882a593Smuzhiyun 	char *buf;
1890*4882a593Smuzhiyun 	int I = 257;
1891*4882a593Smuzhiyun 	int i = 0;
1892*4882a593Smuzhiyun 	urb = usb_alloc_urb(0, GFP_KERNEL);
1893*4882a593Smuzhiyun 	if (!urb)
1894*4882a593Smuzhiyun 		return -ENOMEM;
1895*4882a593Smuzhiyun 	buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
1896*4882a593Smuzhiyun 	if (!buf) {
1897*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "could not get a buffer for flush sequence\n");
1898*4882a593Smuzhiyun 		usb_free_urb(urb);
1899*4882a593Smuzhiyun 		return -ENOMEM;
1900*4882a593Smuzhiyun 	}
1901*4882a593Smuzhiyun 	while (I-- > 0)
1902*4882a593Smuzhiyun 		buf[i++] = 0x55;
1903*4882a593Smuzhiyun 	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
1904*4882a593Smuzhiyun 							   ftdi->bulk_out_endpointAddr), buf, i,
1905*4882a593Smuzhiyun 			  ftdi_elan_write_bulk_callback, ftdi);
1906*4882a593Smuzhiyun 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1907*4882a593Smuzhiyun 	retval = usb_submit_urb(urb, GFP_KERNEL);
1908*4882a593Smuzhiyun 	if (retval) {
1909*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "failed to submit urb containing the flush sequence\n");
1910*4882a593Smuzhiyun 		usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma);
1911*4882a593Smuzhiyun 		usb_free_urb(urb);
1912*4882a593Smuzhiyun 		return -ENOMEM;
1913*4882a593Smuzhiyun 	}
1914*4882a593Smuzhiyun 	usb_free_urb(urb);
1915*4882a593Smuzhiyun 	return 0;
1916*4882a593Smuzhiyun }
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun 
1919*4882a593Smuzhiyun /*
1920*4882a593Smuzhiyun  * send the reset sequence
1921*4882a593Smuzhiyun  *
1922*4882a593Smuzhiyun  */
ftdi_elan_synchronize_reset(struct usb_ftdi * ftdi)1923*4882a593Smuzhiyun static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi)
1924*4882a593Smuzhiyun {
1925*4882a593Smuzhiyun 	int retval;
1926*4882a593Smuzhiyun 	struct urb *urb;
1927*4882a593Smuzhiyun 	char *buf;
1928*4882a593Smuzhiyun 	int I = 4;
1929*4882a593Smuzhiyun 	int i = 0;
1930*4882a593Smuzhiyun 	urb = usb_alloc_urb(0, GFP_KERNEL);
1931*4882a593Smuzhiyun 	if (!urb)
1932*4882a593Smuzhiyun 		return -ENOMEM;
1933*4882a593Smuzhiyun 	buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
1934*4882a593Smuzhiyun 	if (!buf) {
1935*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "could not get a buffer for the reset sequence\n");
1936*4882a593Smuzhiyun 		usb_free_urb(urb);
1937*4882a593Smuzhiyun 		return -ENOMEM;
1938*4882a593Smuzhiyun 	}
1939*4882a593Smuzhiyun 	buf[i++] = 0x55;
1940*4882a593Smuzhiyun 	buf[i++] = 0xAA;
1941*4882a593Smuzhiyun 	buf[i++] = 0x5A;
1942*4882a593Smuzhiyun 	buf[i++] = 0xA5;
1943*4882a593Smuzhiyun 	usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
1944*4882a593Smuzhiyun 							   ftdi->bulk_out_endpointAddr), buf, i,
1945*4882a593Smuzhiyun 			  ftdi_elan_write_bulk_callback, ftdi);
1946*4882a593Smuzhiyun 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1947*4882a593Smuzhiyun 	retval = usb_submit_urb(urb, GFP_KERNEL);
1948*4882a593Smuzhiyun 	if (retval) {
1949*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "failed to submit urb containing the reset sequence\n");
1950*4882a593Smuzhiyun 		usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma);
1951*4882a593Smuzhiyun 		usb_free_urb(urb);
1952*4882a593Smuzhiyun 		return -ENOMEM;
1953*4882a593Smuzhiyun 	}
1954*4882a593Smuzhiyun 	usb_free_urb(urb);
1955*4882a593Smuzhiyun 	return 0;
1956*4882a593Smuzhiyun }
1957*4882a593Smuzhiyun 
ftdi_elan_synchronize(struct usb_ftdi * ftdi)1958*4882a593Smuzhiyun static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
1959*4882a593Smuzhiyun {
1960*4882a593Smuzhiyun 	int retval;
1961*4882a593Smuzhiyun 	int long_stop = 10;
1962*4882a593Smuzhiyun 	int retry_on_timeout = 5;
1963*4882a593Smuzhiyun 	int retry_on_empty = 10;
1964*4882a593Smuzhiyun 	int err_count = 0;
1965*4882a593Smuzhiyun 	retval = ftdi_elan_flush_input_fifo(ftdi);
1966*4882a593Smuzhiyun 	if (retval)
1967*4882a593Smuzhiyun 		return retval;
1968*4882a593Smuzhiyun 	ftdi->bulk_in_left = 0;
1969*4882a593Smuzhiyun 	ftdi->bulk_in_last = -1;
1970*4882a593Smuzhiyun 	while (long_stop-- > 0) {
1971*4882a593Smuzhiyun 		int read_stop;
1972*4882a593Smuzhiyun 		int read_stuck;
1973*4882a593Smuzhiyun 		retval = ftdi_elan_synchronize_flush(ftdi);
1974*4882a593Smuzhiyun 		if (retval)
1975*4882a593Smuzhiyun 			return retval;
1976*4882a593Smuzhiyun 		retval = ftdi_elan_flush_input_fifo(ftdi);
1977*4882a593Smuzhiyun 		if (retval)
1978*4882a593Smuzhiyun 			return retval;
1979*4882a593Smuzhiyun 	reset:retval = ftdi_elan_synchronize_reset(ftdi);
1980*4882a593Smuzhiyun 		if (retval)
1981*4882a593Smuzhiyun 			return retval;
1982*4882a593Smuzhiyun 		read_stop = 100;
1983*4882a593Smuzhiyun 		read_stuck = 10;
1984*4882a593Smuzhiyun 	read:{
1985*4882a593Smuzhiyun 			int packet_bytes = 0;
1986*4882a593Smuzhiyun 			retval = usb_bulk_msg(ftdi->udev,
1987*4882a593Smuzhiyun 					      usb_rcvbulkpipe(ftdi->udev,
1988*4882a593Smuzhiyun 							      ftdi->bulk_in_endpointAddr),
1989*4882a593Smuzhiyun 					      ftdi->bulk_in_buffer, ftdi->bulk_in_size,
1990*4882a593Smuzhiyun 					      &packet_bytes, 500);
1991*4882a593Smuzhiyun 			if (packet_bytes > 2) {
1992*4882a593Smuzhiyun 				char diag[30 *3 + 4];
1993*4882a593Smuzhiyun 				char *d = diag;
1994*4882a593Smuzhiyun 				int m = (sizeof(diag) - 1) / 3 - 1;
1995*4882a593Smuzhiyun 				char *b = ftdi->bulk_in_buffer;
1996*4882a593Smuzhiyun 				int bytes_read = 0;
1997*4882a593Smuzhiyun 				unsigned char c = 0;
1998*4882a593Smuzhiyun 				diag[0] = 0;
1999*4882a593Smuzhiyun 				while (packet_bytes-- > 0) {
2000*4882a593Smuzhiyun 					c = *b++;
2001*4882a593Smuzhiyun 					if (bytes_read < m) {
2002*4882a593Smuzhiyun 						d += sprintf(d, " %02X", c);
2003*4882a593Smuzhiyun 					} else if (bytes_read > m) {
2004*4882a593Smuzhiyun 					} else
2005*4882a593Smuzhiyun 						d += sprintf(d, " ..");
2006*4882a593Smuzhiyun 					bytes_read += 1;
2007*4882a593Smuzhiyun 					continue;
2008*4882a593Smuzhiyun 				}
2009*4882a593Smuzhiyun 				if (c == 0x7E) {
2010*4882a593Smuzhiyun 					return 0;
2011*4882a593Smuzhiyun 				} else {
2012*4882a593Smuzhiyun 					if (c == 0x55) {
2013*4882a593Smuzhiyun 						goto read;
2014*4882a593Smuzhiyun 					} else if (read_stop-- > 0) {
2015*4882a593Smuzhiyun 						goto read;
2016*4882a593Smuzhiyun 					} else {
2017*4882a593Smuzhiyun 						dev_err(&ftdi->udev->dev, "retry limit reached\n");
2018*4882a593Smuzhiyun 						continue;
2019*4882a593Smuzhiyun 					}
2020*4882a593Smuzhiyun 				}
2021*4882a593Smuzhiyun 			} else if (packet_bytes > 1) {
2022*4882a593Smuzhiyun 				unsigned char s1 = ftdi->bulk_in_buffer[0];
2023*4882a593Smuzhiyun 				unsigned char s2 = ftdi->bulk_in_buffer[1];
2024*4882a593Smuzhiyun 				if (s1 == 0x31 && s2 == 0x00) {
2025*4882a593Smuzhiyun 					if (read_stuck-- > 0) {
2026*4882a593Smuzhiyun 						goto read;
2027*4882a593Smuzhiyun 					} else
2028*4882a593Smuzhiyun 						goto reset;
2029*4882a593Smuzhiyun 				} else {
2030*4882a593Smuzhiyun 					if (read_stop-- > 0) {
2031*4882a593Smuzhiyun 						goto read;
2032*4882a593Smuzhiyun 					} else {
2033*4882a593Smuzhiyun 						dev_err(&ftdi->udev->dev, "retry limit reached\n");
2034*4882a593Smuzhiyun 						continue;
2035*4882a593Smuzhiyun 					}
2036*4882a593Smuzhiyun 				}
2037*4882a593Smuzhiyun 			} else if (packet_bytes > 0) {
2038*4882a593Smuzhiyun 				if (read_stop-- > 0) {
2039*4882a593Smuzhiyun 					goto read;
2040*4882a593Smuzhiyun 				} else {
2041*4882a593Smuzhiyun 					dev_err(&ftdi->udev->dev, "retry limit reached\n");
2042*4882a593Smuzhiyun 					continue;
2043*4882a593Smuzhiyun 				}
2044*4882a593Smuzhiyun 			} else if (retval == -ETIMEDOUT) {
2045*4882a593Smuzhiyun 				if (retry_on_timeout-- > 0) {
2046*4882a593Smuzhiyun 					goto read;
2047*4882a593Smuzhiyun 				} else {
2048*4882a593Smuzhiyun 					dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n");
2049*4882a593Smuzhiyun 					continue;
2050*4882a593Smuzhiyun 				}
2051*4882a593Smuzhiyun 			} else if (retval == 0) {
2052*4882a593Smuzhiyun 				if (retry_on_empty-- > 0) {
2053*4882a593Smuzhiyun 					goto read;
2054*4882a593Smuzhiyun 				} else {
2055*4882a593Smuzhiyun 					dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n");
2056*4882a593Smuzhiyun 					continue;
2057*4882a593Smuzhiyun 				}
2058*4882a593Smuzhiyun 			} else {
2059*4882a593Smuzhiyun 				err_count += 1;
2060*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "error = %d\n",
2061*4882a593Smuzhiyun 					retval);
2062*4882a593Smuzhiyun 				if (read_stop-- > 0) {
2063*4882a593Smuzhiyun 					goto read;
2064*4882a593Smuzhiyun 				} else {
2065*4882a593Smuzhiyun 					dev_err(&ftdi->udev->dev, "retry limit reached\n");
2066*4882a593Smuzhiyun 					continue;
2067*4882a593Smuzhiyun 				}
2068*4882a593Smuzhiyun 			}
2069*4882a593Smuzhiyun 		}
2070*4882a593Smuzhiyun 	}
2071*4882a593Smuzhiyun 	dev_err(&ftdi->udev->dev, "failed to synchronize\n");
2072*4882a593Smuzhiyun 	return -EFAULT;
2073*4882a593Smuzhiyun }
2074*4882a593Smuzhiyun 
ftdi_elan_stuck_waiting(struct usb_ftdi * ftdi)2075*4882a593Smuzhiyun static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi)
2076*4882a593Smuzhiyun {
2077*4882a593Smuzhiyun 	int retry_on_empty = 10;
2078*4882a593Smuzhiyun 	int retry_on_timeout = 5;
2079*4882a593Smuzhiyun 	int retry_on_status = 50;
2080*4882a593Smuzhiyun more:{
2081*4882a593Smuzhiyun 		int packet_bytes = 0;
2082*4882a593Smuzhiyun 		int retval = usb_bulk_msg(ftdi->udev,
2083*4882a593Smuzhiyun 					  usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
2084*4882a593Smuzhiyun 					  ftdi->bulk_in_buffer, ftdi->bulk_in_size,
2085*4882a593Smuzhiyun 					  &packet_bytes, 1000);
2086*4882a593Smuzhiyun 		if (packet_bytes > 2) {
2087*4882a593Smuzhiyun 			char diag[30 *3 + 4];
2088*4882a593Smuzhiyun 			char *d = diag;
2089*4882a593Smuzhiyun 			int m = (sizeof(diag) - 1) / 3 - 1;
2090*4882a593Smuzhiyun 			char *b = ftdi->bulk_in_buffer;
2091*4882a593Smuzhiyun 			int bytes_read = 0;
2092*4882a593Smuzhiyun 			diag[0] = 0;
2093*4882a593Smuzhiyun 			while (packet_bytes-- > 0) {
2094*4882a593Smuzhiyun 				char c = *b++;
2095*4882a593Smuzhiyun 				if (bytes_read < m) {
2096*4882a593Smuzhiyun 					d += sprintf(d, " %02X",
2097*4882a593Smuzhiyun 						     0x000000FF & c);
2098*4882a593Smuzhiyun 				} else if (bytes_read > m) {
2099*4882a593Smuzhiyun 				} else
2100*4882a593Smuzhiyun 					d += sprintf(d, " ..");
2101*4882a593Smuzhiyun 				bytes_read += 1;
2102*4882a593Smuzhiyun 				continue;
2103*4882a593Smuzhiyun 			}
2104*4882a593Smuzhiyun 			goto more;
2105*4882a593Smuzhiyun 		} else if (packet_bytes > 1) {
2106*4882a593Smuzhiyun 			char s1 = ftdi->bulk_in_buffer[0];
2107*4882a593Smuzhiyun 			char s2 = ftdi->bulk_in_buffer[1];
2108*4882a593Smuzhiyun 			if (s1 == 0x31 && s2 == 0x60) {
2109*4882a593Smuzhiyun 				return 0;
2110*4882a593Smuzhiyun 			} else if (retry_on_status-- > 0) {
2111*4882a593Smuzhiyun 				msleep(5);
2112*4882a593Smuzhiyun 				goto more;
2113*4882a593Smuzhiyun 			} else
2114*4882a593Smuzhiyun 				return -EFAULT;
2115*4882a593Smuzhiyun 		} else if (packet_bytes > 0) {
2116*4882a593Smuzhiyun 			char b1 = ftdi->bulk_in_buffer[0];
2117*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "only one byte flushed from FTDI = %02X\n", b1);
2118*4882a593Smuzhiyun 			if (retry_on_status-- > 0) {
2119*4882a593Smuzhiyun 				msleep(5);
2120*4882a593Smuzhiyun 				goto more;
2121*4882a593Smuzhiyun 			} else {
2122*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n");
2123*4882a593Smuzhiyun 				return -EFAULT;
2124*4882a593Smuzhiyun 			}
2125*4882a593Smuzhiyun 		} else if (retval == -ETIMEDOUT) {
2126*4882a593Smuzhiyun 			if (retry_on_timeout-- > 0) {
2127*4882a593Smuzhiyun 				goto more;
2128*4882a593Smuzhiyun 			} else {
2129*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n");
2130*4882a593Smuzhiyun 				return -ENOMEM;
2131*4882a593Smuzhiyun 			}
2132*4882a593Smuzhiyun 		} else if (retval == 0) {
2133*4882a593Smuzhiyun 			if (retry_on_empty-- > 0) {
2134*4882a593Smuzhiyun 				goto more;
2135*4882a593Smuzhiyun 			} else {
2136*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n");
2137*4882a593Smuzhiyun 				return -ENOMEM;
2138*4882a593Smuzhiyun 			}
2139*4882a593Smuzhiyun 		} else {
2140*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "error = %d\n", retval);
2141*4882a593Smuzhiyun 			return -ENOMEM;
2142*4882a593Smuzhiyun 		}
2143*4882a593Smuzhiyun 	}
2144*4882a593Smuzhiyun 	return -1;
2145*4882a593Smuzhiyun }
2146*4882a593Smuzhiyun 
ftdi_elan_checkingPCI(struct usb_ftdi * ftdi)2147*4882a593Smuzhiyun static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
2148*4882a593Smuzhiyun {
2149*4882a593Smuzhiyun 	int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg);
2150*4882a593Smuzhiyun 	if (UxxxStatus)
2151*4882a593Smuzhiyun 		return UxxxStatus;
2152*4882a593Smuzhiyun 	if (ftdi->controlreg & 0x00400000) {
2153*4882a593Smuzhiyun 		if (ftdi->card_ejected) {
2154*4882a593Smuzhiyun 		} else {
2155*4882a593Smuzhiyun 			ftdi->card_ejected = 1;
2156*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = %08X\n",
2157*4882a593Smuzhiyun 				ftdi->controlreg);
2158*4882a593Smuzhiyun 		}
2159*4882a593Smuzhiyun 		return -ENODEV;
2160*4882a593Smuzhiyun 	} else {
2161*4882a593Smuzhiyun 		u8 fn = ftdi->function - 1;
2162*4882a593Smuzhiyun 		int activePCIfn = fn << 8;
2163*4882a593Smuzhiyun 		u32 pcidata;
2164*4882a593Smuzhiyun 		u32 pciVID;
2165*4882a593Smuzhiyun 		u32 pciPID;
2166*4882a593Smuzhiyun 		int reg = 0;
2167*4882a593Smuzhiyun 		UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2168*4882a593Smuzhiyun 						   &pcidata);
2169*4882a593Smuzhiyun 		if (UxxxStatus)
2170*4882a593Smuzhiyun 			return UxxxStatus;
2171*4882a593Smuzhiyun 		pciVID = pcidata & 0xFFFF;
2172*4882a593Smuzhiyun 		pciPID = (pcidata >> 16) & 0xFFFF;
2173*4882a593Smuzhiyun 		if (pciVID == ftdi->platform_data.vendor && pciPID ==
2174*4882a593Smuzhiyun 		    ftdi->platform_data.device) {
2175*4882a593Smuzhiyun 			return 0;
2176*4882a593Smuzhiyun 		} else {
2177*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X device=%04X pciPID=%04X\n",
2178*4882a593Smuzhiyun 				ftdi->platform_data.vendor, pciVID,
2179*4882a593Smuzhiyun 				ftdi->platform_data.device, pciPID);
2180*4882a593Smuzhiyun 			return -ENODEV;
2181*4882a593Smuzhiyun 		}
2182*4882a593Smuzhiyun 	}
2183*4882a593Smuzhiyun }
2184*4882a593Smuzhiyun 
2185*4882a593Smuzhiyun 
2186*4882a593Smuzhiyun #define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \
2187*4882a593Smuzhiyun 								   offsetof(struct ohci_regs, member), 0, data);
2188*4882a593Smuzhiyun #define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
2189*4882a593Smuzhiyun 								     offsetof(struct ohci_regs, member), 0, data);
2190*4882a593Smuzhiyun 
2191*4882a593Smuzhiyun #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
2192*4882a593Smuzhiyun #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD |	\
2193*4882a593Smuzhiyun 			OHCI_INTR_WDH)
ftdi_elan_check_controller(struct usb_ftdi * ftdi,int quirk)2194*4882a593Smuzhiyun static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk)
2195*4882a593Smuzhiyun {
2196*4882a593Smuzhiyun 	int devices = 0;
2197*4882a593Smuzhiyun 	int retval;
2198*4882a593Smuzhiyun 	u32 hc_control;
2199*4882a593Smuzhiyun 	int num_ports;
2200*4882a593Smuzhiyun 	u32 control;
2201*4882a593Smuzhiyun 	u32 rh_a = -1;
2202*4882a593Smuzhiyun 	u32 status;
2203*4882a593Smuzhiyun 	u32 fminterval;
2204*4882a593Smuzhiyun 	u32 hc_fminterval;
2205*4882a593Smuzhiyun 	u32 periodicstart;
2206*4882a593Smuzhiyun 	u32 cmdstatus;
2207*4882a593Smuzhiyun 	u32 roothub_a;
2208*4882a593Smuzhiyun 	int mask = OHCI_INTR_INIT;
2209*4882a593Smuzhiyun 	int sleep_time = 0;
2210*4882a593Smuzhiyun 	int reset_timeout = 30;        /* ... allow extra time */
2211*4882a593Smuzhiyun 	int temp;
2212*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE);
2213*4882a593Smuzhiyun 	if (retval)
2214*4882a593Smuzhiyun 		return retval;
2215*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, control, &control);
2216*4882a593Smuzhiyun 	if (retval)
2217*4882a593Smuzhiyun 		return retval;
2218*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a);
2219*4882a593Smuzhiyun 	if (retval)
2220*4882a593Smuzhiyun 		return retval;
2221*4882a593Smuzhiyun 	num_ports = rh_a & RH_A_NDP;
2222*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval);
2223*4882a593Smuzhiyun 	if (retval)
2224*4882a593Smuzhiyun 		return retval;
2225*4882a593Smuzhiyun 	hc_fminterval &= 0x3fff;
2226*4882a593Smuzhiyun 	if (hc_fminterval != FI) {
2227*4882a593Smuzhiyun 	}
2228*4882a593Smuzhiyun 	hc_fminterval |= FSMP(hc_fminterval) << 16;
2229*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, control, &hc_control);
2230*4882a593Smuzhiyun 	if (retval)
2231*4882a593Smuzhiyun 		return retval;
2232*4882a593Smuzhiyun 	switch (hc_control & OHCI_CTRL_HCFS) {
2233*4882a593Smuzhiyun 	case OHCI_USB_OPER:
2234*4882a593Smuzhiyun 		sleep_time = 0;
2235*4882a593Smuzhiyun 		break;
2236*4882a593Smuzhiyun 	case OHCI_USB_SUSPEND:
2237*4882a593Smuzhiyun 	case OHCI_USB_RESUME:
2238*4882a593Smuzhiyun 		hc_control &= OHCI_CTRL_RWC;
2239*4882a593Smuzhiyun 		hc_control |= OHCI_USB_RESUME;
2240*4882a593Smuzhiyun 		sleep_time = 10;
2241*4882a593Smuzhiyun 		break;
2242*4882a593Smuzhiyun 	default:
2243*4882a593Smuzhiyun 		hc_control &= OHCI_CTRL_RWC;
2244*4882a593Smuzhiyun 		hc_control |= OHCI_USB_RESET;
2245*4882a593Smuzhiyun 		sleep_time = 50;
2246*4882a593Smuzhiyun 		break;
2247*4882a593Smuzhiyun 	}
2248*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, control, hc_control);
2249*4882a593Smuzhiyun 	if (retval)
2250*4882a593Smuzhiyun 		return retval;
2251*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, control, &control);
2252*4882a593Smuzhiyun 	if (retval)
2253*4882a593Smuzhiyun 		return retval;
2254*4882a593Smuzhiyun 	msleep(sleep_time);
2255*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
2256*4882a593Smuzhiyun 	if (retval)
2257*4882a593Smuzhiyun 		return retval;
2258*4882a593Smuzhiyun 	if (!(roothub_a & RH_A_NPS)) {        /* power down each port */
2259*4882a593Smuzhiyun 		for (temp = 0; temp < num_ports; temp++) {
2260*4882a593Smuzhiyun 			retval = ftdi_write_pcimem(ftdi,
2261*4882a593Smuzhiyun 						   roothub.portstatus[temp], RH_PS_LSDA);
2262*4882a593Smuzhiyun 			if (retval)
2263*4882a593Smuzhiyun 				return retval;
2264*4882a593Smuzhiyun 		}
2265*4882a593Smuzhiyun 	}
2266*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, control, &control);
2267*4882a593Smuzhiyun 	if (retval)
2268*4882a593Smuzhiyun 		return retval;
2269*4882a593Smuzhiyun retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
2270*4882a593Smuzhiyun 	if (retval)
2271*4882a593Smuzhiyun 		return retval;
2272*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR);
2273*4882a593Smuzhiyun 	if (retval)
2274*4882a593Smuzhiyun 		return retval;
2275*4882a593Smuzhiyun extra:{
2276*4882a593Smuzhiyun 		retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
2277*4882a593Smuzhiyun 		if (retval)
2278*4882a593Smuzhiyun 			return retval;
2279*4882a593Smuzhiyun 		if (0 != (status & OHCI_HCR)) {
2280*4882a593Smuzhiyun 			if (--reset_timeout == 0) {
2281*4882a593Smuzhiyun 				dev_err(&ftdi->udev->dev, "USB HC reset timed out!\n");
2282*4882a593Smuzhiyun 				return -ENODEV;
2283*4882a593Smuzhiyun 			} else {
2284*4882a593Smuzhiyun 				msleep(5);
2285*4882a593Smuzhiyun 				goto extra;
2286*4882a593Smuzhiyun 			}
2287*4882a593Smuzhiyun 		}
2288*4882a593Smuzhiyun 	}
2289*4882a593Smuzhiyun 	if (quirk & OHCI_QUIRK_INITRESET) {
2290*4882a593Smuzhiyun 		retval = ftdi_write_pcimem(ftdi, control, hc_control);
2291*4882a593Smuzhiyun 		if (retval)
2292*4882a593Smuzhiyun 			return retval;
2293*4882a593Smuzhiyun 		retval = ftdi_read_pcimem(ftdi, control, &control);
2294*4882a593Smuzhiyun 		if (retval)
2295*4882a593Smuzhiyun 			return retval;
2296*4882a593Smuzhiyun 	}
2297*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000);
2298*4882a593Smuzhiyun 	if (retval)
2299*4882a593Smuzhiyun 		return retval;
2300*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000);
2301*4882a593Smuzhiyun 	if (retval)
2302*4882a593Smuzhiyun 		return retval;
2303*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000);
2304*4882a593Smuzhiyun 	if (retval)
2305*4882a593Smuzhiyun 		return retval;
2306*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
2307*4882a593Smuzhiyun 	if (retval)
2308*4882a593Smuzhiyun 		return retval;
2309*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, fminterval,
2310*4882a593Smuzhiyun 				   ((fminterval & FIT) ^ FIT) | hc_fminterval);
2311*4882a593Smuzhiyun 	if (retval)
2312*4882a593Smuzhiyun 		return retval;
2313*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, periodicstart,
2314*4882a593Smuzhiyun 				   ((9 *hc_fminterval) / 10) & 0x3fff);
2315*4882a593Smuzhiyun 	if (retval)
2316*4882a593Smuzhiyun 		return retval;
2317*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
2318*4882a593Smuzhiyun 	if (retval)
2319*4882a593Smuzhiyun 		return retval;
2320*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart);
2321*4882a593Smuzhiyun 	if (retval)
2322*4882a593Smuzhiyun 		return retval;
2323*4882a593Smuzhiyun 	if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
2324*4882a593Smuzhiyun 		if (!(quirk & OHCI_QUIRK_INITRESET)) {
2325*4882a593Smuzhiyun 			quirk |= OHCI_QUIRK_INITRESET;
2326*4882a593Smuzhiyun 			goto retry;
2327*4882a593Smuzhiyun 		} else
2328*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n",
2329*4882a593Smuzhiyun 				fminterval, periodicstart);
2330*4882a593Smuzhiyun 	}                        /* start controller operations */
2331*4882a593Smuzhiyun 	hc_control &= OHCI_CTRL_RWC;
2332*4882a593Smuzhiyun 	hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
2333*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, control, hc_control);
2334*4882a593Smuzhiyun 	if (retval)
2335*4882a593Smuzhiyun 		return retval;
2336*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF);
2337*4882a593Smuzhiyun 	if (retval)
2338*4882a593Smuzhiyun 		return retval;
2339*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus);
2340*4882a593Smuzhiyun 	if (retval)
2341*4882a593Smuzhiyun 		return retval;
2342*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, control, &control);
2343*4882a593Smuzhiyun 	if (retval)
2344*4882a593Smuzhiyun 		return retval;
2345*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE);
2346*4882a593Smuzhiyun 	if (retval)
2347*4882a593Smuzhiyun 		return retval;
2348*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, intrstatus, mask);
2349*4882a593Smuzhiyun 	if (retval)
2350*4882a593Smuzhiyun 		return retval;
2351*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, intrdisable,
2352*4882a593Smuzhiyun 				   OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
2353*4882a593Smuzhiyun 				   OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
2354*4882a593Smuzhiyun 				   OHCI_INTR_SO);
2355*4882a593Smuzhiyun 	if (retval)
2356*4882a593Smuzhiyun 		return retval;        /* handle root hub init quirks ... */
2357*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
2358*4882a593Smuzhiyun 	if (retval)
2359*4882a593Smuzhiyun 		return retval;
2360*4882a593Smuzhiyun 	roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
2361*4882a593Smuzhiyun 	if (quirk & OHCI_QUIRK_SUPERIO) {
2362*4882a593Smuzhiyun 		roothub_a |= RH_A_NOCP;
2363*4882a593Smuzhiyun 		roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
2364*4882a593Smuzhiyun 		retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
2365*4882a593Smuzhiyun 		if (retval)
2366*4882a593Smuzhiyun 			return retval;
2367*4882a593Smuzhiyun 	} else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) {
2368*4882a593Smuzhiyun 		roothub_a |= RH_A_NPS;
2369*4882a593Smuzhiyun 		retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
2370*4882a593Smuzhiyun 		if (retval)
2371*4882a593Smuzhiyun 			return retval;
2372*4882a593Smuzhiyun 	}
2373*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC);
2374*4882a593Smuzhiyun 	if (retval)
2375*4882a593Smuzhiyun 		return retval;
2376*4882a593Smuzhiyun 	retval = ftdi_write_pcimem(ftdi, roothub.b,
2377*4882a593Smuzhiyun 				   (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
2378*4882a593Smuzhiyun 	if (retval)
2379*4882a593Smuzhiyun 		return retval;
2380*4882a593Smuzhiyun 	retval = ftdi_read_pcimem(ftdi, control, &control);
2381*4882a593Smuzhiyun 	if (retval)
2382*4882a593Smuzhiyun 		return retval;
2383*4882a593Smuzhiyun 	mdelay((roothub_a >> 23) & 0x1fe);
2384*4882a593Smuzhiyun 	for (temp = 0; temp < num_ports; temp++) {
2385*4882a593Smuzhiyun 		u32 portstatus;
2386*4882a593Smuzhiyun 		retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp],
2387*4882a593Smuzhiyun 					  &portstatus);
2388*4882a593Smuzhiyun 		if (retval)
2389*4882a593Smuzhiyun 			return retval;
2390*4882a593Smuzhiyun 		if (1 & portstatus)
2391*4882a593Smuzhiyun 			devices += 1;
2392*4882a593Smuzhiyun 	}
2393*4882a593Smuzhiyun 	return devices;
2394*4882a593Smuzhiyun }
2395*4882a593Smuzhiyun 
ftdi_elan_setup_controller(struct usb_ftdi * ftdi,int fn)2396*4882a593Smuzhiyun static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn)
2397*4882a593Smuzhiyun {
2398*4882a593Smuzhiyun 	u32 latence_timer;
2399*4882a593Smuzhiyun 	int UxxxStatus;
2400*4882a593Smuzhiyun 	u32 pcidata;
2401*4882a593Smuzhiyun 	int reg = 0;
2402*4882a593Smuzhiyun 	int activePCIfn = fn << 8;
2403*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
2404*4882a593Smuzhiyun 	if (UxxxStatus)
2405*4882a593Smuzhiyun 		return UxxxStatus;
2406*4882a593Smuzhiyun 	reg = 16;
2407*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
2408*4882a593Smuzhiyun 					    0xFFFFFFFF);
2409*4882a593Smuzhiyun 	if (UxxxStatus)
2410*4882a593Smuzhiyun 		return UxxxStatus;
2411*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2412*4882a593Smuzhiyun 					   &pcidata);
2413*4882a593Smuzhiyun 	if (UxxxStatus)
2414*4882a593Smuzhiyun 		return UxxxStatus;
2415*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
2416*4882a593Smuzhiyun 					    0xF0000000);
2417*4882a593Smuzhiyun 	if (UxxxStatus)
2418*4882a593Smuzhiyun 		return UxxxStatus;
2419*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2420*4882a593Smuzhiyun 					   &pcidata);
2421*4882a593Smuzhiyun 	if (UxxxStatus)
2422*4882a593Smuzhiyun 		return UxxxStatus;
2423*4882a593Smuzhiyun 	reg = 12;
2424*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2425*4882a593Smuzhiyun 					   &latence_timer);
2426*4882a593Smuzhiyun 	if (UxxxStatus)
2427*4882a593Smuzhiyun 		return UxxxStatus;
2428*4882a593Smuzhiyun 	latence_timer &= 0xFFFF00FF;
2429*4882a593Smuzhiyun 	latence_timer |= 0x00001600;
2430*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
2431*4882a593Smuzhiyun 					    latence_timer);
2432*4882a593Smuzhiyun 	if (UxxxStatus)
2433*4882a593Smuzhiyun 		return UxxxStatus;
2434*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2435*4882a593Smuzhiyun 					   &pcidata);
2436*4882a593Smuzhiyun 	if (UxxxStatus)
2437*4882a593Smuzhiyun 		return UxxxStatus;
2438*4882a593Smuzhiyun 	reg = 4;
2439*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
2440*4882a593Smuzhiyun 					    0x06);
2441*4882a593Smuzhiyun 	if (UxxxStatus)
2442*4882a593Smuzhiyun 		return UxxxStatus;
2443*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2444*4882a593Smuzhiyun 					   &pcidata);
2445*4882a593Smuzhiyun 	if (UxxxStatus)
2446*4882a593Smuzhiyun 		return UxxxStatus;
2447*4882a593Smuzhiyun 	for (reg = 0; reg <= 0x54; reg += 4) {
2448*4882a593Smuzhiyun 		UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
2449*4882a593Smuzhiyun 		if (UxxxStatus)
2450*4882a593Smuzhiyun 			return UxxxStatus;
2451*4882a593Smuzhiyun 	}
2452*4882a593Smuzhiyun 	return 0;
2453*4882a593Smuzhiyun }
2454*4882a593Smuzhiyun 
ftdi_elan_close_controller(struct usb_ftdi * ftdi,int fn)2455*4882a593Smuzhiyun static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn)
2456*4882a593Smuzhiyun {
2457*4882a593Smuzhiyun 	u32 latence_timer;
2458*4882a593Smuzhiyun 	int UxxxStatus;
2459*4882a593Smuzhiyun 	u32 pcidata;
2460*4882a593Smuzhiyun 	int reg = 0;
2461*4882a593Smuzhiyun 	int activePCIfn = fn << 8;
2462*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
2463*4882a593Smuzhiyun 	if (UxxxStatus)
2464*4882a593Smuzhiyun 		return UxxxStatus;
2465*4882a593Smuzhiyun 	reg = 16;
2466*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
2467*4882a593Smuzhiyun 					    0xFFFFFFFF);
2468*4882a593Smuzhiyun 	if (UxxxStatus)
2469*4882a593Smuzhiyun 		return UxxxStatus;
2470*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2471*4882a593Smuzhiyun 					   &pcidata);
2472*4882a593Smuzhiyun 	if (UxxxStatus)
2473*4882a593Smuzhiyun 		return UxxxStatus;
2474*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
2475*4882a593Smuzhiyun 					    0x00000000);
2476*4882a593Smuzhiyun 	if (UxxxStatus)
2477*4882a593Smuzhiyun 		return UxxxStatus;
2478*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2479*4882a593Smuzhiyun 					   &pcidata);
2480*4882a593Smuzhiyun 	if (UxxxStatus)
2481*4882a593Smuzhiyun 		return UxxxStatus;
2482*4882a593Smuzhiyun 	reg = 12;
2483*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2484*4882a593Smuzhiyun 					   &latence_timer);
2485*4882a593Smuzhiyun 	if (UxxxStatus)
2486*4882a593Smuzhiyun 		return UxxxStatus;
2487*4882a593Smuzhiyun 	latence_timer &= 0xFFFF00FF;
2488*4882a593Smuzhiyun 	latence_timer |= 0x00001600;
2489*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
2490*4882a593Smuzhiyun 					    latence_timer);
2491*4882a593Smuzhiyun 	if (UxxxStatus)
2492*4882a593Smuzhiyun 		return UxxxStatus;
2493*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2494*4882a593Smuzhiyun 					   &pcidata);
2495*4882a593Smuzhiyun 	if (UxxxStatus)
2496*4882a593Smuzhiyun 		return UxxxStatus;
2497*4882a593Smuzhiyun 	reg = 4;
2498*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
2499*4882a593Smuzhiyun 					    0x00);
2500*4882a593Smuzhiyun 	if (UxxxStatus)
2501*4882a593Smuzhiyun 		return UxxxStatus;
2502*4882a593Smuzhiyun 	return ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, &pcidata);
2503*4882a593Smuzhiyun }
2504*4882a593Smuzhiyun 
ftdi_elan_found_controller(struct usb_ftdi * ftdi,int fn,int quirk)2505*4882a593Smuzhiyun static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
2506*4882a593Smuzhiyun {
2507*4882a593Smuzhiyun 	int result;
2508*4882a593Smuzhiyun 	int UxxxStatus;
2509*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_setup_controller(ftdi, fn);
2510*4882a593Smuzhiyun 	if (UxxxStatus)
2511*4882a593Smuzhiyun 		return UxxxStatus;
2512*4882a593Smuzhiyun 	result = ftdi_elan_check_controller(ftdi, quirk);
2513*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_close_controller(ftdi, fn);
2514*4882a593Smuzhiyun 	if (UxxxStatus)
2515*4882a593Smuzhiyun 		return UxxxStatus;
2516*4882a593Smuzhiyun 	return result;
2517*4882a593Smuzhiyun }
2518*4882a593Smuzhiyun 
ftdi_elan_enumeratePCI(struct usb_ftdi * ftdi)2519*4882a593Smuzhiyun static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
2520*4882a593Smuzhiyun {
2521*4882a593Smuzhiyun 	u32 controlreg;
2522*4882a593Smuzhiyun 	u8 sensebits;
2523*4882a593Smuzhiyun 	int UxxxStatus;
2524*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
2525*4882a593Smuzhiyun 	if (UxxxStatus)
2526*4882a593Smuzhiyun 		return UxxxStatus;
2527*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
2528*4882a593Smuzhiyun 	if (UxxxStatus)
2529*4882a593Smuzhiyun 		return UxxxStatus;
2530*4882a593Smuzhiyun 	msleep(750);
2531*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
2532*4882a593Smuzhiyun 	if (UxxxStatus)
2533*4882a593Smuzhiyun 		return UxxxStatus;
2534*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
2535*4882a593Smuzhiyun 	if (UxxxStatus)
2536*4882a593Smuzhiyun 		return UxxxStatus;
2537*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
2538*4882a593Smuzhiyun 	if (UxxxStatus)
2539*4882a593Smuzhiyun 		return UxxxStatus;
2540*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
2541*4882a593Smuzhiyun 	if (UxxxStatus)
2542*4882a593Smuzhiyun 		return UxxxStatus;
2543*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
2544*4882a593Smuzhiyun 	if (UxxxStatus)
2545*4882a593Smuzhiyun 		return UxxxStatus;
2546*4882a593Smuzhiyun 	msleep(250);
2547*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
2548*4882a593Smuzhiyun 	if (UxxxStatus)
2549*4882a593Smuzhiyun 		return UxxxStatus;
2550*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
2551*4882a593Smuzhiyun 	if (UxxxStatus)
2552*4882a593Smuzhiyun 		return UxxxStatus;
2553*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
2554*4882a593Smuzhiyun 	if (UxxxStatus)
2555*4882a593Smuzhiyun 		return UxxxStatus;
2556*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
2557*4882a593Smuzhiyun 	if (UxxxStatus)
2558*4882a593Smuzhiyun 		return UxxxStatus;
2559*4882a593Smuzhiyun 	UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
2560*4882a593Smuzhiyun 	if (UxxxStatus)
2561*4882a593Smuzhiyun 		return UxxxStatus;
2562*4882a593Smuzhiyun 	msleep(1000);
2563*4882a593Smuzhiyun 	sensebits = (controlreg >> 16) & 0x000F;
2564*4882a593Smuzhiyun 	if (0x0D == sensebits)
2565*4882a593Smuzhiyun 		return 0;
2566*4882a593Smuzhiyun 	else
2567*4882a593Smuzhiyun 		return - ENXIO;
2568*4882a593Smuzhiyun }
2569*4882a593Smuzhiyun 
ftdi_elan_setupOHCI(struct usb_ftdi * ftdi)2570*4882a593Smuzhiyun static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
2571*4882a593Smuzhiyun {
2572*4882a593Smuzhiyun 	int UxxxStatus;
2573*4882a593Smuzhiyun 	u32 pcidata;
2574*4882a593Smuzhiyun 	int reg = 0;
2575*4882a593Smuzhiyun 	u8 fn;
2576*4882a593Smuzhiyun 	int activePCIfn = 0;
2577*4882a593Smuzhiyun 	int max_devices = 0;
2578*4882a593Smuzhiyun 	int controllers = 0;
2579*4882a593Smuzhiyun 	int unrecognized = 0;
2580*4882a593Smuzhiyun 	ftdi->function = 0;
2581*4882a593Smuzhiyun 	for (fn = 0; (fn < 4); fn++) {
2582*4882a593Smuzhiyun 		u32 pciVID = 0;
2583*4882a593Smuzhiyun 		u32 pciPID = 0;
2584*4882a593Smuzhiyun 		int devices = 0;
2585*4882a593Smuzhiyun 		activePCIfn = fn << 8;
2586*4882a593Smuzhiyun 		UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
2587*4882a593Smuzhiyun 						   &pcidata);
2588*4882a593Smuzhiyun 		if (UxxxStatus)
2589*4882a593Smuzhiyun 			return UxxxStatus;
2590*4882a593Smuzhiyun 		pciVID = pcidata & 0xFFFF;
2591*4882a593Smuzhiyun 		pciPID = (pcidata >> 16) & 0xFFFF;
2592*4882a593Smuzhiyun 		if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) {
2593*4882a593Smuzhiyun 			devices = ftdi_elan_found_controller(ftdi, fn, 0);
2594*4882a593Smuzhiyun 			controllers += 1;
2595*4882a593Smuzhiyun 		} else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035))
2596*4882a593Smuzhiyun 		{
2597*4882a593Smuzhiyun 			devices = ftdi_elan_found_controller(ftdi, fn, 0);
2598*4882a593Smuzhiyun 			controllers += 1;
2599*4882a593Smuzhiyun 		} else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) {
2600*4882a593Smuzhiyun 			devices = ftdi_elan_found_controller(ftdi, fn, 0);
2601*4882a593Smuzhiyun 			controllers += 1;
2602*4882a593Smuzhiyun 		} else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802))
2603*4882a593Smuzhiyun 		{
2604*4882a593Smuzhiyun 			devices = ftdi_elan_found_controller(ftdi, fn, 0);
2605*4882a593Smuzhiyun 			controllers += 1;
2606*4882a593Smuzhiyun 		} else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) {
2607*4882a593Smuzhiyun 			devices = ftdi_elan_found_controller(ftdi, fn,
2608*4882a593Smuzhiyun 							     OHCI_QUIRK_AMD756);
2609*4882a593Smuzhiyun 			controllers += 1;
2610*4882a593Smuzhiyun 		} else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) {
2611*4882a593Smuzhiyun 			devices = ftdi_elan_found_controller(ftdi, fn,
2612*4882a593Smuzhiyun 							     OHCI_QUIRK_ZFMICRO);
2613*4882a593Smuzhiyun 			controllers += 1;
2614*4882a593Smuzhiyun 		} else if (0 == pcidata) {
2615*4882a593Smuzhiyun 		} else
2616*4882a593Smuzhiyun 			unrecognized += 1;
2617*4882a593Smuzhiyun 		if (devices > max_devices) {
2618*4882a593Smuzhiyun 			max_devices = devices;
2619*4882a593Smuzhiyun 			ftdi->function = fn + 1;
2620*4882a593Smuzhiyun 			ftdi->platform_data.vendor = pciVID;
2621*4882a593Smuzhiyun 			ftdi->platform_data.device = pciPID;
2622*4882a593Smuzhiyun 		}
2623*4882a593Smuzhiyun 	}
2624*4882a593Smuzhiyun 	if (ftdi->function > 0) {
2625*4882a593Smuzhiyun 		return ftdi_elan_setup_controller(ftdi,	ftdi->function - 1);
2626*4882a593Smuzhiyun 	} else if (controllers > 0) {
2627*4882a593Smuzhiyun 		return -ENXIO;
2628*4882a593Smuzhiyun 	} else if (unrecognized > 0) {
2629*4882a593Smuzhiyun 		return -ENXIO;
2630*4882a593Smuzhiyun 	} else {
2631*4882a593Smuzhiyun 		ftdi->enumerated = 0;
2632*4882a593Smuzhiyun 		return -ENXIO;
2633*4882a593Smuzhiyun 	}
2634*4882a593Smuzhiyun }
2635*4882a593Smuzhiyun 
2636*4882a593Smuzhiyun 
2637*4882a593Smuzhiyun /*
2638*4882a593Smuzhiyun  * we use only the first bulk-in and bulk-out endpoints
2639*4882a593Smuzhiyun  */
ftdi_elan_probe(struct usb_interface * interface,const struct usb_device_id * id)2640*4882a593Smuzhiyun static int ftdi_elan_probe(struct usb_interface *interface,
2641*4882a593Smuzhiyun 			   const struct usb_device_id *id)
2642*4882a593Smuzhiyun {
2643*4882a593Smuzhiyun 	struct usb_host_interface *iface_desc;
2644*4882a593Smuzhiyun 	struct usb_endpoint_descriptor *bulk_in, *bulk_out;
2645*4882a593Smuzhiyun 	int retval;
2646*4882a593Smuzhiyun 	struct usb_ftdi *ftdi;
2647*4882a593Smuzhiyun 
2648*4882a593Smuzhiyun 	ftdi = kzalloc(sizeof(struct usb_ftdi), GFP_KERNEL);
2649*4882a593Smuzhiyun 	if (!ftdi)
2650*4882a593Smuzhiyun 		return -ENOMEM;
2651*4882a593Smuzhiyun 
2652*4882a593Smuzhiyun 	mutex_lock(&ftdi_module_lock);
2653*4882a593Smuzhiyun 	list_add_tail(&ftdi->ftdi_list, &ftdi_static_list);
2654*4882a593Smuzhiyun 	ftdi->sequence_num = ++ftdi_instances;
2655*4882a593Smuzhiyun 	mutex_unlock(&ftdi_module_lock);
2656*4882a593Smuzhiyun 	ftdi_elan_init_kref(ftdi);
2657*4882a593Smuzhiyun 	sema_init(&ftdi->sw_lock, 1);
2658*4882a593Smuzhiyun 	ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
2659*4882a593Smuzhiyun 	ftdi->interface = interface;
2660*4882a593Smuzhiyun 	mutex_init(&ftdi->u132_lock);
2661*4882a593Smuzhiyun 	ftdi->expected = 4;
2662*4882a593Smuzhiyun 
2663*4882a593Smuzhiyun 	iface_desc = interface->cur_altsetting;
2664*4882a593Smuzhiyun 	retval = usb_find_common_endpoints(iface_desc,
2665*4882a593Smuzhiyun 			&bulk_in, &bulk_out, NULL, NULL);
2666*4882a593Smuzhiyun 	if (retval) {
2667*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk-out endpoints\n");
2668*4882a593Smuzhiyun 		goto error;
2669*4882a593Smuzhiyun 	}
2670*4882a593Smuzhiyun 
2671*4882a593Smuzhiyun 	ftdi->bulk_in_size = usb_endpoint_maxp(bulk_in);
2672*4882a593Smuzhiyun 	ftdi->bulk_in_endpointAddr = bulk_in->bEndpointAddress;
2673*4882a593Smuzhiyun 	ftdi->bulk_in_buffer = kmalloc(ftdi->bulk_in_size, GFP_KERNEL);
2674*4882a593Smuzhiyun 	if (!ftdi->bulk_in_buffer) {
2675*4882a593Smuzhiyun 		retval = -ENOMEM;
2676*4882a593Smuzhiyun 		goto error;
2677*4882a593Smuzhiyun 	}
2678*4882a593Smuzhiyun 
2679*4882a593Smuzhiyun 	ftdi->bulk_out_endpointAddr = bulk_out->bEndpointAddress;
2680*4882a593Smuzhiyun 
2681*4882a593Smuzhiyun 	dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n",
2682*4882a593Smuzhiyun 		 iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr,
2683*4882a593Smuzhiyun 		 ftdi->bulk_out_endpointAddr);
2684*4882a593Smuzhiyun 	usb_set_intfdata(interface, ftdi);
2685*4882a593Smuzhiyun 	if (iface_desc->desc.bInterfaceNumber == 0 &&
2686*4882a593Smuzhiyun 	    ftdi->bulk_in_endpointAddr == 0x81 &&
2687*4882a593Smuzhiyun 	    ftdi->bulk_out_endpointAddr == 0x02) {
2688*4882a593Smuzhiyun 		retval = usb_register_dev(interface, &ftdi_elan_jtag_class);
2689*4882a593Smuzhiyun 		if (retval) {
2690*4882a593Smuzhiyun 			dev_err(&ftdi->udev->dev, "Not able to get a minor for this device\n");
2691*4882a593Smuzhiyun 			usb_set_intfdata(interface, NULL);
2692*4882a593Smuzhiyun 			retval = -ENOMEM;
2693*4882a593Smuzhiyun 			goto error;
2694*4882a593Smuzhiyun 		} else {
2695*4882a593Smuzhiyun 			ftdi->class = &ftdi_elan_jtag_class;
2696*4882a593Smuzhiyun 			dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface %d now attached to ftdi%d\n",
2697*4882a593Smuzhiyun 				 ftdi, iface_desc->desc.bInterfaceNumber,
2698*4882a593Smuzhiyun 				 interface->minor);
2699*4882a593Smuzhiyun 			return 0;
2700*4882a593Smuzhiyun 		}
2701*4882a593Smuzhiyun 	} else if (iface_desc->desc.bInterfaceNumber == 1 &&
2702*4882a593Smuzhiyun 		   ftdi->bulk_in_endpointAddr == 0x83 &&
2703*4882a593Smuzhiyun 		   ftdi->bulk_out_endpointAddr == 0x04) {
2704*4882a593Smuzhiyun 		ftdi->class = NULL;
2705*4882a593Smuzhiyun 		dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now activated\n",
2706*4882a593Smuzhiyun 			 ftdi, iface_desc->desc.bInterfaceNumber);
2707*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work);
2708*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work);
2709*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work);
2710*4882a593Smuzhiyun 		ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
2711*4882a593Smuzhiyun 		return 0;
2712*4882a593Smuzhiyun 	} else {
2713*4882a593Smuzhiyun 		dev_err(&ftdi->udev->dev,
2714*4882a593Smuzhiyun 			"Could not find ELAN's U132 device\n");
2715*4882a593Smuzhiyun 		retval = -ENODEV;
2716*4882a593Smuzhiyun 		goto error;
2717*4882a593Smuzhiyun 	}
2718*4882a593Smuzhiyun error:if (ftdi) {
2719*4882a593Smuzhiyun 		ftdi_elan_put_kref(ftdi);
2720*4882a593Smuzhiyun 	}
2721*4882a593Smuzhiyun 	return retval;
2722*4882a593Smuzhiyun }
2723*4882a593Smuzhiyun 
ftdi_elan_disconnect(struct usb_interface * interface)2724*4882a593Smuzhiyun static void ftdi_elan_disconnect(struct usb_interface *interface)
2725*4882a593Smuzhiyun {
2726*4882a593Smuzhiyun 	struct usb_ftdi *ftdi = usb_get_intfdata(interface);
2727*4882a593Smuzhiyun 	ftdi->disconnected += 1;
2728*4882a593Smuzhiyun 	if (ftdi->class) {
2729*4882a593Smuzhiyun 		int minor = interface->minor;
2730*4882a593Smuzhiyun 		struct usb_class_driver *class = ftdi->class;
2731*4882a593Smuzhiyun 		usb_set_intfdata(interface, NULL);
2732*4882a593Smuzhiyun 		usb_deregister_dev(interface, class);
2733*4882a593Smuzhiyun 		dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on minor %d now disconnected\n",
2734*4882a593Smuzhiyun 			 minor);
2735*4882a593Smuzhiyun 	} else {
2736*4882a593Smuzhiyun 		ftdi_status_cancel_work(ftdi);
2737*4882a593Smuzhiyun 		ftdi_command_cancel_work(ftdi);
2738*4882a593Smuzhiyun 		ftdi_response_cancel_work(ftdi);
2739*4882a593Smuzhiyun 		ftdi_elan_abandon_completions(ftdi);
2740*4882a593Smuzhiyun 		ftdi_elan_abandon_targets(ftdi);
2741*4882a593Smuzhiyun 		if (ftdi->registered) {
2742*4882a593Smuzhiyun 			platform_device_unregister(&ftdi->platform_dev);
2743*4882a593Smuzhiyun 			ftdi->synchronized = 0;
2744*4882a593Smuzhiyun 			ftdi->enumerated = 0;
2745*4882a593Smuzhiyun 			ftdi->initialized = 0;
2746*4882a593Smuzhiyun 			ftdi->registered = 0;
2747*4882a593Smuzhiyun 		}
2748*4882a593Smuzhiyun 		ftdi->disconnected += 1;
2749*4882a593Smuzhiyun 		usb_set_intfdata(interface, NULL);
2750*4882a593Smuzhiyun 		dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller interface now disconnected\n");
2751*4882a593Smuzhiyun 	}
2752*4882a593Smuzhiyun 	ftdi_elan_put_kref(ftdi);
2753*4882a593Smuzhiyun }
2754*4882a593Smuzhiyun 
2755*4882a593Smuzhiyun static struct usb_driver ftdi_elan_driver = {
2756*4882a593Smuzhiyun 	.name = "ftdi-elan",
2757*4882a593Smuzhiyun 	.probe = ftdi_elan_probe,
2758*4882a593Smuzhiyun 	.disconnect = ftdi_elan_disconnect,
2759*4882a593Smuzhiyun 	.id_table = ftdi_elan_table,
2760*4882a593Smuzhiyun };
ftdi_elan_init(void)2761*4882a593Smuzhiyun static int __init ftdi_elan_init(void)
2762*4882a593Smuzhiyun {
2763*4882a593Smuzhiyun 	int result;
2764*4882a593Smuzhiyun 	pr_info("driver %s\n", ftdi_elan_driver.name);
2765*4882a593Smuzhiyun 	mutex_init(&ftdi_module_lock);
2766*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ftdi_static_list);
2767*4882a593Smuzhiyun 	result = usb_register(&ftdi_elan_driver);
2768*4882a593Smuzhiyun 	if (result) {
2769*4882a593Smuzhiyun 		pr_err("usb_register failed. Error number %d\n", result);
2770*4882a593Smuzhiyun 	}
2771*4882a593Smuzhiyun 	return result;
2772*4882a593Smuzhiyun 
2773*4882a593Smuzhiyun }
2774*4882a593Smuzhiyun 
ftdi_elan_exit(void)2775*4882a593Smuzhiyun static void __exit ftdi_elan_exit(void)
2776*4882a593Smuzhiyun {
2777*4882a593Smuzhiyun 	struct usb_ftdi *ftdi;
2778*4882a593Smuzhiyun 	struct usb_ftdi *temp;
2779*4882a593Smuzhiyun 	usb_deregister(&ftdi_elan_driver);
2780*4882a593Smuzhiyun 	pr_info("ftdi_u132 driver deregistered\n");
2781*4882a593Smuzhiyun 	list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) {
2782*4882a593Smuzhiyun 		ftdi_status_cancel_work(ftdi);
2783*4882a593Smuzhiyun 		ftdi_command_cancel_work(ftdi);
2784*4882a593Smuzhiyun 		ftdi_response_cancel_work(ftdi);
2785*4882a593Smuzhiyun 	}
2786*4882a593Smuzhiyun }
2787*4882a593Smuzhiyun 
2788*4882a593Smuzhiyun 
2789*4882a593Smuzhiyun module_init(ftdi_elan_init);
2790*4882a593Smuzhiyun module_exit(ftdi_elan_exit);
2791