154ebaa4747a92e1e7330c1c11d6c315a732a484
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-3.10 / 001-Add-dwc_otg-driver.patch
1 diff -urN linux-3.10/drivers/usb/core/generic.c linux-rpi-3.10.y/drivers/usb/core/generic.c
2 --- linux-3.10/drivers/usb/core/generic.c 2013-06-30 23:13:29.000000000 +0100
3 +++ linux-rpi-3.10.y/drivers/usb/core/generic.c 2013-07-06 15:25:50.000000000 +0100
4 @@ -152,6 +152,7 @@
5 dev_warn(&udev->dev,
6 "no configuration chosen from %d choice%s\n",
7 num_configs, plural(num_configs));
8 + dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
9 }
10 return i;
11 }
12 diff -urN linux-3.10/drivers/usb/core/message.c linux-rpi-3.10.y/drivers/usb/core/message.c
13 --- linux-3.10/drivers/usb/core/message.c 2013-06-30 23:13:29.000000000 +0100
14 +++ linux-rpi-3.10.y/drivers/usb/core/message.c 2013-07-06 15:25:50.000000000 +0100
15 @@ -1875,6 +1875,85 @@
16 if (cp->string == NULL &&
17 !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
18 cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
19 +/* Uncomment this define to enable the HS Electrical Test support */
20 +#define DWC_HS_ELECT_TST 1
21 +#ifdef DWC_HS_ELECT_TST
22 + /* Here we implement the HS Electrical Test support. The
23 + * tester uses a vendor ID of 0x1A0A to indicate we should
24 + * run a special test sequence. The product ID tells us
25 + * which sequence to run. We invoke the test sequence by
26 + * sending a non-standard SetFeature command to our root
27 + * hub port. Our dwc_otg_hcd_hub_control() routine will
28 + * recognize the command and perform the desired test
29 + * sequence.
30 + */
31 + if (dev->descriptor.idVendor == 0x1A0A) {
32 + /* HSOTG Electrical Test */
33 + dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
34 +
35 + if (dev->bus && dev->bus->root_hub) {
36 + struct usb_device *hdev = dev->bus->root_hub;
37 + dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
38 +
39 + switch (dev->descriptor.idProduct) {
40 + case 0x0101: /* TEST_SE0_NAK */
41 + dev_warn(&dev->dev, "TEST_SE0_NAK\n");
42 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
43 + USB_REQ_SET_FEATURE, USB_RT_PORT,
44 + USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
45 + break;
46 +
47 + case 0x0102: /* TEST_J */
48 + dev_warn(&dev->dev, "TEST_J\n");
49 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
50 + USB_REQ_SET_FEATURE, USB_RT_PORT,
51 + USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
52 + break;
53 +
54 + case 0x0103: /* TEST_K */
55 + dev_warn(&dev->dev, "TEST_K\n");
56 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
57 + USB_REQ_SET_FEATURE, USB_RT_PORT,
58 + USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
59 + break;
60 +
61 + case 0x0104: /* TEST_PACKET */
62 + dev_warn(&dev->dev, "TEST_PACKET\n");
63 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
64 + USB_REQ_SET_FEATURE, USB_RT_PORT,
65 + USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
66 + break;
67 +
68 + case 0x0105: /* TEST_FORCE_ENABLE */
69 + dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
70 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
71 + USB_REQ_SET_FEATURE, USB_RT_PORT,
72 + USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
73 + break;
74 +
75 + case 0x0106: /* HS_HOST_PORT_SUSPEND_RESUME */
76 + dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
77 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
78 + USB_REQ_SET_FEATURE, USB_RT_PORT,
79 + USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
80 + break;
81 +
82 + case 0x0107: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
83 + dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
84 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
85 + USB_REQ_SET_FEATURE, USB_RT_PORT,
86 + USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
87 + break;
88 +
89 + case 0x0108: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
90 + dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
91 + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
92 + USB_REQ_SET_FEATURE, USB_RT_PORT,
93 + USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
94 + }
95 + }
96 + }
97 +#endif /* DWC_HS_ELECT_TST */
98
99 /* Now that the interfaces are installed, re-enable LPM. */
100 usb_unlocked_enable_lpm(dev);
101 diff -urN linux-3.10/drivers/usb/core/otg_whitelist.h linux-rpi-3.10.y/drivers/usb/core/otg_whitelist.h
102 --- linux-3.10/drivers/usb/core/otg_whitelist.h 2013-06-30 23:13:29.000000000 +0100
103 +++ linux-rpi-3.10.y/drivers/usb/core/otg_whitelist.h 2013-07-06 15:25:50.000000000 +0100
104 @@ -19,33 +19,82 @@
105 static struct usb_device_id whitelist_table [] = {
106
107 /* hubs are optional in OTG, but very handy ... */
108 +#define CERT_WITHOUT_HUBS
109 +#if defined(CERT_WITHOUT_HUBS)
110 +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
111 +#else
112 { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
113 { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
114 +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
115 +#endif
116
117 #ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */
118 /* FIXME actually, printers are NOT supposed to use device classes;
119 * they're supposed to use interface classes...
120 */
121 -{ USB_DEVICE_INFO(7, 1, 1) },
122 -{ USB_DEVICE_INFO(7, 1, 2) },
123 -{ USB_DEVICE_INFO(7, 1, 3) },
124 +//{ USB_DEVICE_INFO(7, 1, 1) },
125 +//{ USB_DEVICE_INFO(7, 1, 2) },
126 +//{ USB_DEVICE_INFO(7, 1, 3) },
127 #endif
128
129 #ifdef CONFIG_USB_NET_CDCETHER
130 /* Linux-USB CDC Ethernet gadget */
131 -{ USB_DEVICE(0x0525, 0xa4a1), },
132 +//{ USB_DEVICE(0x0525, 0xa4a1), },
133 /* Linux-USB CDC Ethernet + RNDIS gadget */
134 -{ USB_DEVICE(0x0525, 0xa4a2), },
135 +//{ USB_DEVICE(0x0525, 0xa4a2), },
136 #endif
137
138 #if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
139 /* gadget zero, for testing */
140 -{ USB_DEVICE(0x0525, 0xa4a0), },
141 +//{ USB_DEVICE(0x0525, 0xa4a0), },
142 #endif
143 +
144 +/* OPT Tester */
145 +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
146 +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
147 +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
148 +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
149 +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
150 +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME */
151 +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
152 +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
153 +
154 +/* Sony cameras */
155 +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
156 +
157 +/* Memory Devices */
158 +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
159 +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
160 +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
161 +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD */
162 +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
163 +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
164 +
165 +/* HP Printers */
166 +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
167 +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
168 +
169 +/* Speakers */
170 +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
171 +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
172
173 { } /* Terminating entry */
174 };
175
176 +static inline void report_errors(struct usb_device *dev)
177 +{
178 + /* OTG MESSAGE: report errors here, customize to match your product */
179 + dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
180 + le16_to_cpu(dev->descriptor.idVendor),
181 + le16_to_cpu(dev->descriptor.idProduct));
182 + if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
183 + dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
184 + } else {
185 + dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
186 + }
187 +}
188 +
189 +
190 static int is_targeted(struct usb_device *dev)
191 {
192 struct usb_device_id *id = whitelist_table;
193 @@ -55,58 +104,83 @@
194 return 1;
195
196 /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
197 - if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
198 - le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
199 - return 0;
200 + if (dev->descriptor.idVendor == 0x1a0a &&
201 + dev->descriptor.idProduct == 0xbadd) {
202 + return 0;
203 + } else if (!enable_whitelist) {
204 + return 1;
205 + } else {
206
207 - /* NOTE: can't use usb_match_id() since interface caches
208 - * aren't set up yet. this is cut/paste from that code.
209 - */
210 - for (id = whitelist_table; id->match_flags; id++) {
211 - if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
212 - id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
213 - continue;
214 -
215 - if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
216 - id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
217 - continue;
218 -
219 - /* No need to test id->bcdDevice_lo != 0, since 0 is never
220 - greater than any unsigned number. */
221 - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
222 - (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
223 - continue;
224 -
225 - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
226 - (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
227 - continue;
228 -
229 - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
230 - (id->bDeviceClass != dev->descriptor.bDeviceClass))
231 - continue;
232 -
233 - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
234 - (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
235 - continue;
236 -
237 - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
238 - (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
239 - continue;
240 +#ifdef DEBUG
241 + dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
242 + dev->descriptor.idVendor,
243 + dev->descriptor.idProduct,
244 + dev->descriptor.bDeviceClass,
245 + dev->descriptor.bDeviceSubClass,
246 + dev->descriptor.bDeviceProtocol);
247 +#endif
248
249 return 1;
250 + /* NOTE: can't use usb_match_id() since interface caches
251 + * aren't set up yet. this is cut/paste from that code.
252 + */
253 + for (id = whitelist_table; id->match_flags; id++) {
254 +#ifdef DEBUG
255 + dev_dbg(&dev->dev,
256 + "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
257 + id->idVendor,
258 + id->idProduct,
259 + id->bDeviceClass,
260 + id->bDeviceSubClass,
261 + id->bDeviceProtocol);
262 +#endif
263 +
264 + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
265 + id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
266 + continue;
267 +
268 + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
269 + id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
270 + continue;
271 +
272 + /* No need to test id->bcdDevice_lo != 0, since 0 is never
273 + greater than any unsigned number. */
274 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
275 + (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
276 + continue;
277 +
278 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
279 + (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
280 + continue;
281 +
282 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
283 + (id->bDeviceClass != dev->descriptor.bDeviceClass))
284 + continue;
285 +
286 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
287 + (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
288 + continue;
289 +
290 + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
291 + (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
292 + continue;
293 +
294 + return 1;
295 + }
296 }
297
298 /* add other match criteria here ... */
299
300 -
301 - /* OTG MESSAGE: report errors here, customize to match your product */
302 - dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
303 - le16_to_cpu(dev->descriptor.idVendor),
304 - le16_to_cpu(dev->descriptor.idProduct));
305 #ifdef CONFIG_USB_OTG_WHITELIST
306 + report_errors(dev);
307 return 0;
308 #else
309 - return 1;
310 + if (enable_whitelist) {
311 + report_errors(dev);
312 + return 0;
313 + } else {
314 + return 1;
315 + }
316 #endif
317 }
318
319 diff -urN linux-3.10/drivers/usb/gadget/file_storage.c linux-rpi-3.10.y/drivers/usb/gadget/file_storage.c
320 --- linux-3.10/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100
321 +++ linux-rpi-3.10.y/drivers/usb/gadget/file_storage.c 2013-07-06 15:25:50.000000000 +0100
322 @@ -0,0 +1,3676 @@
323 +/*
324 + * file_storage.c -- File-backed USB Storage Gadget, for USB development
325 + *
326 + * Copyright (C) 2003-2008 Alan Stern
327 + * All rights reserved.
328 + *
329 + * Redistribution and use in source and binary forms, with or without
330 + * modification, are permitted provided that the following conditions
331 + * are met:
332 + * 1. Redistributions of source code must retain the above copyright
333 + * notice, this list of conditions, and the following disclaimer,
334 + * without modification.
335 + * 2. Redistributions in binary form must reproduce the above copyright
336 + * notice, this list of conditions and the following disclaimer in the
337 + * documentation and/or other materials provided with the distribution.
338 + * 3. The names of the above-listed copyright holders may not be used
339 + * to endorse or promote products derived from this software without
340 + * specific prior written permission.
341 + *
342 + * ALTERNATIVELY, this software may be distributed under the terms of the
343 + * GNU General Public License ("GPL") as published by the Free Software
344 + * Foundation, either version 2 of that License or (at your option) any
345 + * later version.
346 + *
347 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
348 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
349 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
350 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
351 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
352 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
353 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
354 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
355 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
356 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
357 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
358 + */
359 +
360 +
361 +/*
362 + * The File-backed Storage Gadget acts as a USB Mass Storage device,
363 + * appearing to the host as a disk drive or as a CD-ROM drive. In addition
364 + * to providing an example of a genuinely useful gadget driver for a USB
365 + * device, it also illustrates a technique of double-buffering for increased
366 + * throughput. Last but not least, it gives an easy way to probe the
367 + * behavior of the Mass Storage drivers in a USB host.
368 + *
369 + * Backing storage is provided by a regular file or a block device, specified
370 + * by the "file" module parameter. Access can be limited to read-only by
371 + * setting the optional "ro" module parameter. (For CD-ROM emulation,
372 + * access is always read-only.) The gadget will indicate that it has
373 + * removable media if the optional "removable" module parameter is set.
374 + *
375 + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
376 + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
377 + * by the optional "transport" module parameter. It also supports the
378 + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
379 + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
380 + * the optional "protocol" module parameter. In addition, the default
381 + * Vendor ID, Product ID, release number and serial number can be overridden.
382 + *
383 + * There is support for multiple logical units (LUNs), each of which has
384 + * its own backing file. The number of LUNs can be set using the optional
385 + * "luns" module parameter (anywhere from 1 to 8), and the corresponding
386 + * files are specified using comma-separated lists for "file" and "ro".
387 + * The default number of LUNs is taken from the number of "file" elements;
388 + * it is 1 if "file" is not given. If "removable" is not set then a backing
389 + * file must be specified for each LUN. If it is set, then an unspecified
390 + * or empty backing filename means the LUN's medium is not loaded. Ideally
391 + * each LUN would be settable independently as a disk drive or a CD-ROM
392 + * drive, but currently all LUNs have to be the same type. The CD-ROM
393 + * emulation includes a single data track and no audio tracks; hence there
394 + * need be only one backing file per LUN.
395 + *
396 + * Requirements are modest; only a bulk-in and a bulk-out endpoint are
397 + * needed (an interrupt-out endpoint is also needed for CBI). The memory
398 + * requirement amounts to two 16K buffers, size configurable by a parameter.
399 + * Support is included for both full-speed and high-speed operation.
400 + *
401 + * Note that the driver is slightly non-portable in that it assumes a
402 + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
403 + * interrupt-in endpoints. With most device controllers this isn't an
404 + * issue, but there may be some with hardware restrictions that prevent
405 + * a buffer from being used by more than one endpoint.
406 + *
407 + * Module options:
408 + *
409 + * file=filename[,filename...]
410 + * Required if "removable" is not set, names of
411 + * the files or block devices used for
412 + * backing storage
413 + * serial=HHHH... Required serial number (string of hex chars)
414 + * ro=b[,b...] Default false, booleans for read-only access
415 + * removable Default false, boolean for removable media
416 + * luns=N Default N = number of filenames, number of
417 + * LUNs to support
418 + * nofua=b[,b...] Default false, booleans for ignore FUA flag
419 + * in SCSI WRITE(10,12) commands
420 + * stall Default determined according to the type of
421 + * USB device controller (usually true),
422 + * boolean to permit the driver to halt
423 + * bulk endpoints
424 + * cdrom Default false, boolean for whether to emulate
425 + * a CD-ROM drive
426 + * transport=XXX Default BBB, transport name (CB, CBI, or BBB)
427 + * protocol=YYY Default SCSI, protocol name (RBC, 8020 or
428 + * ATAPI, QIC, UFI, 8070, or SCSI;
429 + * also 1 - 6)
430 + * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID
431 + * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID
432 + * release=0xRRRR Override the USB release number (bcdDevice)
433 + * buflen=N Default N=16384, buffer size used (will be
434 + * rounded down to a multiple of
435 + * PAGE_CACHE_SIZE)
436 + *
437 + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
438 + * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
439 + * default values are used for everything else.
440 + *
441 + * The pathnames of the backing files and the ro settings are available in
442 + * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
443 + * the gadget's sysfs directory. If the "removable" option is set, writing to
444 + * these files will simulate ejecting/loading the medium (writing an empty
445 + * line means eject) and adjusting a write-enable tab. Changes to the ro
446 + * setting are not allowed when the medium is loaded or if CD-ROM emulation
447 + * is being used.
448 + *
449 + * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
450 + * The driver's SCSI command interface was based on the "Information
451 + * technology - Small Computer System Interface - 2" document from
452 + * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
453 + * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
454 + * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
455 + * "Universal Serial Bus Mass Storage Class UFI Command Specification"
456 + * document, Revision 1.0, December 14, 1998, available at
457 + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
458 + */
459 +
460 +
461 +/*
462 + * Driver Design
463 + *
464 + * The FSG driver is fairly straightforward. There is a main kernel
465 + * thread that handles most of the work. Interrupt routines field
466 + * callbacks from the controller driver: bulk- and interrupt-request
467 + * completion notifications, endpoint-0 events, and disconnect events.
468 + * Completion events are passed to the main thread by wakeup calls. Many
469 + * ep0 requests are handled at interrupt time, but SetInterface,
470 + * SetConfiguration, and device reset requests are forwarded to the
471 + * thread in the form of "exceptions" using SIGUSR1 signals (since they
472 + * should interrupt any ongoing file I/O operations).
473 + *
474 + * The thread's main routine implements the standard command/data/status
475 + * parts of a SCSI interaction. It and its subroutines are full of tests
476 + * for pending signals/exceptions -- all this polling is necessary since
477 + * the kernel has no setjmp/longjmp equivalents. (Maybe this is an
478 + * indication that the driver really wants to be running in userspace.)
479 + * An important point is that so long as the thread is alive it keeps an
480 + * open reference to the backing file. This will prevent unmounting
481 + * the backing file's underlying filesystem and could cause problems
482 + * during system shutdown, for example. To prevent such problems, the
483 + * thread catches INT, TERM, and KILL signals and converts them into
484 + * an EXIT exception.
485 + *
486 + * In normal operation the main thread is started during the gadget's
487 + * fsg_bind() callback and stopped during fsg_unbind(). But it can also
488 + * exit when it receives a signal, and there's no point leaving the
489 + * gadget running when the thread is dead. So just before the thread
490 + * exits, it deregisters the gadget driver. This makes things a little
491 + * tricky: The driver is deregistered at two places, and the exiting
492 + * thread can indirectly call fsg_unbind() which in turn can tell the
493 + * thread to exit. The first problem is resolved through the use of the
494 + * REGISTERED atomic bitflag; the driver will only be deregistered once.
495 + * The second problem is resolved by having fsg_unbind() check
496 + * fsg->state; it won't try to stop the thread if the state is already
497 + * FSG_STATE_TERMINATED.
498 + *
499 + * To provide maximum throughput, the driver uses a circular pipeline of
500 + * buffer heads (struct fsg_buffhd). In principle the pipeline can be
501 + * arbitrarily long; in practice the benefits don't justify having more
502 + * than 2 stages (i.e., double buffering). But it helps to think of the
503 + * pipeline as being a long one. Each buffer head contains a bulk-in and
504 + * a bulk-out request pointer (since the buffer can be used for both
505 + * output and input -- directions always are given from the host's
506 + * point of view) as well as a pointer to the buffer and various state
507 + * variables.
508 + *
509 + * Use of the pipeline follows a simple protocol. There is a variable
510 + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
511 + * At any time that buffer head may still be in use from an earlier
512 + * request, so each buffer head has a state variable indicating whether
513 + * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the
514 + * buffer head to be EMPTY, filling the buffer either by file I/O or by
515 + * USB I/O (during which the buffer head is BUSY), and marking the buffer
516 + * head FULL when the I/O is complete. Then the buffer will be emptied
517 + * (again possibly by USB I/O, during which it is marked BUSY) and
518 + * finally marked EMPTY again (possibly by a completion routine).
519 + *
520 + * A module parameter tells the driver to avoid stalling the bulk
521 + * endpoints wherever the transport specification allows. This is
522 + * necessary for some UDCs like the SuperH, which cannot reliably clear a
523 + * halt on a bulk endpoint. However, under certain circumstances the
524 + * Bulk-only specification requires a stall. In such cases the driver
525 + * will halt the endpoint and set a flag indicating that it should clear
526 + * the halt in software during the next device reset. Hopefully this
527 + * will permit everything to work correctly. Furthermore, although the
528 + * specification allows the bulk-out endpoint to halt when the host sends
529 + * too much data, implementing this would cause an unavoidable race.
530 + * The driver will always use the "no-stall" approach for OUT transfers.
531 + *
532 + * One subtle point concerns sending status-stage responses for ep0
533 + * requests. Some of these requests, such as device reset, can involve
534 + * interrupting an ongoing file I/O operation, which might take an
535 + * arbitrarily long time. During that delay the host might give up on
536 + * the original ep0 request and issue a new one. When that happens the
537 + * driver should not notify the host about completion of the original
538 + * request, as the host will no longer be waiting for it. So the driver
539 + * assigns to each ep0 request a unique tag, and it keeps track of the
540 + * tag value of the request associated with a long-running exception
541 + * (device-reset, interface-change, or configuration-change). When the
542 + * exception handler is finished, the status-stage response is submitted
543 + * only if the current ep0 request tag is equal to the exception request
544 + * tag. Thus only the most recently received ep0 request will get a
545 + * status-stage response.
546 + *
547 + * Warning: This driver source file is too long. It ought to be split up
548 + * into a header file plus about 3 separate .c files, to handle the details
549 + * of the Gadget, USB Mass Storage, and SCSI protocols.
550 + */
551 +
552 +
553 +/* #define VERBOSE_DEBUG */
554 +/* #define DUMP_MSGS */
555 +
556 +
557 +#include <linux/blkdev.h>
558 +#include <linux/completion.h>
559 +#include <linux/dcache.h>
560 +#include <linux/delay.h>
561 +#include <linux/device.h>
562 +#include <linux/fcntl.h>
563 +#include <linux/file.h>
564 +#include <linux/fs.h>
565 +#include <linux/kref.h>
566 +#include <linux/kthread.h>
567 +#include <linux/limits.h>
568 +#include <linux/module.h>
569 +#include <linux/rwsem.h>
570 +#include <linux/slab.h>
571 +#include <linux/spinlock.h>
572 +#include <linux/string.h>
573 +#include <linux/freezer.h>
574 +#include <linux/utsname.h>
575 +
576 +#include <linux/usb/ch9.h>
577 +#include <linux/usb/gadget.h>
578 +
579 +#include "gadget_chips.h"
580 +
581 +
582 +
583 +/*
584 + * Kbuild is not very cooperative with respect to linking separately
585 + * compiled library objects into one module. So for now we won't use
586 + * separate compilation ... ensuring init/exit sections work to shrink
587 + * the runtime footprint, and giving us at least some parts of what
588 + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
589 + */
590 +#include "usbstring.c"
591 +#include "config.c"
592 +#include "epautoconf.c"
593 +
594 +/*-------------------------------------------------------------------------*/
595 +
596 +#define DRIVER_DESC "File-backed Storage Gadget"
597 +#define DRIVER_NAME "g_file_storage"
598 +#define DRIVER_VERSION "1 September 2010"
599 +
600 +static char fsg_string_manufacturer[64];
601 +static const char fsg_string_product[] = DRIVER_DESC;
602 +static const char fsg_string_config[] = "Self-powered";
603 +static const char fsg_string_interface[] = "Mass Storage";
604 +
605 +
606 +#include "storage_common.c"
607 +
608 +
609 +MODULE_DESCRIPTION(DRIVER_DESC);
610 +MODULE_AUTHOR("Alan Stern");
611 +MODULE_LICENSE("Dual BSD/GPL");
612 +
613 +/*
614 + * This driver assumes self-powered hardware and has no way for users to
615 + * trigger remote wakeup. It uses autoconfiguration to select endpoints
616 + * and endpoint addresses.
617 + */
618 +
619 +
620 +/*-------------------------------------------------------------------------*/
621 +
622 +
623 +/* Encapsulate the module parameter settings */
624 +
625 +static struct {
626 + char *file[FSG_MAX_LUNS];
627 + char *serial;
628 + bool ro[FSG_MAX_LUNS];
629 + bool nofua[FSG_MAX_LUNS];
630 + unsigned int num_filenames;
631 + unsigned int num_ros;
632 + unsigned int num_nofuas;
633 + unsigned int nluns;
634 +
635 + bool removable;
636 + bool can_stall;
637 + bool cdrom;
638 +
639 + char *transport_parm;
640 + char *protocol_parm;
641 + unsigned short vendor;
642 + unsigned short product;
643 + unsigned short release;
644 + unsigned int buflen;
645 +
646 + int transport_type;
647 + char *transport_name;
648 + int protocol_type;
649 + char *protocol_name;
650 +
651 +} mod_data = { // Default values
652 + .transport_parm = "BBB",
653 + .protocol_parm = "SCSI",
654 + .removable = 0,
655 + .can_stall = 1,
656 + .cdrom = 0,
657 + .vendor = FSG_VENDOR_ID,
658 + .product = FSG_PRODUCT_ID,
659 + .release = 0xffff, // Use controller chip type
660 + .buflen = 16384,
661 + };
662 +
663 +
664 +module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
665 + S_IRUGO);
666 +MODULE_PARM_DESC(file, "names of backing files or devices");
667 +
668 +module_param_named(serial, mod_data.serial, charp, S_IRUGO);
669 +MODULE_PARM_DESC(serial, "USB serial number");
670 +
671 +module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
672 +MODULE_PARM_DESC(ro, "true to force read-only");
673 +
674 +module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
675 + S_IRUGO);
676 +MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
677 +
678 +module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
679 +MODULE_PARM_DESC(luns, "number of LUNs");
680 +
681 +module_param_named(removable, mod_data.removable, bool, S_IRUGO);
682 +MODULE_PARM_DESC(removable, "true to simulate removable media");
683 +
684 +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
685 +MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
686 +
687 +module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
688 +MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
689 +
690 +/* In the non-TEST version, only the module parameters listed above
691 + * are available. */
692 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
693 +
694 +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
695 +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
696 +
697 +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
698 +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
699 + "8070, or SCSI)");
700 +
701 +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
702 +MODULE_PARM_DESC(vendor, "USB Vendor ID");
703 +
704 +module_param_named(product, mod_data.product, ushort, S_IRUGO);
705 +MODULE_PARM_DESC(product, "USB Product ID");
706 +
707 +module_param_named(release, mod_data.release, ushort, S_IRUGO);
708 +MODULE_PARM_DESC(release, "USB release number");
709 +
710 +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
711 +MODULE_PARM_DESC(buflen, "I/O buffer size");
712 +
713 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
714 +
715 +
716 +/*
717 + * These definitions will permit the compiler to avoid generating code for
718 + * parts of the driver that aren't used in the non-TEST version. Even gcc
719 + * can recognize when a test of a constant expression yields a dead code
720 + * path.
721 + */
722 +
723 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
724 +
725 +#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK)
726 +#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI)
727 +#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI)
728 +
729 +#else
730 +
731 +#define transport_is_bbb() 1
732 +#define transport_is_cbi() 0
733 +#define protocol_is_scsi() 1
734 +
735 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
736 +
737 +
738 +/*-------------------------------------------------------------------------*/
739 +
740 +
741 +struct fsg_dev {
742 + /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
743 + spinlock_t lock;
744 + struct usb_gadget *gadget;
745 +
746 + /* filesem protects: backing files in use */
747 + struct rw_semaphore filesem;
748 +
749 + /* reference counting: wait until all LUNs are released */
750 + struct kref ref;
751 +
752 + struct usb_ep *ep0; // Handy copy of gadget->ep0
753 + struct usb_request *ep0req; // For control responses
754 + unsigned int ep0_req_tag;
755 + const char *ep0req_name;
756 +
757 + struct usb_request *intreq; // For interrupt responses
758 + int intreq_busy;
759 + struct fsg_buffhd *intr_buffhd;
760 +
761 + unsigned int bulk_out_maxpacket;
762 + enum fsg_state state; // For exception handling
763 + unsigned int exception_req_tag;
764 +
765 + u8 config, new_config;
766 +
767 + unsigned int running : 1;
768 + unsigned int bulk_in_enabled : 1;
769 + unsigned int bulk_out_enabled : 1;
770 + unsigned int intr_in_enabled : 1;
771 + unsigned int phase_error : 1;
772 + unsigned int short_packet_received : 1;
773 + unsigned int bad_lun_okay : 1;
774 +
775 + unsigned long atomic_bitflags;
776 +#define REGISTERED 0
777 +#define IGNORE_BULK_OUT 1
778 +#define SUSPENDED 2
779 +
780 + struct usb_ep *bulk_in;
781 + struct usb_ep *bulk_out;
782 + struct usb_ep *intr_in;
783 +
784 + struct fsg_buffhd *next_buffhd_to_fill;
785 + struct fsg_buffhd *next_buffhd_to_drain;
786 +
787 + int thread_wakeup_needed;
788 + struct completion thread_notifier;
789 + struct task_struct *thread_task;
790 +
791 + int cmnd_size;
792 + u8 cmnd[MAX_COMMAND_SIZE];
793 + enum data_direction data_dir;
794 + u32 data_size;
795 + u32 data_size_from_cmnd;
796 + u32 tag;
797 + unsigned int lun;
798 + u32 residue;
799 + u32 usb_amount_left;
800 +
801 + /* The CB protocol offers no way for a host to know when a command
802 + * has completed. As a result the next command may arrive early,
803 + * and we will still have to handle it. For that reason we need
804 + * a buffer to store new commands when using CB (or CBI, which
805 + * does not oblige a host to wait for command completion either). */
806 + int cbbuf_cmnd_size;
807 + u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
808 +
809 + unsigned int nluns;
810 + struct fsg_lun *luns;
811 + struct fsg_lun *curlun;
812 + /* Must be the last entry */
813 + struct fsg_buffhd buffhds[];
814 +};
815 +
816 +typedef void (*fsg_routine_t)(struct fsg_dev *);
817 +
818 +static int exception_in_progress(struct fsg_dev *fsg)
819 +{
820 + return (fsg->state > FSG_STATE_IDLE);
821 +}
822 +
823 +/* Make bulk-out requests be divisible by the maxpacket size */
824 +static void set_bulk_out_req_length(struct fsg_dev *fsg,
825 + struct fsg_buffhd *bh, unsigned int length)
826 +{
827 + unsigned int rem;
828 +
829 + bh->bulk_out_intended_length = length;
830 + rem = length % fsg->bulk_out_maxpacket;
831 + if (rem > 0)
832 + length += fsg->bulk_out_maxpacket - rem;
833 + bh->outreq->length = length;
834 +}
835 +
836 +static struct fsg_dev *the_fsg;
837 +static struct usb_gadget_driver fsg_driver;
838 +
839 +
840 +/*-------------------------------------------------------------------------*/
841 +
842 +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
843 +{
844 + const char *name;
845 +
846 + if (ep == fsg->bulk_in)
847 + name = "bulk-in";
848 + else if (ep == fsg->bulk_out)
849 + name = "bulk-out";
850 + else
851 + name = ep->name;
852 + DBG(fsg, "%s set halt\n", name);
853 + return usb_ep_set_halt(ep);
854 +}
855 +
856 +
857 +/*-------------------------------------------------------------------------*/
858 +
859 +/*
860 + * DESCRIPTORS ... most are static, but strings and (full) configuration
861 + * descriptors are built on demand. Also the (static) config and interface
862 + * descriptors are adjusted during fsg_bind().
863 + */
864 +
865 +/* There is only one configuration. */
866 +#define CONFIG_VALUE 1
867 +
868 +static struct usb_device_descriptor
869 +device_desc = {
870 + .bLength = sizeof device_desc,
871 + .bDescriptorType = USB_DT_DEVICE,
872 +
873 + .bcdUSB = cpu_to_le16(0x0200),
874 + .bDeviceClass = USB_CLASS_PER_INTERFACE,
875 +
876 + /* The next three values can be overridden by module parameters */
877 + .idVendor = cpu_to_le16(FSG_VENDOR_ID),
878 + .idProduct = cpu_to_le16(FSG_PRODUCT_ID),
879 + .bcdDevice = cpu_to_le16(0xffff),
880 +
881 + .iManufacturer = FSG_STRING_MANUFACTURER,
882 + .iProduct = FSG_STRING_PRODUCT,
883 + .iSerialNumber = FSG_STRING_SERIAL,
884 + .bNumConfigurations = 1,
885 +};
886 +
887 +static struct usb_config_descriptor
888 +config_desc = {
889 + .bLength = sizeof config_desc,
890 + .bDescriptorType = USB_DT_CONFIG,
891 +
892 + /* wTotalLength computed by usb_gadget_config_buf() */
893 + .bNumInterfaces = 1,
894 + .bConfigurationValue = CONFIG_VALUE,
895 + .iConfiguration = FSG_STRING_CONFIG,
896 + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
897 + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
898 +};
899 +
900 +
901 +static struct usb_qualifier_descriptor
902 +dev_qualifier = {
903 + .bLength = sizeof dev_qualifier,
904 + .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
905 +
906 + .bcdUSB = cpu_to_le16(0x0200),
907 + .bDeviceClass = USB_CLASS_PER_INTERFACE,
908 +
909 + .bNumConfigurations = 1,
910 +};
911 +
912 +static int populate_bos(struct fsg_dev *fsg, u8 *buf)
913 +{
914 + memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
915 + buf += USB_DT_BOS_SIZE;
916 +
917 + memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
918 + buf += USB_DT_USB_EXT_CAP_SIZE;
919 +
920 + memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
921 +
922 + return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
923 + + USB_DT_USB_EXT_CAP_SIZE;
924 +}
925 +
926 +/*
927 + * Config descriptors must agree with the code that sets configurations
928 + * and with code managing interfaces and their altsettings. They must
929 + * also handle different speeds and other-speed requests.
930 + */
931 +static int populate_config_buf(struct usb_gadget *gadget,
932 + u8 *buf, u8 type, unsigned index)
933 +{
934 + enum usb_device_speed speed = gadget->speed;
935 + int len;
936 + const struct usb_descriptor_header **function;
937 +
938 + if (index > 0)
939 + return -EINVAL;
940 +
941 + if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
942 + speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
943 + function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
944 + ? (const struct usb_descriptor_header **)fsg_hs_function
945 + : (const struct usb_descriptor_header **)fsg_fs_function;
946 +
947 + /* for now, don't advertise srp-only devices */
948 + if (!gadget_is_otg(gadget))
949 + function++;
950 +
951 + len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
952 + ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
953 + return len;
954 +}
955 +
956 +
957 +/*-------------------------------------------------------------------------*/
958 +
959 +/* These routines may be called in process context or in_irq */
960 +
961 +/* Caller must hold fsg->lock */
962 +static void wakeup_thread(struct fsg_dev *fsg)
963 +{
964 + /* Tell the main thread that something has happened */
965 + fsg->thread_wakeup_needed = 1;
966 + if (fsg->thread_task)
967 + wake_up_process(fsg->thread_task);
968 +}
969 +
970 +
971 +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
972 +{
973 + unsigned long flags;
974 +
975 + /* Do nothing if a higher-priority exception is already in progress.
976 + * If a lower-or-equal priority exception is in progress, preempt it
977 + * and notify the main thread by sending it a signal. */
978 + spin_lock_irqsave(&fsg->lock, flags);
979 + if (fsg->state <= new_state) {
980 + fsg->exception_req_tag = fsg->ep0_req_tag;
981 + fsg->state = new_state;
982 + if (fsg->thread_task)
983 + send_sig_info(SIGUSR1, SEND_SIG_FORCED,
984 + fsg->thread_task);
985 + }
986 + spin_unlock_irqrestore(&fsg->lock, flags);
987 +}
988 +
989 +
990 +/*-------------------------------------------------------------------------*/
991 +
992 +/* The disconnect callback and ep0 routines. These always run in_irq,
993 + * except that ep0_queue() is called in the main thread to acknowledge
994 + * completion of various requests: set config, set interface, and
995 + * Bulk-only device reset. */
996 +
997 +static void fsg_disconnect(struct usb_gadget *gadget)
998 +{
999 + struct fsg_dev *fsg = get_gadget_data(gadget);
1000 +
1001 + DBG(fsg, "disconnect or port reset\n");
1002 + raise_exception(fsg, FSG_STATE_DISCONNECT);
1003 +}
1004 +
1005 +
1006 +static int ep0_queue(struct fsg_dev *fsg)
1007 +{
1008 + int rc;
1009 +
1010 + rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
1011 + if (rc != 0 && rc != -ESHUTDOWN) {
1012 +
1013 + /* We can't do much more than wait for a reset */
1014 + WARNING(fsg, "error in submission: %s --> %d\n",
1015 + fsg->ep0->name, rc);
1016 + }
1017 + return rc;
1018 +}
1019 +
1020 +static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
1021 +{
1022 + struct fsg_dev *fsg = ep->driver_data;
1023 +
1024 + if (req->actual > 0)
1025 + dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
1026 + if (req->status || req->actual != req->length)
1027 + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1028 + req->status, req->actual, req->length);
1029 + if (req->status == -ECONNRESET) // Request was cancelled
1030 + usb_ep_fifo_flush(ep);
1031 +
1032 + if (req->status == 0 && req->context)
1033 + ((fsg_routine_t) (req->context))(fsg);
1034 +}
1035 +
1036 +
1037 +/*-------------------------------------------------------------------------*/
1038 +
1039 +/* Bulk and interrupt endpoint completion handlers.
1040 + * These always run in_irq. */
1041 +
1042 +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
1043 +{
1044 + struct fsg_dev *fsg = ep->driver_data;
1045 + struct fsg_buffhd *bh = req->context;
1046 +
1047 + if (req->status || req->actual != req->length)
1048 + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1049 + req->status, req->actual, req->length);
1050 + if (req->status == -ECONNRESET) // Request was cancelled
1051 + usb_ep_fifo_flush(ep);
1052 +
1053 + /* Hold the lock while we update the request and buffer states */
1054 + smp_wmb();
1055 + spin_lock(&fsg->lock);
1056 + bh->inreq_busy = 0;
1057 + bh->state = BUF_STATE_EMPTY;
1058 + wakeup_thread(fsg);
1059 + spin_unlock(&fsg->lock);
1060 +}
1061 +
1062 +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
1063 +{
1064 + struct fsg_dev *fsg = ep->driver_data;
1065 + struct fsg_buffhd *bh = req->context;
1066 +
1067 + dump_msg(fsg, "bulk-out", req->buf, req->actual);
1068 + if (req->status || req->actual != bh->bulk_out_intended_length)
1069 + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1070 + req->status, req->actual,
1071 + bh->bulk_out_intended_length);
1072 + if (req->status == -ECONNRESET) // Request was cancelled
1073 + usb_ep_fifo_flush(ep);
1074 +
1075 + /* Hold the lock while we update the request and buffer states */
1076 + smp_wmb();
1077 + spin_lock(&fsg->lock);
1078 + bh->outreq_busy = 0;
1079 + bh->state = BUF_STATE_FULL;
1080 + wakeup_thread(fsg);
1081 + spin_unlock(&fsg->lock);
1082 +}
1083 +
1084 +
1085 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1086 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1087 +{
1088 + struct fsg_dev *fsg = ep->driver_data;
1089 + struct fsg_buffhd *bh = req->context;
1090 +
1091 + if (req->status || req->actual != req->length)
1092 + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1093 + req->status, req->actual, req->length);
1094 + if (req->status == -ECONNRESET) // Request was cancelled
1095 + usb_ep_fifo_flush(ep);
1096 +
1097 + /* Hold the lock while we update the request and buffer states */
1098 + smp_wmb();
1099 + spin_lock(&fsg->lock);
1100 + fsg->intreq_busy = 0;
1101 + bh->state = BUF_STATE_EMPTY;
1102 + wakeup_thread(fsg);
1103 + spin_unlock(&fsg->lock);
1104 +}
1105 +
1106 +#else
1107 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1108 +{}
1109 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1110 +
1111 +
1112 +/*-------------------------------------------------------------------------*/
1113 +
1114 +/* Ep0 class-specific handlers. These always run in_irq. */
1115 +
1116 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1117 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1118 +{
1119 + struct usb_request *req = fsg->ep0req;
1120 + static u8 cbi_reset_cmnd[6] = {
1121 + SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
1122 +
1123 + /* Error in command transfer? */
1124 + if (req->status || req->length != req->actual ||
1125 + req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
1126 +
1127 + /* Not all controllers allow a protocol stall after
1128 + * receiving control-out data, but we'll try anyway. */
1129 + fsg_set_halt(fsg, fsg->ep0);
1130 + return; // Wait for reset
1131 + }
1132 +
1133 + /* Is it the special reset command? */
1134 + if (req->actual >= sizeof cbi_reset_cmnd &&
1135 + memcmp(req->buf, cbi_reset_cmnd,
1136 + sizeof cbi_reset_cmnd) == 0) {
1137 +
1138 + /* Raise an exception to stop the current operation
1139 + * and reinitialize our state. */
1140 + DBG(fsg, "cbi reset request\n");
1141 + raise_exception(fsg, FSG_STATE_RESET);
1142 + return;
1143 + }
1144 +
1145 + VDBG(fsg, "CB[I] accept device-specific command\n");
1146 + spin_lock(&fsg->lock);
1147 +
1148 + /* Save the command for later */
1149 + if (fsg->cbbuf_cmnd_size)
1150 + WARNING(fsg, "CB[I] overwriting previous command\n");
1151 + fsg->cbbuf_cmnd_size = req->actual;
1152 + memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
1153 +
1154 + wakeup_thread(fsg);
1155 + spin_unlock(&fsg->lock);
1156 +}
1157 +
1158 +#else
1159 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1160 +{}
1161 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1162 +
1163 +
1164 +static int class_setup_req(struct fsg_dev *fsg,
1165 + const struct usb_ctrlrequest *ctrl)
1166 +{
1167 + struct usb_request *req = fsg->ep0req;
1168 + int value = -EOPNOTSUPP;
1169 + u16 w_index = le16_to_cpu(ctrl->wIndex);
1170 + u16 w_value = le16_to_cpu(ctrl->wValue);
1171 + u16 w_length = le16_to_cpu(ctrl->wLength);
1172 +
1173 + if (!fsg->config)
1174 + return value;
1175 +
1176 + /* Handle Bulk-only class-specific requests */
1177 + if (transport_is_bbb()) {
1178 + switch (ctrl->bRequest) {
1179 +
1180 + case US_BULK_RESET_REQUEST:
1181 + if (ctrl->bRequestType != (USB_DIR_OUT |
1182 + USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1183 + break;
1184 + if (w_index != 0 || w_value != 0 || w_length != 0) {
1185 + value = -EDOM;
1186 + break;
1187 + }
1188 +
1189 + /* Raise an exception to stop the current operation
1190 + * and reinitialize our state. */
1191 + DBG(fsg, "bulk reset request\n");
1192 + raise_exception(fsg, FSG_STATE_RESET);
1193 + value = DELAYED_STATUS;
1194 + break;
1195 +
1196 + case US_BULK_GET_MAX_LUN:
1197 + if (ctrl->bRequestType != (USB_DIR_IN |
1198 + USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1199 + break;
1200 + if (w_index != 0 || w_value != 0 || w_length != 1) {
1201 + value = -EDOM;
1202 + break;
1203 + }
1204 + VDBG(fsg, "get max LUN\n");
1205 + *(u8 *) req->buf = fsg->nluns - 1;
1206 + value = 1;
1207 + break;
1208 + }
1209 + }
1210 +
1211 + /* Handle CBI class-specific requests */
1212 + else {
1213 + switch (ctrl->bRequest) {
1214 +
1215 + case USB_CBI_ADSC_REQUEST:
1216 + if (ctrl->bRequestType != (USB_DIR_OUT |
1217 + USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1218 + break;
1219 + if (w_index != 0 || w_value != 0) {
1220 + value = -EDOM;
1221 + break;
1222 + }
1223 + if (w_length > MAX_COMMAND_SIZE) {
1224 + value = -EOVERFLOW;
1225 + break;
1226 + }
1227 + value = w_length;
1228 + fsg->ep0req->context = received_cbi_adsc;
1229 + break;
1230 + }
1231 + }
1232 +
1233 + if (value == -EOPNOTSUPP)
1234 + VDBG(fsg,
1235 + "unknown class-specific control req "
1236 + "%02x.%02x v%04x i%04x l%u\n",
1237 + ctrl->bRequestType, ctrl->bRequest,
1238 + le16_to_cpu(ctrl->wValue), w_index, w_length);
1239 + return value;
1240 +}
1241 +
1242 +
1243 +/*-------------------------------------------------------------------------*/
1244 +
1245 +/* Ep0 standard request handlers. These always run in_irq. */
1246 +
1247 +static int standard_setup_req(struct fsg_dev *fsg,
1248 + const struct usb_ctrlrequest *ctrl)
1249 +{
1250 + struct usb_request *req = fsg->ep0req;
1251 + int value = -EOPNOTSUPP;
1252 + u16 w_index = le16_to_cpu(ctrl->wIndex);
1253 + u16 w_value = le16_to_cpu(ctrl->wValue);
1254 +
1255 + /* Usually this just stores reply data in the pre-allocated ep0 buffer,
1256 + * but config change events will also reconfigure hardware. */
1257 + switch (ctrl->bRequest) {
1258 +
1259 + case USB_REQ_GET_DESCRIPTOR:
1260 + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1261 + USB_RECIP_DEVICE))
1262 + break;
1263 + switch (w_value >> 8) {
1264 +
1265 + case USB_DT_DEVICE:
1266 + VDBG(fsg, "get device descriptor\n");
1267 + device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
1268 + value = sizeof device_desc;
1269 + memcpy(req->buf, &device_desc, value);
1270 + break;
1271 + case USB_DT_DEVICE_QUALIFIER:
1272 + VDBG(fsg, "get device qualifier\n");
1273 + if (!gadget_is_dualspeed(fsg->gadget) ||
1274 + fsg->gadget->speed == USB_SPEED_SUPER)
1275 + break;
1276 + /*
1277 + * Assume ep0 uses the same maxpacket value for both
1278 + * speeds
1279 + */
1280 + dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
1281 + value = sizeof dev_qualifier;
1282 + memcpy(req->buf, &dev_qualifier, value);
1283 + break;
1284 +
1285 + case USB_DT_OTHER_SPEED_CONFIG:
1286 + VDBG(fsg, "get other-speed config descriptor\n");
1287 + if (!gadget_is_dualspeed(fsg->gadget) ||
1288 + fsg->gadget->speed == USB_SPEED_SUPER)
1289 + break;
1290 + goto get_config;
1291 + case USB_DT_CONFIG:
1292 + VDBG(fsg, "get configuration descriptor\n");
1293 +get_config:
1294 + value = populate_config_buf(fsg->gadget,
1295 + req->buf,
1296 + w_value >> 8,
1297 + w_value & 0xff);
1298 + break;
1299 +
1300 + case USB_DT_STRING:
1301 + VDBG(fsg, "get string descriptor\n");
1302 +
1303 + /* wIndex == language code */
1304 + value = usb_gadget_get_string(&fsg_stringtab,
1305 + w_value & 0xff, req->buf);
1306 + break;
1307 +
1308 + case USB_DT_BOS:
1309 + VDBG(fsg, "get bos descriptor\n");
1310 +
1311 + if (gadget_is_superspeed(fsg->gadget))
1312 + value = populate_bos(fsg, req->buf);
1313 + break;
1314 + }
1315 +
1316 + break;
1317 +
1318 + /* One config, two speeds */
1319 + case USB_REQ_SET_CONFIGURATION:
1320 + if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
1321 + USB_RECIP_DEVICE))
1322 + break;
1323 + VDBG(fsg, "set configuration\n");
1324 + if (w_value == CONFIG_VALUE || w_value == 0) {
1325 + fsg->new_config = w_value;
1326 +
1327 + /* Raise an exception to wipe out previous transaction
1328 + * state (queued bufs, etc) and set the new config. */
1329 + raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
1330 + value = DELAYED_STATUS;
1331 + }
1332 + break;
1333 + case USB_REQ_GET_CONFIGURATION:
1334 + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1335 + USB_RECIP_DEVICE))
1336 + break;
1337 + VDBG(fsg, "get configuration\n");
1338 + *(u8 *) req->buf = fsg->config;
1339 + value = 1;
1340 + break;
1341 +
1342 + case USB_REQ_SET_INTERFACE:
1343 + if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
1344 + USB_RECIP_INTERFACE))
1345 + break;
1346 + if (fsg->config && w_index == 0) {
1347 +
1348 + /* Raise an exception to wipe out previous transaction
1349 + * state (queued bufs, etc) and install the new
1350 + * interface altsetting. */
1351 + raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
1352 + value = DELAYED_STATUS;
1353 + }
1354 + break;
1355 + case USB_REQ_GET_INTERFACE:
1356 + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1357 + USB_RECIP_INTERFACE))
1358 + break;
1359 + if (!fsg->config)
1360 + break;
1361 + if (w_index != 0) {
1362 + value = -EDOM;
1363 + break;
1364 + }
1365 + VDBG(fsg, "get interface\n");
1366 + *(u8 *) req->buf = 0;
1367 + value = 1;
1368 + break;
1369 +
1370 + default:
1371 + VDBG(fsg,
1372 + "unknown control req %02x.%02x v%04x i%04x l%u\n",
1373 + ctrl->bRequestType, ctrl->bRequest,
1374 + w_value, w_index, le16_to_cpu(ctrl->wLength));
1375 + }
1376 +
1377 + return value;
1378 +}
1379 +
1380 +
1381 +static int fsg_setup(struct usb_gadget *gadget,
1382 + const struct usb_ctrlrequest *ctrl)
1383 +{
1384 + struct fsg_dev *fsg = get_gadget_data(gadget);
1385 + int rc;
1386 + int w_length = le16_to_cpu(ctrl->wLength);
1387 +
1388 + ++fsg->ep0_req_tag; // Record arrival of a new request
1389 + fsg->ep0req->context = NULL;
1390 + fsg->ep0req->length = 0;
1391 + dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
1392 +
1393 + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
1394 + rc = class_setup_req(fsg, ctrl);
1395 + else
1396 + rc = standard_setup_req(fsg, ctrl);
1397 +
1398 + /* Respond with data/status or defer until later? */
1399 + if (rc >= 0 && rc != DELAYED_STATUS) {
1400 + rc = min(rc, w_length);
1401 + fsg->ep0req->length = rc;
1402 + fsg->ep0req->zero = rc < w_length;
1403 + fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
1404 + "ep0-in" : "ep0-out");
1405 + rc = ep0_queue(fsg);
1406 + }
1407 +
1408 + /* Device either stalls (rc < 0) or reports success */
1409 + return rc;
1410 +}
1411 +
1412 +
1413 +/*-------------------------------------------------------------------------*/
1414 +
1415 +/* All the following routines run in process context */
1416 +
1417 +
1418 +/* Use this for bulk or interrupt transfers, not ep0 */
1419 +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
1420 + struct usb_request *req, int *pbusy,
1421 + enum fsg_buffer_state *state)
1422 +{
1423 + int rc;
1424 +
1425 + if (ep == fsg->bulk_in)
1426 + dump_msg(fsg, "bulk-in", req->buf, req->length);
1427 + else if (ep == fsg->intr_in)
1428 + dump_msg(fsg, "intr-in", req->buf, req->length);
1429 +
1430 + spin_lock_irq(&fsg->lock);
1431 + *pbusy = 1;
1432 + *state = BUF_STATE_BUSY;
1433 + spin_unlock_irq(&fsg->lock);
1434 + rc = usb_ep_queue(ep, req, GFP_KERNEL);
1435 + if (rc != 0) {
1436 + *pbusy = 0;
1437 + *state = BUF_STATE_EMPTY;
1438 +
1439 + /* We can't do much more than wait for a reset */
1440 +
1441 + /* Note: currently the net2280 driver fails zero-length
1442 + * submissions if DMA is enabled. */
1443 + if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
1444 + req->length == 0))
1445 + WARNING(fsg, "error in submission: %s --> %d\n",
1446 + ep->name, rc);
1447 + }
1448 +}
1449 +
1450 +
1451 +static int sleep_thread(struct fsg_dev *fsg)
1452 +{
1453 + int rc = 0;
1454 +
1455 + /* Wait until a signal arrives or we are woken up */
1456 + for (;;) {
1457 + try_to_freeze();
1458 + set_current_state(TASK_INTERRUPTIBLE);
1459 + if (signal_pending(current)) {
1460 + rc = -EINTR;
1461 + break;
1462 + }
1463 + if (fsg->thread_wakeup_needed)
1464 + break;
1465 + schedule();
1466 + }
1467 + __set_current_state(TASK_RUNNING);
1468 + fsg->thread_wakeup_needed = 0;
1469 + return rc;
1470 +}
1471 +
1472 +
1473 +/*-------------------------------------------------------------------------*/
1474 +
1475 +static int do_read(struct fsg_dev *fsg)
1476 +{
1477 + struct fsg_lun *curlun = fsg->curlun;
1478 + u32 lba;
1479 + struct fsg_buffhd *bh;
1480 + int rc;
1481 + u32 amount_left;
1482 + loff_t file_offset, file_offset_tmp;
1483 + unsigned int amount;
1484 + ssize_t nread;
1485 +
1486 + /* Get the starting Logical Block Address and check that it's
1487 + * not too big */
1488 + if (fsg->cmnd[0] == READ_6)
1489 + lba = get_unaligned_be24(&fsg->cmnd[1]);
1490 + else {
1491 + lba = get_unaligned_be32(&fsg->cmnd[2]);
1492 +
1493 + /* We allow DPO (Disable Page Out = don't save data in the
1494 + * cache) and FUA (Force Unit Access = don't read from the
1495 + * cache), but we don't implement them. */
1496 + if ((fsg->cmnd[1] & ~0x18) != 0) {
1497 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1498 + return -EINVAL;
1499 + }
1500 + }
1501 + if (lba >= curlun->num_sectors) {
1502 + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1503 + return -EINVAL;
1504 + }
1505 + file_offset = ((loff_t) lba) << curlun->blkbits;
1506 +
1507 + /* Carry out the file reads */
1508 + amount_left = fsg->data_size_from_cmnd;
1509 + if (unlikely(amount_left == 0))
1510 + return -EIO; // No default reply
1511 +
1512 + for (;;) {
1513 +
1514 + /* Figure out how much we need to read:
1515 + * Try to read the remaining amount.
1516 + * But don't read more than the buffer size.
1517 + * And don't try to read past the end of the file.
1518 + */
1519 + amount = min((unsigned int) amount_left, mod_data.buflen);
1520 + amount = min((loff_t) amount,
1521 + curlun->file_length - file_offset);
1522 +
1523 + /* Wait for the next buffer to become available */
1524 + bh = fsg->next_buffhd_to_fill;
1525 + while (bh->state != BUF_STATE_EMPTY) {
1526 + rc = sleep_thread(fsg);
1527 + if (rc)
1528 + return rc;
1529 + }
1530 +
1531 + /* If we were asked to read past the end of file,
1532 + * end with an empty buffer. */
1533 + if (amount == 0) {
1534 + curlun->sense_data =
1535 + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1536 + curlun->sense_data_info = file_offset >> curlun->blkbits;
1537 + curlun->info_valid = 1;
1538 + bh->inreq->length = 0;
1539 + bh->state = BUF_STATE_FULL;
1540 + break;
1541 + }
1542 +
1543 + /* Perform the read */
1544 + file_offset_tmp = file_offset;
1545 + nread = vfs_read(curlun->filp,
1546 + (char __user *) bh->buf,
1547 + amount, &file_offset_tmp);
1548 + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1549 + (unsigned long long) file_offset,
1550 + (int) nread);
1551 + if (signal_pending(current))
1552 + return -EINTR;
1553 +
1554 + if (nread < 0) {
1555 + LDBG(curlun, "error in file read: %d\n",
1556 + (int) nread);
1557 + nread = 0;
1558 + } else if (nread < amount) {
1559 + LDBG(curlun, "partial file read: %d/%u\n",
1560 + (int) nread, amount);
1561 + nread = round_down(nread, curlun->blksize);
1562 + }
1563 + file_offset += nread;
1564 + amount_left -= nread;
1565 + fsg->residue -= nread;
1566 +
1567 + /* Except at the end of the transfer, nread will be
1568 + * equal to the buffer size, which is divisible by the
1569 + * bulk-in maxpacket size.
1570 + */
1571 + bh->inreq->length = nread;
1572 + bh->state = BUF_STATE_FULL;
1573 +
1574 + /* If an error occurred, report it and its position */
1575 + if (nread < amount) {
1576 + curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1577 + curlun->sense_data_info = file_offset >> curlun->blkbits;
1578 + curlun->info_valid = 1;
1579 + break;
1580 + }
1581 +
1582 + if (amount_left == 0)
1583 + break; // No more left to read
1584 +
1585 + /* Send this buffer and go read some more */
1586 + bh->inreq->zero = 0;
1587 + start_transfer(fsg, fsg->bulk_in, bh->inreq,
1588 + &bh->inreq_busy, &bh->state);
1589 + fsg->next_buffhd_to_fill = bh->next;
1590 + }
1591 +
1592 + return -EIO; // No default reply
1593 +}
1594 +
1595 +
1596 +/*-------------------------------------------------------------------------*/
1597 +
1598 +static int do_write(struct fsg_dev *fsg)
1599 +{
1600 + struct fsg_lun *curlun = fsg->curlun;
1601 + u32 lba;
1602 + struct fsg_buffhd *bh;
1603 + int get_some_more;
1604 + u32 amount_left_to_req, amount_left_to_write;
1605 + loff_t usb_offset, file_offset, file_offset_tmp;
1606 + unsigned int amount;
1607 + ssize_t nwritten;
1608 + int rc;
1609 +
1610 + if (curlun->ro) {
1611 + curlun->sense_data = SS_WRITE_PROTECTED;
1612 + return -EINVAL;
1613 + }
1614 + spin_lock(&curlun->filp->f_lock);
1615 + curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait
1616 + spin_unlock(&curlun->filp->f_lock);
1617 +
1618 + /* Get the starting Logical Block Address and check that it's
1619 + * not too big */
1620 + if (fsg->cmnd[0] == WRITE_6)
1621 + lba = get_unaligned_be24(&fsg->cmnd[1]);
1622 + else {
1623 + lba = get_unaligned_be32(&fsg->cmnd[2]);
1624 +
1625 + /* We allow DPO (Disable Page Out = don't save data in the
1626 + * cache) and FUA (Force Unit Access = write directly to the
1627 + * medium). We don't implement DPO; we implement FUA by
1628 + * performing synchronous output. */
1629 + if ((fsg->cmnd[1] & ~0x18) != 0) {
1630 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1631 + return -EINVAL;
1632 + }
1633 + /* FUA */
1634 + if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
1635 + spin_lock(&curlun->filp->f_lock);
1636 + curlun->filp->f_flags |= O_DSYNC;
1637 + spin_unlock(&curlun->filp->f_lock);
1638 + }
1639 + }
1640 + if (lba >= curlun->num_sectors) {
1641 + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1642 + return -EINVAL;
1643 + }
1644 +
1645 + /* Carry out the file writes */
1646 + get_some_more = 1;
1647 + file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
1648 + amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
1649 +
1650 + while (amount_left_to_write > 0) {
1651 +
1652 + /* Queue a request for more data from the host */
1653 + bh = fsg->next_buffhd_to_fill;
1654 + if (bh->state == BUF_STATE_EMPTY && get_some_more) {
1655 +
1656 + /* Figure out how much we want to get:
1657 + * Try to get the remaining amount,
1658 + * but not more than the buffer size.
1659 + */
1660 + amount = min(amount_left_to_req, mod_data.buflen);
1661 +
1662 + /* Beyond the end of the backing file? */
1663 + if (usb_offset >= curlun->file_length) {
1664 + get_some_more = 0;
1665 + curlun->sense_data =
1666 + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1667 + curlun->sense_data_info = usb_offset >> curlun->blkbits;
1668 + curlun->info_valid = 1;
1669 + continue;
1670 + }
1671 +
1672 + /* Get the next buffer */
1673 + usb_offset += amount;
1674 + fsg->usb_amount_left -= amount;
1675 + amount_left_to_req -= amount;
1676 + if (amount_left_to_req == 0)
1677 + get_some_more = 0;
1678 +
1679 + /* Except at the end of the transfer, amount will be
1680 + * equal to the buffer size, which is divisible by
1681 + * the bulk-out maxpacket size.
1682 + */
1683 + set_bulk_out_req_length(fsg, bh, amount);
1684 + start_transfer(fsg, fsg->bulk_out, bh->outreq,
1685 + &bh->outreq_busy, &bh->state);
1686 + fsg->next_buffhd_to_fill = bh->next;
1687 + continue;
1688 + }
1689 +
1690 + /* Write the received data to the backing file */
1691 + bh = fsg->next_buffhd_to_drain;
1692 + if (bh->state == BUF_STATE_EMPTY && !get_some_more)
1693 + break; // We stopped early
1694 + if (bh->state == BUF_STATE_FULL) {
1695 + smp_rmb();
1696 + fsg->next_buffhd_to_drain = bh->next;
1697 + bh->state = BUF_STATE_EMPTY;
1698 +
1699 + /* Did something go wrong with the transfer? */
1700 + if (bh->outreq->status != 0) {
1701 + curlun->sense_data = SS_COMMUNICATION_FAILURE;
1702 + curlun->sense_data_info = file_offset >> curlun->blkbits;
1703 + curlun->info_valid = 1;
1704 + break;
1705 + }
1706 +
1707 + amount = bh->outreq->actual;
1708 + if (curlun->file_length - file_offset < amount) {
1709 + LERROR(curlun,
1710 + "write %u @ %llu beyond end %llu\n",
1711 + amount, (unsigned long long) file_offset,
1712 + (unsigned long long) curlun->file_length);
1713 + amount = curlun->file_length - file_offset;
1714 + }
1715 +
1716 + /* Don't accept excess data. The spec doesn't say
1717 + * what to do in this case. We'll ignore the error.
1718 + */
1719 + amount = min(amount, bh->bulk_out_intended_length);
1720 +
1721 + /* Don't write a partial block */
1722 + amount = round_down(amount, curlun->blksize);
1723 + if (amount == 0)
1724 + goto empty_write;
1725 +
1726 + /* Perform the write */
1727 + file_offset_tmp = file_offset;
1728 + nwritten = vfs_write(curlun->filp,
1729 + (char __user *) bh->buf,
1730 + amount, &file_offset_tmp);
1731 + VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
1732 + (unsigned long long) file_offset,
1733 + (int) nwritten);
1734 + if (signal_pending(current))
1735 + return -EINTR; // Interrupted!
1736 +
1737 + if (nwritten < 0) {
1738 + LDBG(curlun, "error in file write: %d\n",
1739 + (int) nwritten);
1740 + nwritten = 0;
1741 + } else if (nwritten < amount) {
1742 + LDBG(curlun, "partial file write: %d/%u\n",
1743 + (int) nwritten, amount);
1744 + nwritten = round_down(nwritten, curlun->blksize);
1745 + }
1746 + file_offset += nwritten;
1747 + amount_left_to_write -= nwritten;
1748 + fsg->residue -= nwritten;
1749 +
1750 + /* If an error occurred, report it and its position */
1751 + if (nwritten < amount) {
1752 + curlun->sense_data = SS_WRITE_ERROR;
1753 + curlun->sense_data_info = file_offset >> curlun->blkbits;
1754 + curlun->info_valid = 1;
1755 + break;
1756 + }
1757 +
1758 + empty_write:
1759 + /* Did the host decide to stop early? */
1760 + if (bh->outreq->actual < bh->bulk_out_intended_length) {
1761 + fsg->short_packet_received = 1;
1762 + break;
1763 + }
1764 + continue;
1765 + }
1766 +
1767 + /* Wait for something to happen */
1768 + rc = sleep_thread(fsg);
1769 + if (rc)
1770 + return rc;
1771 + }
1772 +
1773 + return -EIO; // No default reply
1774 +}
1775 +
1776 +
1777 +/*-------------------------------------------------------------------------*/
1778 +
1779 +static int do_synchronize_cache(struct fsg_dev *fsg)
1780 +{
1781 + struct fsg_lun *curlun = fsg->curlun;
1782 + int rc;
1783 +
1784 + /* We ignore the requested LBA and write out all file's
1785 + * dirty data buffers. */
1786 + rc = fsg_lun_fsync_sub(curlun);
1787 + if (rc)
1788 + curlun->sense_data = SS_WRITE_ERROR;
1789 + return 0;
1790 +}
1791 +
1792 +
1793 +/*-------------------------------------------------------------------------*/
1794 +
1795 +static void invalidate_sub(struct fsg_lun *curlun)
1796 +{
1797 + struct file *filp = curlun->filp;
1798 + struct inode *inode = filp->f_path.dentry->d_inode;
1799 + unsigned long rc;
1800 +
1801 + rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
1802 + VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
1803 +}
1804 +
1805 +static int do_verify(struct fsg_dev *fsg)
1806 +{
1807 + struct fsg_lun *curlun = fsg->curlun;
1808 + u32 lba;
1809 + u32 verification_length;
1810 + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
1811 + loff_t file_offset, file_offset_tmp;
1812 + u32 amount_left;
1813 + unsigned int amount;
1814 + ssize_t nread;
1815 +
1816 + /* Get the starting Logical Block Address and check that it's
1817 + * not too big */
1818 + lba = get_unaligned_be32(&fsg->cmnd[2]);
1819 + if (lba >= curlun->num_sectors) {
1820 + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1821 + return -EINVAL;
1822 + }
1823 +
1824 + /* We allow DPO (Disable Page Out = don't save data in the
1825 + * cache) but we don't implement it. */
1826 + if ((fsg->cmnd[1] & ~0x10) != 0) {
1827 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1828 + return -EINVAL;
1829 + }
1830 +
1831 + verification_length = get_unaligned_be16(&fsg->cmnd[7]);
1832 + if (unlikely(verification_length == 0))
1833 + return -EIO; // No default reply
1834 +
1835 + /* Prepare to carry out the file verify */
1836 + amount_left = verification_length << curlun->blkbits;
1837 + file_offset = ((loff_t) lba) << curlun->blkbits;
1838 +
1839 + /* Write out all the dirty buffers before invalidating them */
1840 + fsg_lun_fsync_sub(curlun);
1841 + if (signal_pending(current))
1842 + return -EINTR;
1843 +
1844 + invalidate_sub(curlun);
1845 + if (signal_pending(current))
1846 + return -EINTR;
1847 +
1848 + /* Just try to read the requested blocks */
1849 + while (amount_left > 0) {
1850 +
1851 + /* Figure out how much we need to read:
1852 + * Try to read the remaining amount, but not more than
1853 + * the buffer size.
1854 + * And don't try to read past the end of the file.
1855 + */
1856 + amount = min((unsigned int) amount_left, mod_data.buflen);
1857 + amount = min((loff_t) amount,
1858 + curlun->file_length - file_offset);
1859 + if (amount == 0) {
1860 + curlun->sense_data =
1861 + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1862 + curlun->sense_data_info = file_offset >> curlun->blkbits;
1863 + curlun->info_valid = 1;
1864 + break;
1865 + }
1866 +
1867 + /* Perform the read */
1868 + file_offset_tmp = file_offset;
1869 + nread = vfs_read(curlun->filp,
1870 + (char __user *) bh->buf,
1871 + amount, &file_offset_tmp);
1872 + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1873 + (unsigned long long) file_offset,
1874 + (int) nread);
1875 + if (signal_pending(current))
1876 + return -EINTR;
1877 +
1878 + if (nread < 0) {
1879 + LDBG(curlun, "error in file verify: %d\n",
1880 + (int) nread);
1881 + nread = 0;
1882 + } else if (nread < amount) {
1883 + LDBG(curlun, "partial file verify: %d/%u\n",
1884 + (int) nread, amount);
1885 + nread = round_down(nread, curlun->blksize);
1886 + }
1887 + if (nread == 0) {
1888 + curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1889 + curlun->sense_data_info = file_offset >> curlun->blkbits;
1890 + curlun->info_valid = 1;
1891 + break;
1892 + }
1893 + file_offset += nread;
1894 + amount_left -= nread;
1895 + }
1896 + return 0;
1897 +}
1898 +
1899 +
1900 +/*-------------------------------------------------------------------------*/
1901 +
1902 +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1903 +{
1904 + u8 *buf = (u8 *) bh->buf;
1905 +
1906 + static char vendor_id[] = "Linux ";
1907 + static char product_disk_id[] = "File-Stor Gadget";
1908 + static char product_cdrom_id[] = "File-CD Gadget ";
1909 +
1910 + if (!fsg->curlun) { // Unsupported LUNs are okay
1911 + fsg->bad_lun_okay = 1;
1912 + memset(buf, 0, 36);
1913 + buf[0] = 0x7f; // Unsupported, no device-type
1914 + buf[4] = 31; // Additional length
1915 + return 36;
1916 + }
1917 +
1918 + memset(buf, 0, 8);
1919 + buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
1920 + if (mod_data.removable)
1921 + buf[1] = 0x80;
1922 + buf[2] = 2; // ANSI SCSI level 2
1923 + buf[3] = 2; // SCSI-2 INQUIRY data format
1924 + buf[4] = 31; // Additional length
1925 + // No special options
1926 + sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
1927 + (mod_data.cdrom ? product_cdrom_id :
1928 + product_disk_id),
1929 + mod_data.release);
1930 + return 36;
1931 +}
1932 +
1933 +
1934 +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1935 +{
1936 + struct fsg_lun *curlun = fsg->curlun;
1937 + u8 *buf = (u8 *) bh->buf;
1938 + u32 sd, sdinfo;
1939 + int valid;
1940 +
1941 + /*
1942 + * From the SCSI-2 spec., section 7.9 (Unit attention condition):
1943 + *
1944 + * If a REQUEST SENSE command is received from an initiator
1945 + * with a pending unit attention condition (before the target
1946 + * generates the contingent allegiance condition), then the
1947 + * target shall either:
1948 + * a) report any pending sense data and preserve the unit
1949 + * attention condition on the logical unit, or,
1950 + * b) report the unit attention condition, may discard any
1951 + * pending sense data, and clear the unit attention
1952 + * condition on the logical unit for that initiator.
1953 + *
1954 + * FSG normally uses option a); enable this code to use option b).
1955 + */
1956 +#if 0
1957 + if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
1958 + curlun->sense_data = curlun->unit_attention_data;
1959 + curlun->unit_attention_data = SS_NO_SENSE;
1960 + }
1961 +#endif
1962 +
1963 + if (!curlun) { // Unsupported LUNs are okay
1964 + fsg->bad_lun_okay = 1;
1965 + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
1966 + sdinfo = 0;
1967 + valid = 0;
1968 + } else {
1969 + sd = curlun->sense_data;
1970 + sdinfo = curlun->sense_data_info;
1971 + valid = curlun->info_valid << 7;
1972 + curlun->sense_data = SS_NO_SENSE;
1973 + curlun->sense_data_info = 0;
1974 + curlun->info_valid = 0;
1975 + }
1976 +
1977 + memset(buf, 0, 18);
1978 + buf[0] = valid | 0x70; // Valid, current error
1979 + buf[2] = SK(sd);
1980 + put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */
1981 + buf[7] = 18 - 8; // Additional sense length
1982 + buf[12] = ASC(sd);
1983 + buf[13] = ASCQ(sd);
1984 + return 18;
1985 +}
1986 +
1987 +
1988 +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1989 +{
1990 + struct fsg_lun *curlun = fsg->curlun;
1991 + u32 lba = get_unaligned_be32(&fsg->cmnd[2]);
1992 + int pmi = fsg->cmnd[8];
1993 + u8 *buf = (u8 *) bh->buf;
1994 +
1995 + /* Check the PMI and LBA fields */
1996 + if (pmi > 1 || (pmi == 0 && lba != 0)) {
1997 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1998 + return -EINVAL;
1999 + }
2000 +
2001 + put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
2002 + /* Max logical block */
2003 + put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
2004 + return 8;
2005 +}
2006 +
2007 +
2008 +static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2009 +{
2010 + struct fsg_lun *curlun = fsg->curlun;
2011 + int msf = fsg->cmnd[1] & 0x02;
2012 + u32 lba = get_unaligned_be32(&fsg->cmnd[2]);
2013 + u8 *buf = (u8 *) bh->buf;
2014 +
2015 + if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */
2016 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2017 + return -EINVAL;
2018 + }
2019 + if (lba >= curlun->num_sectors) {
2020 + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
2021 + return -EINVAL;
2022 + }
2023 +
2024 + memset(buf, 0, 8);
2025 + buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */
2026 + store_cdrom_address(&buf[4], msf, lba);
2027 + return 8;
2028 +}
2029 +
2030 +
2031 +static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2032 +{
2033 + struct fsg_lun *curlun = fsg->curlun;
2034 + int msf = fsg->cmnd[1] & 0x02;
2035 + int start_track = fsg->cmnd[6];
2036 + u8 *buf = (u8 *) bh->buf;
2037 +
2038 + if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
2039 + start_track > 1) {
2040 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2041 + return -EINVAL;
2042 + }
2043 +
2044 + memset(buf, 0, 20);
2045 + buf[1] = (20-2); /* TOC data length */
2046 + buf[2] = 1; /* First track number */
2047 + buf[3] = 1; /* Last track number */
2048 + buf[5] = 0x16; /* Data track, copying allowed */
2049 + buf[6] = 0x01; /* Only track is number 1 */
2050 + store_cdrom_address(&buf[8], msf, 0);
2051 +
2052 + buf[13] = 0x16; /* Lead-out track is data */
2053 + buf[14] = 0xAA; /* Lead-out track number */
2054 + store_cdrom_address(&buf[16], msf, curlun->num_sectors);
2055 + return 20;
2056 +}
2057 +
2058 +
2059 +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2060 +{
2061 + struct fsg_lun *curlun = fsg->curlun;
2062 + int mscmnd = fsg->cmnd[0];
2063 + u8 *buf = (u8 *) bh->buf;
2064 + u8 *buf0 = buf;
2065 + int pc, page_code;
2066 + int changeable_values, all_pages;
2067 + int valid_page = 0;
2068 + int len, limit;
2069 +
2070 + if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD
2071 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2072 + return -EINVAL;
2073 + }
2074 + pc = fsg->cmnd[2] >> 6;
2075 + page_code = fsg->cmnd[2] & 0x3f;
2076 + if (pc == 3) {
2077 + curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
2078 + return -EINVAL;
2079 + }
2080 + changeable_values = (pc == 1);
2081 + all_pages = (page_code == 0x3f);
2082 +
2083 + /* Write the mode parameter header. Fixed values are: default
2084 + * medium type, no cache control (DPOFUA), and no block descriptors.
2085 + * The only variable value is the WriteProtect bit. We will fill in
2086 + * the mode data length later. */
2087 + memset(buf, 0, 8);
2088 + if (mscmnd == MODE_SENSE) {
2089 + buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
2090 + buf += 4;
2091 + limit = 255;
2092 + } else { // MODE_SENSE_10
2093 + buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
2094 + buf += 8;
2095 + limit = 65535; // Should really be mod_data.buflen
2096 + }
2097 +
2098 + /* No block descriptors */
2099 +
2100 + /* The mode pages, in numerical order. The only page we support
2101 + * is the Caching page. */
2102 + if (page_code == 0x08 || all_pages) {
2103 + valid_page = 1;
2104 + buf[0] = 0x08; // Page code
2105 + buf[1] = 10; // Page length
2106 + memset(buf+2, 0, 10); // None of the fields are changeable
2107 +
2108 + if (!changeable_values) {
2109 + buf[2] = 0x04; // Write cache enable,
2110 + // Read cache not disabled
2111 + // No cache retention priorities
2112 + put_unaligned_be16(0xffff, &buf[4]);
2113 + /* Don't disable prefetch */
2114 + /* Minimum prefetch = 0 */
2115 + put_unaligned_be16(0xffff, &buf[8]);
2116 + /* Maximum prefetch */
2117 + put_unaligned_be16(0xffff, &buf[10]);
2118 + /* Maximum prefetch ceiling */
2119 + }
2120 + buf += 12;
2121 + }
2122 +
2123 + /* Check that a valid page was requested and the mode data length
2124 + * isn't too long. */
2125 + len = buf - buf0;
2126 + if (!valid_page || len > limit) {
2127 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2128 + return -EINVAL;
2129 + }
2130 +
2131 + /* Store the mode data length */
2132 + if (mscmnd == MODE_SENSE)
2133 + buf0[0] = len - 1;
2134 + else
2135 + put_unaligned_be16(len - 2, buf0);
2136 + return len;
2137 +}
2138 +
2139 +
2140 +static int do_start_stop(struct fsg_dev *fsg)
2141 +{
2142 + struct fsg_lun *curlun = fsg->curlun;
2143 + int loej, start;
2144 +
2145 + if (!mod_data.removable) {
2146 + curlun->sense_data = SS_INVALID_COMMAND;
2147 + return -EINVAL;
2148 + }
2149 +
2150 + // int immed = fsg->cmnd[1] & 0x01;
2151 + loej = fsg->cmnd[4] & 0x02;
2152 + start = fsg->cmnd[4] & 0x01;
2153 +
2154 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
2155 + if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed
2156 + (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start
2157 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2158 + return -EINVAL;
2159 + }
2160 +
2161 + if (!start) {
2162 +
2163 + /* Are we allowed to unload the media? */
2164 + if (curlun->prevent_medium_removal) {
2165 + LDBG(curlun, "unload attempt prevented\n");
2166 + curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
2167 + return -EINVAL;
2168 + }
2169 + if (loej) { // Simulate an unload/eject
2170 + up_read(&fsg->filesem);
2171 + down_write(&fsg->filesem);
2172 + fsg_lun_close(curlun);
2173 + up_write(&fsg->filesem);
2174 + down_read(&fsg->filesem);
2175 + }
2176 + } else {
2177 +
2178 + /* Our emulation doesn't support mounting; the medium is
2179 + * available for use as soon as it is loaded. */
2180 + if (!fsg_lun_is_open(curlun)) {
2181 + curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2182 + return -EINVAL;
2183 + }
2184 + }
2185 +#endif
2186 + return 0;
2187 +}
2188 +
2189 +
2190 +static int do_prevent_allow(struct fsg_dev *fsg)
2191 +{
2192 + struct fsg_lun *curlun = fsg->curlun;
2193 + int prevent;
2194 +
2195 + if (!mod_data.removable) {
2196 + curlun->sense_data = SS_INVALID_COMMAND;
2197 + return -EINVAL;
2198 + }
2199 +
2200 + prevent = fsg->cmnd[4] & 0x01;
2201 + if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent
2202 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2203 + return -EINVAL;
2204 + }
2205 +
2206 + if (curlun->prevent_medium_removal && !prevent)
2207 + fsg_lun_fsync_sub(curlun);
2208 + curlun->prevent_medium_removal = prevent;
2209 + return 0;
2210 +}
2211 +
2212 +
2213 +static int do_read_format_capacities(struct fsg_dev *fsg,
2214 + struct fsg_buffhd *bh)
2215 +{
2216 + struct fsg_lun *curlun = fsg->curlun;
2217 + u8 *buf = (u8 *) bh->buf;
2218 +
2219 + buf[0] = buf[1] = buf[2] = 0;
2220 + buf[3] = 8; // Only the Current/Maximum Capacity Descriptor
2221 + buf += 4;
2222 +
2223 + put_unaligned_be32(curlun->num_sectors, &buf[0]);
2224 + /* Number of blocks */
2225 + put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
2226 + buf[4] = 0x02; /* Current capacity */
2227 + return 12;
2228 +}
2229 +
2230 +
2231 +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2232 +{
2233 + struct fsg_lun *curlun = fsg->curlun;
2234 +
2235 + /* We don't support MODE SELECT */
2236 + curlun->sense_data = SS_INVALID_COMMAND;
2237 + return -EINVAL;
2238 +}
2239 +
2240 +
2241 +/*-------------------------------------------------------------------------*/
2242 +
2243 +static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
2244 +{
2245 + int rc;
2246 +
2247 + rc = fsg_set_halt(fsg, fsg->bulk_in);
2248 + if (rc == -EAGAIN)
2249 + VDBG(fsg, "delayed bulk-in endpoint halt\n");
2250 + while (rc != 0) {
2251 + if (rc != -EAGAIN) {
2252 + WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
2253 + rc = 0;
2254 + break;
2255 + }
2256 +
2257 + /* Wait for a short time and then try again */
2258 + if (msleep_interruptible(100) != 0)
2259 + return -EINTR;
2260 + rc = usb_ep_set_halt(fsg->bulk_in);
2261 + }
2262 + return rc;
2263 +}
2264 +
2265 +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
2266 +{
2267 + int rc;
2268 +
2269 + DBG(fsg, "bulk-in set wedge\n");
2270 + rc = usb_ep_set_wedge(fsg->bulk_in);
2271 + if (rc == -EAGAIN)
2272 + VDBG(fsg, "delayed bulk-in endpoint wedge\n");
2273 + while (rc != 0) {
2274 + if (rc != -EAGAIN) {
2275 + WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
2276 + rc = 0;
2277 + break;
2278 + }
2279 +
2280 + /* Wait for a short time and then try again */
2281 + if (msleep_interruptible(100) != 0)
2282 + return -EINTR;
2283 + rc = usb_ep_set_wedge(fsg->bulk_in);
2284 + }
2285 + return rc;
2286 +}
2287 +
2288 +static int throw_away_data(struct fsg_dev *fsg)
2289 +{
2290 + struct fsg_buffhd *bh;
2291 + u32 amount;
2292 + int rc;
2293 +
2294 + while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
2295 + fsg->usb_amount_left > 0) {
2296 +
2297 + /* Throw away the data in a filled buffer */
2298 + if (bh->state == BUF_STATE_FULL) {
2299 + smp_rmb();
2300 + bh->state = BUF_STATE_EMPTY;
2301 + fsg->next_buffhd_to_drain = bh->next;
2302 +
2303 + /* A short packet or an error ends everything */
2304 + if (bh->outreq->actual < bh->bulk_out_intended_length ||
2305 + bh->outreq->status != 0) {
2306 + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2307 + return -EINTR;
2308 + }
2309 + continue;
2310 + }
2311 +
2312 + /* Try to submit another request if we need one */
2313 + bh = fsg->next_buffhd_to_fill;
2314 + if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
2315 + amount = min(fsg->usb_amount_left,
2316 + (u32) mod_data.buflen);
2317 +
2318 + /* Except at the end of the transfer, amount will be
2319 + * equal to the buffer size, which is divisible by
2320 + * the bulk-out maxpacket size.
2321 + */
2322 + set_bulk_out_req_length(fsg, bh, amount);
2323 + start_transfer(fsg, fsg->bulk_out, bh->outreq,
2324 + &bh->outreq_busy, &bh->state);
2325 + fsg->next_buffhd_to_fill = bh->next;
2326 + fsg->usb_amount_left -= amount;
2327 + continue;
2328 + }
2329 +
2330 + /* Otherwise wait for something to happen */
2331 + rc = sleep_thread(fsg);
2332 + if (rc)
2333 + return rc;
2334 + }
2335 + return 0;
2336 +}
2337 +
2338 +
2339 +static int finish_reply(struct fsg_dev *fsg)
2340 +{
2341 + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
2342 + int rc = 0;
2343 +
2344 + switch (fsg->data_dir) {
2345 + case DATA_DIR_NONE:
2346 + break; // Nothing to send
2347 +
2348 + /* If we don't know whether the host wants to read or write,
2349 + * this must be CB or CBI with an unknown command. We mustn't
2350 + * try to send or receive any data. So stall both bulk pipes
2351 + * if we can and wait for a reset. */
2352 + case DATA_DIR_UNKNOWN:
2353 + if (mod_data.can_stall) {
2354 + fsg_set_halt(fsg, fsg->bulk_out);
2355 + rc = halt_bulk_in_endpoint(fsg);
2356 + }
2357 + break;
2358 +
2359 + /* All but the last buffer of data must have already been sent */
2360 + case DATA_DIR_TO_HOST:
2361 + if (fsg->data_size == 0)
2362 + ; // Nothing to send
2363 +
2364 + /* If there's no residue, simply send the last buffer */
2365 + else if (fsg->residue == 0) {
2366 + bh->inreq->zero = 0;
2367 + start_transfer(fsg, fsg->bulk_in, bh->inreq,
2368 + &bh->inreq_busy, &bh->state);
2369 + fsg->next_buffhd_to_fill = bh->next;
2370 + }
2371 +
2372 + /* There is a residue. For CB and CBI, simply mark the end
2373 + * of the data with a short packet. However, if we are
2374 + * allowed to stall, there was no data at all (residue ==
2375 + * data_size), and the command failed (invalid LUN or
2376 + * sense data is set), then halt the bulk-in endpoint
2377 + * instead. */
2378 + else if (!transport_is_bbb()) {
2379 + if (mod_data.can_stall &&
2380 + fsg->residue == fsg->data_size &&
2381 + (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
2382 + bh->state = BUF_STATE_EMPTY;
2383 + rc = halt_bulk_in_endpoint(fsg);
2384 + } else {
2385 + bh->inreq->zero = 1;
2386 + start_transfer(fsg, fsg->bulk_in, bh->inreq,
2387 + &bh->inreq_busy, &bh->state);
2388 + fsg->next_buffhd_to_fill = bh->next;
2389 + }
2390 + }
2391 +
2392 + /*
2393 + * For Bulk-only, mark the end of the data with a short
2394 + * packet. If we are allowed to stall, halt the bulk-in
2395 + * endpoint. (Note: This violates the Bulk-Only Transport
2396 + * specification, which requires us to pad the data if we
2397 + * don't halt the endpoint. Presumably nobody will mind.)
2398 + */
2399 + else {
2400 + bh->inreq->zero = 1;
2401 + start_transfer(fsg, fsg->bulk_in, bh->inreq,
2402 + &bh->inreq_busy, &bh->state);
2403 + fsg->next_buffhd_to_fill = bh->next;
2404 + if (mod_data.can_stall)
2405 + rc = halt_bulk_in_endpoint(fsg);
2406 + }
2407 + break;
2408 +
2409 + /* We have processed all we want from the data the host has sent.
2410 + * There may still be outstanding bulk-out requests. */
2411 + case DATA_DIR_FROM_HOST:
2412 + if (fsg->residue == 0)
2413 + ; // Nothing to receive
2414 +
2415 + /* Did the host stop sending unexpectedly early? */
2416 + else if (fsg->short_packet_received) {
2417 + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2418 + rc = -EINTR;
2419 + }
2420 +
2421 + /* We haven't processed all the incoming data. Even though
2422 + * we may be allowed to stall, doing so would cause a race.
2423 + * The controller may already have ACK'ed all the remaining
2424 + * bulk-out packets, in which case the host wouldn't see a
2425 + * STALL. Not realizing the endpoint was halted, it wouldn't
2426 + * clear the halt -- leading to problems later on. */
2427 +#if 0
2428 + else if (mod_data.can_stall) {
2429 + fsg_set_halt(fsg, fsg->bulk_out);
2430 + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2431 + rc = -EINTR;
2432 + }
2433 +#endif
2434 +
2435 + /* We can't stall. Read in the excess data and throw it
2436 + * all away. */
2437 + else
2438 + rc = throw_away_data(fsg);
2439 + break;
2440 + }
2441 + return rc;
2442 +}
2443 +
2444 +
2445 +static int send_status(struct fsg_dev *fsg)
2446 +{
2447 + struct fsg_lun *curlun = fsg->curlun;
2448 + struct fsg_buffhd *bh;
2449 + int rc;
2450 + u8 status = US_BULK_STAT_OK;
2451 + u32 sd, sdinfo = 0;
2452 +
2453 + /* Wait for the next buffer to become available */
2454 + bh = fsg->next_buffhd_to_fill;
2455 + while (bh->state != BUF_STATE_EMPTY) {
2456 + rc = sleep_thread(fsg);
2457 + if (rc)
2458 + return rc;
2459 + }
2460 +
2461 + if (curlun) {
2462 + sd = curlun->sense_data;
2463 + sdinfo = curlun->sense_data_info;
2464 + } else if (fsg->bad_lun_okay)
2465 + sd = SS_NO_SENSE;
2466 + else
2467 + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2468 +
2469 + if (fsg->phase_error) {
2470 + DBG(fsg, "sending phase-error status\n");
2471 + status = US_BULK_STAT_PHASE;
2472 + sd = SS_INVALID_COMMAND;
2473 + } else if (sd != SS_NO_SENSE) {
2474 + DBG(fsg, "sending command-failure status\n");
2475 + status = US_BULK_STAT_FAIL;
2476 + VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
2477 + " info x%x\n",
2478 + SK(sd), ASC(sd), ASCQ(sd), sdinfo);
2479 + }
2480 +
2481 + if (transport_is_bbb()) {
2482 + struct bulk_cs_wrap *csw = bh->buf;
2483 +
2484 + /* Store and send the Bulk-only CSW */
2485 + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
2486 + csw->Tag = fsg->tag;
2487 + csw->Residue = cpu_to_le32(fsg->residue);
2488 + csw->Status = status;
2489 +
2490 + bh->inreq->length = US_BULK_CS_WRAP_LEN;
2491 + bh->inreq->zero = 0;
2492 + start_transfer(fsg, fsg->bulk_in, bh->inreq,
2493 + &bh->inreq_busy, &bh->state);
2494 +
2495 + } else if (mod_data.transport_type == USB_PR_CB) {
2496 +
2497 + /* Control-Bulk transport has no status phase! */
2498 + return 0;
2499 +
2500 + } else { // USB_PR_CBI
2501 + struct interrupt_data *buf = bh->buf;
2502 +
2503 + /* Store and send the Interrupt data. UFI sends the ASC
2504 + * and ASCQ bytes. Everything else sends a Type (which
2505 + * is always 0) and the status Value. */
2506 + if (mod_data.protocol_type == USB_SC_UFI) {
2507 + buf->bType = ASC(sd);
2508 + buf->bValue = ASCQ(sd);
2509 + } else {
2510 + buf->bType = 0;
2511 + buf->bValue = status;
2512 + }
2513 + fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
2514 +
2515 + fsg->intr_buffhd = bh; // Point to the right buffhd
2516 + fsg->intreq->buf = bh->inreq->buf;
2517 + fsg->intreq->context = bh;
2518 + start_transfer(fsg, fsg->intr_in, fsg->intreq,
2519 + &fsg->intreq_busy, &bh->state);
2520 + }
2521 +
2522 + fsg->next_buffhd_to_fill = bh->next;
2523 + return 0;
2524 +}
2525 +
2526 +
2527 +/*-------------------------------------------------------------------------*/
2528 +
2529 +/* Check whether the command is properly formed and whether its data size
2530 + * and direction agree with the values we already have. */
2531 +static int check_command(struct fsg_dev *fsg, int cmnd_size,
2532 + enum data_direction data_dir, unsigned int mask,
2533 + int needs_medium, const char *name)
2534 +{
2535 + int i;
2536 + int lun = fsg->cmnd[1] >> 5;
2537 + static const char dirletter[4] = {'u', 'o', 'i', 'n'};
2538 + char hdlen[20];
2539 + struct fsg_lun *curlun;
2540 +
2541 + /* Adjust the expected cmnd_size for protocol encapsulation padding.
2542 + * Transparent SCSI doesn't pad. */
2543 + if (protocol_is_scsi())
2544 + ;
2545 +
2546 + /* There's some disagreement as to whether RBC pads commands or not.
2547 + * We'll play it safe and accept either form. */
2548 + else if (mod_data.protocol_type == USB_SC_RBC) {
2549 + if (fsg->cmnd_size == 12)
2550 + cmnd_size = 12;
2551 +
2552 + /* All the other protocols pad to 12 bytes */
2553 + } else
2554 + cmnd_size = 12;
2555 +
2556 + hdlen[0] = 0;
2557 + if (fsg->data_dir != DATA_DIR_UNKNOWN)
2558 + sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
2559 + fsg->data_size);
2560 + VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n",
2561 + name, cmnd_size, dirletter[(int) data_dir],
2562 + fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
2563 +
2564 + /* We can't reply at all until we know the correct data direction
2565 + * and size. */
2566 + if (fsg->data_size_from_cmnd == 0)
2567 + data_dir = DATA_DIR_NONE;
2568 + if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI
2569 + fsg->data_dir = data_dir;
2570 + fsg->data_size = fsg->data_size_from_cmnd;
2571 +
2572 + } else { // Bulk-only
2573 + if (fsg->data_size < fsg->data_size_from_cmnd) {
2574 +
2575 + /* Host data size < Device data size is a phase error.
2576 + * Carry out the command, but only transfer as much
2577 + * as we are allowed. */
2578 + fsg->data_size_from_cmnd = fsg->data_size;
2579 + fsg->phase_error = 1;
2580 + }
2581 + }
2582 + fsg->residue = fsg->usb_amount_left = fsg->data_size;
2583 +
2584 + /* Conflicting data directions is a phase error */
2585 + if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
2586 + fsg->phase_error = 1;
2587 + return -EINVAL;
2588 + }
2589 +
2590 + /* Verify the length of the command itself */
2591 + if (cmnd_size != fsg->cmnd_size) {
2592 +
2593 + /* Special case workaround: There are plenty of buggy SCSI
2594 + * implementations. Many have issues with cbw->Length
2595 + * field passing a wrong command size. For those cases we
2596 + * always try to work around the problem by using the length
2597 + * sent by the host side provided it is at least as large
2598 + * as the correct command length.
2599 + * Examples of such cases would be MS-Windows, which issues
2600 + * REQUEST SENSE with cbw->Length == 12 where it should
2601 + * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
2602 + * REQUEST SENSE with cbw->Length == 10 where it should
2603 + * be 6 as well.
2604 + */
2605 + if (cmnd_size <= fsg->cmnd_size) {
2606 + DBG(fsg, "%s is buggy! Expected length %d "
2607 + "but we got %d\n", name,
2608 + cmnd_size, fsg->cmnd_size);
2609 + cmnd_size = fsg->cmnd_size;
2610 + } else {
2611 + fsg->phase_error = 1;
2612 + return -EINVAL;
2613 + }
2614 + }
2615 +
2616 + /* Check that the LUN values are consistent */
2617 + if (transport_is_bbb()) {
2618 + if (fsg->lun != lun)
2619 + DBG(fsg, "using LUN %d from CBW, "
2620 + "not LUN %d from CDB\n",
2621 + fsg->lun, lun);
2622 + }
2623 +
2624 + /* Check the LUN */
2625 + curlun = fsg->curlun;
2626 + if (curlun) {
2627 + if (fsg->cmnd[0] != REQUEST_SENSE) {
2628 + curlun->sense_data = SS_NO_SENSE;
2629 + curlun->sense_data_info = 0;
2630 + curlun->info_valid = 0;
2631 + }
2632 + } else {
2633 + fsg->bad_lun_okay = 0;
2634 +
2635 + /* INQUIRY and REQUEST SENSE commands are explicitly allowed
2636 + * to use unsupported LUNs; all others may not. */
2637 + if (fsg->cmnd[0] != INQUIRY &&
2638 + fsg->cmnd[0] != REQUEST_SENSE) {
2639 + DBG(fsg, "unsupported LUN %d\n", fsg->lun);
2640 + return -EINVAL;
2641 + }
2642 + }
2643 +
2644 + /* If a unit attention condition exists, only INQUIRY and
2645 + * REQUEST SENSE commands are allowed; anything else must fail. */
2646 + if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
2647 + fsg->cmnd[0] != INQUIRY &&
2648 + fsg->cmnd[0] != REQUEST_SENSE) {
2649 + curlun->sense_data = curlun->unit_attention_data;
2650 + curlun->unit_attention_data = SS_NO_SENSE;
2651 + return -EINVAL;
2652 + }
2653 +
2654 + /* Check that only command bytes listed in the mask are non-zero */
2655 + fsg->cmnd[1] &= 0x1f; // Mask away the LUN
2656 + for (i = 1; i < cmnd_size; ++i) {
2657 + if (fsg->cmnd[i] && !(mask & (1 << i))) {
2658 + if (curlun)
2659 + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2660 + return -EINVAL;
2661 + }
2662 + }
2663 +
2664 + /* If the medium isn't mounted and the command needs to access
2665 + * it, return an error. */
2666 + if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
2667 + curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2668 + return -EINVAL;
2669 + }
2670 +
2671 + return 0;
2672 +}
2673 +
2674 +/* wrapper of check_command for data size in blocks handling */
2675 +static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
2676 + enum data_direction data_dir, unsigned int mask,
2677 + int needs_medium, const char *name)
2678 +{
2679 + if (fsg->curlun)
2680 + fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
2681 + return check_command(fsg, cmnd_size, data_dir,
2682 + mask, needs_medium, name);
2683 +}
2684 +
2685 +static int do_scsi_command(struct fsg_dev *fsg)
2686 +{
2687 + struct fsg_buffhd *bh;
2688 + int rc;
2689 + int reply = -EINVAL;
2690 + int i;
2691 + static char unknown[16];
2692 +
2693 + dump_cdb(fsg);
2694 +
2695 + /* Wait for the next buffer to become available for data or status */
2696 + bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
2697 + while (bh->state != BUF_STATE_EMPTY) {
2698 + rc = sleep_thread(fsg);
2699 + if (rc)
2700 + return rc;
2701 + }
2702 + fsg->phase_error = 0;
2703 + fsg->short_packet_received = 0;
2704 +
2705 + down_read(&fsg->filesem); // We're using the backing file
2706 + switch (fsg->cmnd[0]) {
2707 +
2708 + case INQUIRY:
2709 + fsg->data_size_from_cmnd = fsg->cmnd[4];
2710 + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2711 + (1<<4), 0,
2712 + "INQUIRY")) == 0)
2713 + reply = do_inquiry(fsg, bh);
2714 + break;
2715 +
2716 + case MODE_SELECT:
2717 + fsg->data_size_from_cmnd = fsg->cmnd[4];
2718 + if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
2719 + (1<<1) | (1<<4), 0,
2720 + "MODE SELECT(6)")) == 0)
2721 + reply = do_mode_select(fsg, bh);
2722 + break;
2723 +
2724 + case MODE_SELECT_10:
2725 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2726 + if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
2727 + (1<<1) | (3<<7), 0,
2728 + "MODE SELECT(10)")) == 0)
2729 + reply = do_mode_select(fsg, bh);
2730 + break;
2731 +
2732 + case MODE_SENSE:
2733 + fsg->data_size_from_cmnd = fsg->cmnd[4];
2734 + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2735 + (1<<1) | (1<<2) | (1<<4), 0,
2736 + "MODE SENSE(6)")) == 0)
2737 + reply = do_mode_sense(fsg, bh);
2738 + break;
2739 +
2740 + case MODE_SENSE_10:
2741 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2742 + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2743 + (1<<1) | (1<<2) | (3<<7), 0,
2744 + "MODE SENSE(10)")) == 0)
2745 + reply = do_mode_sense(fsg, bh);
2746 + break;
2747 +
2748 + case ALLOW_MEDIUM_REMOVAL:
2749 + fsg->data_size_from_cmnd = 0;
2750 + if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2751 + (1<<4), 0,
2752 + "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
2753 + reply = do_prevent_allow(fsg);
2754 + break;
2755 +
2756 + case READ_6:
2757 + i = fsg->cmnd[4];
2758 + fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2759 + if ((reply = check_command_size_in_blocks(fsg, 6,
2760 + DATA_DIR_TO_HOST,
2761 + (7<<1) | (1<<4), 1,
2762 + "READ(6)")) == 0)
2763 + reply = do_read(fsg);
2764 + break;
2765 +
2766 + case READ_10:
2767 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2768 + if ((reply = check_command_size_in_blocks(fsg, 10,
2769 + DATA_DIR_TO_HOST,
2770 + (1<<1) | (0xf<<2) | (3<<7), 1,
2771 + "READ(10)")) == 0)
2772 + reply = do_read(fsg);
2773 + break;
2774 +
2775 + case READ_12:
2776 + fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2777 + if ((reply = check_command_size_in_blocks(fsg, 12,
2778 + DATA_DIR_TO_HOST,
2779 + (1<<1) | (0xf<<2) | (0xf<<6), 1,
2780 + "READ(12)")) == 0)
2781 + reply = do_read(fsg);
2782 + break;
2783 +
2784 + case READ_CAPACITY:
2785 + fsg->data_size_from_cmnd = 8;
2786 + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2787 + (0xf<<2) | (1<<8), 1,
2788 + "READ CAPACITY")) == 0)
2789 + reply = do_read_capacity(fsg, bh);
2790 + break;
2791 +
2792 + case READ_HEADER:
2793 + if (!mod_data.cdrom)
2794 + goto unknown_cmnd;
2795 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2796 + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2797 + (3<<7) | (0x1f<<1), 1,
2798 + "READ HEADER")) == 0)
2799 + reply = do_read_header(fsg, bh);
2800 + break;
2801 +
2802 + case READ_TOC:
2803 + if (!mod_data.cdrom)
2804 + goto unknown_cmnd;
2805 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2806 + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2807 + (7<<6) | (1<<1), 1,
2808 + "READ TOC")) == 0)
2809 + reply = do_read_toc(fsg, bh);
2810 + break;
2811 +
2812 + case READ_FORMAT_CAPACITIES:
2813 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2814 + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2815 + (3<<7), 1,
2816 + "READ FORMAT CAPACITIES")) == 0)
2817 + reply = do_read_format_capacities(fsg, bh);
2818 + break;
2819 +
2820 + case REQUEST_SENSE:
2821 + fsg->data_size_from_cmnd = fsg->cmnd[4];
2822 + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2823 + (1<<4), 0,
2824 + "REQUEST SENSE")) == 0)
2825 + reply = do_request_sense(fsg, bh);
2826 + break;
2827 +
2828 + case START_STOP:
2829 + fsg->data_size_from_cmnd = 0;
2830 + if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2831 + (1<<1) | (1<<4), 0,
2832 + "START-STOP UNIT")) == 0)
2833 + reply = do_start_stop(fsg);
2834 + break;
2835 +
2836 + case SYNCHRONIZE_CACHE:
2837 + fsg->data_size_from_cmnd = 0;
2838 + if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2839 + (0xf<<2) | (3<<7), 1,
2840 + "SYNCHRONIZE CACHE")) == 0)
2841 + reply = do_synchronize_cache(fsg);
2842 + break;
2843 +
2844 + case TEST_UNIT_READY:
2845 + fsg->data_size_from_cmnd = 0;
2846 + reply = check_command(fsg, 6, DATA_DIR_NONE,
2847 + 0, 1,
2848 + "TEST UNIT READY");
2849 + break;
2850 +
2851 + /* Although optional, this command is used by MS-Windows. We
2852 + * support a minimal version: BytChk must be 0. */
2853 + case VERIFY:
2854 + fsg->data_size_from_cmnd = 0;
2855 + if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2856 + (1<<1) | (0xf<<2) | (3<<7), 1,
2857 + "VERIFY")) == 0)
2858 + reply = do_verify(fsg);
2859 + break;
2860 +
2861 + case WRITE_6:
2862 + i = fsg->cmnd[4];
2863 + fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2864 + if ((reply = check_command_size_in_blocks(fsg, 6,
2865 + DATA_DIR_FROM_HOST,
2866 + (7<<1) | (1<<4), 1,
2867 + "WRITE(6)")) == 0)
2868 + reply = do_write(fsg);
2869 + break;
2870 +
2871 + case WRITE_10:
2872 + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2873 + if ((reply = check_command_size_in_blocks(fsg, 10,
2874 + DATA_DIR_FROM_HOST,
2875 + (1<<1) | (0xf<<2) | (3<<7), 1,
2876 + "WRITE(10)")) == 0)
2877 + reply = do_write(fsg);
2878 + break;
2879 +
2880 + case WRITE_12:
2881 + fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2882 + if ((reply = check_command_size_in_blocks(fsg, 12,
2883 + DATA_DIR_FROM_HOST,
2884 + (1<<1) | (0xf<<2) | (0xf<<6), 1,
2885 + "WRITE(12)")) == 0)
2886 + reply = do_write(fsg);
2887 + break;
2888 +
2889 + /* Some mandatory commands that we recognize but don't implement.
2890 + * They don't mean much in this setting. It's left as an exercise
2891 + * for anyone interested to implement RESERVE and RELEASE in terms
2892 + * of Posix locks. */
2893 + case FORMAT_UNIT:
2894 + case RELEASE:
2895 + case RESERVE:
2896 + case SEND_DIAGNOSTIC:
2897 + // Fall through
2898 +
2899 + default:
2900 + unknown_cmnd:
2901 + fsg->data_size_from_cmnd = 0;
2902 + sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
2903 + if ((reply = check_command(fsg, fsg->cmnd_size,
2904 + DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
2905 + fsg->curlun->sense_data = SS_INVALID_COMMAND;
2906 + reply = -EINVAL;
2907 + }
2908 + break;
2909 + }
2910 + up_read(&fsg->filesem);
2911 +
2912 + if (reply == -EINTR || signal_pending(current))
2913 + return -EINTR;
2914 +
2915 + /* Set up the single reply buffer for finish_reply() */
2916 + if (reply == -EINVAL)
2917 + reply = 0; // Error reply length
2918 + if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
2919 + reply = min((u32) reply, fsg->data_size_from_cmnd);
2920 + bh->inreq->length = reply;
2921 + bh->state = BUF_STATE_FULL;
2922 + fsg->residue -= reply;
2923 + } // Otherwise it's already set
2924 +
2925 + return 0;
2926 +}
2927 +
2928 +
2929 +/*-------------------------------------------------------------------------*/
2930 +
2931 +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2932 +{
2933 + struct usb_request *req = bh->outreq;
2934 + struct bulk_cb_wrap *cbw = req->buf;
2935 +
2936 + /* Was this a real packet? Should it be ignored? */
2937 + if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
2938 + return -EINVAL;
2939 +
2940 + /* Is the CBW valid? */
2941 + if (req->actual != US_BULK_CB_WRAP_LEN ||
2942 + cbw->Signature != cpu_to_le32(
2943 + US_BULK_CB_SIGN)) {
2944 + DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
2945 + req->actual,
2946 + le32_to_cpu(cbw->Signature));
2947 +
2948 + /* The Bulk-only spec says we MUST stall the IN endpoint
2949 + * (6.6.1), so it's unavoidable. It also says we must
2950 + * retain this state until the next reset, but there's
2951 + * no way to tell the controller driver it should ignore
2952 + * Clear-Feature(HALT) requests.
2953 + *
2954 + * We aren't required to halt the OUT endpoint; instead
2955 + * we can simply accept and discard any data received
2956 + * until the next reset. */
2957 + wedge_bulk_in_endpoint(fsg);
2958 + set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
2959 + return -EINVAL;
2960 + }
2961 +
2962 + /* Is the CBW meaningful? */
2963 + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
2964 + cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
2965 + DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
2966 + "cmdlen %u\n",
2967 + cbw->Lun, cbw->Flags, cbw->Length);
2968 +
2969 + /* We can do anything we want here, so let's stall the
2970 + * bulk pipes if we are allowed to. */
2971 + if (mod_data.can_stall) {
2972 + fsg_set_halt(fsg, fsg->bulk_out);
2973 + halt_bulk_in_endpoint(fsg);
2974 + }
2975 + return -EINVAL;
2976 + }
2977 +
2978 + /* Save the command for later */
2979 + fsg->cmnd_size = cbw->Length;
2980 + memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
2981 + if (cbw->Flags & US_BULK_FLAG_IN)
2982 + fsg->data_dir = DATA_DIR_TO_HOST;
2983 + else
2984 + fsg->data_dir = DATA_DIR_FROM_HOST;
2985 + fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
2986 + if (fsg->data_size == 0)
2987 + fsg->data_dir = DATA_DIR_NONE;
2988 + fsg->lun = cbw->Lun;
2989 + fsg->tag = cbw->Tag;
2990 + return 0;
2991 +}
2992 +
2993 +
2994 +static int get_next_command(struct fsg_dev *fsg)
2995 +{
2996 + struct fsg_buffhd *bh;
2997 + int rc = 0;
2998 +
2999 + if (transport_is_bbb()) {
3000 +
3001 + /* Wait for the next buffer to become available */
3002 + bh = fsg->next_buffhd_to_fill;
3003 + while (bh->state != BUF_STATE_EMPTY) {
3004 + rc = sleep_thread(fsg);
3005 + if (rc)
3006 + return rc;
3007 + }
3008 +
3009 + /* Queue a request to read a Bulk-only CBW */
3010 + set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
3011 + start_transfer(fsg, fsg->bulk_out, bh->outreq,
3012 + &bh->outreq_busy, &bh->state);
3013 +
3014 + /* We will drain the buffer in software, which means we
3015 + * can reuse it for the next filling. No need to advance
3016 + * next_buffhd_to_fill. */
3017 +
3018 + /* Wait for the CBW to arrive */
3019 + while (bh->state != BUF_STATE_FULL) {
3020 + rc = sleep_thread(fsg);
3021 + if (rc)
3022 + return rc;
3023 + }
3024 + smp_rmb();
3025 + rc = received_cbw(fsg, bh);
3026 + bh->state = BUF_STATE_EMPTY;
3027 +
3028 + } else { // USB_PR_CB or USB_PR_CBI
3029 +
3030 + /* Wait for the next command to arrive */
3031 + while (fsg->cbbuf_cmnd_size == 0) {
3032 + rc = sleep_thread(fsg);
3033 + if (rc)
3034 + return rc;
3035 + }
3036 +
3037 + /* Is the previous status interrupt request still busy?
3038 + * The host is allowed to skip reading the status,
3039 + * so we must cancel it. */
3040 + if (fsg->intreq_busy)
3041 + usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3042 +
3043 + /* Copy the command and mark the buffer empty */
3044 + fsg->data_dir = DATA_DIR_UNKNOWN;
3045 + spin_lock_irq(&fsg->lock);
3046 + fsg->cmnd_size = fsg->cbbuf_cmnd_size;
3047 + memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
3048 + fsg->cbbuf_cmnd_size = 0;
3049 + spin_unlock_irq(&fsg->lock);
3050 +
3051 + /* Use LUN from the command */
3052 + fsg->lun = fsg->cmnd[1] >> 5;
3053 + }
3054 +
3055 + /* Update current lun */
3056 + if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
3057 + fsg->curlun = &fsg->luns[fsg->lun];
3058 + else
3059 + fsg->curlun = NULL;
3060 +
3061 + return rc;
3062 +}
3063 +
3064 +
3065 +/*-------------------------------------------------------------------------*/
3066 +
3067 +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
3068 + const struct usb_endpoint_descriptor *d)
3069 +{
3070 + int rc;
3071 +
3072 + ep->driver_data = fsg;
3073 + ep->desc = d;
3074 + rc = usb_ep_enable(ep);
3075 + if (rc)
3076 + ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
3077 + return rc;
3078 +}
3079 +
3080 +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
3081 + struct usb_request **preq)
3082 +{
3083 + *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
3084 + if (*preq)
3085 + return 0;
3086 + ERROR(fsg, "can't allocate request for %s\n", ep->name);
3087 + return -ENOMEM;
3088 +}
3089 +
3090 +/*
3091 + * Reset interface setting and re-init endpoint state (toggle etc).
3092 + * Call with altsetting < 0 to disable the interface. The only other
3093 + * available altsetting is 0, which enables the interface.
3094 + */
3095 +static int do_set_interface(struct fsg_dev *fsg, int altsetting)
3096 +{
3097 + int rc = 0;
3098 + int i;
3099 + const struct usb_endpoint_descriptor *d;
3100 +
3101 + if (fsg->running)
3102 + DBG(fsg, "reset interface\n");
3103 +
3104 +reset:
3105 + /* Deallocate the requests */
3106 + for (i = 0; i < fsg_num_buffers; ++i) {
3107 + struct fsg_buffhd *bh = &fsg->buffhds[i];
3108 +
3109 + if (bh->inreq) {
3110 + usb_ep_free_request(fsg->bulk_in, bh->inreq);
3111 + bh->inreq = NULL;
3112 + }
3113 + if (bh->outreq) {
3114 + usb_ep_free_request(fsg->bulk_out, bh->outreq);
3115 + bh->outreq = NULL;
3116 + }
3117 + }
3118 + if (fsg->intreq) {
3119 + usb_ep_free_request(fsg->intr_in, fsg->intreq);
3120 + fsg->intreq = NULL;
3121 + }
3122 +
3123 + /* Disable the endpoints */
3124 + if (fsg->bulk_in_enabled) {
3125 + usb_ep_disable(fsg->bulk_in);
3126 + fsg->bulk_in_enabled = 0;
3127 + }
3128 + if (fsg->bulk_out_enabled) {
3129 + usb_ep_disable(fsg->bulk_out);
3130 + fsg->bulk_out_enabled = 0;
3131 + }
3132 + if (fsg->intr_in_enabled) {
3133 + usb_ep_disable(fsg->intr_in);
3134 + fsg->intr_in_enabled = 0;
3135 + }
3136 +
3137 + fsg->running = 0;
3138 + if (altsetting < 0 || rc != 0)
3139 + return rc;
3140 +
3141 + DBG(fsg, "set interface %d\n", altsetting);
3142 +
3143 + /* Enable the endpoints */
3144 + d = fsg_ep_desc(fsg->gadget,
3145 + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
3146 + &fsg_ss_bulk_in_desc);
3147 + if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
3148 + goto reset;
3149 + fsg->bulk_in_enabled = 1;
3150 +
3151 + d = fsg_ep_desc(fsg->gadget,
3152 + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
3153 + &fsg_ss_bulk_out_desc);
3154 + if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
3155 + goto reset;
3156 + fsg->bulk_out_enabled = 1;
3157 + fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
3158 + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3159 +
3160 + if (transport_is_cbi()) {
3161 + d = fsg_ep_desc(fsg->gadget,
3162 + &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
3163 + &fsg_ss_intr_in_desc);
3164 + if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
3165 + goto reset;
3166 + fsg->intr_in_enabled = 1;
3167 + }
3168 +
3169 + /* Allocate the requests */
3170 + for (i = 0; i < fsg_num_buffers; ++i) {
3171 + struct fsg_buffhd *bh = &fsg->buffhds[i];
3172 +
3173 + if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
3174 + goto reset;
3175 + if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
3176 + goto reset;
3177 + bh->inreq->buf = bh->outreq->buf = bh->buf;
3178 + bh->inreq->context = bh->outreq->context = bh;
3179 + bh->inreq->complete = bulk_in_complete;
3180 + bh->outreq->complete = bulk_out_complete;
3181 + }
3182 + if (transport_is_cbi()) {
3183 + if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
3184 + goto reset;
3185 + fsg->intreq->complete = intr_in_complete;
3186 + }
3187 +
3188 + fsg->running = 1;
3189 + for (i = 0; i < fsg->nluns; ++i)
3190 + fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3191 + return rc;
3192 +}
3193 +
3194 +
3195 +/*
3196 + * Change our operational configuration. This code must agree with the code
3197 + * that returns config descriptors, and with interface altsetting code.
3198 + *
3199 + * It's also responsible for power management interactions. Some
3200 + * configurations might not work with our current power sources.
3201 + * For now we just assume the gadget is always self-powered.
3202 + */
3203 +static int do_set_config(struct fsg_dev *fsg, u8 new_config)
3204 +{
3205 + int rc = 0;
3206 +
3207 + /* Disable the single interface */
3208 + if (fsg->config != 0) {
3209 + DBG(fsg, "reset config\n");
3210 + fsg->config = 0;
3211 + rc = do_set_interface(fsg, -1);
3212 + }
3213 +
3214 + /* Enable the interface */
3215 + if (new_config != 0) {
3216 + fsg->config = new_config;
3217 + if ((rc = do_set_interface(fsg, 0)) != 0)
3218 + fsg->config = 0; // Reset on errors
3219 + else
3220 + INFO(fsg, "%s config #%d\n",
3221 + usb_speed_string(fsg->gadget->speed),
3222 + fsg->config);
3223 + }
3224 + return rc;
3225 +}
3226 +
3227 +
3228 +/*-------------------------------------------------------------------------*/
3229 +
3230 +static void handle_exception(struct fsg_dev *fsg)
3231 +{
3232 + siginfo_t info;
3233 + int sig;
3234 + int i;
3235 + int num_active;
3236 + struct fsg_buffhd *bh;
3237 + enum fsg_state old_state;
3238 + u8 new_config;
3239 + struct fsg_lun *curlun;
3240 + unsigned int exception_req_tag;
3241 + int rc;
3242 +
3243 + /* Clear the existing signals. Anything but SIGUSR1 is converted
3244 + * into a high-priority EXIT exception. */
3245 + for (;;) {
3246 + sig = dequeue_signal_lock(current, &current->blocked, &info);
3247 + if (!sig)
3248 + break;
3249 + if (sig != SIGUSR1) {
3250 + if (fsg->state < FSG_STATE_EXIT)
3251 + DBG(fsg, "Main thread exiting on signal\n");
3252 + raise_exception(fsg, FSG_STATE_EXIT);
3253 + }
3254 + }
3255 +
3256 + /* Cancel all the pending transfers */
3257 + if (fsg->intreq_busy)
3258 + usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3259 + for (i = 0; i < fsg_num_buffers; ++i) {
3260 + bh = &fsg->buffhds[i];
3261 + if (bh->inreq_busy)
3262 + usb_ep_dequeue(fsg->bulk_in, bh->inreq);
3263 + if (bh->outreq_busy)
3264 + usb_ep_dequeue(fsg->bulk_out, bh->outreq);
3265 + }
3266 +
3267 + /* Wait until everything is idle */
3268 + for (;;) {
3269 + num_active = fsg->intreq_busy;
3270 + for (i = 0; i < fsg_num_buffers; ++i) {
3271 + bh = &fsg->buffhds[i];
3272 + num_active += bh->inreq_busy + bh->outreq_busy;
3273 + }
3274 + if (num_active == 0)
3275 + break;
3276 + if (sleep_thread(fsg))
3277 + return;
3278 + }
3279 +
3280 + /* Clear out the controller's fifos */
3281 + if (fsg->bulk_in_enabled)
3282 + usb_ep_fifo_flush(fsg->bulk_in);
3283 + if (fsg->bulk_out_enabled)
3284 + usb_ep_fifo_flush(fsg->bulk_out);
3285 + if (fsg->intr_in_enabled)
3286 + usb_ep_fifo_flush(fsg->intr_in);
3287 +
3288 + /* Reset the I/O buffer states and pointers, the SCSI
3289 + * state, and the exception. Then invoke the handler. */
3290 + spin_lock_irq(&fsg->lock);
3291 +
3292 + for (i = 0; i < fsg_num_buffers; ++i) {
3293 + bh = &fsg->buffhds[i];
3294 + bh->state = BUF_STATE_EMPTY;
3295 + }
3296 + fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
3297 + &fsg->buffhds[0];
3298 +
3299 + exception_req_tag = fsg->exception_req_tag;
3300 + new_config = fsg->new_config;
3301 + old_state = fsg->state;
3302 +
3303 + if (old_state == FSG_STATE_ABORT_BULK_OUT)
3304 + fsg->state = FSG_STATE_STATUS_PHASE;
3305 + else {
3306 + for (i = 0; i < fsg->nluns; ++i) {
3307 + curlun = &fsg->luns[i];
3308 + curlun->prevent_medium_removal = 0;
3309 + curlun->sense_data = curlun->unit_attention_data =
3310 + SS_NO_SENSE;
3311 + curlun->sense_data_info = 0;
3312 + curlun->info_valid = 0;
3313 + }
3314 + fsg->state = FSG_STATE_IDLE;
3315 + }
3316 + spin_unlock_irq(&fsg->lock);
3317 +
3318 + /* Carry out any extra actions required for the exception */
3319 + switch (old_state) {
3320 + default:
3321 + break;
3322 +
3323 + case FSG_STATE_ABORT_BULK_OUT:
3324 + send_status(fsg);
3325 + spin_lock_irq(&fsg->lock);
3326 + if (fsg->state == FSG_STATE_STATUS_PHASE)
3327 + fsg->state = FSG_STATE_IDLE;
3328 + spin_unlock_irq(&fsg->lock);
3329 + break;
3330 +
3331 + case FSG_STATE_RESET:
3332 + /* In case we were forced against our will to halt a
3333 + * bulk endpoint, clear the halt now. (The SuperH UDC
3334 + * requires this.) */
3335 + if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3336 + usb_ep_clear_halt(fsg->bulk_in);
3337 +
3338 + if (transport_is_bbb()) {
3339 + if (fsg->ep0_req_tag == exception_req_tag)
3340 + ep0_queue(fsg); // Complete the status stage
3341 +
3342 + } else if (transport_is_cbi())
3343 + send_status(fsg); // Status by interrupt pipe
3344 +
3345 + /* Technically this should go here, but it would only be
3346 + * a waste of time. Ditto for the INTERFACE_CHANGE and
3347 + * CONFIG_CHANGE cases. */
3348 + // for (i = 0; i < fsg->nluns; ++i)
3349 + // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3350 + break;
3351 +
3352 + case FSG_STATE_INTERFACE_CHANGE:
3353 + rc = do_set_interface(fsg, 0);
3354 + if (fsg->ep0_req_tag != exception_req_tag)
3355 + break;
3356 + if (rc != 0) // STALL on errors
3357 + fsg_set_halt(fsg, fsg->ep0);
3358 + else // Complete the status stage
3359 + ep0_queue(fsg);
3360 + break;
3361 +
3362 + case FSG_STATE_CONFIG_CHANGE:
3363 + rc = do_set_config(fsg, new_config);
3364 + if (fsg->ep0_req_tag != exception_req_tag)
3365 + break;
3366 + if (rc != 0) // STALL on errors
3367 + fsg_set_halt(fsg, fsg->ep0);
3368 + else // Complete the status stage
3369 + ep0_queue(fsg);
3370 + break;
3371 +
3372 + case FSG_STATE_DISCONNECT:
3373 + for (i = 0; i < fsg->nluns; ++i)
3374 + fsg_lun_fsync_sub(fsg->luns + i);
3375 + do_set_config(fsg, 0); // Unconfigured state
3376 + break;
3377 +
3378 + case FSG_STATE_EXIT:
3379 + case FSG_STATE_TERMINATED:
3380 + do_set_config(fsg, 0); // Free resources
3381 + spin_lock_irq(&fsg->lock);
3382 + fsg->state = FSG_STATE_TERMINATED; // Stop the thread
3383 + spin_unlock_irq(&fsg->lock);
3384 + break;
3385 + }
3386 +}
3387 +
3388 +
3389 +/*-------------------------------------------------------------------------*/
3390 +
3391 +static int fsg_main_thread(void *fsg_)
3392 +{
3393 + struct fsg_dev *fsg = fsg_;
3394 +
3395 + /* Allow the thread to be killed by a signal, but set the signal mask
3396 + * to block everything but INT, TERM, KILL, and USR1. */
3397 + allow_signal(SIGINT);
3398 + allow_signal(SIGTERM);
3399 + allow_signal(SIGKILL);
3400 + allow_signal(SIGUSR1);
3401 +
3402 + /* Allow the thread to be frozen */
3403 + set_freezable();
3404 +
3405 + /* Arrange for userspace references to be interpreted as kernel
3406 + * pointers. That way we can pass a kernel pointer to a routine
3407 + * that expects a __user pointer and it will work okay. */
3408 + set_fs(get_ds());
3409 +
3410 + /* The main loop */
3411 + while (fsg->state != FSG_STATE_TERMINATED) {
3412 + if (exception_in_progress(fsg) || signal_pending(current)) {
3413 + handle_exception(fsg);
3414 + continue;
3415 + }
3416 +
3417 + if (!fsg->running) {
3418 + sleep_thread(fsg);
3419 + continue;
3420 + }
3421 +
3422 + if (get_next_command(fsg))
3423 + continue;
3424 +
3425 + spin_lock_irq(&fsg->lock);
3426 + if (!exception_in_progress(fsg))
3427 + fsg->state = FSG_STATE_DATA_PHASE;
3428 + spin_unlock_irq(&fsg->lock);
3429 +
3430 + if (do_scsi_command(fsg) || finish_reply(fsg))
3431 + continue;
3432 +
3433 + spin_lock_irq(&fsg->lock);
3434 + if (!exception_in_progress(fsg))
3435 + fsg->state = FSG_STATE_STATUS_PHASE;
3436 + spin_unlock_irq(&fsg->lock);
3437 +
3438 + if (send_status(fsg))
3439 + continue;
3440 +
3441 + spin_lock_irq(&fsg->lock);
3442 + if (!exception_in_progress(fsg))
3443 + fsg->state = FSG_STATE_IDLE;
3444 + spin_unlock_irq(&fsg->lock);
3445 + }
3446 +
3447 + spin_lock_irq(&fsg->lock);
3448 + fsg->thread_task = NULL;
3449 + spin_unlock_irq(&fsg->lock);
3450 +
3451 + /* If we are exiting because of a signal, unregister the
3452 + * gadget driver. */
3453 + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
3454 + usb_gadget_unregister_driver(&fsg_driver);
3455 +
3456 + /* Let the unbind and cleanup routines know the thread has exited */
3457 + complete_and_exit(&fsg->thread_notifier, 0);
3458 +}
3459 +
3460 +
3461 +/*-------------------------------------------------------------------------*/
3462 +
3463 +
3464 +/* The write permissions and store_xxx pointers are set in fsg_bind() */
3465 +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
3466 +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
3467 +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
3468 +
3469 +
3470 +/*-------------------------------------------------------------------------*/
3471 +
3472 +static void fsg_release(struct kref *ref)
3473 +{
3474 + struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
3475 +
3476 + kfree(fsg->luns);
3477 + kfree(fsg);
3478 +}
3479 +
3480 +static void lun_release(struct device *dev)
3481 +{
3482 + struct rw_semaphore *filesem = dev_get_drvdata(dev);
3483 + struct fsg_dev *fsg =
3484 + container_of(filesem, struct fsg_dev, filesem);
3485 +
3486 + kref_put(&fsg->ref, fsg_release);
3487 +}
3488 +
3489 +static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
3490 +{
3491 + struct fsg_dev *fsg = get_gadget_data(gadget);
3492 + int i;
3493 + struct fsg_lun *curlun;
3494 + struct usb_request *req = fsg->ep0req;
3495 +
3496 + DBG(fsg, "unbind\n");
3497 + clear_bit(REGISTERED, &fsg->atomic_bitflags);
3498 +
3499 + /* If the thread isn't already dead, tell it to exit now */
3500 + if (fsg->state != FSG_STATE_TERMINATED) {
3501 + raise_exception(fsg, FSG_STATE_EXIT);
3502 + wait_for_completion(&fsg->thread_notifier);
3503 +
3504 + /* The cleanup routine waits for this completion also */
3505 + complete(&fsg->thread_notifier);
3506 + }
3507 +
3508 + /* Unregister the sysfs attribute files and the LUNs */
3509 + for (i = 0; i < fsg->nluns; ++i) {
3510 + curlun = &fsg->luns[i];
3511 + if (curlun->registered) {
3512 + device_remove_file(&curlun->dev, &dev_attr_nofua);
3513 + device_remove_file(&curlun->dev, &dev_attr_ro);
3514 + device_remove_file(&curlun->dev, &dev_attr_file);
3515 + fsg_lun_close(curlun);
3516 + device_unregister(&curlun->dev);
3517 + curlun->registered = 0;
3518 + }
3519 + }
3520 +
3521 + /* Free the data buffers */
3522 + for (i = 0; i < fsg_num_buffers; ++i)
3523 + kfree(fsg->buffhds[i].buf);
3524 +
3525 + /* Free the request and buffer for endpoint 0 */
3526 + if (req) {
3527 + kfree(req->buf);
3528 + usb_ep_free_request(fsg->ep0, req);
3529 + }
3530 +
3531 + set_gadget_data(gadget, NULL);
3532 +}
3533 +
3534 +
3535 +static int __init check_parameters(struct fsg_dev *fsg)
3536 +{
3537 + int prot;
3538 + int gcnum;
3539 +
3540 + /* Store the default values */
3541 + mod_data.transport_type = USB_PR_BULK;
3542 + mod_data.transport_name = "Bulk-only";
3543 + mod_data.protocol_type = USB_SC_SCSI;
3544 + mod_data.protocol_name = "Transparent SCSI";
3545 +
3546 + /* Some peripheral controllers are known not to be able to
3547 + * halt bulk endpoints correctly. If one of them is present,
3548 + * disable stalls.
3549 + */
3550 + if (gadget_is_at91(fsg->gadget))
3551 + mod_data.can_stall = 0;
3552 +
3553 + if (mod_data.release == 0xffff) { // Parameter wasn't set
3554 + gcnum = usb_gadget_controller_number(fsg->gadget);
3555 + if (gcnum >= 0)
3556 + mod_data.release = 0x0300 + gcnum;
3557 + else {
3558 + WARNING(fsg, "controller '%s' not recognized\n",
3559 + fsg->gadget->name);
3560 + mod_data.release = 0x0399;
3561 + }
3562 + }
3563 +
3564 + prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
3565 +
3566 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
3567 + if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
3568 + ; // Use default setting
3569 + } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
3570 + mod_data.transport_type = USB_PR_CB;
3571 + mod_data.transport_name = "Control-Bulk";
3572 + } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
3573 + mod_data.transport_type = USB_PR_CBI;
3574 + mod_data.transport_name = "Control-Bulk-Interrupt";
3575 + } else {
3576 + ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
3577 + return -EINVAL;
3578 + }
3579 +
3580 + if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
3581 + prot == USB_SC_SCSI) {
3582 + ; // Use default setting
3583 + } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
3584 + prot == USB_SC_RBC) {
3585 + mod_data.protocol_type = USB_SC_RBC;
3586 + mod_data.protocol_name = "RBC";
3587 + } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
3588 + strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
3589 + prot == USB_SC_8020) {
3590 + mod_data.protocol_type = USB_SC_8020;
3591 + mod_data.protocol_name = "8020i (ATAPI)";
3592 + } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
3593 + prot == USB_SC_QIC) {
3594 + mod_data.protocol_type = USB_SC_QIC;
3595 + mod_data.protocol_name = "QIC-157";
3596 + } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
3597 + prot == USB_SC_UFI) {
3598 + mod_data.protocol_type = USB_SC_UFI;
3599 + mod_data.protocol_name = "UFI";
3600 + } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
3601 + prot == USB_SC_8070) {
3602 + mod_data.protocol_type = USB_SC_8070;
3603 + mod_data.protocol_name = "8070i";
3604 + } else {
3605 + ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
3606 + return -EINVAL;
3607 + }
3608 +
3609 + mod_data.buflen &= PAGE_CACHE_MASK;
3610 + if (mod_data.buflen <= 0) {
3611 + ERROR(fsg, "invalid buflen\n");
3612 + return -ETOOSMALL;
3613 + }
3614 +
3615 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
3616 +
3617 + /* Serial string handling.
3618 + * On a real device, the serial string would be loaded
3619 + * from permanent storage. */
3620 + if (mod_data.serial) {
3621 + const char *ch;
3622 + unsigned len = 0;
3623 +
3624 + /* Sanity check :
3625 + * The CB[I] specification limits the serial string to
3626 + * 12 uppercase hexadecimal characters.
3627 + * BBB need at least 12 uppercase hexadecimal characters,
3628 + * with a maximum of 126. */
3629 + for (ch = mod_data.serial; *ch; ++ch) {
3630 + ++len;
3631 + if ((*ch < '0' || *ch > '9') &&
3632 + (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
3633 + WARNING(fsg,
3634 + "Invalid serial string character: %c\n",
3635 + *ch);
3636 + goto no_serial;
3637 + }
3638 + }
3639 + if (len > 126 ||
3640 + (mod_data.transport_type == USB_PR_BULK && len < 12) ||
3641 + (mod_data.transport_type != USB_PR_BULK && len > 12)) {
3642 + WARNING(fsg, "Invalid serial string length!\n");
3643 + goto no_serial;
3644 + }
3645 + fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
3646 + } else {
3647 + WARNING(fsg, "No serial-number string provided!\n");
3648 + no_serial:
3649 + device_desc.iSerialNumber = 0;
3650 + }
3651 +
3652 + return 0;
3653 +}
3654 +
3655 +
3656 +static int __init fsg_bind(struct usb_gadget *gadget)
3657 +{
3658 + struct fsg_dev *fsg = the_fsg;
3659 + int rc;
3660 + int i;
3661 + struct fsg_lun *curlun;
3662 + struct usb_ep *ep;
3663 + struct usb_request *req;
3664 + char *pathbuf, *p;
3665 +
3666 + fsg->gadget = gadget;
3667 + set_gadget_data(gadget, fsg);
3668 + fsg->ep0 = gadget->ep0;
3669 + fsg->ep0->driver_data = fsg;
3670 +
3671 + if ((rc = check_parameters(fsg)) != 0)
3672 + goto out;
3673 +
3674 + if (mod_data.removable) { // Enable the store_xxx attributes
3675 + dev_attr_file.attr.mode = 0644;
3676 + dev_attr_file.store = fsg_store_file;
3677 + if (!mod_data.cdrom) {
3678 + dev_attr_ro.attr.mode = 0644;
3679 + dev_attr_ro.store = fsg_store_ro;
3680 + }
3681 + }
3682 +
3683 + /* Only for removable media? */
3684 + dev_attr_nofua.attr.mode = 0644;
3685 + dev_attr_nofua.store = fsg_store_nofua;
3686 +
3687 + /* Find out how many LUNs there should be */
3688 + i = mod_data.nluns;
3689 + if (i == 0)
3690 + i = max(mod_data.num_filenames, 1u);
3691 + if (i > FSG_MAX_LUNS) {
3692 + ERROR(fsg, "invalid number of LUNs: %d\n", i);
3693 + rc = -EINVAL;
3694 + goto out;
3695 + }
3696 +
3697 + /* Create the LUNs, open their backing files, and register the
3698 + * LUN devices in sysfs. */
3699 + fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
3700 + if (!fsg->luns) {
3701 + rc = -ENOMEM;
3702 + goto out;
3703 + }
3704 + fsg->nluns = i;
3705 +
3706 + for (i = 0; i < fsg->nluns; ++i) {
3707 + curlun = &fsg->luns[i];
3708 + curlun->cdrom = !!mod_data.cdrom;
3709 + curlun->ro = mod_data.cdrom || mod_data.ro[i];
3710 + curlun->initially_ro = curlun->ro;
3711 + curlun->removable = mod_data.removable;
3712 + curlun->nofua = mod_data.nofua[i];
3713 + curlun->dev.release = lun_release;
3714 + curlun->dev.parent = &gadget->dev;
3715 + curlun->dev.driver = &fsg_driver.driver;
3716 + dev_set_drvdata(&curlun->dev, &fsg->filesem);
3717 + dev_set_name(&curlun->dev,"%s-lun%d",
3718 + dev_name(&gadget->dev), i);
3719 +
3720 + kref_get(&fsg->ref);
3721 + rc = device_register(&curlun->dev);
3722 + if (rc) {
3723 + INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
3724 + put_device(&curlun->dev);
3725 + goto out;
3726 + }
3727 + curlun->registered = 1;
3728 +
3729 + rc = device_create_file(&curlun->dev, &dev_attr_ro);
3730 + if (rc)
3731 + goto out;
3732 + rc = device_create_file(&curlun->dev, &dev_attr_nofua);
3733 + if (rc)
3734 + goto out;
3735 + rc = device_create_file(&curlun->dev, &dev_attr_file);
3736 + if (rc)
3737 + goto out;
3738 +
3739 + if (mod_data.file[i] && *mod_data.file[i]) {
3740 + rc = fsg_lun_open(curlun, mod_data.file[i]);
3741 + if (rc)
3742 + goto out;
3743 + } else if (!mod_data.removable) {
3744 + ERROR(fsg, "no file given for LUN%d\n", i);
3745 + rc = -EINVAL;
3746 + goto out;
3747 + }
3748 + }
3749 +
3750 + /* Find all the endpoints we will use */
3751 + usb_ep_autoconfig_reset(gadget);
3752 + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
3753 + if (!ep)
3754 + goto autoconf_fail;
3755 + ep->driver_data = fsg; // claim the endpoint
3756 + fsg->bulk_in = ep;
3757 +
3758 + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
3759 + if (!ep)
3760 + goto autoconf_fail;
3761 + ep->driver_data = fsg; // claim the endpoint
3762 + fsg->bulk_out = ep;
3763 +
3764 + if (transport_is_cbi()) {
3765 + ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
3766 + if (!ep)
3767 + goto autoconf_fail;
3768 + ep->driver_data = fsg; // claim the endpoint
3769 + fsg->intr_in = ep;
3770 + }
3771 +
3772 + /* Fix up the descriptors */
3773 + device_desc.idVendor = cpu_to_le16(mod_data.vendor);
3774 + device_desc.idProduct = cpu_to_le16(mod_data.product);
3775 + device_desc.bcdDevice = cpu_to_le16(mod_data.release);
3776 +
3777 + i = (transport_is_cbi() ? 3 : 2); // Number of endpoints
3778 + fsg_intf_desc.bNumEndpoints = i;
3779 + fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
3780 + fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
3781 + fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3782 +
3783 + if (gadget_is_dualspeed(gadget)) {
3784 + fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3785 +
3786 + /* Assume endpoint addresses are the same for both speeds */
3787 + fsg_hs_bulk_in_desc.bEndpointAddress =
3788 + fsg_fs_bulk_in_desc.bEndpointAddress;
3789 + fsg_hs_bulk_out_desc.bEndpointAddress =
3790 + fsg_fs_bulk_out_desc.bEndpointAddress;
3791 + fsg_hs_intr_in_desc.bEndpointAddress =
3792 + fsg_fs_intr_in_desc.bEndpointAddress;
3793 + }
3794 +
3795 + if (gadget_is_superspeed(gadget)) {
3796 + unsigned max_burst;
3797 +
3798 + fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3799 +
3800 + /* Calculate bMaxBurst, we know packet size is 1024 */
3801 + max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
3802 +
3803 + /* Assume endpoint addresses are the same for both speeds */
3804 + fsg_ss_bulk_in_desc.bEndpointAddress =
3805 + fsg_fs_bulk_in_desc.bEndpointAddress;
3806 + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
3807 +
3808 + fsg_ss_bulk_out_desc.bEndpointAddress =
3809 + fsg_fs_bulk_out_desc.bEndpointAddress;
3810 + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
3811 + }
3812 +
3813 + if (gadget_is_otg(gadget))
3814 + fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
3815 +
3816 + rc = -ENOMEM;
3817 +
3818 + /* Allocate the request and buffer for endpoint 0 */
3819 + fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
3820 + if (!req)
3821 + goto out;
3822 + req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
3823 + if (!req->buf)
3824 + goto out;
3825 + req->complete = ep0_complete;
3826 +
3827 + /* Allocate the data buffers */
3828 + for (i = 0; i < fsg_num_buffers; ++i) {
3829 + struct fsg_buffhd *bh = &fsg->buffhds[i];
3830 +
3831 + /* Allocate for the bulk-in endpoint. We assume that
3832 + * the buffer will also work with the bulk-out (and
3833 + * interrupt-in) endpoint. */
3834 + bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
3835 + if (!bh->buf)
3836 + goto out;
3837 + bh->next = bh + 1;
3838 + }
3839 + fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
3840 +
3841 + /* This should reflect the actual gadget power source */
3842 + usb_gadget_set_selfpowered(gadget);
3843 +
3844 + snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
3845 + "%s %s with %s",
3846 + init_utsname()->sysname, init_utsname()->release,
3847 + gadget->name);
3848 +
3849 + fsg->thread_task = kthread_create(fsg_main_thread, fsg,
3850 + "file-storage-gadget");
3851 + if (IS_ERR(fsg->thread_task)) {
3852 + rc = PTR_ERR(fsg->thread_task);
3853 + goto out;
3854 + }
3855 +
3856 + INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
3857 + INFO(fsg, "NOTE: This driver is deprecated. "
3858 + "Consider using g_mass_storage instead.\n");
3859 + INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
3860 +
3861 + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
3862 + for (i = 0; i < fsg->nluns; ++i) {
3863 + curlun = &fsg->luns[i];
3864 + if (fsg_lun_is_open(curlun)) {
3865 + p = NULL;
3866 + if (pathbuf) {
3867 + p = d_path(&curlun->filp->f_path,
3868 + pathbuf, PATH_MAX);
3869 + if (IS_ERR(p))
3870 + p = NULL;
3871 + }
3872 + LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
3873 + curlun->ro, curlun->nofua, (p ? p : "(error)"));
3874 + }
3875 + }
3876 + kfree(pathbuf);
3877 +
3878 + DBG(fsg, "transport=%s (x%02x)\n",
3879 + mod_data.transport_name, mod_data.transport_type);
3880 + DBG(fsg, "protocol=%s (x%02x)\n",
3881 + mod_data.protocol_name, mod_data.protocol_type);
3882 + DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
3883 + mod_data.vendor, mod_data.product, mod_data.release);
3884 + DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
3885 + mod_data.removable, mod_data.can_stall,
3886 + mod_data.cdrom, mod_data.buflen);
3887 + DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
3888 +
3889 + set_bit(REGISTERED, &fsg->atomic_bitflags);
3890 +
3891 + /* Tell the thread to start working */
3892 + wake_up_process(fsg->thread_task);
3893 + return 0;
3894 +
3895 +autoconf_fail:
3896 + ERROR(fsg, "unable to autoconfigure all endpoints\n");
3897 + rc = -ENOTSUPP;
3898 +
3899 +out:
3900 + fsg->state = FSG_STATE_TERMINATED; // The thread is dead
3901 + fsg_unbind(gadget);
3902 + complete(&fsg->thread_notifier);
3903 + return rc;
3904 +}
3905 +
3906 +
3907 +/*-------------------------------------------------------------------------*/
3908 +
3909 +static void fsg_suspend(struct usb_gadget *gadget)
3910 +{
3911 + struct fsg_dev *fsg = get_gadget_data(gadget);
3912 +
3913 + DBG(fsg, "suspend\n");
3914 + set_bit(SUSPENDED, &fsg->atomic_bitflags);
3915 +}
3916 +
3917 +static void fsg_resume(struct usb_gadget *gadget)
3918 +{
3919 + struct fsg_dev *fsg = get_gadget_data(gadget);
3920 +
3921 + DBG(fsg, "resume\n");
3922 + clear_bit(SUSPENDED, &fsg->atomic_bitflags);
3923 +}
3924 +
3925 +
3926 +/*-------------------------------------------------------------------------*/
3927 +
3928 +static struct usb_gadget_driver fsg_driver = {
3929 + .max_speed = USB_SPEED_SUPER,
3930 + .function = (char *) fsg_string_product,
3931 + .unbind = fsg_unbind,
3932 + .disconnect = fsg_disconnect,
3933 + .setup = fsg_setup,
3934 + .suspend = fsg_suspend,
3935 + .resume = fsg_resume,
3936 +
3937 + .driver = {
3938 + .name = DRIVER_NAME,
3939 + .owner = THIS_MODULE,
3940 + // .release = ...
3941 + // .suspend = ...
3942 + // .resume = ...
3943 + },
3944 +};
3945 +
3946 +
3947 +static int __init fsg_alloc(void)
3948 +{
3949 + struct fsg_dev *fsg;
3950 +
3951 + fsg = kzalloc(sizeof *fsg +
3952 + fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
3953 +
3954 + if (!fsg)
3955 + return -ENOMEM;
3956 + spin_lock_init(&fsg->lock);
3957 + init_rwsem(&fsg->filesem);
3958 + kref_init(&fsg->ref);
3959 + init_completion(&fsg->thread_notifier);
3960 +
3961 + the_fsg = fsg;
3962 + return 0;
3963 +}
3964 +
3965 +
3966 +static int __init fsg_init(void)
3967 +{
3968 + int rc;
3969 + struct fsg_dev *fsg;
3970 +
3971 + rc = fsg_num_buffers_validate();
3972 + if (rc != 0)
3973 + return rc;
3974 +
3975 + if ((rc = fsg_alloc()) != 0)
3976 + return rc;
3977 + fsg = the_fsg;
3978 + if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
3979 + kref_put(&fsg->ref, fsg_release);
3980 + return rc;
3981 +}
3982 +module_init(fsg_init);
3983 +
3984 +
3985 +static void __exit fsg_cleanup(void)
3986 +{
3987 + struct fsg_dev *fsg = the_fsg;
3988 +
3989 + /* Unregister the driver iff the thread hasn't already done so */
3990 + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
3991 + usb_gadget_unregister_driver(&fsg_driver);
3992 +
3993 + /* Wait for the thread to finish up */
3994 + wait_for_completion(&fsg->thread_notifier);
3995 +
3996 + kref_put(&fsg->ref, fsg_release);
3997 +}
3998 +module_exit(fsg_cleanup);
3999 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/changes.txt linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/changes.txt
4000 --- linux-3.10/drivers/usb/host/dwc_common_port/changes.txt 1970-01-01 01:00:00.000000000 +0100
4001 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/changes.txt 2013-07-06 15:25:50.000000000 +0100
4002 @@ -0,0 +1,174 @@
4003 +
4004 +dwc_read_reg32() and friends now take an additional parameter, a pointer to an
4005 +IO context struct. The IO context struct should live in an os-dependent struct
4006 +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct
4007 +named 'os_dep' embedded in the main device struct. So there these calls look
4008 +like this:
4009 +
4010 + dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);
4011 +
4012 + dwc_write_reg32(&usb3_dev->os_dep.ioctx,
4013 + &pcd->dev_global_regs->dcfg, 0);
4014 +
4015 +Note that for the existing Linux driver ports, it is not necessary to actually
4016 +define the 'ioctx' member in the os-dependent struct. Since Linux does not
4017 +require an IO context, its macros for dwc_read_reg32() and friends do not
4018 +use the context pointer, so it is optimized away by the compiler. But it is
4019 +necessary to add the pointer parameter to all of the call sites, to be ready
4020 +for any future ports (such as FreeBSD) which do require an IO context.
4021 +
4022 +
4023 +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now
4024 +take an additional parameter, a pointer to a memory context. Examples:
4025 +
4026 + addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);
4027 +
4028 + dwc_free(&usb3_dev->os_dep.memctx, addr);
4029 +
4030 +Again, for the Linux ports, it is not necessary to actually define the memctx
4031 +member, but it is necessary to add the pointer parameter to all of the call
4032 +sites.
4033 +
4034 +
4035 +Same for dwc_dma_alloc() and dwc_dma_free(). Examples:
4036 +
4037 + virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);
4038 +
4039 + dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);
4040 +
4041 +
4042 +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:
4043 +
4044 + mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);
4045 +
4046 + dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);
4047 +
4048 +
4049 +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:
4050 +
4051 + lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);
4052 +
4053 + dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);
4054 +
4055 +
4056 +Same for dwc_timer_alloc(). Example:
4057 +
4058 + timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",
4059 + cb_func, cb_data);
4060 +
4061 +
4062 +Same for dwc_waitq_alloc(). Example:
4063 +
4064 + waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);
4065 +
4066 +
4067 +Same for dwc_thread_run(). Example:
4068 +
4069 + thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,
4070 + "dwc_usb3_thd1", data);
4071 +
4072 +
4073 +Same for dwc_workq_alloc(). Example:
4074 +
4075 + workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");
4076 +
4077 +
4078 +Same for dwc_task_alloc(). Example:
4079 +
4080 + task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",
4081 + cb_func, cb_data);
4082 +
4083 +
4084 +In addition to the context pointer additions, a few core functions have had
4085 +other changes made to their parameters:
4086 +
4087 +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()
4088 +has been changed from a uint64_t to a dwc_irqflags_t.
4089 +
4090 +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the
4091 +FreeBSD equivalent of that function requires it.
4092 +
4093 +And, in addition to the context pointer, dwc_task_alloc() also adds a
4094 +'char *name' parameter, to be consistent with dwc_thread_run() and
4095 +dwc_workq_alloc(), and because the FreeBSD equivalent of that function
4096 +requires a unique name.
4097 +
4098 +
4099 +Here is a complete list of the core functions that now take a pointer to a
4100 +context as their first parameter:
4101 +
4102 + dwc_read_reg32
4103 + dwc_read_reg64
4104 + dwc_write_reg32
4105 + dwc_write_reg64
4106 + dwc_modify_reg32
4107 + dwc_modify_reg64
4108 + dwc_alloc
4109 + dwc_alloc_atomic
4110 + dwc_strdup
4111 + dwc_free
4112 + dwc_dma_alloc
4113 + dwc_dma_free
4114 + dwc_mutex_alloc
4115 + dwc_mutex_free
4116 + dwc_spinlock_alloc
4117 + dwc_spinlock_free
4118 + dwc_timer_alloc
4119 + dwc_waitq_alloc
4120 + dwc_thread_run
4121 + dwc_workq_alloc
4122 + dwc_task_alloc Also adds a 'char *name' as its 2nd parameter
4123 +
4124 +And here are the core functions that have other changes to their parameters:
4125 +
4126 + dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *'
4127 + dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'
4128 + dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter
4129 +
4130 +
4131 +
4132 +The changes to the core functions also require some of the other library
4133 +functions to change:
4134 +
4135 + dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'
4136 + (for memory allocation) as the 1st param and a 'void *mtxctx'
4137 + (for mutex allocation) as the 2nd param.
4138 +
4139 + dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),
4140 + dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a
4141 + 'void *memctx' as the 1st param.
4142 +
4143 + dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a
4144 + 'void *memctx' as the 1st param.
4145 +
4146 + dwc_modpow() now takes a 'void *memctx' as the 1st param.
4147 +
4148 + dwc_alloc_notification_manager() now takes a 'void *memctx' as the
4149 + 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd
4150 + param, and also now returns an integer value that is non-zero if
4151 + allocation of its data structures or work queue fails.
4152 +
4153 + dwc_register_notifier() now takes a 'void *memctx' as the 1st param.
4154 +
4155 + dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first
4156 + param, and also now returns an integer value that is non-zero if
4157 + allocation of its data structures fails.
4158 +
4159 +
4160 +
4161 +Other miscellaneous changes:
4162 +
4163 +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to
4164 +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.
4165 +
4166 +The following #define's have been added to allow selectively compiling library
4167 +features:
4168 +
4169 + DWC_CCLIB
4170 + DWC_CRYPTOLIB
4171 + DWC_NOTIFYLIB
4172 + DWC_UTFLIB
4173 +
4174 +A DWC_LIBMODULE #define has also been added. If this is not defined, then the
4175 +module code in dwc_common_linux.c is not compiled in. This allows linking the
4176 +library code directly into a driver module, instead of as a standalone module.
4177 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4178 --- linux-3.10/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
4179 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2013-07-06 15:25:50.000000000 +0100
4180 @@ -0,0 +1,270 @@
4181 +# Doxyfile 1.4.5
4182 +
4183 +#---------------------------------------------------------------------------
4184 +# Project related configuration options
4185 +#---------------------------------------------------------------------------
4186 +PROJECT_NAME = "Synopsys DWC Portability and Common Library for UWB"
4187 +PROJECT_NUMBER =
4188 +OUTPUT_DIRECTORY = doc
4189 +CREATE_SUBDIRS = NO
4190 +OUTPUT_LANGUAGE = English
4191 +BRIEF_MEMBER_DESC = YES
4192 +REPEAT_BRIEF = YES
4193 +ABBREVIATE_BRIEF = "The $name class" \
4194 + "The $name widget" \
4195 + "The $name file" \
4196 + is \
4197 + provides \
4198 + specifies \
4199 + contains \
4200 + represents \
4201 + a \
4202 + an \
4203 + the
4204 +ALWAYS_DETAILED_SEC = YES
4205 +INLINE_INHERITED_MEMB = NO
4206 +FULL_PATH_NAMES = NO
4207 +STRIP_FROM_PATH = ..
4208 +STRIP_FROM_INC_PATH =
4209 +SHORT_NAMES = NO
4210 +JAVADOC_AUTOBRIEF = YES
4211 +MULTILINE_CPP_IS_BRIEF = NO
4212 +DETAILS_AT_TOP = YES
4213 +INHERIT_DOCS = YES
4214 +SEPARATE_MEMBER_PAGES = NO
4215 +TAB_SIZE = 8
4216 +ALIASES =
4217 +OPTIMIZE_OUTPUT_FOR_C = YES
4218 +OPTIMIZE_OUTPUT_JAVA = NO
4219 +BUILTIN_STL_SUPPORT = NO
4220 +DISTRIBUTE_GROUP_DOC = NO
4221 +SUBGROUPING = NO
4222 +#---------------------------------------------------------------------------
4223 +# Build related configuration options
4224 +#---------------------------------------------------------------------------
4225 +EXTRACT_ALL = NO
4226 +EXTRACT_PRIVATE = NO
4227 +EXTRACT_STATIC = YES
4228 +EXTRACT_LOCAL_CLASSES = NO
4229 +EXTRACT_LOCAL_METHODS = NO
4230 +HIDE_UNDOC_MEMBERS = NO
4231 +HIDE_UNDOC_CLASSES = NO
4232 +HIDE_FRIEND_COMPOUNDS = NO
4233 +HIDE_IN_BODY_DOCS = NO
4234 +INTERNAL_DOCS = NO
4235 +CASE_SENSE_NAMES = YES
4236 +HIDE_SCOPE_NAMES = NO
4237 +SHOW_INCLUDE_FILES = NO
4238 +INLINE_INFO = YES
4239 +SORT_MEMBER_DOCS = NO
4240 +SORT_BRIEF_DOCS = NO
4241 +SORT_BY_SCOPE_NAME = NO
4242 +GENERATE_TODOLIST = YES
4243 +GENERATE_TESTLIST = YES
4244 +GENERATE_BUGLIST = YES
4245 +GENERATE_DEPRECATEDLIST= YES
4246 +ENABLED_SECTIONS =
4247 +MAX_INITIALIZER_LINES = 30
4248 +SHOW_USED_FILES = YES
4249 +SHOW_DIRECTORIES = YES
4250 +FILE_VERSION_FILTER =
4251 +#---------------------------------------------------------------------------
4252 +# configuration options related to warning and progress messages
4253 +#---------------------------------------------------------------------------
4254 +QUIET = YES
4255 +WARNINGS = YES
4256 +WARN_IF_UNDOCUMENTED = NO
4257 +WARN_IF_DOC_ERROR = YES
4258 +WARN_NO_PARAMDOC = YES
4259 +WARN_FORMAT = "$file:$line: $text"
4260 +WARN_LOGFILE =
4261 +#---------------------------------------------------------------------------
4262 +# configuration options related to the input files
4263 +#---------------------------------------------------------------------------
4264 +INPUT = .
4265 +FILE_PATTERNS = *.c \
4266 + *.cc \
4267 + *.cxx \
4268 + *.cpp \
4269 + *.c++ \
4270 + *.d \
4271 + *.java \
4272 + *.ii \
4273 + *.ixx \
4274 + *.ipp \
4275 + *.i++ \
4276 + *.inl \
4277 + *.h \
4278 + *.hh \
4279 + *.hxx \
4280 + *.hpp \
4281 + *.h++ \
4282 + *.idl \
4283 + *.odl \
4284 + *.cs \
4285 + *.php \
4286 + *.php3 \
4287 + *.inc \
4288 + *.m \
4289 + *.mm \
4290 + *.dox \
4291 + *.py \
4292 + *.C \
4293 + *.CC \
4294 + *.C++ \
4295 + *.II \
4296 + *.I++ \
4297 + *.H \
4298 + *.HH \
4299 + *.H++ \
4300 + *.CS \
4301 + *.PHP \
4302 + *.PHP3 \
4303 + *.M \
4304 + *.MM \
4305 + *.PY
4306 +RECURSIVE = NO
4307 +EXCLUDE =
4308 +EXCLUDE_SYMLINKS = NO
4309 +EXCLUDE_PATTERNS =
4310 +EXAMPLE_PATH =
4311 +EXAMPLE_PATTERNS = *
4312 +EXAMPLE_RECURSIVE = NO
4313 +IMAGE_PATH =
4314 +INPUT_FILTER =
4315 +FILTER_PATTERNS =
4316 +FILTER_SOURCE_FILES = NO
4317 +#---------------------------------------------------------------------------
4318 +# configuration options related to source browsing
4319 +#---------------------------------------------------------------------------
4320 +SOURCE_BROWSER = NO
4321 +INLINE_SOURCES = NO
4322 +STRIP_CODE_COMMENTS = YES
4323 +REFERENCED_BY_RELATION = YES
4324 +REFERENCES_RELATION = YES
4325 +USE_HTAGS = NO
4326 +VERBATIM_HEADERS = NO
4327 +#---------------------------------------------------------------------------
4328 +# configuration options related to the alphabetical class index
4329 +#---------------------------------------------------------------------------
4330 +ALPHABETICAL_INDEX = NO
4331 +COLS_IN_ALPHA_INDEX = 5
4332 +IGNORE_PREFIX =
4333 +#---------------------------------------------------------------------------
4334 +# configuration options related to the HTML output
4335 +#---------------------------------------------------------------------------
4336 +GENERATE_HTML = YES
4337 +HTML_OUTPUT = html
4338 +HTML_FILE_EXTENSION = .html
4339 +HTML_HEADER =
4340 +HTML_FOOTER =
4341 +HTML_STYLESHEET =
4342 +HTML_ALIGN_MEMBERS = YES
4343 +GENERATE_HTMLHELP = NO
4344 +CHM_FILE =
4345 +HHC_LOCATION =
4346 +GENERATE_CHI = NO
4347 +BINARY_TOC = NO
4348 +TOC_EXPAND = NO
4349 +DISABLE_INDEX = NO
4350 +ENUM_VALUES_PER_LINE = 4
4351 +GENERATE_TREEVIEW = YES
4352 +TREEVIEW_WIDTH = 250
4353 +#---------------------------------------------------------------------------
4354 +# configuration options related to the LaTeX output
4355 +#---------------------------------------------------------------------------
4356 +GENERATE_LATEX = NO
4357 +LATEX_OUTPUT = latex
4358 +LATEX_CMD_NAME = latex
4359 +MAKEINDEX_CMD_NAME = makeindex
4360 +COMPACT_LATEX = NO
4361 +PAPER_TYPE = a4wide
4362 +EXTRA_PACKAGES =
4363 +LATEX_HEADER =
4364 +PDF_HYPERLINKS = NO
4365 +USE_PDFLATEX = NO
4366 +LATEX_BATCHMODE = NO
4367 +LATEX_HIDE_INDICES = NO
4368 +#---------------------------------------------------------------------------
4369 +# configuration options related to the RTF output
4370 +#---------------------------------------------------------------------------
4371 +GENERATE_RTF = NO
4372 +RTF_OUTPUT = rtf
4373 +COMPACT_RTF = NO
4374 +RTF_HYPERLINKS = NO
4375 +RTF_STYLESHEET_FILE =
4376 +RTF_EXTENSIONS_FILE =
4377 +#---------------------------------------------------------------------------
4378 +# configuration options related to the man page output
4379 +#---------------------------------------------------------------------------
4380 +GENERATE_MAN = NO
4381 +MAN_OUTPUT = man
4382 +MAN_EXTENSION = .3
4383 +MAN_LINKS = NO
4384 +#---------------------------------------------------------------------------
4385 +# configuration options related to the XML output
4386 +#---------------------------------------------------------------------------
4387 +GENERATE_XML = NO
4388 +XML_OUTPUT = xml
4389 +XML_SCHEMA =
4390 +XML_DTD =
4391 +XML_PROGRAMLISTING = YES
4392 +#---------------------------------------------------------------------------
4393 +# configuration options for the AutoGen Definitions output
4394 +#---------------------------------------------------------------------------
4395 +GENERATE_AUTOGEN_DEF = NO
4396 +#---------------------------------------------------------------------------
4397 +# configuration options related to the Perl module output
4398 +#---------------------------------------------------------------------------
4399 +GENERATE_PERLMOD = NO
4400 +PERLMOD_LATEX = NO
4401 +PERLMOD_PRETTY = YES
4402 +PERLMOD_MAKEVAR_PREFIX =
4403 +#---------------------------------------------------------------------------
4404 +# Configuration options related to the preprocessor
4405 +#---------------------------------------------------------------------------
4406 +ENABLE_PREPROCESSING = YES
4407 +MACRO_EXPANSION = NO
4408 +EXPAND_ONLY_PREDEF = NO
4409 +SEARCH_INCLUDES = YES
4410 +INCLUDE_PATH =
4411 +INCLUDE_FILE_PATTERNS =
4412 +PREDEFINED = DEBUG DEBUG_MEMORY
4413 +EXPAND_AS_DEFINED =
4414 +SKIP_FUNCTION_MACROS = YES
4415 +#---------------------------------------------------------------------------
4416 +# Configuration::additions related to external references
4417 +#---------------------------------------------------------------------------
4418 +TAGFILES =
4419 +GENERATE_TAGFILE =
4420 +ALLEXTERNALS = NO
4421 +EXTERNAL_GROUPS = YES
4422 +PERL_PATH = /usr/bin/perl
4423 +#---------------------------------------------------------------------------
4424 +# Configuration options related to the dot tool
4425 +#---------------------------------------------------------------------------
4426 +CLASS_DIAGRAMS = YES
4427 +HIDE_UNDOC_RELATIONS = YES
4428 +HAVE_DOT = NO
4429 +CLASS_GRAPH = YES
4430 +COLLABORATION_GRAPH = YES
4431 +GROUP_GRAPHS = YES
4432 +UML_LOOK = NO
4433 +TEMPLATE_RELATIONS = NO
4434 +INCLUDE_GRAPH = NO
4435 +INCLUDED_BY_GRAPH = YES
4436 +CALL_GRAPH = NO
4437 +GRAPHICAL_HIERARCHY = YES
4438 +DIRECTORY_GRAPH = YES
4439 +DOT_IMAGE_FORMAT = png
4440 +DOT_PATH =
4441 +DOTFILE_DIRS =
4442 +MAX_DOT_GRAPH_DEPTH = 1000
4443 +DOT_TRANSPARENT = NO
4444 +DOT_MULTI_TARGETS = NO
4445 +GENERATE_LEGEND = YES
4446 +DOT_CLEANUP = YES
4447 +#---------------------------------------------------------------------------
4448 +# Configuration::additions related to the search engine
4449 +#---------------------------------------------------------------------------
4450 +SEARCHENGINE = NO
4451 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_cc.c
4452 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100
4453 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_cc.c 2013-07-06 15:25:50.000000000 +0100
4454 @@ -0,0 +1,532 @@
4455 +/* =========================================================================
4456 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
4457 + * $Revision: #4 $
4458 + * $Date: 2010/11/04 $
4459 + * $Change: 1621692 $
4460 + *
4461 + * Synopsys Portability Library Software and documentation
4462 + * (hereinafter, "Software") is an Unsupported proprietary work of
4463 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
4464 + * between Synopsys and you.
4465 + *
4466 + * The Software IS NOT an item of Licensed Software or Licensed Product
4467 + * under any End User Software License Agreement or Agreement for
4468 + * Licensed Product with Synopsys or any supplement thereto. You are
4469 + * permitted to use and redistribute this Software in source and binary
4470 + * forms, with or without modification, provided that redistributions
4471 + * of source code must retain this notice. You may not view, use,
4472 + * disclose, copy or distribute this file or any information contained
4473 + * herein except pursuant to this license grant from Synopsys. If you
4474 + * do not agree with this notice, including the disclaimer below, then
4475 + * you are not authorized to use the Software.
4476 + *
4477 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4478 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4479 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
4480 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
4481 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4482 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4483 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4484 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
4485 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4486 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4487 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4488 + * DAMAGE.
4489 + * ========================================================================= */
4490 +#ifdef DWC_CCLIB
4491 +
4492 +#include "dwc_cc.h"
4493 +
4494 +typedef struct dwc_cc
4495 +{
4496 + uint32_t uid;
4497 + uint8_t chid[16];
4498 + uint8_t cdid[16];
4499 + uint8_t ck[16];
4500 + uint8_t *name;
4501 + uint8_t length;
4502 + DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
4503 +} dwc_cc_t;
4504 +
4505 +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
4506 +
4507 +/** The main structure for CC management. */
4508 +struct dwc_cc_if
4509 +{
4510 + dwc_mutex_t *mutex;
4511 + char *filename;
4512 +
4513 + unsigned is_host:1;
4514 +
4515 + dwc_notifier_t *notifier;
4516 +
4517 + struct context_list list;
4518 +};
4519 +
4520 +#ifdef DEBUG
4521 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
4522 +{
4523 + int i;
4524 + DWC_PRINTF("%s: ", name);
4525 + for (i=0; i<len; i++) {
4526 + DWC_PRINTF("%02x ", bytes[i]);
4527 + }
4528 + DWC_PRINTF("\n");
4529 +}
4530 +#else
4531 +#define dump_bytes(x...)
4532 +#endif
4533 +
4534 +static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
4535 +{
4536 + dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
4537 + if (!cc) {
4538 + return NULL;
4539 + }
4540 + DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
4541 +
4542 + if (name) {
4543 + cc->length = length;
4544 + cc->name = dwc_alloc(mem_ctx, length);
4545 + if (!cc->name) {
4546 + dwc_free(mem_ctx, cc);
4547 + return NULL;
4548 + }
4549 +
4550 + DWC_MEMCPY(cc->name, name, length);
4551 + }
4552 +
4553 + return cc;
4554 +}
4555 +
4556 +static void free_cc(void *mem_ctx, dwc_cc_t *cc)
4557 +{
4558 + if (cc->name) {
4559 + dwc_free(mem_ctx, cc->name);
4560 + }
4561 + dwc_free(mem_ctx, cc);
4562 +}
4563 +
4564 +static uint32_t next_uid(dwc_cc_if_t *cc_if)
4565 +{
4566 + uint32_t uid = 0;
4567 + dwc_cc_t *cc;
4568 + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4569 + if (cc->uid > uid) {
4570 + uid = cc->uid;
4571 + }
4572 + }
4573 +
4574 + if (uid == 0) {
4575 + uid = 255;
4576 + }
4577 +
4578 + return uid + 1;
4579 +}
4580 +
4581 +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
4582 +{
4583 + dwc_cc_t *cc;
4584 + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4585 + if (cc->uid == uid) {
4586 + return cc;
4587 + }
4588 + }
4589 + return NULL;
4590 +}
4591 +
4592 +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
4593 +{
4594 + unsigned int size = 0;
4595 + dwc_cc_t *cc;
4596 + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4597 + size += (48 + 1);
4598 + if (cc->name) {
4599 + size += cc->length;
4600 + }
4601 + }
4602 + return size;
4603 +}
4604 +
4605 +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
4606 +{
4607 + uint32_t uid = 0;
4608 + dwc_cc_t *cc;
4609 +
4610 + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4611 + if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
4612 + uid = cc->uid;
4613 + break;
4614 + }
4615 + }
4616 + return uid;
4617 +}
4618 +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
4619 +{
4620 + uint32_t uid = 0;
4621 + dwc_cc_t *cc;
4622 +
4623 + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4624 + if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
4625 + uid = cc->uid;
4626 + break;
4627 + }
4628 + }
4629 + return uid;
4630 +}
4631 +
4632 +/* Internal cc_add */
4633 +static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4634 + uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4635 +{
4636 + dwc_cc_t *cc;
4637 + uint32_t uid;
4638 +
4639 + if (cc_if->is_host) {
4640 + uid = cc_match_cdid(cc_if, cdid);
4641 + }
4642 + else {
4643 + uid = cc_match_chid(cc_if, chid);
4644 + }
4645 +
4646 + if (uid) {
4647 + DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
4648 + cc = cc_find(cc_if, uid);
4649 + }
4650 + else {
4651 + cc = alloc_cc(mem_ctx, name, length);
4652 + cc->uid = next_uid(cc_if);
4653 + DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
4654 + }
4655 +
4656 + DWC_MEMCPY(&(cc->chid[0]), chid, 16);
4657 + DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
4658 + DWC_MEMCPY(&(cc->ck[0]), ck, 16);
4659 +
4660 + DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
4661 + dump_bytes("CHID", cc->chid, 16);
4662 + dump_bytes("CDID", cc->cdid, 16);
4663 + dump_bytes("CK", cc->ck, 16);
4664 + return cc->uid;
4665 +}
4666 +
4667 +/* Internal cc_clear */
4668 +static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
4669 +{
4670 + while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
4671 + dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
4672 + DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
4673 + free_cc(mem_ctx, cc);
4674 + }
4675 +}
4676 +
4677 +dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
4678 + dwc_notifier_t *notifier, unsigned is_host)
4679 +{
4680 + dwc_cc_if_t *cc_if = NULL;
4681 +
4682 + /* Allocate a common_cc_if structure */
4683 + cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
4684 +
4685 + if (!cc_if)
4686 + return NULL;
4687 +
4688 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4689 + DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
4690 +#else
4691 + cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
4692 +#endif
4693 + if (!cc_if->mutex) {
4694 + dwc_free(mem_ctx, cc_if);
4695 + return NULL;
4696 + }
4697 +
4698 + DWC_CIRCLEQ_INIT(&cc_if->list);
4699 + cc_if->is_host = is_host;
4700 + cc_if->notifier = notifier;
4701 + return cc_if;
4702 +}
4703 +
4704 +void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
4705 +{
4706 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4707 + DWC_MUTEX_FREE(cc_if->mutex);
4708 +#else
4709 + dwc_mutex_free(mtx_ctx, cc_if->mutex);
4710 +#endif
4711 + cc_clear(mem_ctx, cc_if);
4712 + dwc_free(mem_ctx, cc_if);
4713 +}
4714 +
4715 +static void cc_changed(dwc_cc_if_t *cc_if)
4716 +{
4717 + if (cc_if->notifier) {
4718 + dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
4719 + }
4720 +}
4721 +
4722 +void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
4723 +{
4724 + DWC_MUTEX_LOCK(cc_if->mutex);
4725 + cc_clear(mem_ctx, cc_if);
4726 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4727 + cc_changed(cc_if);
4728 +}
4729 +
4730 +int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4731 + uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4732 +{
4733 + uint32_t uid;
4734 +
4735 + DWC_MUTEX_LOCK(cc_if->mutex);
4736 + uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
4737 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4738 + cc_changed(cc_if);
4739 +
4740 + return uid;
4741 +}
4742 +
4743 +void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
4744 + uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4745 +{
4746 + dwc_cc_t* cc;
4747 +
4748 + DWC_DEBUGC("Change connection context %d", id);
4749 +
4750 + DWC_MUTEX_LOCK(cc_if->mutex);
4751 + cc = cc_find(cc_if, id);
4752 + if (!cc) {
4753 + DWC_ERROR("Uid %d not found in cc list\n", id);
4754 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4755 + return;
4756 + }
4757 +
4758 + if (chid) {
4759 + DWC_MEMCPY(&(cc->chid[0]), chid, 16);
4760 + }
4761 + if (cdid) {
4762 + DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
4763 + }
4764 + if (ck) {
4765 + DWC_MEMCPY(&(cc->ck[0]), ck, 16);
4766 + }
4767 +
4768 + if (name) {
4769 + if (cc->name) {
4770 + dwc_free(mem_ctx, cc->name);
4771 + }
4772 + cc->name = dwc_alloc(mem_ctx, length);
4773 + if (!cc->name) {
4774 + DWC_ERROR("Out of memory in dwc_cc_change()\n");
4775 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4776 + return;
4777 + }
4778 + cc->length = length;
4779 + DWC_MEMCPY(cc->name, name, length);
4780 + }
4781 +
4782 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4783 +
4784 + cc_changed(cc_if);
4785 +
4786 + DWC_DEBUGC("Changed connection context id=%d\n", id);
4787 + dump_bytes("New CHID", cc->chid, 16);
4788 + dump_bytes("New CDID", cc->cdid, 16);
4789 + dump_bytes("New CK", cc->ck, 16);
4790 +}
4791 +
4792 +void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
4793 +{
4794 + dwc_cc_t *cc;
4795 +
4796 + DWC_DEBUGC("Removing connection context %d", id);
4797 +
4798 + DWC_MUTEX_LOCK(cc_if->mutex);
4799 + cc = cc_find(cc_if, id);
4800 + if (!cc) {
4801 + DWC_ERROR("Uid %d not found in cc list\n", id);
4802 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4803 + return;
4804 + }
4805 +
4806 + DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
4807 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4808 + free_cc(mem_ctx, cc);
4809 +
4810 + cc_changed(cc_if);
4811 +}
4812 +
4813 +uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
4814 +{
4815 + uint8_t *buf, *x;
4816 + uint8_t zero = 0;
4817 + dwc_cc_t *cc;
4818 +
4819 + DWC_MUTEX_LOCK(cc_if->mutex);
4820 + *length = cc_data_size(cc_if);
4821 + if (!(*length)) {
4822 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4823 + return NULL;
4824 + }
4825 +
4826 + DWC_DEBUGC("Creating data for saving (length=%d)", *length);
4827 +
4828 + buf = dwc_alloc(mem_ctx, *length);
4829 + if (!buf) {
4830 + *length = 0;
4831 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4832 + return NULL;
4833 + }
4834 +
4835 + x = buf;
4836 + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4837 + DWC_MEMCPY(x, cc->chid, 16);
4838 + x += 16;
4839 + DWC_MEMCPY(x, cc->cdid, 16);
4840 + x += 16;
4841 + DWC_MEMCPY(x, cc->ck, 16);
4842 + x += 16;
4843 + if (cc->name) {
4844 + DWC_MEMCPY(x, &cc->length, 1);
4845 + x += 1;
4846 + DWC_MEMCPY(x, cc->name, cc->length);
4847 + x += cc->length;
4848 + }
4849 + else {
4850 + DWC_MEMCPY(x, &zero, 1);
4851 + x += 1;
4852 + }
4853 + }
4854 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4855 +
4856 + return buf;
4857 +}
4858 +
4859 +void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
4860 +{
4861 + uint8_t name_length;
4862 + uint8_t *name;
4863 + uint8_t *chid;
4864 + uint8_t *cdid;
4865 + uint8_t *ck;
4866 + uint32_t i = 0;
4867 +
4868 + DWC_MUTEX_LOCK(cc_if->mutex);
4869 + cc_clear(mem_ctx, cc_if);
4870 +
4871 + while (i < length) {
4872 + chid = &data[i];
4873 + i += 16;
4874 + cdid = &data[i];
4875 + i += 16;
4876 + ck = &data[i];
4877 + i += 16;
4878 +
4879 + name_length = data[i];
4880 + i ++;
4881 +
4882 + if (name_length) {
4883 + name = &data[i];
4884 + i += name_length;
4885 + }
4886 + else {
4887 + name = NULL;
4888 + }
4889 +
4890 + /* check to see if we haven't overflown the buffer */
4891 + if (i > length) {
4892 + DWC_ERROR("Data format error while attempting to load CCs "
4893 + "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
4894 + break;
4895 + }
4896 +
4897 + cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
4898 + }
4899 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4900 +
4901 + cc_changed(cc_if);
4902 +}
4903 +
4904 +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
4905 +{
4906 + uint32_t uid = 0;
4907 +
4908 + DWC_MUTEX_LOCK(cc_if->mutex);
4909 + uid = cc_match_chid(cc_if, chid);
4910 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4911 + return uid;
4912 +}
4913 +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
4914 +{
4915 + uint32_t uid = 0;
4916 +
4917 + DWC_MUTEX_LOCK(cc_if->mutex);
4918 + uid = cc_match_cdid(cc_if, cdid);
4919 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4920 + return uid;
4921 +}
4922 +
4923 +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
4924 +{
4925 + uint8_t *ck = NULL;
4926 + dwc_cc_t *cc;
4927 +
4928 + DWC_MUTEX_LOCK(cc_if->mutex);
4929 + cc = cc_find(cc_if, id);
4930 + if (cc) {
4931 + ck = cc->ck;
4932 + }
4933 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4934 +
4935 + return ck;
4936 +
4937 +}
4938 +
4939 +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
4940 +{
4941 + uint8_t *retval = NULL;
4942 + dwc_cc_t *cc;
4943 +
4944 + DWC_MUTEX_LOCK(cc_if->mutex);
4945 + cc = cc_find(cc_if, id);
4946 + if (cc) {
4947 + retval = cc->chid;
4948 + }
4949 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4950 +
4951 + return retval;
4952 +}
4953 +
4954 +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
4955 +{
4956 + uint8_t *retval = NULL;
4957 + dwc_cc_t *cc;
4958 +
4959 + DWC_MUTEX_LOCK(cc_if->mutex);
4960 + cc = cc_find(cc_if, id);
4961 + if (cc) {
4962 + retval = cc->cdid;
4963 + }
4964 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4965 +
4966 + return retval;
4967 +}
4968 +
4969 +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
4970 +{
4971 + uint8_t *retval = NULL;
4972 + dwc_cc_t *cc;
4973 +
4974 + DWC_MUTEX_LOCK(cc_if->mutex);
4975 + *length = 0;
4976 + cc = cc_find(cc_if, id);
4977 + if (cc) {
4978 + *length = cc->length;
4979 + retval = cc->name;
4980 + }
4981 + DWC_MUTEX_UNLOCK(cc_if->mutex);
4982 +
4983 + return retval;
4984 +}
4985 +
4986 +#endif /* DWC_CCLIB */
4987 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_cc.h
4988 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100
4989 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_cc.h 2013-07-06 15:25:50.000000000 +0100
4990 @@ -0,0 +1,225 @@
4991 +/* =========================================================================
4992 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
4993 + * $Revision: #4 $
4994 + * $Date: 2010/09/28 $
4995 + * $Change: 1596182 $
4996 + *
4997 + * Synopsys Portability Library Software and documentation
4998 + * (hereinafter, "Software") is an Unsupported proprietary work of
4999 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
5000 + * between Synopsys and you.
5001 + *
5002 + * The Software IS NOT an item of Licensed Software or Licensed Product
5003 + * under any End User Software License Agreement or Agreement for
5004 + * Licensed Product with Synopsys or any supplement thereto. You are
5005 + * permitted to use and redistribute this Software in source and binary
5006 + * forms, with or without modification, provided that redistributions
5007 + * of source code must retain this notice. You may not view, use,
5008 + * disclose, copy or distribute this file or any information contained
5009 + * herein except pursuant to this license grant from Synopsys. If you
5010 + * do not agree with this notice, including the disclaimer below, then
5011 + * you are not authorized to use the Software.
5012 + *
5013 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
5014 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5015 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
5016 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
5017 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5018 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5019 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5020 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
5021 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5022 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5023 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
5024 + * DAMAGE.
5025 + * ========================================================================= */
5026 +#ifndef _DWC_CC_H_
5027 +#define _DWC_CC_H_
5028 +
5029 +#ifdef __cplusplus
5030 +extern "C" {
5031 +#endif
5032 +
5033 +/** @file
5034 + *
5035 + * This file defines the Context Context library.
5036 + *
5037 + * The main data structure is dwc_cc_if_t which is returned by either the
5038 + * dwc_cc_if_alloc function or returned by the module to the user via a provided
5039 + * function. The data structure is opaque and should only be manipulated via the
5040 + * functions provied in this API.
5041 + *
5042 + * It manages a list of connection contexts and operations can be performed to
5043 + * add, remove, query, search, and change, those contexts. Additionally,
5044 + * a dwc_notifier_t object can be requested from the manager so that
5045 + * the user can be notified whenever the context list has changed.
5046 + */
5047 +
5048 +#include "dwc_os.h"
5049 +#include "dwc_list.h"
5050 +#include "dwc_notifier.h"
5051 +
5052 +
5053 +/* Notifications */
5054 +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
5055 +
5056 +struct dwc_cc_if;
5057 +typedef struct dwc_cc_if dwc_cc_if_t;
5058 +
5059 +
5060 +/** @name Connection Context Operations */
5061 +/** @{ */
5062 +
5063 +/** This function allocates memory for a dwc_cc_if_t structure, initializes
5064 + * fields to default values, and returns a pointer to the structure or NULL on
5065 + * error. */
5066 +extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
5067 + dwc_notifier_t *notifier, unsigned is_host);
5068 +
5069 +/** Frees the memory for the specified CC structure allocated from
5070 + * dwc_cc_if_alloc(). */
5071 +extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);
5072 +
5073 +/** Removes all contexts from the connection context list */
5074 +extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);
5075 +
5076 +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
5077 + * If a CHID already exists, the CK and name are overwritten. Statistics are
5078 + * not overwritten.
5079 + *
5080 + * @param cc_if The cc_if structure.
5081 + * @param chid A pointer to the 16-byte CHID. This value will be copied.
5082 + * @param ck A pointer to the 16-byte CK. This value will be copied.
5083 + * @param cdid A pointer to the 16-byte CDID. This value will be copied.
5084 + * @param name An optional host friendly name as defined in the association model
5085 + * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name.
5086 + * @param length The length othe unicode string.
5087 + * @return A unique identifier used to refer to this context that is valid for
5088 + * as long as this context is still in the list. */
5089 +extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5090 + uint8_t *cdid, uint8_t *ck, uint8_t *name,
5091 + uint8_t length);
5092 +
5093 +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
5094 + * list, preserving any accumulated statistics. This would typically be called
5095 + * if the host decideds to change the context with a SET_CONNECTION request.
5096 + *
5097 + * @param cc_if The cc_if structure.
5098 + * @param id The identifier of the connection context.
5099 + * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL
5100 + * indicates no change.
5101 + * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL
5102 + * indicates no change.
5103 + * @param ck A pointer to the 16-byte CK. This value will be copied. NULL
5104 + * indicates no change.
5105 + * @param name Host friendly name UTF16-LE. NULL indicates no change.
5106 + * @param length Length of name. */
5107 +extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,
5108 + uint8_t *chid, uint8_t *cdid, uint8_t *ck,
5109 + uint8_t *name, uint8_t length);
5110 +
5111 +/** Remove the specified connection context.
5112 + * @param cc_if The cc_if structure.
5113 + * @param id The identifier of the connection context to remove. */
5114 +extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);
5115 +
5116 +/** Get a binary block of data for the connection context list and attributes.
5117 + * This data can be used by the OS specific driver to save the connection
5118 + * context list into non-volatile memory.
5119 + *
5120 + * @param cc_if The cc_if structure.
5121 + * @param length Return the length of the data buffer.
5122 + * @return A pointer to the data buffer. The memory for this buffer should be
5123 + * freed with DWC_FREE() after use. */
5124 +extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,
5125 + unsigned int *length);
5126 +
5127 +/** Restore the connection context list from the binary data that was previously
5128 + * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific
5129 + * driver to load a connection context list from non-volatile memory.
5130 + *
5131 + * @param cc_if The cc_if structure.
5132 + * @param data The data bytes as returned from dwc_cc_data_for_save.
5133 + * @param length The length of the data. */
5134 +extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,
5135 + uint8_t *data, unsigned int length);
5136 +
5137 +/** Find the connection context from the specified CHID.
5138 + *
5139 + * @param cc_if The cc_if structure.
5140 + * @param chid A pointer to the CHID data.
5141 + * @return A non-zero identifier of the connection context if the CHID matches.
5142 + * Otherwise returns 0. */
5143 +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
5144 +
5145 +/** Find the connection context from the specified CDID.
5146 + *
5147 + * @param cc_if The cc_if structure.
5148 + * @param cdid A pointer to the CDID data.
5149 + * @return A non-zero identifier of the connection context if the CHID matches.
5150 + * Otherwise returns 0. */
5151 +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
5152 +
5153 +/** Retrieve the CK from the specified connection context.
5154 + *
5155 + * @param cc_if The cc_if structure.
5156 + * @param id The identifier of the connection context.
5157 + * @return A pointer to the CK data. The memory does not need to be freed. */
5158 +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
5159 +
5160 +/** Retrieve the CHID from the specified connection context.
5161 + *
5162 + * @param cc_if The cc_if structure.
5163 + * @param id The identifier of the connection context.
5164 + * @return A pointer to the CHID data. The memory does not need to be freed. */
5165 +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
5166 +
5167 +/** Retrieve the CDID from the specified connection context.
5168 + *
5169 + * @param cc_if The cc_if structure.
5170 + * @param id The identifier of the connection context.
5171 + * @return A pointer to the CDID data. The memory does not need to be freed. */
5172 +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
5173 +
5174 +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
5175 +
5176 +/** Checks a buffer for non-zero.
5177 + * @param id A pointer to a 16 byte buffer.
5178 + * @return true if the 16 byte value is non-zero. */
5179 +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
5180 + int i;
5181 + for (i=0; i<16; i++) {
5182 + if (id[i]) return 1;
5183 + }
5184 + return 0;
5185 +}
5186 +
5187 +/** Checks a buffer for zero.
5188 + * @param id A pointer to a 16 byte buffer.
5189 + * @return true if the 16 byte value is zero. */
5190 +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
5191 + return !dwc_assoc_is_not_zero_id(id);
5192 +}
5193 +
5194 +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
5195 + * buffer. */
5196 +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
5197 + char *ptr = buffer;
5198 + int i;
5199 + for (i=0; i<16; i++) {
5200 + ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
5201 + if (i < 15) {
5202 + ptr += DWC_SPRINTF(ptr, " ");
5203 + }
5204 + }
5205 + return ptr - buffer;
5206 +}
5207 +
5208 +/** @} */
5209 +
5210 +#ifdef __cplusplus
5211 +}
5212 +#endif
5213 +
5214 +#endif /* _DWC_CC_H_ */
5215 +
5216 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5217 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1970-01-01 01:00:00.000000000 +0100
5218 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2013-07-06 15:25:50.000000000 +0100
5219 @@ -0,0 +1,1308 @@
5220 +#include "dwc_os.h"
5221 +#include "dwc_list.h"
5222 +
5223 +#ifdef DWC_CCLIB
5224 +# include "dwc_cc.h"
5225 +#endif
5226 +
5227 +#ifdef DWC_CRYPTOLIB
5228 +# include "dwc_modpow.h"
5229 +# include "dwc_dh.h"
5230 +# include "dwc_crypto.h"
5231 +#endif
5232 +
5233 +#ifdef DWC_NOTIFYLIB
5234 +# include "dwc_notifier.h"
5235 +#endif
5236 +
5237 +/* OS-Level Implementations */
5238 +
5239 +/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */
5240 +
5241 +
5242 +/* MISC */
5243 +
5244 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
5245 +{
5246 + return memset(dest, byte, size);
5247 +}
5248 +
5249 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
5250 +{
5251 + return memcpy(dest, src, size);
5252 +}
5253 +
5254 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
5255 +{
5256 + bcopy(src, dest, size);
5257 + return dest;
5258 +}
5259 +
5260 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
5261 +{
5262 + return memcmp(m1, m2, size);
5263 +}
5264 +
5265 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
5266 +{
5267 + return strncmp(s1, s2, size);
5268 +}
5269 +
5270 +int DWC_STRCMP(void *s1, void *s2)
5271 +{
5272 + return strcmp(s1, s2);
5273 +}
5274 +
5275 +int DWC_STRLEN(char const *str)
5276 +{
5277 + return strlen(str);
5278 +}
5279 +
5280 +char *DWC_STRCPY(char *to, char const *from)
5281 +{
5282 + return strcpy(to, from);
5283 +}
5284 +
5285 +char *DWC_STRDUP(char const *str)
5286 +{
5287 + int len = DWC_STRLEN(str) + 1;
5288 + char *new = DWC_ALLOC_ATOMIC(len);
5289 +
5290 + if (!new) {
5291 + return NULL;
5292 + }
5293 +
5294 + DWC_MEMCPY(new, str, len);
5295 + return new;
5296 +}
5297 +
5298 +int DWC_ATOI(char *str, int32_t *value)
5299 +{
5300 + char *end = NULL;
5301 +
5302 + *value = strtol(str, &end, 0);
5303 + if (*end == '\0') {
5304 + return 0;
5305 + }
5306 +
5307 + return -1;
5308 +}
5309 +
5310 +int DWC_ATOUI(char *str, uint32_t *value)
5311 +{
5312 + char *end = NULL;
5313 +
5314 + *value = strtoul(str, &end, 0);
5315 + if (*end == '\0') {
5316 + return 0;
5317 + }
5318 +
5319 + return -1;
5320 +}
5321 +
5322 +
5323 +#ifdef DWC_UTFLIB
5324 +/* From usbstring.c */
5325 +
5326 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
5327 +{
5328 + int count = 0;
5329 + u8 c;
5330 + u16 uchar;
5331 +
5332 + /* this insists on correct encodings, though not minimal ones.
5333 + * BUT it currently rejects legit 4-byte UTF-8 code points,
5334 + * which need surrogate pairs. (Unicode 3.1 can use them.)
5335 + */
5336 + while (len != 0 && (c = (u8) *s++) != 0) {
5337 + if (unlikely(c & 0x80)) {
5338 + // 2-byte sequence:
5339 + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
5340 + if ((c & 0xe0) == 0xc0) {
5341 + uchar = (c & 0x1f) << 6;
5342 +
5343 + c = (u8) *s++;
5344 + if ((c & 0xc0) != 0xc0)
5345 + goto fail;
5346 + c &= 0x3f;
5347 + uchar |= c;
5348 +
5349 + // 3-byte sequence (most CJKV characters):
5350 + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
5351 + } else if ((c & 0xf0) == 0xe0) {
5352 + uchar = (c & 0x0f) << 12;
5353 +
5354 + c = (u8) *s++;
5355 + if ((c & 0xc0) != 0xc0)
5356 + goto fail;
5357 + c &= 0x3f;
5358 + uchar |= c << 6;
5359 +
5360 + c = (u8) *s++;
5361 + if ((c & 0xc0) != 0xc0)
5362 + goto fail;
5363 + c &= 0x3f;
5364 + uchar |= c;
5365 +
5366 + /* no bogus surrogates */
5367 + if (0xd800 <= uchar && uchar <= 0xdfff)
5368 + goto fail;
5369 +
5370 + // 4-byte sequence (surrogate pairs, currently rare):
5371 + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
5372 + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
5373 + // (uuuuu = wwww + 1)
5374 + // FIXME accept the surrogate code points (only)
5375 + } else
5376 + goto fail;
5377 + } else
5378 + uchar = c;
5379 + put_unaligned (cpu_to_le16 (uchar), cp++);
5380 + count++;
5381 + len--;
5382 + }
5383 + return count;
5384 +fail:
5385 + return -1;
5386 +}
5387 +
5388 +#endif /* DWC_UTFLIB */
5389 +
5390 +
5391 +/* dwc_debug.h */
5392 +
5393 +dwc_bool_t DWC_IN_IRQ(void)
5394 +{
5395 +// return in_irq();
5396 + return 0;
5397 +}
5398 +
5399 +dwc_bool_t DWC_IN_BH(void)
5400 +{
5401 +// return in_softirq();
5402 + return 0;
5403 +}
5404 +
5405 +void DWC_VPRINTF(char *format, va_list args)
5406 +{
5407 + vprintf(format, args);
5408 +}
5409 +
5410 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
5411 +{
5412 + return vsnprintf(str, size, format, args);
5413 +}
5414 +
5415 +void DWC_PRINTF(char *format, ...)
5416 +{
5417 + va_list args;
5418 +
5419 + va_start(args, format);
5420 + DWC_VPRINTF(format, args);
5421 + va_end(args);
5422 +}
5423 +
5424 +int DWC_SPRINTF(char *buffer, char *format, ...)
5425 +{
5426 + int retval;
5427 + va_list args;
5428 +
5429 + va_start(args, format);
5430 + retval = vsprintf(buffer, format, args);
5431 + va_end(args);
5432 + return retval;
5433 +}
5434 +
5435 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
5436 +{
5437 + int retval;
5438 + va_list args;
5439 +
5440 + va_start(args, format);
5441 + retval = vsnprintf(buffer, size, format, args);
5442 + va_end(args);
5443 + return retval;
5444 +}
5445 +
5446 +void __DWC_WARN(char *format, ...)
5447 +{
5448 + va_list args;
5449 +
5450 + va_start(args, format);
5451 + DWC_VPRINTF(format, args);
5452 + va_end(args);
5453 +}
5454 +
5455 +void __DWC_ERROR(char *format, ...)
5456 +{
5457 + va_list args;
5458 +
5459 + va_start(args, format);
5460 + DWC_VPRINTF(format, args);
5461 + va_end(args);
5462 +}
5463 +
5464 +void DWC_EXCEPTION(char *format, ...)
5465 +{
5466 + va_list args;
5467 +
5468 + va_start(args, format);
5469 + DWC_VPRINTF(format, args);
5470 + va_end(args);
5471 +// BUG_ON(1); ???
5472 +}
5473 +
5474 +#ifdef DEBUG
5475 +void __DWC_DEBUG(char *format, ...)
5476 +{
5477 + va_list args;
5478 +
5479 + va_start(args, format);
5480 + DWC_VPRINTF(format, args);
5481 + va_end(args);
5482 +}
5483 +#endif
5484 +
5485 +
5486 +/* dwc_mem.h */
5487 +
5488 +#if 0
5489 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
5490 + uint32_t align,
5491 + uint32_t alloc)
5492 +{
5493 + struct dma_pool *pool = dma_pool_create("Pool", NULL,
5494 + size, align, alloc);
5495 + return (dwc_pool_t *)pool;
5496 +}
5497 +
5498 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
5499 +{
5500 + dma_pool_destroy((struct dma_pool *)pool);
5501 +}
5502 +
5503 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5504 +{
5505 +// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
5506 + return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
5507 +}
5508 +
5509 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5510 +{
5511 + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
5512 + memset(..);
5513 +}
5514 +
5515 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
5516 +{
5517 + dma_pool_free(pool, vaddr, daddr);
5518 +}
5519 +#endif
5520 +
5521 +static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5522 +{
5523 + if (error)
5524 + return;
5525 + *(bus_addr_t *)arg = segs[0].ds_addr;
5526 +}
5527 +
5528 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
5529 +{
5530 + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5531 + int error;
5532 +
5533 + error = bus_dma_tag_create(
5534 +#if __FreeBSD_version >= 700000
5535 + bus_get_dma_tag(dma->dev), /* parent */
5536 +#else
5537 + NULL, /* parent */
5538 +#endif
5539 + 4, 0, /* alignment, bounds */
5540 + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
5541 + BUS_SPACE_MAXADDR, /* highaddr */
5542 + NULL, NULL, /* filter, filterarg */
5543 + size, /* maxsize */
5544 + 1, /* nsegments */
5545 + size, /* maxsegsize */
5546 + 0, /* flags */
5547 + NULL, /* lockfunc */
5548 + NULL, /* lockarg */
5549 + &dma->dma_tag);
5550 + if (error) {
5551 + device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",
5552 + __func__, error);
5553 + goto fail_0;
5554 + }
5555 +
5556 + error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,
5557 + BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
5558 + if (error) {
5559 + device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
5560 + __func__, (uintmax_t)size, error);
5561 + goto fail_1;
5562 + }
5563 +
5564 + dma->dma_paddr = 0;
5565 + error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,
5566 + dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);
5567 + if (error || dma->dma_paddr == 0) {
5568 + device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",
5569 + __func__, error);
5570 + goto fail_2;
5571 + }
5572 +
5573 + *dma_addr = dma->dma_paddr;
5574 + return dma->dma_vaddr;
5575 +
5576 +fail_2:
5577 + bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5578 +fail_1:
5579 + bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5580 + bus_dma_tag_destroy(dma->dma_tag);
5581 +fail_0:
5582 + dma->dma_map = NULL;
5583 + dma->dma_tag = NULL;
5584 +
5585 + return NULL;
5586 +}
5587 +
5588 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
5589 +{
5590 + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5591 +
5592 + if (dma->dma_tag == NULL)
5593 + return;
5594 + if (dma->dma_map != NULL) {
5595 + bus_dmamap_sync(dma->dma_tag, dma->dma_map,
5596 + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
5597 + bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5598 + bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5599 + dma->dma_map = NULL;
5600 + }
5601 +
5602 + bus_dma_tag_destroy(dma->dma_tag);
5603 + dma->dma_tag = NULL;
5604 +}
5605 +
5606 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
5607 +{
5608 + return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
5609 +}
5610 +
5611 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
5612 +{
5613 + return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
5614 +}
5615 +
5616 +void __DWC_FREE(void *mem_ctx, void *addr)
5617 +{
5618 + free(addr, M_DEVBUF);
5619 +}
5620 +
5621 +
5622 +#ifdef DWC_CRYPTOLIB
5623 +/* dwc_crypto.h */
5624 +
5625 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
5626 +{
5627 + get_random_bytes(buffer, length);
5628 +}
5629 +
5630 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
5631 +{
5632 + struct crypto_blkcipher *tfm;
5633 + struct blkcipher_desc desc;
5634 + struct scatterlist sgd;
5635 + struct scatterlist sgs;
5636 +
5637 + tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
5638 + if (tfm == NULL) {
5639 + printk("failed to load transform for aes CBC\n");
5640 + return -1;
5641 + }
5642 +
5643 + crypto_blkcipher_setkey(tfm, key, keylen);
5644 + crypto_blkcipher_set_iv(tfm, iv, 16);
5645 +
5646 + sg_init_one(&sgd, out, messagelen);
5647 + sg_init_one(&sgs, message, messagelen);
5648 +
5649 + desc.tfm = tfm;
5650 + desc.flags = 0;
5651 +
5652 + if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
5653 + crypto_free_blkcipher(tfm);
5654 + DWC_ERROR("AES CBC encryption failed");
5655 + return -1;
5656 + }
5657 +
5658 + crypto_free_blkcipher(tfm);
5659 + return 0;
5660 +}
5661 +
5662 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
5663 +{
5664 + struct crypto_hash *tfm;
5665 + struct hash_desc desc;
5666 + struct scatterlist sg;
5667 +
5668 + tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
5669 + if (IS_ERR(tfm)) {
5670 + DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
5671 + return 0;
5672 + }
5673 + desc.tfm = tfm;
5674 + desc.flags = 0;
5675 +
5676 + sg_init_one(&sg, message, len);
5677 + crypto_hash_digest(&desc, &sg, len, out);
5678 + crypto_free_hash(tfm);
5679 +
5680 + return 1;
5681 +}
5682 +
5683 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
5684 + uint8_t *key, uint32_t keylen, uint8_t *out)
5685 +{
5686 + struct crypto_hash *tfm;
5687 + struct hash_desc desc;
5688 + struct scatterlist sg;
5689 +
5690 + tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
5691 + if (IS_ERR(tfm)) {
5692 + DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
5693 + return 0;
5694 + }
5695 + desc.tfm = tfm;
5696 + desc.flags = 0;
5697 +
5698 + sg_init_one(&sg, message, messagelen);
5699 + crypto_hash_setkey(tfm, key, keylen);
5700 + crypto_hash_digest(&desc, &sg, messagelen, out);
5701 + crypto_free_hash(tfm);
5702 +
5703 + return 1;
5704 +}
5705 +
5706 +#endif /* DWC_CRYPTOLIB */
5707 +
5708 +
5709 +/* Byte Ordering Conversions */
5710 +
5711 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
5712 +{
5713 +#ifdef __LITTLE_ENDIAN
5714 + return *p;
5715 +#else
5716 + uint8_t *u_p = (uint8_t *)p;
5717 +
5718 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5719 +#endif
5720 +}
5721 +
5722 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
5723 +{
5724 +#ifdef __BIG_ENDIAN
5725 + return *p;
5726 +#else
5727 + uint8_t *u_p = (uint8_t *)p;
5728 +
5729 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5730 +#endif
5731 +}
5732 +
5733 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
5734 +{
5735 +#ifdef __LITTLE_ENDIAN
5736 + return *p;
5737 +#else
5738 + uint8_t *u_p = (uint8_t *)p;
5739 +
5740 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5741 +#endif
5742 +}
5743 +
5744 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
5745 +{
5746 +#ifdef __BIG_ENDIAN
5747 + return *p;
5748 +#else
5749 + uint8_t *u_p = (uint8_t *)p;
5750 +
5751 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5752 +#endif
5753 +}
5754 +
5755 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
5756 +{
5757 +#ifdef __LITTLE_ENDIAN
5758 + return *p;
5759 +#else
5760 + uint8_t *u_p = (uint8_t *)p;
5761 + return (u_p[1] | (u_p[0] << 8));
5762 +#endif
5763 +}
5764 +
5765 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
5766 +{
5767 +#ifdef __BIG_ENDIAN
5768 + return *p;
5769 +#else
5770 + uint8_t *u_p = (uint8_t *)p;
5771 + return (u_p[1] | (u_p[0] << 8));
5772 +#endif
5773 +}
5774 +
5775 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
5776 +{
5777 +#ifdef __LITTLE_ENDIAN
5778 + return *p;
5779 +#else
5780 + uint8_t *u_p = (uint8_t *)p;
5781 + return (u_p[1] | (u_p[0] << 8));
5782 +#endif
5783 +}
5784 +
5785 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
5786 +{
5787 +#ifdef __BIG_ENDIAN
5788 + return *p;
5789 +#else
5790 + uint8_t *u_p = (uint8_t *)p;
5791 + return (u_p[1] | (u_p[0] << 8));
5792 +#endif
5793 +}
5794 +
5795 +
5796 +/* Registers */
5797 +
5798 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
5799 +{
5800 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
5801 + bus_size_t ior = (bus_size_t)reg;
5802 +
5803 + return bus_space_read_4(io->iot, io->ioh, ior);
5804 +}
5805 +
5806 +#if 0
5807 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
5808 +{
5809 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
5810 + bus_size_t ior = (bus_size_t)reg;
5811 +
5812 + return bus_space_read_8(io->iot, io->ioh, ior);
5813 +}
5814 +#endif
5815 +
5816 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
5817 +{
5818 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
5819 + bus_size_t ior = (bus_size_t)reg;
5820 +
5821 + bus_space_write_4(io->iot, io->ioh, ior, value);
5822 +}
5823 +
5824 +#if 0
5825 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
5826 +{
5827 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
5828 + bus_size_t ior = (bus_size_t)reg;
5829 +
5830 + bus_space_write_8(io->iot, io->ioh, ior, value);
5831 +}
5832 +#endif
5833 +
5834 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
5835 + uint32_t set_mask)
5836 +{
5837 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
5838 + bus_size_t ior = (bus_size_t)reg;
5839 +
5840 + bus_space_write_4(io->iot, io->ioh, ior,
5841 + (bus_space_read_4(io->iot, io->ioh, ior) &
5842 + ~clear_mask) | set_mask);
5843 +}
5844 +
5845 +#if 0
5846 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
5847 + uint64_t set_mask)
5848 +{
5849 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
5850 + bus_size_t ior = (bus_size_t)reg;
5851 +
5852 + bus_space_write_8(io->iot, io->ioh, ior,
5853 + (bus_space_read_8(io->iot, io->ioh, ior) &
5854 + ~clear_mask) | set_mask);
5855 +}
5856 +#endif
5857 +
5858 +
5859 +/* Locking */
5860 +
5861 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
5862 +{
5863 + struct mtx *sl = DWC_ALLOC(sizeof(*sl));
5864 +
5865 + if (!sl) {
5866 + DWC_ERROR("Cannot allocate memory for spinlock");
5867 + return NULL;
5868 + }
5869 +
5870 + mtx_init(sl, "dw3spn", NULL, MTX_SPIN);
5871 + return (dwc_spinlock_t *)sl;
5872 +}
5873 +
5874 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
5875 +{
5876 + struct mtx *sl = (struct mtx *)lock;
5877 +
5878 + mtx_destroy(sl);
5879 + DWC_FREE(sl);
5880 +}
5881 +
5882 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
5883 +{
5884 + mtx_lock_spin((struct mtx *)lock); // ???
5885 +}
5886 +
5887 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
5888 +{
5889 + mtx_unlock_spin((struct mtx *)lock); // ???
5890 +}
5891 +
5892 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
5893 +{
5894 + mtx_lock_spin((struct mtx *)lock);
5895 +}
5896 +
5897 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
5898 +{
5899 + mtx_unlock_spin((struct mtx *)lock);
5900 +}
5901 +
5902 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
5903 +{
5904 + struct mtx *m;
5905 + dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));
5906 +
5907 + if (!mutex) {
5908 + DWC_ERROR("Cannot allocate memory for mutex");
5909 + return NULL;
5910 + }
5911 +
5912 + m = (struct mtx *)mutex;
5913 + mtx_init(m, "dw3mtx", NULL, MTX_DEF);
5914 + return mutex;
5915 +}
5916 +
5917 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
5918 +#else
5919 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
5920 +{
5921 + mtx_destroy((struct mtx *)mutex);
5922 + DWC_FREE(mutex);
5923 +}
5924 +#endif
5925 +
5926 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
5927 +{
5928 + struct mtx *m = (struct mtx *)mutex;
5929 +
5930 + mtx_lock(m);
5931 +}
5932 +
5933 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
5934 +{
5935 + struct mtx *m = (struct mtx *)mutex;
5936 +
5937 + return mtx_trylock(m);
5938 +}
5939 +
5940 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
5941 +{
5942 + struct mtx *m = (struct mtx *)mutex;
5943 +
5944 + mtx_unlock(m);
5945 +}
5946 +
5947 +
5948 +/* Timing */
5949 +
5950 +void DWC_UDELAY(uint32_t usecs)
5951 +{
5952 + DELAY(usecs);
5953 +}
5954 +
5955 +void DWC_MDELAY(uint32_t msecs)
5956 +{
5957 + do {
5958 + DELAY(1000);
5959 + } while (--msecs);
5960 +}
5961 +
5962 +void DWC_MSLEEP(uint32_t msecs)
5963 +{
5964 + struct timeval tv;
5965 +
5966 + tv.tv_sec = msecs / 1000;
5967 + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
5968 + pause("dw3slp", tvtohz(&tv));
5969 +}
5970 +
5971 +uint32_t DWC_TIME(void)
5972 +{
5973 + struct timeval tv;
5974 +
5975 + microuptime(&tv); // or getmicrouptime? (less precise, but faster)
5976 + return tv.tv_sec * 1000 + tv.tv_usec / 1000;
5977 +}
5978 +
5979 +
5980 +/* Timers */
5981 +
5982 +struct dwc_timer {
5983 + struct callout t;
5984 + char *name;
5985 + dwc_spinlock_t *lock;
5986 + dwc_timer_callback_t cb;
5987 + void *data;
5988 +};
5989 +
5990 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
5991 +{
5992 + dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
5993 +
5994 + if (!t) {
5995 + DWC_ERROR("Cannot allocate memory for timer");
5996 + return NULL;
5997 + }
5998 +
5999 + callout_init(&t->t, 1);
6000 +
6001 + t->name = DWC_STRDUP(name);
6002 + if (!t->name) {
6003 + DWC_ERROR("Cannot allocate memory for timer->name");
6004 + goto no_name;
6005 + }
6006 +
6007 + t->lock = DWC_SPINLOCK_ALLOC();
6008 + if (!t->lock) {
6009 + DWC_ERROR("Cannot allocate memory for lock");
6010 + goto no_lock;
6011 + }
6012 +
6013 + t->cb = cb;
6014 + t->data = data;
6015 +
6016 + return t;
6017 +
6018 + no_lock:
6019 + DWC_FREE(t->name);
6020 + no_name:
6021 + DWC_FREE(t);
6022 +
6023 + return NULL;
6024 +}
6025 +
6026 +void DWC_TIMER_FREE(dwc_timer_t *timer)
6027 +{
6028 + callout_stop(&timer->t);
6029 + DWC_SPINLOCK_FREE(timer->lock);
6030 + DWC_FREE(timer->name);
6031 + DWC_FREE(timer);
6032 +}
6033 +
6034 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
6035 +{
6036 + struct timeval tv;
6037 +
6038 + tv.tv_sec = time / 1000;
6039 + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6040 + callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
6041 +}
6042 +
6043 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
6044 +{
6045 + callout_stop(&timer->t);
6046 +}
6047 +
6048 +
6049 +/* Wait Queues */
6050 +
6051 +struct dwc_waitq {
6052 + struct mtx lock;
6053 + int abort;
6054 +};
6055 +
6056 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
6057 +{
6058 + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
6059 +
6060 + if (!wq) {
6061 + DWC_ERROR("Cannot allocate memory for waitqueue");
6062 + return NULL;
6063 + }
6064 +
6065 + mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);
6066 + wq->abort = 0;
6067 +
6068 + return wq;
6069 +}
6070 +
6071 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
6072 +{
6073 + mtx_destroy(&wq->lock);
6074 + DWC_FREE(wq);
6075 +}
6076 +
6077 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
6078 +{
6079 +// intrmask_t ipl;
6080 + int result = 0;
6081 +
6082 + mtx_lock(&wq->lock);
6083 +// ipl = splbio();
6084 +
6085 + /* Skip the sleep if already aborted or triggered */
6086 + if (!wq->abort && !cond(data)) {
6087 +// splx(ipl);
6088 + result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout
6089 +// ipl = splbio();
6090 + }
6091 +
6092 + if (result == ERESTART) { // signaled - restart
6093 + result = -DWC_E_RESTART;
6094 +
6095 + } else if (result == EINTR) { // signaled - interrupt
6096 + result = -DWC_E_ABORT;
6097 +
6098 + } else if (wq->abort) {
6099 + result = -DWC_E_ABORT;
6100 +
6101 + } else {
6102 + result = 0;
6103 + }
6104 +
6105 + wq->abort = 0;
6106 +// splx(ipl);
6107 + mtx_unlock(&wq->lock);
6108 + return result;
6109 +}
6110 +
6111 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
6112 + void *data, int32_t msecs)
6113 +{
6114 + struct timeval tv, tv1, tv2;
6115 +// intrmask_t ipl;
6116 + int result = 0;
6117 +
6118 + tv.tv_sec = msecs / 1000;
6119 + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6120 +
6121 + mtx_lock(&wq->lock);
6122 +// ipl = splbio();
6123 +
6124 + /* Skip the sleep if already aborted or triggered */
6125 + if (!wq->abort && !cond(data)) {
6126 +// splx(ipl);
6127 + getmicrouptime(&tv1);
6128 + result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));
6129 + getmicrouptime(&tv2);
6130 +// ipl = splbio();
6131 + }
6132 +
6133 + if (result == 0) { // awoken
6134 + if (wq->abort) {
6135 + result = -DWC_E_ABORT;
6136 + } else {
6137 + tv2.tv_usec -= tv1.tv_usec;
6138 + if (tv2.tv_usec < 0) {
6139 + tv2.tv_usec += 1000000;
6140 + tv2.tv_sec--;
6141 + }
6142 +
6143 + tv2.tv_sec -= tv1.tv_sec;
6144 + result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
6145 + result = msecs - result;
6146 + if (result <= 0)
6147 + result = 1;
6148 + }
6149 + } else if (result == ERESTART) { // signaled - restart
6150 + result = -DWC_E_RESTART;
6151 +
6152 + } else if (result == EINTR) { // signaled - interrupt
6153 + result = -DWC_E_ABORT;
6154 +
6155 + } else { // timed out
6156 + result = -DWC_E_TIMEOUT;
6157 + }
6158 +
6159 + wq->abort = 0;
6160 +// splx(ipl);
6161 + mtx_unlock(&wq->lock);
6162 + return result;
6163 +}
6164 +
6165 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
6166 +{
6167 + wakeup(wq);
6168 +}
6169 +
6170 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
6171 +{
6172 +// intrmask_t ipl;
6173 +
6174 + mtx_lock(&wq->lock);
6175 +// ipl = splbio();
6176 + wq->abort = 1;
6177 + wakeup(wq);
6178 +// splx(ipl);
6179 + mtx_unlock(&wq->lock);
6180 +}
6181 +
6182 +
6183 +/* Threading */
6184 +
6185 +struct dwc_thread {
6186 + struct proc *proc;
6187 + int abort;
6188 +};
6189 +
6190 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
6191 +{
6192 + int retval;
6193 + dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
6194 +
6195 + if (!thread) {
6196 + return NULL;
6197 + }
6198 +
6199 + thread->abort = 0;
6200 + retval = kthread_create((void (*)(void *))func, data, &thread->proc,
6201 + RFPROC | RFNOWAIT, 0, "%s", name);
6202 + if (retval) {
6203 + DWC_FREE(thread);
6204 + return NULL;
6205 + }
6206 +
6207 + return thread;
6208 +}
6209 +
6210 +int DWC_THREAD_STOP(dwc_thread_t *thread)
6211 +{
6212 + int retval;
6213 +
6214 + thread->abort = 1;
6215 + retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
6216 +
6217 + if (retval == 0) {
6218 + /* DWC_THREAD_EXIT() will free the thread struct */
6219 + return 0;
6220 + }
6221 +
6222 + /* NOTE: We leak the thread struct if thread doesn't die */
6223 +
6224 + if (retval == EWOULDBLOCK) {
6225 + return -DWC_E_TIMEOUT;
6226 + }
6227 +
6228 + return -DWC_E_UNKNOWN;
6229 +}
6230 +
6231 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
6232 +{
6233 + return thread->abort;
6234 +}
6235 +
6236 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
6237 +{
6238 + wakeup(&thread->abort);
6239 + DWC_FREE(thread);
6240 + kthread_exit(0);
6241 +}
6242 +
6243 +
6244 +/* tasklets
6245 + - Runs in interrupt context (cannot sleep)
6246 + - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]
6247 + - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]
6248 + */
6249 +struct dwc_tasklet {
6250 + struct task t;
6251 + dwc_tasklet_callback_t cb;
6252 + void *data;
6253 +};
6254 +
6255 +static void tasklet_callback(void *data, int pending) // what to do with pending ???
6256 +{
6257 + dwc_tasklet_t *task = (dwc_tasklet_t *)data;
6258 +
6259 + task->cb(task->data);
6260 +}
6261 +
6262 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
6263 +{
6264 + dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
6265 +
6266 + if (task) {
6267 + task->cb = cb;
6268 + task->data = data;
6269 + TASK_INIT(&task->t, 0, tasklet_callback, task);
6270 + } else {
6271 + DWC_ERROR("Cannot allocate memory for tasklet");
6272 + }
6273 +
6274 + return task;
6275 +}
6276 +
6277 +void DWC_TASK_FREE(dwc_tasklet_t *task)
6278 +{
6279 + taskqueue_drain(taskqueue_fast, &task->t); // ???
6280 + DWC_FREE(task);
6281 +}
6282 +
6283 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
6284 +{
6285 + /* Uses predefined system queue */
6286 + taskqueue_enqueue_fast(taskqueue_fast, &task->t);
6287 +}
6288 +
6289 +
6290 +/* workqueues
6291 + - Runs in process context (can sleep)
6292 + */
6293 +typedef struct work_container {
6294 + dwc_work_callback_t cb;
6295 + void *data;
6296 + dwc_workq_t *wq;
6297 + char *name;
6298 + int hz;
6299 +
6300 +#ifdef DEBUG
6301 + DWC_CIRCLEQ_ENTRY(work_container) entry;
6302 +#endif
6303 + struct task task;
6304 +} work_container_t;
6305 +
6306 +#ifdef DEBUG
6307 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
6308 +#endif
6309 +
6310 +struct dwc_workq {
6311 + struct taskqueue *taskq;
6312 + dwc_spinlock_t *lock;
6313 + dwc_waitq_t *waitq;
6314 + int pending;
6315 +
6316 +#ifdef DEBUG
6317 + struct work_container_queue entries;
6318 +#endif
6319 +};
6320 +
6321 +static void do_work(void *data, int pending) // what to do with pending ???
6322 +{
6323 + work_container_t *container = (work_container_t *)data;
6324 + dwc_workq_t *wq = container->wq;
6325 + dwc_irqflags_t flags;
6326 +
6327 + if (container->hz) {
6328 + pause("dw3wrk", container->hz);
6329 + }
6330 +
6331 + container->cb(container->data);
6332 + DWC_DEBUG("Work done: %s, container=%p", container->name, container);
6333 +
6334 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6335 +
6336 +#ifdef DEBUG
6337 + DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
6338 +#endif
6339 + if (container->name)
6340 + DWC_FREE(container->name);
6341 + DWC_FREE(container);
6342 + wq->pending--;
6343 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6344 + DWC_WAITQ_TRIGGER(wq->waitq);
6345 +}
6346 +
6347 +static int work_done(void *data)
6348 +{
6349 + dwc_workq_t *workq = (dwc_workq_t *)data;
6350 +
6351 + return workq->pending == 0;
6352 +}
6353 +
6354 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
6355 +{
6356 + return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
6357 +}
6358 +
6359 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
6360 +{
6361 + dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
6362 +
6363 + if (!wq) {
6364 + DWC_ERROR("Cannot allocate memory for workqueue");
6365 + return NULL;
6366 + }
6367 +
6368 + wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);
6369 + if (!wq->taskq) {
6370 + DWC_ERROR("Cannot allocate memory for taskqueue");
6371 + goto no_taskq;
6372 + }
6373 +
6374 + wq->pending = 0;
6375 +
6376 + wq->lock = DWC_SPINLOCK_ALLOC();
6377 + if (!wq->lock) {
6378 + DWC_ERROR("Cannot allocate memory for spinlock");
6379 + goto no_lock;
6380 + }
6381 +
6382 + wq->waitq = DWC_WAITQ_ALLOC();
6383 + if (!wq->waitq) {
6384 + DWC_ERROR("Cannot allocate memory for waitqueue");
6385 + goto no_waitq;
6386 + }
6387 +
6388 + taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");
6389 +
6390 +#ifdef DEBUG
6391 + DWC_CIRCLEQ_INIT(&wq->entries);
6392 +#endif
6393 + return wq;
6394 +
6395 + no_waitq:
6396 + DWC_SPINLOCK_FREE(wq->lock);
6397 + no_lock:
6398 + taskqueue_free(wq->taskq);
6399 + no_taskq:
6400 + DWC_FREE(wq);
6401 +
6402 + return NULL;
6403 +}
6404 +
6405 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
6406 +{
6407 +#ifdef DEBUG
6408 + dwc_irqflags_t flags;
6409 +
6410 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6411 +
6412 + if (wq->pending != 0) {
6413 + struct work_container *container;
6414 +
6415 + DWC_ERROR("Destroying work queue with pending work");
6416 +
6417 + DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {
6418 + DWC_ERROR("Work %s still pending", container->name);
6419 + }
6420 + }
6421 +
6422 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6423 +#endif
6424 + DWC_WAITQ_FREE(wq->waitq);
6425 + DWC_SPINLOCK_FREE(wq->lock);
6426 + taskqueue_free(wq->taskq);
6427 + DWC_FREE(wq);
6428 +}
6429 +
6430 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
6431 + char *format, ...)
6432 +{
6433 + dwc_irqflags_t flags;
6434 + work_container_t *container;
6435 + static char name[128];
6436 + va_list args;
6437 +
6438 + va_start(args, format);
6439 + DWC_VSNPRINTF(name, 128, format, args);
6440 + va_end(args);
6441 +
6442 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6443 + wq->pending++;
6444 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6445 + DWC_WAITQ_TRIGGER(wq->waitq);
6446 +
6447 + container = DWC_ALLOC_ATOMIC(sizeof(*container));
6448 + if (!container) {
6449 + DWC_ERROR("Cannot allocate memory for container");
6450 + return;
6451 + }
6452 +
6453 + container->name = DWC_STRDUP(name);
6454 + if (!container->name) {
6455 + DWC_ERROR("Cannot allocate memory for container->name");
6456 + DWC_FREE(container);
6457 + return;
6458 + }
6459 +
6460 + container->cb = cb;
6461 + container->data = data;
6462 + container->wq = wq;
6463 + container->hz = 0;
6464 +
6465 + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6466 +
6467 + TASK_INIT(&container->task, 0, do_work, container);
6468 +
6469 +#ifdef DEBUG
6470 + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6471 +#endif
6472 + taskqueue_enqueue_fast(wq->taskq, &container->task);
6473 +}
6474 +
6475 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
6476 + void *data, uint32_t time, char *format, ...)
6477 +{
6478 + dwc_irqflags_t flags;
6479 + work_container_t *container;
6480 + static char name[128];
6481 + struct timeval tv;
6482 + va_list args;
6483 +
6484 + va_start(args, format);
6485 + DWC_VSNPRINTF(name, 128, format, args);
6486 + va_end(args);
6487 +
6488 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6489 + wq->pending++;
6490 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6491 + DWC_WAITQ_TRIGGER(wq->waitq);
6492 +
6493 + container = DWC_ALLOC_ATOMIC(sizeof(*container));
6494 + if (!container) {
6495 + DWC_ERROR("Cannot allocate memory for container");
6496 + return;
6497 + }
6498 +
6499 + container->name = DWC_STRDUP(name);
6500 + if (!container->name) {
6501 + DWC_ERROR("Cannot allocate memory for container->name");
6502 + DWC_FREE(container);
6503 + return;
6504 + }
6505 +
6506 + container->cb = cb;
6507 + container->data = data;
6508 + container->wq = wq;
6509 +
6510 + tv.tv_sec = time / 1000;
6511 + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6512 + container->hz = tvtohz(&tv);
6513 +
6514 + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6515 +
6516 + TASK_INIT(&container->task, 0, do_work, container);
6517 +
6518 +#ifdef DEBUG
6519 + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6520 +#endif
6521 + taskqueue_enqueue_fast(wq->taskq, &container->task);
6522 +}
6523 +
6524 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
6525 +{
6526 + return wq->pending;
6527 +}
6528 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6529 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100
6530 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2013-07-06 15:25:50.000000000 +0100
6531 @@ -0,0 +1,1426 @@
6532 +#include <linux/kernel.h>
6533 +#include <linux/init.h>
6534 +#include <linux/module.h>
6535 +#include <linux/kthread.h>
6536 +
6537 +#ifdef DWC_CCLIB
6538 +# include "dwc_cc.h"
6539 +#endif
6540 +
6541 +#ifdef DWC_CRYPTOLIB
6542 +# include "dwc_modpow.h"
6543 +# include "dwc_dh.h"
6544 +# include "dwc_crypto.h"
6545 +#endif
6546 +
6547 +#ifdef DWC_NOTIFYLIB
6548 +# include "dwc_notifier.h"
6549 +#endif
6550 +
6551 +/* OS-Level Implementations */
6552 +
6553 +/* This is the Linux kernel implementation of the DWC platform library. */
6554 +#include <linux/moduleparam.h>
6555 +#include <linux/ctype.h>
6556 +#include <linux/crypto.h>
6557 +#include <linux/delay.h>
6558 +#include <linux/device.h>
6559 +#include <linux/dma-mapping.h>
6560 +#include <linux/cdev.h>
6561 +#include <linux/errno.h>
6562 +#include <linux/interrupt.h>
6563 +#include <linux/jiffies.h>
6564 +#include <linux/list.h>
6565 +#include <linux/pci.h>
6566 +#include <linux/random.h>
6567 +#include <linux/scatterlist.h>
6568 +#include <linux/slab.h>
6569 +#include <linux/stat.h>
6570 +#include <linux/string.h>
6571 +#include <linux/timer.h>
6572 +#include <linux/usb.h>
6573 +
6574 +#include <linux/version.h>
6575 +
6576 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
6577 +# include <linux/usb/gadget.h>
6578 +#else
6579 +# include <linux/usb_gadget.h>
6580 +#endif
6581 +
6582 +#include <asm/io.h>
6583 +#include <asm/page.h>
6584 +#include <asm/uaccess.h>
6585 +#include <asm/unaligned.h>
6586 +
6587 +#include "dwc_os.h"
6588 +#include "dwc_list.h"
6589 +
6590 +
6591 +/* MISC */
6592 +
6593 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
6594 +{
6595 + return memset(dest, byte, size);
6596 +}
6597 +
6598 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
6599 +{
6600 + return memcpy(dest, src, size);
6601 +}
6602 +
6603 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
6604 +{
6605 + return memmove(dest, src, size);
6606 +}
6607 +
6608 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
6609 +{
6610 + return memcmp(m1, m2, size);
6611 +}
6612 +
6613 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
6614 +{
6615 + return strncmp(s1, s2, size);
6616 +}
6617 +
6618 +int DWC_STRCMP(void *s1, void *s2)
6619 +{
6620 + return strcmp(s1, s2);
6621 +}
6622 +
6623 +int DWC_STRLEN(char const *str)
6624 +{
6625 + return strlen(str);
6626 +}
6627 +
6628 +char *DWC_STRCPY(char *to, char const *from)
6629 +{
6630 + return strcpy(to, from);
6631 +}
6632 +
6633 +char *DWC_STRDUP(char const *str)
6634 +{
6635 + int len = DWC_STRLEN(str) + 1;
6636 + char *new = DWC_ALLOC_ATOMIC(len);
6637 +
6638 + if (!new) {
6639 + return NULL;
6640 + }
6641 +
6642 + DWC_MEMCPY(new, str, len);
6643 + return new;
6644 +}
6645 +
6646 +int DWC_ATOI(const char *str, int32_t *value)
6647 +{
6648 + char *end = NULL;
6649 +
6650 + *value = simple_strtol(str, &end, 0);
6651 + if (*end == '\0') {
6652 + return 0;
6653 + }
6654 +
6655 + return -1;
6656 +}
6657 +
6658 +int DWC_ATOUI(const char *str, uint32_t *value)
6659 +{
6660 + char *end = NULL;
6661 +
6662 + *value = simple_strtoul(str, &end, 0);
6663 + if (*end == '\0') {
6664 + return 0;
6665 + }
6666 +
6667 + return -1;
6668 +}
6669 +
6670 +
6671 +#ifdef DWC_UTFLIB
6672 +/* From usbstring.c */
6673 +
6674 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
6675 +{
6676 + int count = 0;
6677 + u8 c;
6678 + u16 uchar;
6679 +
6680 + /* this insists on correct encodings, though not minimal ones.
6681 + * BUT it currently rejects legit 4-byte UTF-8 code points,
6682 + * which need surrogate pairs. (Unicode 3.1 can use them.)
6683 + */
6684 + while (len != 0 && (c = (u8) *s++) != 0) {
6685 + if (unlikely(c & 0x80)) {
6686 + // 2-byte sequence:
6687 + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
6688 + if ((c & 0xe0) == 0xc0) {
6689 + uchar = (c & 0x1f) << 6;
6690 +
6691 + c = (u8) *s++;
6692 + if ((c & 0xc0) != 0xc0)
6693 + goto fail;
6694 + c &= 0x3f;
6695 + uchar |= c;
6696 +
6697 + // 3-byte sequence (most CJKV characters):
6698 + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
6699 + } else if ((c & 0xf0) == 0xe0) {
6700 + uchar = (c & 0x0f) << 12;
6701 +
6702 + c = (u8) *s++;
6703 + if ((c & 0xc0) != 0xc0)
6704 + goto fail;
6705 + c &= 0x3f;
6706 + uchar |= c << 6;
6707 +
6708 + c = (u8) *s++;
6709 + if ((c & 0xc0) != 0xc0)
6710 + goto fail;
6711 + c &= 0x3f;
6712 + uchar |= c;
6713 +
6714 + /* no bogus surrogates */
6715 + if (0xd800 <= uchar && uchar <= 0xdfff)
6716 + goto fail;
6717 +
6718 + // 4-byte sequence (surrogate pairs, currently rare):
6719 + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
6720 + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
6721 + // (uuuuu = wwww + 1)
6722 + // FIXME accept the surrogate code points (only)
6723 + } else
6724 + goto fail;
6725 + } else
6726 + uchar = c;
6727 + put_unaligned (cpu_to_le16 (uchar), cp++);
6728 + count++;
6729 + len--;
6730 + }
6731 + return count;
6732 +fail:
6733 + return -1;
6734 +}
6735 +#endif /* DWC_UTFLIB */
6736 +
6737 +
6738 +/* dwc_debug.h */
6739 +
6740 +dwc_bool_t DWC_IN_IRQ(void)
6741 +{
6742 + return in_irq();
6743 +}
6744 +
6745 +dwc_bool_t DWC_IN_BH(void)
6746 +{
6747 + return in_softirq();
6748 +}
6749 +
6750 +void DWC_VPRINTF(char *format, va_list args)
6751 +{
6752 + vprintk(format, args);
6753 +}
6754 +
6755 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
6756 +{
6757 + return vsnprintf(str, size, format, args);
6758 +}
6759 +
6760 +void DWC_PRINTF(char *format, ...)
6761 +{
6762 + va_list args;
6763 +
6764 + va_start(args, format);
6765 + DWC_VPRINTF(format, args);
6766 + va_end(args);
6767 +}
6768 +
6769 +int DWC_SPRINTF(char *buffer, char *format, ...)
6770 +{
6771 + int retval;
6772 + va_list args;
6773 +
6774 + va_start(args, format);
6775 + retval = vsprintf(buffer, format, args);
6776 + va_end(args);
6777 + return retval;
6778 +}
6779 +
6780 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
6781 +{
6782 + int retval;
6783 + va_list args;
6784 +
6785 + va_start(args, format);
6786 + retval = vsnprintf(buffer, size, format, args);
6787 + va_end(args);
6788 + return retval;
6789 +}
6790 +
6791 +void __DWC_WARN(char *format, ...)
6792 +{
6793 + va_list args;
6794 +
6795 + va_start(args, format);
6796 + DWC_PRINTF(KERN_WARNING);
6797 + DWC_VPRINTF(format, args);
6798 + va_end(args);
6799 +}
6800 +
6801 +void __DWC_ERROR(char *format, ...)
6802 +{
6803 + va_list args;
6804 +
6805 + va_start(args, format);
6806 + DWC_PRINTF(KERN_ERR);
6807 + DWC_VPRINTF(format, args);
6808 + va_end(args);
6809 +}
6810 +
6811 +void DWC_EXCEPTION(char *format, ...)
6812 +{
6813 + va_list args;
6814 +
6815 + va_start(args, format);
6816 + DWC_PRINTF(KERN_ERR);
6817 + DWC_VPRINTF(format, args);
6818 + va_end(args);
6819 + BUG_ON(1);
6820 +}
6821 +
6822 +#ifdef DEBUG
6823 +void __DWC_DEBUG(char *format, ...)
6824 +{
6825 + va_list args;
6826 +
6827 + va_start(args, format);
6828 + DWC_PRINTF(KERN_DEBUG);
6829 + DWC_VPRINTF(format, args);
6830 + va_end(args);
6831 +}
6832 +#endif
6833 +
6834 +
6835 +/* dwc_mem.h */
6836 +
6837 +#if 0
6838 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
6839 + uint32_t align,
6840 + uint32_t alloc)
6841 +{
6842 + struct dma_pool *pool = dma_pool_create("Pool", NULL,
6843 + size, align, alloc);
6844 + return (dwc_pool_t *)pool;
6845 +}
6846 +
6847 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
6848 +{
6849 + dma_pool_destroy((struct dma_pool *)pool);
6850 +}
6851 +
6852 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
6853 +{
6854 + return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
6855 +}
6856 +
6857 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
6858 +{
6859 + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
6860 + memset(..);
6861 +}
6862 +
6863 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
6864 +{
6865 + dma_pool_free(pool, vaddr, daddr);
6866 +}
6867 +#endif
6868 +
6869 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
6870 +{
6871 +#ifdef xxCOSIM /* Only works for 32-bit cosim */
6872 + void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);
6873 +#else
6874 + void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);
6875 +#endif
6876 + if (!buf) {
6877 + return NULL;
6878 + }
6879 +
6880 + memset(buf, 0, (size_t)size);
6881 + return buf;
6882 +}
6883 +
6884 +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
6885 +{
6886 + void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
6887 + if (!buf) {
6888 + return NULL;
6889 + }
6890 + memset(buf, 0, (size_t)size);
6891 + return buf;
6892 +}
6893 +
6894 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
6895 +{
6896 + dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);
6897 +}
6898 +
6899 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
6900 +{
6901 + return kzalloc(size, GFP_KERNEL);
6902 +}
6903 +
6904 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
6905 +{
6906 + return kzalloc(size, GFP_ATOMIC);
6907 +}
6908 +
6909 +void __DWC_FREE(void *mem_ctx, void *addr)
6910 +{
6911 + kfree(addr);
6912 +}
6913 +
6914 +
6915 +#ifdef DWC_CRYPTOLIB
6916 +/* dwc_crypto.h */
6917 +
6918 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
6919 +{
6920 + get_random_bytes(buffer, length);
6921 +}
6922 +
6923 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
6924 +{
6925 + struct crypto_blkcipher *tfm;
6926 + struct blkcipher_desc desc;
6927 + struct scatterlist sgd;
6928 + struct scatterlist sgs;
6929 +
6930 + tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
6931 + if (tfm == NULL) {
6932 + printk("failed to load transform for aes CBC\n");
6933 + return -1;
6934 + }
6935 +
6936 + crypto_blkcipher_setkey(tfm, key, keylen);
6937 + crypto_blkcipher_set_iv(tfm, iv, 16);
6938 +
6939 + sg_init_one(&sgd, out, messagelen);
6940 + sg_init_one(&sgs, message, messagelen);
6941 +
6942 + desc.tfm = tfm;
6943 + desc.flags = 0;
6944 +
6945 + if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
6946 + crypto_free_blkcipher(tfm);
6947 + DWC_ERROR("AES CBC encryption failed");
6948 + return -1;
6949 + }
6950 +
6951 + crypto_free_blkcipher(tfm);
6952 + return 0;
6953 +}
6954 +
6955 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
6956 +{
6957 + struct crypto_hash *tfm;
6958 + struct hash_desc desc;
6959 + struct scatterlist sg;
6960 +
6961 + tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
6962 + if (IS_ERR(tfm)) {
6963 + DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
6964 + return 0;
6965 + }
6966 + desc.tfm = tfm;
6967 + desc.flags = 0;
6968 +
6969 + sg_init_one(&sg, message, len);
6970 + crypto_hash_digest(&desc, &sg, len, out);
6971 + crypto_free_hash(tfm);
6972 +
6973 + return 1;
6974 +}
6975 +
6976 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
6977 + uint8_t *key, uint32_t keylen, uint8_t *out)
6978 +{
6979 + struct crypto_hash *tfm;
6980 + struct hash_desc desc;
6981 + struct scatterlist sg;
6982 +
6983 + tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
6984 + if (IS_ERR(tfm)) {
6985 + DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
6986 + return 0;
6987 + }
6988 + desc.tfm = tfm;
6989 + desc.flags = 0;
6990 +
6991 + sg_init_one(&sg, message, messagelen);
6992 + crypto_hash_setkey(tfm, key, keylen);
6993 + crypto_hash_digest(&desc, &sg, messagelen, out);
6994 + crypto_free_hash(tfm);
6995 +
6996 + return 1;
6997 +}
6998 +#endif /* DWC_CRYPTOLIB */
6999 +
7000 +
7001 +/* Byte Ordering Conversions */
7002 +
7003 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
7004 +{
7005 +#ifdef __LITTLE_ENDIAN
7006 + return *p;
7007 +#else
7008 + uint8_t *u_p = (uint8_t *)p;
7009 +
7010 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7011 +#endif
7012 +}
7013 +
7014 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
7015 +{
7016 +#ifdef __BIG_ENDIAN
7017 + return *p;
7018 +#else
7019 + uint8_t *u_p = (uint8_t *)p;
7020 +
7021 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7022 +#endif
7023 +}
7024 +
7025 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
7026 +{
7027 +#ifdef __LITTLE_ENDIAN
7028 + return *p;
7029 +#else
7030 + uint8_t *u_p = (uint8_t *)p;
7031 +
7032 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7033 +#endif
7034 +}
7035 +
7036 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
7037 +{
7038 +#ifdef __BIG_ENDIAN
7039 + return *p;
7040 +#else
7041 + uint8_t *u_p = (uint8_t *)p;
7042 +
7043 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7044 +#endif
7045 +}
7046 +
7047 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
7048 +{
7049 +#ifdef __LITTLE_ENDIAN
7050 + return *p;
7051 +#else
7052 + uint8_t *u_p = (uint8_t *)p;
7053 + return (u_p[1] | (u_p[0] << 8));
7054 +#endif
7055 +}
7056 +
7057 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
7058 +{
7059 +#ifdef __BIG_ENDIAN
7060 + return *p;
7061 +#else
7062 + uint8_t *u_p = (uint8_t *)p;
7063 + return (u_p[1] | (u_p[0] << 8));
7064 +#endif
7065 +}
7066 +
7067 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
7068 +{
7069 +#ifdef __LITTLE_ENDIAN
7070 + return *p;
7071 +#else
7072 + uint8_t *u_p = (uint8_t *)p;
7073 + return (u_p[1] | (u_p[0] << 8));
7074 +#endif
7075 +}
7076 +
7077 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
7078 +{
7079 +#ifdef __BIG_ENDIAN
7080 + return *p;
7081 +#else
7082 + uint8_t *u_p = (uint8_t *)p;
7083 + return (u_p[1] | (u_p[0] << 8));
7084 +#endif
7085 +}
7086 +
7087 +
7088 +/* Registers */
7089 +
7090 +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
7091 +{
7092 + return readl(reg);
7093 +}
7094 +
7095 +#if 0
7096 +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
7097 +{
7098 +}
7099 +#endif
7100 +
7101 +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
7102 +{
7103 + writel(value, reg);
7104 +}
7105 +
7106 +#if 0
7107 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
7108 +{
7109 +}
7110 +#endif
7111 +
7112 +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
7113 +{
7114 + writel((readl(reg) & ~clear_mask) | set_mask, reg);
7115 +}
7116 +
7117 +#if 0
7118 +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)
7119 +{
7120 +}
7121 +#endif
7122 +
7123 +
7124 +/* Locking */
7125 +
7126 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
7127 +{
7128 + spinlock_t *sl = (spinlock_t *)1;
7129 +
7130 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7131 + sl = DWC_ALLOC(sizeof(*sl));
7132 + if (!sl) {
7133 + DWC_ERROR("Cannot allocate memory for spinlock\n");
7134 + return NULL;
7135 + }
7136 +
7137 + spin_lock_init(sl);
7138 +#endif
7139 + return (dwc_spinlock_t *)sl;
7140 +}
7141 +
7142 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
7143 +{
7144 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7145 + DWC_FREE(lock);
7146 +#endif
7147 +}
7148 +
7149 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
7150 +{
7151 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7152 + spin_lock((spinlock_t *)lock);
7153 +#endif
7154 +}
7155 +
7156 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
7157 +{
7158 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7159 + spin_unlock((spinlock_t *)lock);
7160 +#endif
7161 +}
7162 +
7163 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
7164 +{
7165 + dwc_irqflags_t f;
7166 +
7167 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7168 + spin_lock_irqsave((spinlock_t *)lock, f);
7169 +#else
7170 + local_irq_save(f);
7171 +#endif
7172 + *flags = f;
7173 +}
7174 +
7175 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
7176 +{
7177 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7178 + spin_unlock_irqrestore((spinlock_t *)lock, flags);
7179 +#else
7180 + local_irq_restore(flags);
7181 +#endif
7182 +}
7183 +
7184 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
7185 +{
7186 + struct mutex *m;
7187 + dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));
7188 +
7189 + if (!mutex) {
7190 + DWC_ERROR("Cannot allocate memory for mutex\n");
7191 + return NULL;
7192 + }
7193 +
7194 + m = (struct mutex *)mutex;
7195 + mutex_init(m);
7196 + return mutex;
7197 +}
7198 +
7199 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
7200 +#else
7201 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
7202 +{
7203 + mutex_destroy((struct mutex *)mutex);
7204 + DWC_FREE(mutex);
7205 +}
7206 +#endif
7207 +
7208 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
7209 +{
7210 + struct mutex *m = (struct mutex *)mutex;
7211 + mutex_lock(m);
7212 +}
7213 +
7214 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
7215 +{
7216 + struct mutex *m = (struct mutex *)mutex;
7217 + return mutex_trylock(m);
7218 +}
7219 +
7220 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
7221 +{
7222 + struct mutex *m = (struct mutex *)mutex;
7223 + mutex_unlock(m);
7224 +}
7225 +
7226 +
7227 +/* Timing */
7228 +
7229 +void DWC_UDELAY(uint32_t usecs)
7230 +{
7231 + udelay(usecs);
7232 +}
7233 +
7234 +void DWC_MDELAY(uint32_t msecs)
7235 +{
7236 + mdelay(msecs);
7237 +}
7238 +
7239 +void DWC_MSLEEP(uint32_t msecs)
7240 +{
7241 + msleep(msecs);
7242 +}
7243 +
7244 +uint32_t DWC_TIME(void)
7245 +{
7246 + return jiffies_to_msecs(jiffies);
7247 +}
7248 +
7249 +
7250 +/* Timers */
7251 +
7252 +struct dwc_timer {
7253 + struct timer_list *t;
7254 + char *name;
7255 + dwc_timer_callback_t cb;
7256 + void *data;
7257 + uint8_t scheduled;
7258 + dwc_spinlock_t *lock;
7259 +};
7260 +
7261 +static void timer_callback(unsigned long data)
7262 +{
7263 + dwc_timer_t *timer = (dwc_timer_t *)data;
7264 + dwc_irqflags_t flags;
7265 +
7266 + DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7267 + timer->scheduled = 0;
7268 + DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7269 + DWC_DEBUGC("Timer %s callback", timer->name);
7270 + timer->cb(timer->data);
7271 +}
7272 +
7273 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
7274 +{
7275 + dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
7276 +
7277 + if (!t) {
7278 + DWC_ERROR("Cannot allocate memory for timer");
7279 + return NULL;
7280 + }
7281 +
7282 + t->t = DWC_ALLOC(sizeof(*t->t));
7283 + if (!t->t) {
7284 + DWC_ERROR("Cannot allocate memory for timer->t");
7285 + goto no_timer;
7286 + }
7287 +
7288 + t->name = DWC_STRDUP(name);
7289 + if (!t->name) {
7290 + DWC_ERROR("Cannot allocate memory for timer->name");
7291 + goto no_name;
7292 + }
7293 +
7294 + t->lock = DWC_SPINLOCK_ALLOC();
7295 + if (!t->lock) {
7296 + DWC_ERROR("Cannot allocate memory for lock");
7297 + goto no_lock;
7298 + }
7299 +
7300 + t->scheduled = 0;
7301 + t->t->base = &boot_tvec_bases;
7302 + t->t->expires = jiffies;
7303 + setup_timer(t->t, timer_callback, (unsigned long)t);
7304 +
7305 + t->cb = cb;
7306 + t->data = data;
7307 +
7308 + return t;
7309 +
7310 + no_lock:
7311 + DWC_FREE(t->name);
7312 + no_name:
7313 + DWC_FREE(t->t);
7314 + no_timer:
7315 + DWC_FREE(t);
7316 + return NULL;
7317 +}
7318 +
7319 +void DWC_TIMER_FREE(dwc_timer_t *timer)
7320 +{
7321 + dwc_irqflags_t flags;
7322 +
7323 + DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7324 +
7325 + if (timer->scheduled) {
7326 + del_timer(timer->t);
7327 + timer->scheduled = 0;
7328 + }
7329 +
7330 + DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7331 + DWC_SPINLOCK_FREE(timer->lock);
7332 + DWC_FREE(timer->t);
7333 + DWC_FREE(timer->name);
7334 + DWC_FREE(timer);
7335 +}
7336 +
7337 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
7338 +{
7339 + dwc_irqflags_t flags;
7340 +
7341 + DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7342 +
7343 + if (!timer->scheduled) {
7344 + timer->scheduled = 1;
7345 + DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);
7346 + timer->t->expires = jiffies + msecs_to_jiffies(time);
7347 + add_timer(timer->t);
7348 + } else {
7349 + DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);
7350 + mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
7351 + }
7352 +
7353 + DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7354 +}
7355 +
7356 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
7357 +{
7358 + del_timer(timer->t);
7359 +}
7360 +
7361 +
7362 +/* Wait Queues */
7363 +
7364 +struct dwc_waitq {
7365 + wait_queue_head_t queue;
7366 + int abort;
7367 +};
7368 +
7369 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
7370 +{
7371 + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
7372 +
7373 + if (!wq) {
7374 + DWC_ERROR("Cannot allocate memory for waitqueue\n");
7375 + return NULL;
7376 + }
7377 +
7378 + init_waitqueue_head(&wq->queue);
7379 + wq->abort = 0;
7380 + return wq;
7381 +}
7382 +
7383 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
7384 +{
7385 + DWC_FREE(wq);
7386 +}
7387 +
7388 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
7389 +{
7390 + int result = wait_event_interruptible(wq->queue,
7391 + cond(data) || wq->abort);
7392 + if (result == -ERESTARTSYS) {
7393 + wq->abort = 0;
7394 + return -DWC_E_RESTART;
7395 + }
7396 +
7397 + if (wq->abort == 1) {
7398 + wq->abort = 0;
7399 + return -DWC_E_ABORT;
7400 + }
7401 +
7402 + wq->abort = 0;
7403 +
7404 + if (result == 0) {
7405 + return 0;
7406 + }
7407 +
7408 + return -DWC_E_UNKNOWN;
7409 +}
7410 +
7411 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
7412 + void *data, int32_t msecs)
7413 +{
7414 + int32_t tmsecs;
7415 + int result = wait_event_interruptible_timeout(wq->queue,
7416 + cond(data) || wq->abort,
7417 + msecs_to_jiffies(msecs));
7418 + if (result == -ERESTARTSYS) {
7419 + wq->abort = 0;
7420 + return -DWC_E_RESTART;
7421 + }
7422 +
7423 + if (wq->abort == 1) {
7424 + wq->abort = 0;
7425 + return -DWC_E_ABORT;
7426 + }
7427 +
7428 + wq->abort = 0;
7429 +
7430 + if (result > 0) {
7431 + tmsecs = jiffies_to_msecs(result);
7432 + if (!tmsecs) {
7433 + return 1;
7434 + }
7435 +
7436 + return tmsecs;
7437 + }
7438 +
7439 + if (result == 0) {
7440 + return -DWC_E_TIMEOUT;
7441 + }
7442 +
7443 + return -DWC_E_UNKNOWN;
7444 +}
7445 +
7446 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
7447 +{
7448 + wq->abort = 0;
7449 + wake_up_interruptible(&wq->queue);
7450 +}
7451 +
7452 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
7453 +{
7454 + wq->abort = 1;
7455 + wake_up_interruptible(&wq->queue);
7456 +}
7457 +
7458 +
7459 +/* Threading */
7460 +
7461 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
7462 +{
7463 + struct task_struct *thread = kthread_run(func, data, name);
7464 +
7465 + if (thread == ERR_PTR(-ENOMEM)) {
7466 + return NULL;
7467 + }
7468 +
7469 + return (dwc_thread_t *)thread;
7470 +}
7471 +
7472 +int DWC_THREAD_STOP(dwc_thread_t *thread)
7473 +{
7474 + return kthread_stop((struct task_struct *)thread);
7475 +}
7476 +
7477 +dwc_bool_t DWC_THREAD_SHOULD_STOP(void)
7478 +{
7479 + return kthread_should_stop();
7480 +}
7481 +
7482 +
7483 +/* tasklets
7484 + - run in interrupt context (cannot sleep)
7485 + - each tasklet runs on a single CPU
7486 + - different tasklets can be running simultaneously on different CPUs
7487 + */
7488 +struct dwc_tasklet {
7489 + struct tasklet_struct t;
7490 + dwc_tasklet_callback_t cb;
7491 + void *data;
7492 +};
7493 +
7494 +static void tasklet_callback(unsigned long data)
7495 +{
7496 + dwc_tasklet_t *t = (dwc_tasklet_t *)data;
7497 + t->cb(t->data);
7498 +}
7499 +
7500 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
7501 +{
7502 + dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
7503 +
7504 + if (t) {
7505 + t->cb = cb;
7506 + t->data = data;
7507 + tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
7508 + } else {
7509 + DWC_ERROR("Cannot allocate memory for tasklet\n");
7510 + }
7511 +
7512 + return t;
7513 +}
7514 +
7515 +void DWC_TASK_FREE(dwc_tasklet_t *task)
7516 +{
7517 + DWC_FREE(task);
7518 +}
7519 +
7520 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
7521 +{
7522 + tasklet_schedule(&task->t);
7523 +}
7524 +
7525 +void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task)
7526 +{
7527 + tasklet_hi_schedule(&task->t);
7528 +}
7529 +
7530 +
7531 +/* workqueues
7532 + - run in process context (can sleep)
7533 + */
7534 +typedef struct work_container {
7535 + dwc_work_callback_t cb;
7536 + void *data;
7537 + dwc_workq_t *wq;
7538 + char *name;
7539 +
7540 +#ifdef DEBUG
7541 + DWC_CIRCLEQ_ENTRY(work_container) entry;
7542 +#endif
7543 + struct delayed_work work;
7544 +} work_container_t;
7545 +
7546 +#ifdef DEBUG
7547 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
7548 +#endif
7549 +
7550 +struct dwc_workq {
7551 + struct workqueue_struct *wq;
7552 + dwc_spinlock_t *lock;
7553 + dwc_waitq_t *waitq;
7554 + int pending;
7555 +
7556 +#ifdef DEBUG
7557 + struct work_container_queue entries;
7558 +#endif
7559 +};
7560 +
7561 +static void do_work(struct work_struct *work)
7562 +{
7563 + dwc_irqflags_t flags;
7564 + struct delayed_work *dw = container_of(work, struct delayed_work, work);
7565 + work_container_t *container = container_of(dw, struct work_container, work);
7566 + dwc_workq_t *wq = container->wq;
7567 +
7568 + container->cb(container->data);
7569 +
7570 +#ifdef DEBUG
7571 + DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
7572 +#endif
7573 + DWC_DEBUGC("Work done: %s, container=%p", container->name, container);
7574 + if (container->name) {
7575 + DWC_FREE(container->name);
7576 + }
7577 + DWC_FREE(container);
7578 +
7579 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7580 + wq->pending--;
7581 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7582 + DWC_WAITQ_TRIGGER(wq->waitq);
7583 +}
7584 +
7585 +static int work_done(void *data)
7586 +{
7587 + dwc_workq_t *workq = (dwc_workq_t *)data;
7588 + return workq->pending == 0;
7589 +}
7590 +
7591 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
7592 +{
7593 + return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
7594 +}
7595 +
7596 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
7597 +{
7598 + dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
7599 +
7600 + if (!wq) {
7601 + return NULL;
7602 + }
7603 +
7604 + wq->wq = create_singlethread_workqueue(name);
7605 + if (!wq->wq) {
7606 + goto no_wq;
7607 + }
7608 +
7609 + wq->pending = 0;
7610 +
7611 + wq->lock = DWC_SPINLOCK_ALLOC();
7612 + if (!wq->lock) {
7613 + goto no_lock;
7614 + }
7615 +
7616 + wq->waitq = DWC_WAITQ_ALLOC();
7617 + if (!wq->waitq) {
7618 + goto no_waitq;
7619 + }
7620 +
7621 +#ifdef DEBUG
7622 + DWC_CIRCLEQ_INIT(&wq->entries);
7623 +#endif
7624 + return wq;
7625 +
7626 + no_waitq:
7627 + DWC_SPINLOCK_FREE(wq->lock);
7628 + no_lock:
7629 + destroy_workqueue(wq->wq);
7630 + no_wq:
7631 + DWC_FREE(wq);
7632 +
7633 + return NULL;
7634 +}
7635 +
7636 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
7637 +{
7638 +#ifdef DEBUG
7639 + if (wq->pending != 0) {
7640 + struct work_container *wc;
7641 + DWC_ERROR("Destroying work queue with pending work");
7642 + DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
7643 + DWC_ERROR("Work %s still pending", wc->name);
7644 + }
7645 + }
7646 +#endif
7647 + destroy_workqueue(wq->wq);
7648 + DWC_SPINLOCK_FREE(wq->lock);
7649 + DWC_WAITQ_FREE(wq->waitq);
7650 + DWC_FREE(wq);
7651 +}
7652 +
7653 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
7654 + char *format, ...)
7655 +{
7656 + dwc_irqflags_t flags;
7657 + work_container_t *container;
7658 + static char name[128];
7659 + va_list args;
7660 +
7661 + va_start(args, format);
7662 + DWC_VSNPRINTF(name, 128, format, args);
7663 + va_end(args);
7664 +
7665 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7666 + wq->pending++;
7667 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7668 + DWC_WAITQ_TRIGGER(wq->waitq);
7669 +
7670 + container = DWC_ALLOC_ATOMIC(sizeof(*container));
7671 + if (!container) {
7672 + DWC_ERROR("Cannot allocate memory for container\n");
7673 + return;
7674 + }
7675 +
7676 + container->name = DWC_STRDUP(name);
7677 + if (!container->name) {
7678 + DWC_ERROR("Cannot allocate memory for container->name\n");
7679 + DWC_FREE(container);
7680 + return;
7681 + }
7682 +
7683 + container->cb = cb;
7684 + container->data = data;
7685 + container->wq = wq;
7686 + DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
7687 + INIT_WORK(&container->work.work, do_work);
7688 +
7689 +#ifdef DEBUG
7690 + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
7691 +#endif
7692 + queue_work(wq->wq, &container->work.work);
7693 +}
7694 +
7695 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
7696 + void *data, uint32_t time, char *format, ...)
7697 +{
7698 + dwc_irqflags_t flags;
7699 + work_container_t *container;
7700 + static char name[128];
7701 + va_list args;
7702 +
7703 + va_start(args, format);
7704 + DWC_VSNPRINTF(name, 128, format, args);
7705 + va_end(args);
7706 +
7707 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7708 + wq->pending++;
7709 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7710 + DWC_WAITQ_TRIGGER(wq->waitq);
7711 +
7712 + container = DWC_ALLOC_ATOMIC(sizeof(*container));
7713 + if (!container) {
7714 + DWC_ERROR("Cannot allocate memory for container\n");
7715 + return;
7716 + }
7717 +
7718 + container->name = DWC_STRDUP(name);
7719 + if (!container->name) {
7720 + DWC_ERROR("Cannot allocate memory for container->name\n");
7721 + DWC_FREE(container);
7722 + return;
7723 + }
7724 +
7725 + container->cb = cb;
7726 + container->data = data;
7727 + container->wq = wq;
7728 + DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
7729 + INIT_DELAYED_WORK(&container->work, do_work);
7730 +
7731 +#ifdef DEBUG
7732 + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
7733 +#endif
7734 + queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
7735 +}
7736 +
7737 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
7738 +{
7739 + return wq->pending;
7740 +}
7741 +
7742 +
7743 +#ifdef DWC_LIBMODULE
7744 +
7745 +#ifdef DWC_CCLIB
7746 +/* CC */
7747 +EXPORT_SYMBOL(dwc_cc_if_alloc);
7748 +EXPORT_SYMBOL(dwc_cc_if_free);
7749 +EXPORT_SYMBOL(dwc_cc_clear);
7750 +EXPORT_SYMBOL(dwc_cc_add);
7751 +EXPORT_SYMBOL(dwc_cc_remove);
7752 +EXPORT_SYMBOL(dwc_cc_change);
7753 +EXPORT_SYMBOL(dwc_cc_data_for_save);
7754 +EXPORT_SYMBOL(dwc_cc_restore_from_data);
7755 +EXPORT_SYMBOL(dwc_cc_match_chid);
7756 +EXPORT_SYMBOL(dwc_cc_match_cdid);
7757 +EXPORT_SYMBOL(dwc_cc_ck);
7758 +EXPORT_SYMBOL(dwc_cc_chid);
7759 +EXPORT_SYMBOL(dwc_cc_cdid);
7760 +EXPORT_SYMBOL(dwc_cc_name);
7761 +#endif /* DWC_CCLIB */
7762 +
7763 +#ifdef DWC_CRYPTOLIB
7764 +# ifndef CONFIG_MACH_IPMATE
7765 +/* Modpow */
7766 +EXPORT_SYMBOL(dwc_modpow);
7767 +
7768 +/* DH */
7769 +EXPORT_SYMBOL(dwc_dh_modpow);
7770 +EXPORT_SYMBOL(dwc_dh_derive_keys);
7771 +EXPORT_SYMBOL(dwc_dh_pk);
7772 +# endif /* CONFIG_MACH_IPMATE */
7773 +
7774 +/* Crypto */
7775 +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
7776 +EXPORT_SYMBOL(dwc_wusb_cmf);
7777 +EXPORT_SYMBOL(dwc_wusb_prf);
7778 +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
7779 +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
7780 +EXPORT_SYMBOL(dwc_wusb_gen_key);
7781 +EXPORT_SYMBOL(dwc_wusb_gen_mic);
7782 +#endif /* DWC_CRYPTOLIB */
7783 +
7784 +/* Notification */
7785 +#ifdef DWC_NOTIFYLIB
7786 +EXPORT_SYMBOL(dwc_alloc_notification_manager);
7787 +EXPORT_SYMBOL(dwc_free_notification_manager);
7788 +EXPORT_SYMBOL(dwc_register_notifier);
7789 +EXPORT_SYMBOL(dwc_unregister_notifier);
7790 +EXPORT_SYMBOL(dwc_add_observer);
7791 +EXPORT_SYMBOL(dwc_remove_observer);
7792 +EXPORT_SYMBOL(dwc_notify);
7793 +#endif
7794 +
7795 +/* Memory Debugging Routines */
7796 +#ifdef DWC_DEBUG_MEMORY
7797 +EXPORT_SYMBOL(dwc_alloc_debug);
7798 +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
7799 +EXPORT_SYMBOL(dwc_free_debug);
7800 +EXPORT_SYMBOL(dwc_dma_alloc_debug);
7801 +EXPORT_SYMBOL(dwc_dma_free_debug);
7802 +#endif
7803 +
7804 +EXPORT_SYMBOL(DWC_MEMSET);
7805 +EXPORT_SYMBOL(DWC_MEMCPY);
7806 +EXPORT_SYMBOL(DWC_MEMMOVE);
7807 +EXPORT_SYMBOL(DWC_MEMCMP);
7808 +EXPORT_SYMBOL(DWC_STRNCMP);
7809 +EXPORT_SYMBOL(DWC_STRCMP);
7810 +EXPORT_SYMBOL(DWC_STRLEN);
7811 +EXPORT_SYMBOL(DWC_STRCPY);
7812 +EXPORT_SYMBOL(DWC_STRDUP);
7813 +EXPORT_SYMBOL(DWC_ATOI);
7814 +EXPORT_SYMBOL(DWC_ATOUI);
7815 +
7816 +#ifdef DWC_UTFLIB
7817 +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
7818 +#endif /* DWC_UTFLIB */
7819 +
7820 +EXPORT_SYMBOL(DWC_IN_IRQ);
7821 +EXPORT_SYMBOL(DWC_IN_BH);
7822 +EXPORT_SYMBOL(DWC_VPRINTF);
7823 +EXPORT_SYMBOL(DWC_VSNPRINTF);
7824 +EXPORT_SYMBOL(DWC_PRINTF);
7825 +EXPORT_SYMBOL(DWC_SPRINTF);
7826 +EXPORT_SYMBOL(DWC_SNPRINTF);
7827 +EXPORT_SYMBOL(__DWC_WARN);
7828 +EXPORT_SYMBOL(__DWC_ERROR);
7829 +EXPORT_SYMBOL(DWC_EXCEPTION);
7830 +
7831 +#ifdef DEBUG
7832 +EXPORT_SYMBOL(__DWC_DEBUG);
7833 +#endif
7834 +
7835 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
7836 +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
7837 +EXPORT_SYMBOL(__DWC_DMA_FREE);
7838 +EXPORT_SYMBOL(__DWC_ALLOC);
7839 +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
7840 +EXPORT_SYMBOL(__DWC_FREE);
7841 +
7842 +#ifdef DWC_CRYPTOLIB
7843 +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
7844 +EXPORT_SYMBOL(DWC_AES_CBC);
7845 +EXPORT_SYMBOL(DWC_SHA256);
7846 +EXPORT_SYMBOL(DWC_HMAC_SHA256);
7847 +#endif
7848 +
7849 +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
7850 +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
7851 +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
7852 +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
7853 +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
7854 +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
7855 +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
7856 +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
7857 +EXPORT_SYMBOL(DWC_READ_REG32);
7858 +EXPORT_SYMBOL(DWC_WRITE_REG32);
7859 +EXPORT_SYMBOL(DWC_MODIFY_REG32);
7860 +
7861 +#if 0
7862 +EXPORT_SYMBOL(DWC_READ_REG64);
7863 +EXPORT_SYMBOL(DWC_WRITE_REG64);
7864 +EXPORT_SYMBOL(DWC_MODIFY_REG64);
7865 +#endif
7866 +
7867 +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
7868 +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
7869 +EXPORT_SYMBOL(DWC_SPINLOCK);
7870 +EXPORT_SYMBOL(DWC_SPINUNLOCK);
7871 +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
7872 +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
7873 +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
7874 +
7875 +#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))
7876 +EXPORT_SYMBOL(DWC_MUTEX_FREE);
7877 +#endif
7878 +
7879 +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
7880 +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
7881 +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
7882 +EXPORT_SYMBOL(DWC_UDELAY);
7883 +EXPORT_SYMBOL(DWC_MDELAY);
7884 +EXPORT_SYMBOL(DWC_MSLEEP);
7885 +EXPORT_SYMBOL(DWC_TIME);
7886 +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
7887 +EXPORT_SYMBOL(DWC_TIMER_FREE);
7888 +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
7889 +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
7890 +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
7891 +EXPORT_SYMBOL(DWC_WAITQ_FREE);
7892 +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
7893 +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
7894 +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
7895 +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
7896 +EXPORT_SYMBOL(DWC_THREAD_RUN);
7897 +EXPORT_SYMBOL(DWC_THREAD_STOP);
7898 +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
7899 +EXPORT_SYMBOL(DWC_TASK_ALLOC);
7900 +EXPORT_SYMBOL(DWC_TASK_FREE);
7901 +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
7902 +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
7903 +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
7904 +EXPORT_SYMBOL(DWC_WORKQ_FREE);
7905 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
7906 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
7907 +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
7908 +
7909 +static int dwc_common_port_init_module(void)
7910 +{
7911 + int result = 0;
7912 +
7913 + printk(KERN_DEBUG "Module dwc_common_port init\n" );
7914 +
7915 +#ifdef DWC_DEBUG_MEMORY
7916 + result = dwc_memory_debug_start(NULL);
7917 + if (result) {
7918 + printk(KERN_ERR
7919 + "dwc_memory_debug_start() failed with error %d\n",
7920 + result);
7921 + return result;
7922 + }
7923 +#endif
7924 +
7925 +#ifdef DWC_NOTIFYLIB
7926 + result = dwc_alloc_notification_manager(NULL, NULL);
7927 + if (result) {
7928 + printk(KERN_ERR
7929 + "dwc_alloc_notification_manager() failed with error %d\n",
7930 + result);
7931 + return result;
7932 + }
7933 +#endif
7934 + return result;
7935 +}
7936 +
7937 +static void dwc_common_port_exit_module(void)
7938 +{
7939 + printk(KERN_DEBUG "Module dwc_common_port exit\n" );
7940 +
7941 +#ifdef DWC_NOTIFYLIB
7942 + dwc_free_notification_manager();
7943 +#endif
7944 +
7945 +#ifdef DWC_DEBUG_MEMORY
7946 + dwc_memory_debug_stop();
7947 +#endif
7948 +}
7949 +
7950 +module_init(dwc_common_port_init_module);
7951 +module_exit(dwc_common_port_exit_module);
7952 +
7953 +MODULE_DESCRIPTION("DWC Common Library - Portable version");
7954 +MODULE_AUTHOR("Synopsys Inc.");
7955 +MODULE_LICENSE ("GPL");
7956 +
7957 +#endif /* DWC_LIBMODULE */
7958 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
7959 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1970-01-01 01:00:00.000000000 +0100
7960 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2013-07-06 15:25:50.000000000 +0100
7961 @@ -0,0 +1,1275 @@
7962 +#include "dwc_os.h"
7963 +#include "dwc_list.h"
7964 +
7965 +#ifdef DWC_CCLIB
7966 +# include "dwc_cc.h"
7967 +#endif
7968 +
7969 +#ifdef DWC_CRYPTOLIB
7970 +# include "dwc_modpow.h"
7971 +# include "dwc_dh.h"
7972 +# include "dwc_crypto.h"
7973 +#endif
7974 +
7975 +#ifdef DWC_NOTIFYLIB
7976 +# include "dwc_notifier.h"
7977 +#endif
7978 +
7979 +/* OS-Level Implementations */
7980 +
7981 +/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */
7982 +
7983 +
7984 +/* MISC */
7985 +
7986 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
7987 +{
7988 + return memset(dest, byte, size);
7989 +}
7990 +
7991 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
7992 +{
7993 + return memcpy(dest, src, size);
7994 +}
7995 +
7996 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
7997 +{
7998 + bcopy(src, dest, size);
7999 + return dest;
8000 +}
8001 +
8002 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
8003 +{
8004 + return memcmp(m1, m2, size);
8005 +}
8006 +
8007 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
8008 +{
8009 + return strncmp(s1, s2, size);
8010 +}
8011 +
8012 +int DWC_STRCMP(void *s1, void *s2)
8013 +{
8014 + return strcmp(s1, s2);
8015 +}
8016 +
8017 +int DWC_STRLEN(char const *str)
8018 +{
8019 + return strlen(str);
8020 +}
8021 +
8022 +char *DWC_STRCPY(char *to, char const *from)
8023 +{
8024 + return strcpy(to, from);
8025 +}
8026 +
8027 +char *DWC_STRDUP(char const *str)
8028 +{
8029 + int len = DWC_STRLEN(str) + 1;
8030 + char *new = DWC_ALLOC_ATOMIC(len);
8031 +
8032 + if (!new) {
8033 + return NULL;
8034 + }
8035 +
8036 + DWC_MEMCPY(new, str, len);
8037 + return new;
8038 +}
8039 +
8040 +int DWC_ATOI(char *str, int32_t *value)
8041 +{
8042 + char *end = NULL;
8043 +
8044 + /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'
8045 + * should be equivalent on 2's complement machines
8046 + */
8047 + *value = strtoul(str, &end, 0);
8048 + if (*end == '\0') {
8049 + return 0;
8050 + }
8051 +
8052 + return -1;
8053 +}
8054 +
8055 +int DWC_ATOUI(char *str, uint32_t *value)
8056 +{
8057 + char *end = NULL;
8058 +
8059 + *value = strtoul(str, &end, 0);
8060 + if (*end == '\0') {
8061 + return 0;
8062 + }
8063 +
8064 + return -1;
8065 +}
8066 +
8067 +
8068 +#ifdef DWC_UTFLIB
8069 +/* From usbstring.c */
8070 +
8071 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
8072 +{
8073 + int count = 0;
8074 + u8 c;
8075 + u16 uchar;
8076 +
8077 + /* this insists on correct encodings, though not minimal ones.
8078 + * BUT it currently rejects legit 4-byte UTF-8 code points,
8079 + * which need surrogate pairs. (Unicode 3.1 can use them.)
8080 + */
8081 + while (len != 0 && (c = (u8) *s++) != 0) {
8082 + if (unlikely(c & 0x80)) {
8083 + // 2-byte sequence:
8084 + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
8085 + if ((c & 0xe0) == 0xc0) {
8086 + uchar = (c & 0x1f) << 6;
8087 +
8088 + c = (u8) *s++;
8089 + if ((c & 0xc0) != 0xc0)
8090 + goto fail;
8091 + c &= 0x3f;
8092 + uchar |= c;
8093 +
8094 + // 3-byte sequence (most CJKV characters):
8095 + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
8096 + } else if ((c & 0xf0) == 0xe0) {
8097 + uchar = (c & 0x0f) << 12;
8098 +
8099 + c = (u8) *s++;
8100 + if ((c & 0xc0) != 0xc0)
8101 + goto fail;
8102 + c &= 0x3f;
8103 + uchar |= c << 6;
8104 +
8105 + c = (u8) *s++;
8106 + if ((c & 0xc0) != 0xc0)
8107 + goto fail;
8108 + c &= 0x3f;
8109 + uchar |= c;
8110 +
8111 + /* no bogus surrogates */
8112 + if (0xd800 <= uchar && uchar <= 0xdfff)
8113 + goto fail;
8114 +
8115 + // 4-byte sequence (surrogate pairs, currently rare):
8116 + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
8117 + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
8118 + // (uuuuu = wwww + 1)
8119 + // FIXME accept the surrogate code points (only)
8120 + } else
8121 + goto fail;
8122 + } else
8123 + uchar = c;
8124 + put_unaligned (cpu_to_le16 (uchar), cp++);
8125 + count++;
8126 + len--;
8127 + }
8128 + return count;
8129 +fail:
8130 + return -1;
8131 +}
8132 +
8133 +#endif /* DWC_UTFLIB */
8134 +
8135 +
8136 +/* dwc_debug.h */
8137 +
8138 +dwc_bool_t DWC_IN_IRQ(void)
8139 +{
8140 +// return in_irq();
8141 + return 0;
8142 +}
8143 +
8144 +dwc_bool_t DWC_IN_BH(void)
8145 +{
8146 +// return in_softirq();
8147 + return 0;
8148 +}
8149 +
8150 +void DWC_VPRINTF(char *format, va_list args)
8151 +{
8152 + vprintf(format, args);
8153 +}
8154 +
8155 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
8156 +{
8157 + return vsnprintf(str, size, format, args);
8158 +}
8159 +
8160 +void DWC_PRINTF(char *format, ...)
8161 +{
8162 + va_list args;
8163 +
8164 + va_start(args, format);
8165 + DWC_VPRINTF(format, args);
8166 + va_end(args);
8167 +}
8168 +
8169 +int DWC_SPRINTF(char *buffer, char *format, ...)
8170 +{
8171 + int retval;
8172 + va_list args;
8173 +
8174 + va_start(args, format);
8175 + retval = vsprintf(buffer, format, args);
8176 + va_end(args);
8177 + return retval;
8178 +}
8179 +
8180 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
8181 +{
8182 + int retval;
8183 + va_list args;
8184 +
8185 + va_start(args, format);
8186 + retval = vsnprintf(buffer, size, format, args);
8187 + va_end(args);
8188 + return retval;
8189 +}
8190 +
8191 +void __DWC_WARN(char *format, ...)
8192 +{
8193 + va_list args;
8194 +
8195 + va_start(args, format);
8196 + DWC_VPRINTF(format, args);
8197 + va_end(args);
8198 +}
8199 +
8200 +void __DWC_ERROR(char *format, ...)
8201 +{
8202 + va_list args;
8203 +
8204 + va_start(args, format);
8205 + DWC_VPRINTF(format, args);
8206 + va_end(args);
8207 +}
8208 +
8209 +void DWC_EXCEPTION(char *format, ...)
8210 +{
8211 + va_list args;
8212 +
8213 + va_start(args, format);
8214 + DWC_VPRINTF(format, args);
8215 + va_end(args);
8216 +// BUG_ON(1); ???
8217 +}
8218 +
8219 +#ifdef DEBUG
8220 +void __DWC_DEBUG(char *format, ...)
8221 +{
8222 + va_list args;
8223 +
8224 + va_start(args, format);
8225 + DWC_VPRINTF(format, args);
8226 + va_end(args);
8227 +}
8228 +#endif
8229 +
8230 +
8231 +/* dwc_mem.h */
8232 +
8233 +#if 0
8234 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
8235 + uint32_t align,
8236 + uint32_t alloc)
8237 +{
8238 + struct dma_pool *pool = dma_pool_create("Pool", NULL,
8239 + size, align, alloc);
8240 + return (dwc_pool_t *)pool;
8241 +}
8242 +
8243 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
8244 +{
8245 + dma_pool_destroy((struct dma_pool *)pool);
8246 +}
8247 +
8248 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8249 +{
8250 +// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
8251 + return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
8252 +}
8253 +
8254 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8255 +{
8256 + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
8257 + memset(..);
8258 +}
8259 +
8260 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
8261 +{
8262 + dma_pool_free(pool, vaddr, daddr);
8263 +}
8264 +#endif
8265 +
8266 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
8267 +{
8268 + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8269 + int error;
8270 +
8271 + error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,
8272 + sizeof(dma->segs) / sizeof(dma->segs[0]),
8273 + &dma->nsegs, BUS_DMA_NOWAIT);
8274 + if (error) {
8275 + printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,
8276 + (uintmax_t)size, error);
8277 + goto fail_0;
8278 + }
8279 +
8280 + error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,
8281 + (caddr_t *)&dma->dma_vaddr,
8282 + BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
8283 + if (error) {
8284 + printf("%s: bus_dmamem_map failed: %d\n", __func__, error);
8285 + goto fail_1;
8286 + }
8287 +
8288 + error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
8289 + BUS_DMA_NOWAIT, &dma->dma_map);
8290 + if (error) {
8291 + printf("%s: bus_dmamap_create failed: %d\n", __func__, error);
8292 + goto fail_2;
8293 + }
8294 +
8295 + error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
8296 + size, NULL, BUS_DMA_NOWAIT);
8297 + if (error) {
8298 + printf("%s: bus_dmamap_load failed: %d\n", __func__, error);
8299 + goto fail_3;
8300 + }
8301 +
8302 + dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;
8303 + *dma_addr = dma->dma_paddr;
8304 + return dma->dma_vaddr;
8305 +
8306 +fail_3:
8307 + bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8308 +fail_2:
8309 + bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8310 +fail_1:
8311 + bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8312 +fail_0:
8313 + dma->dma_map = NULL;
8314 + dma->dma_vaddr = NULL;
8315 + dma->nsegs = 0;
8316 +
8317 + return NULL;
8318 +}
8319 +
8320 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
8321 +{
8322 + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8323 +
8324 + if (dma->dma_map != NULL) {
8325 + bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,
8326 + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
8327 + bus_dmamap_unload(dma->dma_tag, dma->dma_map);
8328 + bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8329 + bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8330 + bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8331 + dma->dma_paddr = 0;
8332 + dma->dma_map = NULL;
8333 + dma->dma_vaddr = NULL;
8334 + dma->nsegs = 0;
8335 + }
8336 +}
8337 +
8338 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
8339 +{
8340 + return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
8341 +}
8342 +
8343 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
8344 +{
8345 + return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
8346 +}
8347 +
8348 +void __DWC_FREE(void *mem_ctx, void *addr)
8349 +{
8350 + free(addr, M_DEVBUF);
8351 +}
8352 +
8353 +
8354 +#ifdef DWC_CRYPTOLIB
8355 +/* dwc_crypto.h */
8356 +
8357 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
8358 +{
8359 + get_random_bytes(buffer, length);
8360 +}
8361 +
8362 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
8363 +{
8364 + struct crypto_blkcipher *tfm;
8365 + struct blkcipher_desc desc;
8366 + struct scatterlist sgd;
8367 + struct scatterlist sgs;
8368 +
8369 + tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
8370 + if (tfm == NULL) {
8371 + printk("failed to load transform for aes CBC\n");
8372 + return -1;
8373 + }
8374 +
8375 + crypto_blkcipher_setkey(tfm, key, keylen);
8376 + crypto_blkcipher_set_iv(tfm, iv, 16);
8377 +
8378 + sg_init_one(&sgd, out, messagelen);
8379 + sg_init_one(&sgs, message, messagelen);
8380 +
8381 + desc.tfm = tfm;
8382 + desc.flags = 0;
8383 +
8384 + if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
8385 + crypto_free_blkcipher(tfm);
8386 + DWC_ERROR("AES CBC encryption failed");
8387 + return -1;
8388 + }
8389 +
8390 + crypto_free_blkcipher(tfm);
8391 + return 0;
8392 +}
8393 +
8394 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
8395 +{
8396 + struct crypto_hash *tfm;
8397 + struct hash_desc desc;
8398 + struct scatterlist sg;
8399 +
8400 + tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
8401 + if (IS_ERR(tfm)) {
8402 + DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
8403 + return 0;
8404 + }
8405 + desc.tfm = tfm;
8406 + desc.flags = 0;
8407 +
8408 + sg_init_one(&sg, message, len);
8409 + crypto_hash_digest(&desc, &sg, len, out);
8410 + crypto_free_hash(tfm);
8411 +
8412 + return 1;
8413 +}
8414 +
8415 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
8416 + uint8_t *key, uint32_t keylen, uint8_t *out)
8417 +{
8418 + struct crypto_hash *tfm;
8419 + struct hash_desc desc;
8420 + struct scatterlist sg;
8421 +
8422 + tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
8423 + if (IS_ERR(tfm)) {
8424 + DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
8425 + return 0;
8426 + }
8427 + desc.tfm = tfm;
8428 + desc.flags = 0;
8429 +
8430 + sg_init_one(&sg, message, messagelen);
8431 + crypto_hash_setkey(tfm, key, keylen);
8432 + crypto_hash_digest(&desc, &sg, messagelen, out);
8433 + crypto_free_hash(tfm);
8434 +
8435 + return 1;
8436 +}
8437 +
8438 +#endif /* DWC_CRYPTOLIB */
8439 +
8440 +
8441 +/* Byte Ordering Conversions */
8442 +
8443 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
8444 +{
8445 +#ifdef __LITTLE_ENDIAN
8446 + return *p;
8447 +#else
8448 + uint8_t *u_p = (uint8_t *)p;
8449 +
8450 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8451 +#endif
8452 +}
8453 +
8454 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
8455 +{
8456 +#ifdef __BIG_ENDIAN
8457 + return *p;
8458 +#else
8459 + uint8_t *u_p = (uint8_t *)p;
8460 +
8461 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8462 +#endif
8463 +}
8464 +
8465 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
8466 +{
8467 +#ifdef __LITTLE_ENDIAN
8468 + return *p;
8469 +#else
8470 + uint8_t *u_p = (uint8_t *)p;
8471 +
8472 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8473 +#endif
8474 +}
8475 +
8476 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
8477 +{
8478 +#ifdef __BIG_ENDIAN
8479 + return *p;
8480 +#else
8481 + uint8_t *u_p = (uint8_t *)p;
8482 +
8483 + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8484 +#endif
8485 +}
8486 +
8487 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
8488 +{
8489 +#ifdef __LITTLE_ENDIAN
8490 + return *p;
8491 +#else
8492 + uint8_t *u_p = (uint8_t *)p;
8493 + return (u_p[1] | (u_p[0] << 8));
8494 +#endif
8495 +}
8496 +
8497 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
8498 +{
8499 +#ifdef __BIG_ENDIAN
8500 + return *p;
8501 +#else
8502 + uint8_t *u_p = (uint8_t *)p;
8503 + return (u_p[1] | (u_p[0] << 8));
8504 +#endif
8505 +}
8506 +
8507 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
8508 +{
8509 +#ifdef __LITTLE_ENDIAN
8510 + return *p;
8511 +#else
8512 + uint8_t *u_p = (uint8_t *)p;
8513 + return (u_p[1] | (u_p[0] << 8));
8514 +#endif
8515 +}
8516 +
8517 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
8518 +{
8519 +#ifdef __BIG_ENDIAN
8520 + return *p;
8521 +#else
8522 + uint8_t *u_p = (uint8_t *)p;
8523 + return (u_p[1] | (u_p[0] << 8));
8524 +#endif
8525 +}
8526 +
8527 +
8528 +/* Registers */
8529 +
8530 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
8531 +{
8532 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8533 + bus_size_t ior = (bus_size_t)reg;
8534 +
8535 + return bus_space_read_4(io->iot, io->ioh, ior);
8536 +}
8537 +
8538 +#if 0
8539 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
8540 +{
8541 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8542 + bus_size_t ior = (bus_size_t)reg;
8543 +
8544 + return bus_space_read_8(io->iot, io->ioh, ior);
8545 +}
8546 +#endif
8547 +
8548 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
8549 +{
8550 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8551 + bus_size_t ior = (bus_size_t)reg;
8552 +
8553 + bus_space_write_4(io->iot, io->ioh, ior, value);
8554 +}
8555 +
8556 +#if 0
8557 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
8558 +{
8559 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8560 + bus_size_t ior = (bus_size_t)reg;
8561 +
8562 + bus_space_write_8(io->iot, io->ioh, ior, value);
8563 +}
8564 +#endif
8565 +
8566 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
8567 + uint32_t set_mask)
8568 +{
8569 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8570 + bus_size_t ior = (bus_size_t)reg;
8571 +
8572 + bus_space_write_4(io->iot, io->ioh, ior,
8573 + (bus_space_read_4(io->iot, io->ioh, ior) &
8574 + ~clear_mask) | set_mask);
8575 +}
8576 +
8577 +#if 0
8578 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
8579 + uint64_t set_mask)
8580 +{
8581 + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8582 + bus_size_t ior = (bus_size_t)reg;
8583 +
8584 + bus_space_write_8(io->iot, io->ioh, ior,
8585 + (bus_space_read_8(io->iot, io->ioh, ior) &
8586 + ~clear_mask) | set_mask);
8587 +}
8588 +#endif
8589 +
8590 +
8591 +/* Locking */
8592 +
8593 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
8594 +{
8595 + struct simplelock *sl = DWC_ALLOC(sizeof(*sl));
8596 +
8597 + if (!sl) {
8598 + DWC_ERROR("Cannot allocate memory for spinlock");
8599 + return NULL;
8600 + }
8601 +
8602 + simple_lock_init(sl);
8603 + return (dwc_spinlock_t *)sl;
8604 +}
8605 +
8606 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
8607 +{
8608 + struct simplelock *sl = (struct simplelock *)lock;
8609 +
8610 + DWC_FREE(sl);
8611 +}
8612 +
8613 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
8614 +{
8615 + simple_lock((struct simplelock *)lock);
8616 +}
8617 +
8618 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
8619 +{
8620 + simple_unlock((struct simplelock *)lock);
8621 +}
8622 +
8623 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
8624 +{
8625 + simple_lock((struct simplelock *)lock);
8626 + *flags = splbio();
8627 +}
8628 +
8629 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
8630 +{
8631 + splx(flags);
8632 + simple_unlock((struct simplelock *)lock);
8633 +}
8634 +
8635 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
8636 +{
8637 + dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));
8638 +
8639 + if (!mutex) {
8640 + DWC_ERROR("Cannot allocate memory for mutex");
8641 + return NULL;
8642 + }
8643 +
8644 + lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);
8645 + return mutex;
8646 +}
8647 +
8648 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
8649 +#else
8650 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
8651 +{
8652 + DWC_FREE(mutex);
8653 +}
8654 +#endif
8655 +
8656 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
8657 +{
8658 + lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);
8659 +}
8660 +
8661 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
8662 +{
8663 + int status;
8664 +
8665 + status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);
8666 + return status == 0;
8667 +}
8668 +
8669 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
8670 +{
8671 + lockmgr((struct lock *)mutex, LK_RELEASE, NULL);
8672 +}
8673 +
8674 +
8675 +/* Timing */
8676 +
8677 +void DWC_UDELAY(uint32_t usecs)
8678 +{
8679 + DELAY(usecs);
8680 +}
8681 +
8682 +void DWC_MDELAY(uint32_t msecs)
8683 +{
8684 + do {
8685 + DELAY(1000);
8686 + } while (--msecs);
8687 +}
8688 +
8689 +void DWC_MSLEEP(uint32_t msecs)
8690 +{
8691 + struct timeval tv;
8692 +
8693 + tv.tv_sec = msecs / 1000;
8694 + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
8695 + tsleep(&tv, 0, "dw3slp", tvtohz(&tv));
8696 +}
8697 +
8698 +uint32_t DWC_TIME(void)
8699 +{
8700 + struct timeval tv;
8701 +
8702 + microuptime(&tv); // or getmicrouptime? (less precise, but faster)
8703 + return tv.tv_sec * 1000 + tv.tv_usec / 1000;
8704 +}
8705 +
8706 +
8707 +/* Timers */
8708 +
8709 +struct dwc_timer {
8710 + struct callout t;
8711 + char *name;
8712 + dwc_spinlock_t *lock;
8713 + dwc_timer_callback_t cb;
8714 + void *data;
8715 +};
8716 +
8717 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
8718 +{
8719 + dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
8720 +
8721 + if (!t) {
8722 + DWC_ERROR("Cannot allocate memory for timer");
8723 + return NULL;
8724 + }
8725 +
8726 + callout_init(&t->t);
8727 +
8728 + t->name = DWC_STRDUP(name);
8729 + if (!t->name) {
8730 + DWC_ERROR("Cannot allocate memory for timer->name");
8731 + goto no_name;
8732 + }
8733 +
8734 + t->lock = DWC_SPINLOCK_ALLOC();
8735 + if (!t->lock) {
8736 + DWC_ERROR("Cannot allocate memory for timer->lock");
8737 + goto no_lock;
8738 + }
8739 +
8740 + t->cb = cb;
8741 + t->data = data;
8742 +
8743 + return t;
8744 +
8745 + no_lock:
8746 + DWC_FREE(t->name);
8747 + no_name:
8748 + DWC_FREE(t);
8749 +
8750 + return NULL;
8751 +}
8752 +
8753 +void DWC_TIMER_FREE(dwc_timer_t *timer)
8754 +{
8755 + callout_stop(&timer->t);
8756 + DWC_SPINLOCK_FREE(timer->lock);
8757 + DWC_FREE(timer->name);
8758 + DWC_FREE(timer);
8759 +}
8760 +
8761 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
8762 +{
8763 + struct timeval tv;
8764 +
8765 + tv.tv_sec = time / 1000;
8766 + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
8767 + callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
8768 +}
8769 +
8770 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
8771 +{
8772 + callout_stop(&timer->t);
8773 +}
8774 +
8775 +
8776 +/* Wait Queues */
8777 +
8778 +struct dwc_waitq {
8779 + struct simplelock lock;
8780 + int abort;
8781 +};
8782 +
8783 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
8784 +{
8785 + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
8786 +
8787 + if (!wq) {
8788 + DWC_ERROR("Cannot allocate memory for waitqueue");
8789 + return NULL;
8790 + }
8791 +
8792 + simple_lock_init(&wq->lock);
8793 + wq->abort = 0;
8794 +
8795 + return wq;
8796 +}
8797 +
8798 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
8799 +{
8800 + DWC_FREE(wq);
8801 +}
8802 +
8803 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
8804 +{
8805 + int ipl;
8806 + int result = 0;
8807 +
8808 + simple_lock(&wq->lock);
8809 + ipl = splbio();
8810 +
8811 + /* Skip the sleep if already aborted or triggered */
8812 + if (!wq->abort && !cond(data)) {
8813 + splx(ipl);
8814 + result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout
8815 + ipl = splbio();
8816 + }
8817 +
8818 + if (result == 0) { // awoken
8819 + if (wq->abort) {
8820 + wq->abort = 0;
8821 + result = -DWC_E_ABORT;
8822 + } else {
8823 + result = 0;
8824 + }
8825 +
8826 + splx(ipl);
8827 + simple_unlock(&wq->lock);
8828 + } else {
8829 + wq->abort = 0;
8830 + splx(ipl);
8831 + simple_unlock(&wq->lock);
8832 +
8833 + if (result == ERESTART) { // signaled - restart
8834 + result = -DWC_E_RESTART;
8835 + } else { // signaled - must be EINTR
8836 + result = -DWC_E_ABORT;
8837 + }
8838 + }
8839 +
8840 + return result;
8841 +}
8842 +
8843 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
8844 + void *data, int32_t msecs)
8845 +{
8846 + struct timeval tv, tv1, tv2;
8847 + int ipl;
8848 + int result = 0;
8849 +
8850 + tv.tv_sec = msecs / 1000;
8851 + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
8852 +
8853 + simple_lock(&wq->lock);
8854 + ipl = splbio();
8855 +
8856 + /* Skip the sleep if already aborted or triggered */
8857 + if (!wq->abort && !cond(data)) {
8858 + splx(ipl);
8859 + getmicrouptime(&tv1);
8860 + result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);
8861 + getmicrouptime(&tv2);
8862 + ipl = splbio();
8863 + }
8864 +
8865 + if (result == 0) { // awoken
8866 + if (wq->abort) {
8867 + wq->abort = 0;
8868 + splx(ipl);
8869 + simple_unlock(&wq->lock);
8870 + result = -DWC_E_ABORT;
8871 + } else {
8872 + splx(ipl);
8873 + simple_unlock(&wq->lock);
8874 +
8875 + tv2.tv_usec -= tv1.tv_usec;
8876 + if (tv2.tv_usec < 0) {
8877 + tv2.tv_usec += 1000000;
8878 + tv2.tv_sec--;
8879 + }
8880 +
8881 + tv2.tv_sec -= tv1.tv_sec;
8882 + result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
8883 + result = msecs - result;
8884 + if (result <= 0)
8885 + result = 1;
8886 + }
8887 + } else {
8888 + wq->abort = 0;
8889 + splx(ipl);
8890 + simple_unlock(&wq->lock);
8891 +
8892 + if (result == ERESTART) { // signaled - restart
8893 + result = -DWC_E_RESTART;
8894 +
8895 + } else if (result == EINTR) { // signaled - interrupt
8896 + result = -DWC_E_ABORT;
8897 +
8898 + } else { // timed out
8899 + result = -DWC_E_TIMEOUT;
8900 + }
8901 + }
8902 +
8903 + return result;
8904 +}
8905 +
8906 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
8907 +{
8908 + wakeup(wq);
8909 +}
8910 +
8911 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
8912 +{
8913 + int ipl;
8914 +
8915 + simple_lock(&wq->lock);
8916 + ipl = splbio();
8917 + wq->abort = 1;
8918 + wakeup(wq);
8919 + splx(ipl);
8920 + simple_unlock(&wq->lock);
8921 +}
8922 +
8923 +
8924 +/* Threading */
8925 +
8926 +struct dwc_thread {
8927 + struct proc *proc;
8928 + int abort;
8929 +};
8930 +
8931 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
8932 +{
8933 + int retval;
8934 + dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
8935 +
8936 + if (!thread) {
8937 + return NULL;
8938 + }
8939 +
8940 + thread->abort = 0;
8941 + retval = kthread_create1((void (*)(void *))func, data, &thread->proc,
8942 + "%s", name);
8943 + if (retval) {
8944 + DWC_FREE(thread);
8945 + return NULL;
8946 + }
8947 +
8948 + return thread;
8949 +}
8950 +
8951 +int DWC_THREAD_STOP(dwc_thread_t *thread)
8952 +{
8953 + int retval;
8954 +
8955 + thread->abort = 1;
8956 + retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
8957 +
8958 + if (retval == 0) {
8959 + /* DWC_THREAD_EXIT() will free the thread struct */
8960 + return 0;
8961 + }
8962 +
8963 + /* NOTE: We leak the thread struct if thread doesn't die */
8964 +
8965 + if (retval == EWOULDBLOCK) {
8966 + return -DWC_E_TIMEOUT;
8967 + }
8968 +
8969 + return -DWC_E_UNKNOWN;
8970 +}
8971 +
8972 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
8973 +{
8974 + return thread->abort;
8975 +}
8976 +
8977 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
8978 +{
8979 + wakeup(&thread->abort);
8980 + DWC_FREE(thread);
8981 + kthread_exit(0);
8982 +}
8983 +
8984 +/* tasklets
8985 + - Runs in interrupt context (cannot sleep)
8986 + - Each tasklet runs on a single CPU
8987 + - Different tasklets can be running simultaneously on different CPUs
8988 + [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-
8989 + halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]
8990 + */
8991 +struct dwc_tasklet {
8992 + dwc_tasklet_callback_t cb;
8993 + void *data;
8994 +};
8995 +
8996 +static void tasklet_callback(void *data)
8997 +{
8998 + dwc_tasklet_t *task = (dwc_tasklet_t *)data;
8999 +
9000 + task->cb(task->data);
9001 +}
9002 +
9003 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
9004 +{
9005 + dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
9006 +
9007 + if (task) {
9008 + task->cb = cb;
9009 + task->data = data;
9010 + } else {
9011 + DWC_ERROR("Cannot allocate memory for tasklet");
9012 + }
9013 +
9014 + return task;
9015 +}
9016 +
9017 +void DWC_TASK_FREE(dwc_tasklet_t *task)
9018 +{
9019 + DWC_FREE(task);
9020 +}
9021 +
9022 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
9023 +{
9024 + tasklet_callback(task);
9025 +}
9026 +
9027 +
9028 +/* workqueues
9029 + - Runs in process context (can sleep)
9030 + */
9031 +typedef struct work_container {
9032 + dwc_work_callback_t cb;
9033 + void *data;
9034 + dwc_workq_t *wq;
9035 + char *name;
9036 + int hz;
9037 + struct work task;
9038 +} work_container_t;
9039 +
9040 +struct dwc_workq {
9041 + struct workqueue *taskq;
9042 + dwc_spinlock_t *lock;
9043 + dwc_waitq_t *waitq;
9044 + int pending;
9045 + struct work_container *container;
9046 +};
9047 +
9048 +static void do_work(struct work *task, void *data)
9049 +{
9050 + dwc_workq_t *wq = (dwc_workq_t *)data;
9051 + work_container_t *container = wq->container;
9052 + dwc_irqflags_t flags;
9053 +
9054 + if (container->hz) {
9055 + tsleep(container, 0, "dw3wrk", container->hz);
9056 + }
9057 +
9058 + container->cb(container->data);
9059 + DWC_DEBUG("Work done: %s, container=%p", container->name, container);
9060 +
9061 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9062 + if (container->name)
9063 + DWC_FREE(container->name);
9064 + DWC_FREE(container);
9065 + wq->pending--;
9066 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9067 + DWC_WAITQ_TRIGGER(wq->waitq);
9068 +}
9069 +
9070 +static int work_done(void *data)
9071 +{
9072 + dwc_workq_t *workq = (dwc_workq_t *)data;
9073 +
9074 + return workq->pending == 0;
9075 +}
9076 +
9077 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
9078 +{
9079 + return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
9080 +}
9081 +
9082 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
9083 +{
9084 + int result;
9085 + dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
9086 +
9087 + if (!wq) {
9088 + DWC_ERROR("Cannot allocate memory for workqueue");
9089 + return NULL;
9090 + }
9091 +
9092 + result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,
9093 + IPL_BIO, 0);
9094 + if (result) {
9095 + DWC_ERROR("Cannot create workqueue");
9096 + goto no_taskq;
9097 + }
9098 +
9099 + wq->pending = 0;
9100 +
9101 + wq->lock = DWC_SPINLOCK_ALLOC();
9102 + if (!wq->lock) {
9103 + DWC_ERROR("Cannot allocate memory for spinlock");
9104 + goto no_lock;
9105 + }
9106 +
9107 + wq->waitq = DWC_WAITQ_ALLOC();
9108 + if (!wq->waitq) {
9109 + DWC_ERROR("Cannot allocate memory for waitqueue");
9110 + goto no_waitq;
9111 + }
9112 +
9113 + return wq;
9114 +
9115 + no_waitq:
9116 + DWC_SPINLOCK_FREE(wq->lock);
9117 + no_lock:
9118 + workqueue_destroy(wq->taskq);
9119 + no_taskq:
9120 + DWC_FREE(wq);
9121 +
9122 + return NULL;
9123 +}
9124 +
9125 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
9126 +{
9127 +#ifdef DEBUG
9128 + dwc_irqflags_t flags;
9129 +
9130 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9131 +
9132 + if (wq->pending != 0) {
9133 + struct work_container *container = wq->container;
9134 +
9135 + DWC_ERROR("Destroying work queue with pending work");
9136 +
9137 + if (container && container->name) {
9138 + DWC_ERROR("Work %s still pending", container->name);
9139 + }
9140 + }
9141 +
9142 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9143 +#endif
9144 + DWC_WAITQ_FREE(wq->waitq);
9145 + DWC_SPINLOCK_FREE(wq->lock);
9146 + workqueue_destroy(wq->taskq);
9147 + DWC_FREE(wq);
9148 +}
9149 +
9150 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
9151 + char *format, ...)
9152 +{
9153 + dwc_irqflags_t flags;
9154 + work_container_t *container;
9155 + static char name[128];
9156 + va_list args;
9157 +
9158 + va_start(args, format);
9159 + DWC_VSNPRINTF(name, 128, format, args);
9160 + va_end(args);
9161 +
9162 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9163 + wq->pending++;
9164 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9165 + DWC_WAITQ_TRIGGER(wq->waitq);
9166 +
9167 + container = DWC_ALLOC_ATOMIC(sizeof(*container));
9168 + if (!container) {
9169 + DWC_ERROR("Cannot allocate memory for container");
9170 + return;
9171 + }
9172 +
9173 + container->name = DWC_STRDUP(name);
9174 + if (!container->name) {
9175 + DWC_ERROR("Cannot allocate memory for container->name");
9176 + DWC_FREE(container);
9177 + return;
9178 + }
9179 +
9180 + container->cb = cb;
9181 + container->data = data;
9182 + container->wq = wq;
9183 + container->hz = 0;
9184 + wq->container = container;
9185 +
9186 + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9187 + workqueue_enqueue(wq->taskq, &container->task);
9188 +}
9189 +
9190 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
9191 + void *data, uint32_t time, char *format, ...)
9192 +{
9193 + dwc_irqflags_t flags;
9194 + work_container_t *container;
9195 + static char name[128];
9196 + struct timeval tv;
9197 + va_list args;
9198 +
9199 + va_start(args, format);
9200 + DWC_VSNPRINTF(name, 128, format, args);
9201 + va_end(args);
9202 +
9203 + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9204 + wq->pending++;
9205 + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9206 + DWC_WAITQ_TRIGGER(wq->waitq);
9207 +
9208 + container = DWC_ALLOC_ATOMIC(sizeof(*container));
9209 + if (!container) {
9210 + DWC_ERROR("Cannot allocate memory for container");
9211 + return;
9212 + }
9213 +
9214 + container->name = DWC_STRDUP(name);
9215 + if (!container->name) {
9216 + DWC_ERROR("Cannot allocate memory for container->name");
9217 + DWC_FREE(container);
9218 + return;
9219 + }
9220 +
9221 + container->cb = cb;
9222 + container->data = data;
9223 + container->wq = wq;
9224 + tv.tv_sec = time / 1000;
9225 + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9226 + container->hz = tvtohz(&tv);
9227 + wq->container = container;
9228 +
9229 + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9230 + workqueue_enqueue(wq->taskq, &container->task);
9231 +}
9232 +
9233 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
9234 +{
9235 + return wq->pending;
9236 +}
9237 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_crypto.c
9238 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_crypto.c 1970-01-01 01:00:00.000000000 +0100
9239 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_crypto.c 2013-07-06 15:25:50.000000000 +0100
9240 @@ -0,0 +1,308 @@
9241 +/* =========================================================================
9242 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
9243 + * $Revision: #5 $
9244 + * $Date: 2010/09/28 $
9245 + * $Change: 1596182 $
9246 + *
9247 + * Synopsys Portability Library Software and documentation
9248 + * (hereinafter, "Software") is an Unsupported proprietary work of
9249 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9250 + * between Synopsys and you.
9251 + *
9252 + * The Software IS NOT an item of Licensed Software or Licensed Product
9253 + * under any End User Software License Agreement or Agreement for
9254 + * Licensed Product with Synopsys or any supplement thereto. You are
9255 + * permitted to use and redistribute this Software in source and binary
9256 + * forms, with or without modification, provided that redistributions
9257 + * of source code must retain this notice. You may not view, use,
9258 + * disclose, copy or distribute this file or any information contained
9259 + * herein except pursuant to this license grant from Synopsys. If you
9260 + * do not agree with this notice, including the disclaimer below, then
9261 + * you are not authorized to use the Software.
9262 + *
9263 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9264 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9265 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9266 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9267 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9268 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9269 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9270 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9271 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9272 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9273 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9274 + * DAMAGE.
9275 + * ========================================================================= */
9276 +
9277 +/** @file
9278 + * This file contains the WUSB cryptographic routines.
9279 + */
9280 +
9281 +#ifdef DWC_CRYPTOLIB
9282 +
9283 +#include "dwc_crypto.h"
9284 +#include "usb.h"
9285 +
9286 +#ifdef DEBUG
9287 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
9288 +{
9289 + int i;
9290 + DWC_PRINTF("%s: ", name);
9291 + for (i=0; i<len; i++) {
9292 + DWC_PRINTF("%02x ", bytes[i]);
9293 + }
9294 + DWC_PRINTF("\n");
9295 +}
9296 +#else
9297 +#define dump_bytes(x...)
9298 +#endif
9299 +
9300 +/* Display a block */
9301 +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
9302 +{
9303 +#ifdef DWC_DEBUG_CRYPTO
9304 + int i, blksize = 16;
9305 +
9306 + DWC_DEBUG("%s", prefix);
9307 +
9308 + if (suffix == NULL) {
9309 + suffix = "\n";
9310 + blksize = a;
9311 + }
9312 +
9313 + for (i = 0; i < blksize; i++)
9314 + DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? " " : " ");
9315 + DWC_PRINT(suffix);
9316 +#endif
9317 +}
9318 +
9319 +/**
9320 + * Encrypts an array of bytes using the AES encryption engine.
9321 + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
9322 + * in-place.
9323 + *
9324 + * @return 0 on success, negative error code on error.
9325 + */
9326 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
9327 +{
9328 + u8 block_t[16];
9329 + DWC_MEMSET(block_t, 0, 16);
9330 +
9331 + return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
9332 +}
9333 +
9334 +/**
9335 + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
9336 + * This function takes a data string and returns the encrypted CBC
9337 + * Counter-mode MIC.
9338 + *
9339 + * @param key The 128-bit symmetric key.
9340 + * @param nonce The CCM nonce.
9341 + * @param label The unique 14-byte ASCII text label.
9342 + * @param bytes The byte array to be encrypted.
9343 + * @param len Length of the byte array.
9344 + * @param result Byte array to receive the 8-byte encrypted MIC.
9345 + */
9346 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9347 + char *label, u8 *bytes, int len, u8 *result)
9348 +{
9349 + u8 block_m[16];
9350 + u8 block_x[16];
9351 + u8 block_t[8];
9352 + int idx, blkNum;
9353 + u16 la = (u16)(len + 14);
9354 +
9355 + /* Set the AES-128 key */
9356 + //dwc_aes_setkey(tfm, key, 16);
9357 +
9358 + /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
9359 + block_m[0] = 0x59;
9360 + for (idx = 0; idx < 13; idx++)
9361 + block_m[idx + 1] = nonce[idx];
9362 + block_m[14] = 0;
9363 + block_m[15] = 0;
9364 +
9365 + /* Produce the CBC IV */
9366 + dwc_wusb_aes_encrypt(block_m, key, block_x);
9367 + show_block(block_m, "CBC IV in: ", "\n", 0);
9368 + show_block(block_x, "CBC IV out:", "\n", 0);
9369 +
9370 + /* Fill block B1 from l(a) = Blen + 14, and A */
9371 + block_x[0] ^= (u8)(la >> 8);
9372 + block_x[1] ^= (u8)la;
9373 + for (idx = 0; idx < 14; idx++)
9374 + block_x[idx + 2] ^= label[idx];
9375 + show_block(block_x, "After xor: ", "b1\n", 16);
9376 +
9377 + dwc_wusb_aes_encrypt(block_x, key, block_x);
9378 + show_block(block_x, "After AES: ", "b1\n", 16);
9379 +
9380 + idx = 0;
9381 + blkNum = 0;
9382 +
9383 + /* Fill remaining blocks with B */
9384 + while (len-- > 0) {
9385 + block_x[idx] ^= *bytes++;
9386 + if (++idx >= 16) {
9387 + idx = 0;
9388 + show_block(block_x, "After xor: ", "\n", blkNum);
9389 + dwc_wusb_aes_encrypt(block_x, key, block_x);
9390 + show_block(block_x, "After AES: ", "\n", blkNum);
9391 + blkNum++;
9392 + }
9393 + }
9394 +
9395 + /* Handle partial last block */
9396 + if (idx > 0) {
9397 + show_block(block_x, "After xor: ", "\n", blkNum);
9398 + dwc_wusb_aes_encrypt(block_x, key, block_x);
9399 + show_block(block_x, "After AES: ", "\n", blkNum);
9400 + }
9401 +
9402 + /* Save the MIC tag */
9403 + DWC_MEMCPY(block_t, block_x, 8);
9404 + show_block(block_t, "MIC tag : ", NULL, 8);
9405 +
9406 + /* Fill block A0 from flags = 0x01, N, and counter = 0 */
9407 + block_m[0] = 0x01;
9408 + block_m[14] = 0;
9409 + block_m[15] = 0;
9410 +
9411 + /* Encrypt the counter */
9412 + dwc_wusb_aes_encrypt(block_m, key, block_x);
9413 + show_block(block_x, "CTR[MIC] : ", NULL, 8);
9414 +
9415 + /* XOR with MIC tag */
9416 + for (idx = 0; idx < 8; idx++) {
9417 + block_t[idx] ^= block_x[idx];
9418 + }
9419 +
9420 + /* Return result to caller */
9421 + DWC_MEMCPY(result, block_t, 8);
9422 + show_block(result, "CCM-MIC : ", NULL, 8);
9423 +
9424 +}
9425 +
9426 +/**
9427 + * The PRF function described in section 6.5 of the WUSB spec. This function
9428 + * concatenates MIC values returned from dwc_cmf() to create a value of
9429 + * the requested length.
9430 + *
9431 + * @param prf_len Length of the PRF function in bits (64, 128, or 256).
9432 + * @param key, nonce, label, bytes, len Same as for dwc_cmf().
9433 + * @param result Byte array to receive the result.
9434 + */
9435 +void dwc_wusb_prf(int prf_len, u8 *key,
9436 + u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
9437 +{
9438 + int i;
9439 +
9440 + nonce[0] = 0;
9441 + for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
9442 + dwc_wusb_cmf(key, nonce, label, bytes, len, result);
9443 + result += 8;
9444 + }
9445 +}
9446 +
9447 +/**
9448 + * Fills in CCM Nonce per the WUSB spec.
9449 + *
9450 + * @param[in] haddr Host address.
9451 + * @param[in] daddr Device address.
9452 + * @param[in] tkid Session Key(PTK) identifier.
9453 + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
9454 + */
9455 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9456 + uint8_t *nonce)
9457 +{
9458 +
9459 + DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
9460 +
9461 + DWC_MEMSET(&nonce[0], 0, 16);
9462 +
9463 + DWC_MEMCPY(&nonce[6], tkid, 3);
9464 + nonce[9] = daddr & 0xFF;
9465 + nonce[10] = (daddr >> 8) & 0xFF;
9466 + nonce[11] = haddr & 0xFF;
9467 + nonce[12] = (haddr >> 8) & 0xFF;
9468 +
9469 + dump_bytes("CCM nonce", nonce, 16);
9470 +}
9471 +
9472 +/**
9473 + * Generates a 16-byte cryptographic-grade random number for the Host/Device
9474 + * Nonce.
9475 + */
9476 +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
9477 +{
9478 + uint8_t inonce[16];
9479 + uint32_t temp[4];
9480 +
9481 + /* Fill in the Nonce */
9482 + DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
9483 + inonce[9] = addr & 0xFF;
9484 + inonce[10] = (addr >> 8) & 0xFF;
9485 + inonce[11] = inonce[9];
9486 + inonce[12] = inonce[10];
9487 +
9488 + /* Collect "randomness samples" */
9489 + DWC_RANDOM_BYTES((uint8_t *)temp, 16);
9490 +
9491 + dwc_wusb_prf_128((uint8_t *)temp, nonce,
9492 + "Random Numbers", (uint8_t *)temp, sizeof(temp),
9493 + nonce);
9494 +}
9495 +
9496 +/**
9497 + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
9498 + * WUSB spec.
9499 + *
9500 + * @param[in] ccm_nonce Pointer to CCM Nonce.
9501 + * @param[in] mk Master Key to derive the session from
9502 + * @param[in] hnonce Pointer to Host Nonce.
9503 + * @param[in] dnonce Pointer to Device Nonce.
9504 + * @param[out] kck Pointer to where the KCK output is to be written.
9505 + * @param[out] ptk Pointer to where the PTK output is to be written.
9506 + */
9507 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
9508 + uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
9509 +{
9510 + uint8_t idata[32];
9511 + uint8_t odata[32];
9512 +
9513 + dump_bytes("ck", mk, 16);
9514 + dump_bytes("hnonce", hnonce, 16);
9515 + dump_bytes("dnonce", dnonce, 16);
9516 +
9517 + /* The data is the HNonce and DNonce concatenated */
9518 + DWC_MEMCPY(&idata[0], hnonce, 16);
9519 + DWC_MEMCPY(&idata[16], dnonce, 16);
9520 +
9521 + dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
9522 +
9523 + /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
9524 + DWC_MEMCPY(kck, &odata[0], 16);
9525 + DWC_MEMCPY(ptk, &odata[16], 16);
9526 +
9527 + dump_bytes("kck", kck, 16);
9528 + dump_bytes("ptk", ptk, 16);
9529 +}
9530 +
9531 +/**
9532 + * Generates the Message Integrity Code over the Handshake data per the
9533 + * WUSB spec.
9534 + *
9535 + * @param ccm_nonce Pointer to CCM Nonce.
9536 + * @param kck Pointer to Key Confirmation Key.
9537 + * @param data Pointer to Handshake data to be checked.
9538 + * @param mic Pointer to where the MIC output is to be written.
9539 + */
9540 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
9541 + uint8_t *data, uint8_t *mic)
9542 +{
9543 +
9544 + dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
9545 + data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
9546 +}
9547 +
9548 +#endif /* DWC_CRYPTOLIB */
9549 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_crypto.h
9550 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_crypto.h 1970-01-01 01:00:00.000000000 +0100
9551 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_crypto.h 2013-07-06 15:25:50.000000000 +0100
9552 @@ -0,0 +1,111 @@
9553 +/* =========================================================================
9554 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
9555 + * $Revision: #3 $
9556 + * $Date: 2010/09/28 $
9557 + * $Change: 1596182 $
9558 + *
9559 + * Synopsys Portability Library Software and documentation
9560 + * (hereinafter, "Software") is an Unsupported proprietary work of
9561 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9562 + * between Synopsys and you.
9563 + *
9564 + * The Software IS NOT an item of Licensed Software or Licensed Product
9565 + * under any End User Software License Agreement or Agreement for
9566 + * Licensed Product with Synopsys or any supplement thereto. You are
9567 + * permitted to use and redistribute this Software in source and binary
9568 + * forms, with or without modification, provided that redistributions
9569 + * of source code must retain this notice. You may not view, use,
9570 + * disclose, copy or distribute this file or any information contained
9571 + * herein except pursuant to this license grant from Synopsys. If you
9572 + * do not agree with this notice, including the disclaimer below, then
9573 + * you are not authorized to use the Software.
9574 + *
9575 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9576 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9577 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9578 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9579 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9580 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9581 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9582 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9583 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9584 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9585 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9586 + * DAMAGE.
9587 + * ========================================================================= */
9588 +
9589 +#ifndef _DWC_CRYPTO_H_
9590 +#define _DWC_CRYPTO_H_
9591 +
9592 +#ifdef __cplusplus
9593 +extern "C" {
9594 +#endif
9595 +
9596 +/** @file
9597 + *
9598 + * This file contains declarations for the WUSB Cryptographic routines as
9599 + * defined in the WUSB spec. They are only to be used internally by the DWC UWB
9600 + * modules.
9601 + */
9602 +
9603 +#include "dwc_os.h"
9604 +
9605 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
9606 +
9607 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9608 + char *label, u8 *bytes, int len, u8 *result);
9609 +void dwc_wusb_prf(int prf_len, u8 *key,
9610 + u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
9611 +
9612 +/**
9613 + * The PRF-64 function described in section 6.5 of the WUSB spec.
9614 + *
9615 + * @param key, nonce, label, bytes, len, result Same as for dwc_prf().
9616 + */
9617 +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
9618 + char *label, u8 *bytes, int len, u8 *result)
9619 +{
9620 + dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
9621 +}
9622 +
9623 +/**
9624 + * The PRF-128 function described in section 6.5 of the WUSB spec.
9625 + *
9626 + * @param key, nonce, label, bytes, len, result Same as for dwc_prf().
9627 + */
9628 +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
9629 + char *label, u8 *bytes, int len, u8 *result)
9630 +{
9631 + dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
9632 +}
9633 +
9634 +/**
9635 + * The PRF-256 function described in section 6.5 of the WUSB spec.
9636 + *
9637 + * @param key, nonce, label, bytes, len, result Same as for dwc_prf().
9638 + */
9639 +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
9640 + char *label, u8 *bytes, int len, u8 *result)
9641 +{
9642 + dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
9643 +}
9644 +
9645 +
9646 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9647 + uint8_t *nonce);
9648 +void dwc_wusb_gen_nonce(uint16_t addr,
9649 + uint8_t *nonce);
9650 +
9651 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
9652 + uint8_t *hnonce, uint8_t *dnonce,
9653 + uint8_t *kck, uint8_t *ptk);
9654 +
9655 +
9656 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
9657 + *kck, uint8_t *data, uint8_t *mic);
9658 +
9659 +#ifdef __cplusplus
9660 +}
9661 +#endif
9662 +
9663 +#endif /* _DWC_CRYPTO_H_ */
9664 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_dh.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_dh.c
9665 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_dh.c 1970-01-01 01:00:00.000000000 +0100
9666 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_dh.c 2013-07-06 15:25:50.000000000 +0100
9667 @@ -0,0 +1,291 @@
9668 +/* =========================================================================
9669 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
9670 + * $Revision: #3 $
9671 + * $Date: 2010/09/28 $
9672 + * $Change: 1596182 $
9673 + *
9674 + * Synopsys Portability Library Software and documentation
9675 + * (hereinafter, "Software") is an Unsupported proprietary work of
9676 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9677 + * between Synopsys and you.
9678 + *
9679 + * The Software IS NOT an item of Licensed Software or Licensed Product
9680 + * under any End User Software License Agreement or Agreement for
9681 + * Licensed Product with Synopsys or any supplement thereto. You are
9682 + * permitted to use and redistribute this Software in source and binary
9683 + * forms, with or without modification, provided that redistributions
9684 + * of source code must retain this notice. You may not view, use,
9685 + * disclose, copy or distribute this file or any information contained
9686 + * herein except pursuant to this license grant from Synopsys. If you
9687 + * do not agree with this notice, including the disclaimer below, then
9688 + * you are not authorized to use the Software.
9689 + *
9690 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9691 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9692 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9693 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9694 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9695 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9696 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9697 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9698 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9699 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9700 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9701 + * DAMAGE.
9702 + * ========================================================================= */
9703 +#ifdef DWC_CRYPTOLIB
9704 +
9705 +#ifndef CONFIG_MACH_IPMATE
9706 +
9707 +#include "dwc_dh.h"
9708 +#include "dwc_modpow.h"
9709 +
9710 +#ifdef DEBUG
9711 +/* This function prints out a buffer in the format described in the Association
9712 + * Model specification. */
9713 +static void dh_dump(char *str, void *_num, int len)
9714 +{
9715 + uint8_t *num = _num;
9716 + int i;
9717 + DWC_PRINTF("%s\n", str);
9718 + for (i = 0; i < len; i ++) {
9719 + DWC_PRINTF("%02x", num[i]);
9720 + if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
9721 + if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
9722 + }
9723 +
9724 + DWC_PRINTF("\n");
9725 +}
9726 +#else
9727 +#define dh_dump(_x...) do {; } while(0)
9728 +#endif
9729 +
9730 +/* Constant g value */
9731 +static __u32 dh_g[] = {
9732 + 0x02000000,
9733 +};
9734 +
9735 +/* Constant p value */
9736 +static __u32 dh_p[] = {
9737 + 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
9738 + 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
9739 + 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
9740 + 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
9741 + 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
9742 + 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
9743 + 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
9744 + 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
9745 + 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
9746 + 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
9747 + 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
9748 + 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
9749 +};
9750 +
9751 +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
9752 +{
9753 + uint8_t *in = _in;
9754 + uint8_t *out = _out;
9755 + int i;
9756 + for (i=0; i<len; i++) {
9757 + out[i] = in[len-1-i];
9758 + }
9759 +}
9760 +
9761 +/* Computes the modular exponentiation (num^exp % mod). num, exp, and mod are
9762 + * big endian numbers of size len, in bytes. Each len value must be a multiple
9763 + * of 4. */
9764 +int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
9765 + void *exp, uint32_t exp_len,
9766 + void *mod, uint32_t mod_len,
9767 + void *out)
9768 +{
9769 + /* modpow() takes little endian numbers. AM uses big-endian. This
9770 + * function swaps bytes of numbers before passing onto modpow. */
9771 +
9772 + int retval = 0;
9773 + uint32_t *result;
9774 +
9775 + uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
9776 + uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
9777 + uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
9778 +
9779 + dh_swap_bytes(num, &bignum_num[1], num_len);
9780 + bignum_num[0] = num_len / 4;
9781 +
9782 + dh_swap_bytes(exp, &bignum_exp[1], exp_len);
9783 + bignum_exp[0] = exp_len / 4;
9784 +
9785 + dh_swap_bytes(mod, &bignum_mod[1], mod_len);
9786 + bignum_mod[0] = mod_len / 4;
9787 +
9788 + result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
9789 + if (!result) {
9790 + retval = -1;
9791 + goto dh_modpow_nomem;
9792 + }
9793 +
9794 + dh_swap_bytes(&result[1], out, result[0] * 4);
9795 + dwc_free(mem_ctx, result);
9796 +
9797 + dh_modpow_nomem:
9798 + dwc_free(mem_ctx, bignum_num);
9799 + dwc_free(mem_ctx, bignum_exp);
9800 + dwc_free(mem_ctx, bignum_mod);
9801 + return retval;
9802 +}
9803 +
9804 +
9805 +int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
9806 +{
9807 + int retval;
9808 + uint8_t m3[385];
9809 +
9810 +#ifndef DH_TEST_VECTORS
9811 + DWC_RANDOM_BYTES(exp, 32);
9812 +#endif
9813 +
9814 + /* Compute the pkd */
9815 + if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
9816 + exp, 32,
9817 + dh_p, 384, pk))) {
9818 + return retval;
9819 + }
9820 +
9821 + m3[384] = nd;
9822 + DWC_MEMCPY(&m3[0], pk, 384);
9823 + DWC_SHA256(m3, 385, hash);
9824 +
9825 + dh_dump("PK", pk, 384);
9826 + dh_dump("SHA-256(M3)", hash, 32);
9827 + return 0;
9828 +}
9829 +
9830 +int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
9831 + uint8_t *exp, int is_host,
9832 + char *dd, uint8_t *ck, uint8_t *kdk)
9833 +{
9834 + int retval;
9835 + uint8_t mv[784];
9836 + uint8_t sha_result[32];
9837 + uint8_t dhkey[384];
9838 + uint8_t shared_secret[384];
9839 + char *message;
9840 + uint32_t vd;
9841 +
9842 + uint8_t *pk;
9843 +
9844 + if (is_host) {
9845 + pk = pkd;
9846 + }
9847 + else {
9848 + pk = pkh;
9849 + }
9850 +
9851 + if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
9852 + exp, 32,
9853 + dh_p, 384, shared_secret))) {
9854 + return retval;
9855 + }
9856 + dh_dump("Shared Secret", shared_secret, 384);
9857 +
9858 + DWC_SHA256(shared_secret, 384, dhkey);
9859 + dh_dump("DHKEY", dhkey, 384);
9860 +
9861 + DWC_MEMCPY(&mv[0], pkd, 384);
9862 + DWC_MEMCPY(&mv[384], pkh, 384);
9863 + DWC_MEMCPY(&mv[768], "displayed digest", 16);
9864 + dh_dump("MV", mv, 784);
9865 +
9866 + DWC_SHA256(mv, 784, sha_result);
9867 + dh_dump("SHA-256(MV)", sha_result, 32);
9868 + dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
9869 +
9870 + dh_swap_bytes(sha_result, &vd, 4);
9871 +#ifdef DEBUG
9872 + DWC_PRINTF("Vd (decimal) = %d\n", vd);
9873 +#endif
9874 +
9875 + switch (nd) {
9876 + case 2:
9877 + vd = vd % 100;
9878 + DWC_SPRINTF(dd, "%02d", vd);
9879 + break;
9880 + case 3:
9881 + vd = vd % 1000;
9882 + DWC_SPRINTF(dd, "%03d", vd);
9883 + break;
9884 + case 4:
9885 + vd = vd % 10000;
9886 + DWC_SPRINTF(dd, "%04d", vd);
9887 + break;
9888 + }
9889 +#ifdef DEBUG
9890 + DWC_PRINTF("Display Digits: %s\n", dd);
9891 +#endif
9892 +
9893 + message = "connection key";
9894 + DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
9895 + dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
9896 + DWC_MEMCPY(ck, sha_result, 16);
9897 +
9898 + message = "key derivation key";
9899 + DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
9900 + dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
9901 + DWC_MEMCPY(kdk, sha_result, 32);
9902 +
9903 + return 0;
9904 +}
9905 +
9906 +
9907 +#ifdef DH_TEST_VECTORS
9908 +
9909 +static __u8 dh_a[] = {
9910 + 0x44, 0x00, 0x51, 0xd6,
9911 + 0xf0, 0xb5, 0x5e, 0xa9,
9912 + 0x67, 0xab, 0x31, 0xc6,
9913 + 0x8a, 0x8b, 0x5e, 0x37,
9914 + 0xd9, 0x10, 0xda, 0xe0,
9915 + 0xe2, 0xd4, 0x59, 0xa4,
9916 + 0x86, 0x45, 0x9c, 0xaa,
9917 + 0xdf, 0x36, 0x75, 0x16,
9918 +};
9919 +
9920 +static __u8 dh_b[] = {
9921 + 0x5d, 0xae, 0xc7, 0x86,
9922 + 0x79, 0x80, 0xa3, 0x24,
9923 + 0x8c, 0xe3, 0x57, 0x8f,
9924 + 0xc7, 0x5f, 0x1b, 0x0f,
9925 + 0x2d, 0xf8, 0x9d, 0x30,
9926 + 0x6f, 0xa4, 0x52, 0xcd,
9927 + 0xe0, 0x7a, 0x04, 0x8a,
9928 + 0xde, 0xd9, 0x26, 0x56,
9929 +};
9930 +
9931 +void dwc_run_dh_test_vectors(void *mem_ctx)
9932 +{
9933 + uint8_t pkd[384];
9934 + uint8_t pkh[384];
9935 + uint8_t hashd[32];
9936 + uint8_t hashh[32];
9937 + uint8_t ck[16];
9938 + uint8_t kdk[32];
9939 + char dd[5];
9940 +
9941 + DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
9942 +
9943 + /* compute the PKd and SHA-256(PKd || Nd) */
9944 + DWC_PRINTF("Computing PKd\n");
9945 + dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
9946 +
9947 + /* compute the PKd and SHA-256(PKh || Nd) */
9948 + DWC_PRINTF("Computing PKh\n");
9949 + dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
9950 +
9951 + /* compute the dhkey */
9952 + dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
9953 +}
9954 +#endif /* DH_TEST_VECTORS */
9955 +
9956 +#endif /* !CONFIG_MACH_IPMATE */
9957 +
9958 +#endif /* DWC_CRYPTOLIB */
9959 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_dh.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_dh.h
9960 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_dh.h 1970-01-01 01:00:00.000000000 +0100
9961 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_dh.h 2013-07-06 15:25:50.000000000 +0100
9962 @@ -0,0 +1,106 @@
9963 +/* =========================================================================
9964 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
9965 + * $Revision: #4 $
9966 + * $Date: 2010/09/28 $
9967 + * $Change: 1596182 $
9968 + *
9969 + * Synopsys Portability Library Software and documentation
9970 + * (hereinafter, "Software") is an Unsupported proprietary work of
9971 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9972 + * between Synopsys and you.
9973 + *
9974 + * The Software IS NOT an item of Licensed Software or Licensed Product
9975 + * under any End User Software License Agreement or Agreement for
9976 + * Licensed Product with Synopsys or any supplement thereto. You are
9977 + * permitted to use and redistribute this Software in source and binary
9978 + * forms, with or without modification, provided that redistributions
9979 + * of source code must retain this notice. You may not view, use,
9980 + * disclose, copy or distribute this file or any information contained
9981 + * herein except pursuant to this license grant from Synopsys. If you
9982 + * do not agree with this notice, including the disclaimer below, then
9983 + * you are not authorized to use the Software.
9984 + *
9985 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9986 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9987 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9988 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9989 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9990 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9991 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9992 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9993 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9994 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9995 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9996 + * DAMAGE.
9997 + * ========================================================================= */
9998 +#ifndef _DWC_DH_H_
9999 +#define _DWC_DH_H_
10000 +
10001 +#ifdef __cplusplus
10002 +extern "C" {
10003 +#endif
10004 +
10005 +#include "dwc_os.h"
10006 +
10007 +/** @file
10008 + *
10009 + * This file defines the common functions on device and host for performing
10010 + * numeric association as defined in the WUSB spec. They are only to be
10011 + * used internally by the DWC UWB modules. */
10012 +
10013 +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
10014 +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
10015 + uint8_t *key, uint32_t keylen,
10016 + uint8_t *out);
10017 +extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10018 + void *exp, uint32_t exp_len,
10019 + void *mod, uint32_t mod_len,
10020 + void *out);
10021 +
10022 +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
10023 + *
10024 + * PK = g^exp mod p.
10025 + *
10026 + * Input:
10027 + * Nd = Number of digits on the device.
10028 + *
10029 + * Output:
10030 + * exp = A 32-byte buffer to be filled with a randomly generated number.
10031 + * used as either A or B.
10032 + * pk = A 384-byte buffer to be filled with the PKH or PKD.
10033 + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
10034 + */
10035 +extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
10036 +
10037 +/** Computes the DHKEY, and VD.
10038 + *
10039 + * If called from host, then it will comput DHKEY=PKD^exp % p.
10040 + * If called from device, then it will comput DHKEY=PKH^exp % p.
10041 + *
10042 + * Input:
10043 + * pkd = The PKD value.
10044 + * pkh = The PKH value.
10045 + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
10046 + * is_host = Set to non zero if a WUSB host is calling this function.
10047 + *
10048 + * Output:
10049 +
10050 + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
10051 + * to the user. This buffer should be at 5 bytes long to hold 4 digits plus a
10052 + * null termination character. This buffer can be used directly for display.
10053 + * ck = A 16-byte buffer to be filled with the CK.
10054 + * kdk = A 32-byte buffer to be filled with the KDK.
10055 + */
10056 +extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10057 + uint8_t *exp, int is_host,
10058 + char *dd, uint8_t *ck, uint8_t *kdk);
10059 +
10060 +#ifdef DH_TEST_VECTORS
10061 +extern void dwc_run_dh_test_vectors(void);
10062 +#endif
10063 +
10064 +#ifdef __cplusplus
10065 +}
10066 +#endif
10067 +
10068 +#endif /* _DWC_DH_H_ */
10069 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_list.h
10070 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100
10071 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_list.h 2013-07-06 15:25:50.000000000 +0100
10072 @@ -0,0 +1,594 @@
10073 +/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */
10074 +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
10075 +
10076 +/*
10077 + * Copyright (c) 1991, 1993
10078 + * The Regents of the University of California. All rights reserved.
10079 + *
10080 + * Redistribution and use in source and binary forms, with or without
10081 + * modification, are permitted provided that the following conditions
10082 + * are met:
10083 + * 1. Redistributions of source code must retain the above copyright
10084 + * notice, this list of conditions and the following disclaimer.
10085 + * 2. Redistributions in binary form must reproduce the above copyright
10086 + * notice, this list of conditions and the following disclaimer in the
10087 + * documentation and/or other materials provided with the distribution.
10088 + * 3. Neither the name of the University nor the names of its contributors
10089 + * may be used to endorse or promote products derived from this software
10090 + * without specific prior written permission.
10091 + *
10092 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
10093 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10094 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10095 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
10096 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10097 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10098 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10099 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10100 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10101 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10102 + * SUCH DAMAGE.
10103 + *
10104 + * @(#)queue.h 8.5 (Berkeley) 8/20/94
10105 + */
10106 +
10107 +#ifndef _DWC_LIST_H_
10108 +#define _DWC_LIST_H_
10109 +
10110 +#ifdef __cplusplus
10111 +extern "C" {
10112 +#endif
10113 +
10114 +/** @file
10115 + *
10116 + * This file defines linked list operations. It is derived from BSD with
10117 + * only the MACRO names being prefixed with DWC_. This is because a few of
10118 + * these names conflict with those on Linux. For documentation on use, see the
10119 + * inline comments in the source code. The original license for this source
10120 + * code applies and is preserved in the dwc_list.h source file.
10121 + */
10122 +
10123 +/*
10124 + * This file defines five types of data structures: singly-linked lists,
10125 + * lists, simple queues, tail queues, and circular queues.
10126 + *
10127 + *
10128 + * A singly-linked list is headed by a single forward pointer. The elements
10129 + * are singly linked for minimum space and pointer manipulation overhead at
10130 + * the expense of O(n) removal for arbitrary elements. New elements can be
10131 + * added to the list after an existing element or at the head of the list.
10132 + * Elements being removed from the head of the list should use the explicit
10133 + * macro for this purpose for optimum efficiency. A singly-linked list may
10134 + * only be traversed in the forward direction. Singly-linked lists are ideal
10135 + * for applications with large datasets and few or no removals or for
10136 + * implementing a LIFO queue.
10137 + *
10138 + * A list is headed by a single forward pointer (or an array of forward
10139 + * pointers for a hash table header). The elements are doubly linked
10140 + * so that an arbitrary element can be removed without a need to
10141 + * traverse the list. New elements can be added to the list before
10142 + * or after an existing element or at the head of the list. A list
10143 + * may only be traversed in the forward direction.
10144 + *
10145 + * A simple queue is headed by a pair of pointers, one the head of the
10146 + * list and the other to the tail of the list. The elements are singly
10147 + * linked to save space, so elements can only be removed from the
10148 + * head of the list. New elements can be added to the list before or after
10149 + * an existing element, at the head of the list, or at the end of the
10150 + * list. A simple queue may only be traversed in the forward direction.
10151 + *
10152 + * A tail queue is headed by a pair of pointers, one to the head of the
10153 + * list and the other to the tail of the list. The elements are doubly
10154 + * linked so that an arbitrary element can be removed without a need to
10155 + * traverse the list. New elements can be added to the list before or
10156 + * after an existing element, at the head of the list, or at the end of
10157 + * the list. A tail queue may be traversed in either direction.
10158 + *
10159 + * A circle queue is headed by a pair of pointers, one to the head of the
10160 + * list and the other to the tail of the list. The elements are doubly
10161 + * linked so that an arbitrary element can be removed without a need to
10162 + * traverse the list. New elements can be added to the list before or after
10163 + * an existing element, at the head of the list, or at the end of the list.
10164 + * A circle queue may be traversed in either direction, but has a more
10165 + * complex end of list detection.
10166 + *
10167 + * For details on the use of these macros, see the queue(3) manual page.
10168 + */
10169 +
10170 +/*
10171 + * Double-linked List.
10172 + */
10173 +
10174 +typedef struct dwc_list_link {
10175 + struct dwc_list_link *next;
10176 + struct dwc_list_link *prev;
10177 +} dwc_list_link_t;
10178 +
10179 +#define DWC_LIST_INIT(link) do { \
10180 + (link)->next = (link); \
10181 + (link)->prev = (link); \
10182 +} while (0)
10183 +
10184 +#define DWC_LIST_FIRST(link) ((link)->next)
10185 +#define DWC_LIST_LAST(link) ((link)->prev)
10186 +#define DWC_LIST_END(link) (link)
10187 +#define DWC_LIST_NEXT(link) ((link)->next)
10188 +#define DWC_LIST_PREV(link) ((link)->prev)
10189 +#define DWC_LIST_EMPTY(link) \
10190 + (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
10191 +#define DWC_LIST_ENTRY(link, type, field) \
10192 + (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))
10193 +
10194 +#if 0
10195 +#define DWC_LIST_INSERT_HEAD(list, link) do { \
10196 + (link)->next = (list)->next; \
10197 + (link)->prev = (list); \
10198 + (list)->next->prev = (link); \
10199 + (list)->next = (link); \
10200 +} while (0)
10201 +
10202 +#define DWC_LIST_INSERT_TAIL(list, link) do { \
10203 + (link)->next = (list); \
10204 + (link)->prev = (list)->prev; \
10205 + (list)->prev->next = (link); \
10206 + (list)->prev = (link); \
10207 +} while (0)
10208 +#else
10209 +#define DWC_LIST_INSERT_HEAD(list, link) do { \
10210 + dwc_list_link_t *__next__ = (list)->next; \
10211 + __next__->prev = (link); \
10212 + (link)->next = __next__; \
10213 + (link)->prev = (list); \
10214 + (list)->next = (link); \
10215 +} while (0)
10216 +
10217 +#define DWC_LIST_INSERT_TAIL(list, link) do { \
10218 + dwc_list_link_t *__prev__ = (list)->prev; \
10219 + (list)->prev = (link); \
10220 + (link)->next = (list); \
10221 + (link)->prev = __prev__; \
10222 + __prev__->next = (link); \
10223 +} while (0)
10224 +#endif
10225 +
10226 +#if 0
10227 +static inline void __list_add(struct list_head *new,
10228 + struct list_head *prev,
10229 + struct list_head *next)
10230 +{
10231 + next->prev = new;
10232 + new->next = next;
10233 + new->prev = prev;
10234 + prev->next = new;
10235 +}
10236 +
10237 +static inline void list_add(struct list_head *new, struct list_head *head)
10238 +{
10239 + __list_add(new, head, head->next);
10240 +}
10241 +
10242 +static inline void list_add_tail(struct list_head *new, struct list_head *head)
10243 +{
10244 + __list_add(new, head->prev, head);
10245 +}
10246 +
10247 +static inline void __list_del(struct list_head * prev, struct list_head * next)
10248 +{
10249 + next->prev = prev;
10250 + prev->next = next;
10251 +}
10252 +
10253 +static inline void list_del(struct list_head *entry)
10254 +{
10255 + __list_del(entry->prev, entry->next);
10256 + entry->next = LIST_POISON1;
10257 + entry->prev = LIST_POISON2;
10258 +}
10259 +#endif
10260 +
10261 +#define DWC_LIST_REMOVE(link) do { \
10262 + (link)->next->prev = (link)->prev; \
10263 + (link)->prev->next = (link)->next; \
10264 +} while (0)
10265 +
10266 +#define DWC_LIST_REMOVE_INIT(link) do { \
10267 + DWC_LIST_REMOVE(link); \
10268 + DWC_LIST_INIT(link); \
10269 +} while (0)
10270 +
10271 +#define DWC_LIST_MOVE_HEAD(list, link) do { \
10272 + DWC_LIST_REMOVE(link); \
10273 + DWC_LIST_INSERT_HEAD(list, link); \
10274 +} while (0)
10275 +
10276 +#define DWC_LIST_MOVE_TAIL(list, link) do { \
10277 + DWC_LIST_REMOVE(link); \
10278 + DWC_LIST_INSERT_TAIL(list, link); \
10279 +} while (0)
10280 +
10281 +#define DWC_LIST_FOREACH(var, list) \
10282 + for((var) = DWC_LIST_FIRST(list); \
10283 + (var) != DWC_LIST_END(list); \
10284 + (var) = DWC_LIST_NEXT(var))
10285 +
10286 +#define DWC_LIST_FOREACH_SAFE(var, var2, list) \
10287 + for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \
10288 + (var) != DWC_LIST_END(list); \
10289 + (var) = (var2), (var2) = DWC_LIST_NEXT(var2))
10290 +
10291 +#define DWC_LIST_FOREACH_REVERSE(var, list) \
10292 + for((var) = DWC_LIST_LAST(list); \
10293 + (var) != DWC_LIST_END(list); \
10294 + (var) = DWC_LIST_PREV(var))
10295 +
10296 +/*
10297 + * Singly-linked List definitions.
10298 + */
10299 +#define DWC_SLIST_HEAD(name, type) \
10300 +struct name { \
10301 + struct type *slh_first; /* first element */ \
10302 +}
10303 +
10304 +#define DWC_SLIST_HEAD_INITIALIZER(head) \
10305 + { NULL }
10306 +
10307 +#define DWC_SLIST_ENTRY(type) \
10308 +struct { \
10309 + struct type *sle_next; /* next element */ \
10310 +}
10311 +
10312 +/*
10313 + * Singly-linked List access methods.
10314 + */
10315 +#define DWC_SLIST_FIRST(head) ((head)->slh_first)
10316 +#define DWC_SLIST_END(head) NULL
10317 +#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
10318 +#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next)
10319 +
10320 +#define DWC_SLIST_FOREACH(var, head, field) \
10321 + for((var) = SLIST_FIRST(head); \
10322 + (var) != SLIST_END(head); \
10323 + (var) = SLIST_NEXT(var, field))
10324 +
10325 +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \
10326 + for((varp) = &SLIST_FIRST((head)); \
10327 + ((var) = *(varp)) != SLIST_END(head); \
10328 + (varp) = &SLIST_NEXT((var), field))
10329 +
10330 +/*
10331 + * Singly-linked List functions.
10332 + */
10333 +#define DWC_SLIST_INIT(head) { \
10334 + SLIST_FIRST(head) = SLIST_END(head); \
10335 +}
10336 +
10337 +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \
10338 + (elm)->field.sle_next = (slistelm)->field.sle_next; \
10339 + (slistelm)->field.sle_next = (elm); \
10340 +} while (0)
10341 +
10342 +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \
10343 + (elm)->field.sle_next = (head)->slh_first; \
10344 + (head)->slh_first = (elm); \
10345 +} while (0)
10346 +
10347 +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \
10348 + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
10349 +} while (0)
10350 +
10351 +#define DWC_SLIST_REMOVE_HEAD(head, field) do { \
10352 + (head)->slh_first = (head)->slh_first->field.sle_next; \
10353 +} while (0)
10354 +
10355 +#define DWC_SLIST_REMOVE(head, elm, type, field) do { \
10356 + if ((head)->slh_first == (elm)) { \
10357 + SLIST_REMOVE_HEAD((head), field); \
10358 + } \
10359 + else { \
10360 + struct type *curelm = (head)->slh_first; \
10361 + while( curelm->field.sle_next != (elm) ) \
10362 + curelm = curelm->field.sle_next; \
10363 + curelm->field.sle_next = \
10364 + curelm->field.sle_next->field.sle_next; \
10365 + } \
10366 +} while (0)
10367 +
10368 +/*
10369 + * Simple queue definitions.
10370 + */
10371 +#define DWC_SIMPLEQ_HEAD(name, type) \
10372 +struct name { \
10373 + struct type *sqh_first; /* first element */ \
10374 + struct type **sqh_last; /* addr of last next element */ \
10375 +}
10376 +
10377 +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \
10378 + { NULL, &(head).sqh_first }
10379 +
10380 +#define DWC_SIMPLEQ_ENTRY(type) \
10381 +struct { \
10382 + struct type *sqe_next; /* next element */ \
10383 +}
10384 +
10385 +/*
10386 + * Simple queue access methods.
10387 + */
10388 +#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first)
10389 +#define DWC_SIMPLEQ_END(head) NULL
10390 +#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
10391 +#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
10392 +
10393 +#define DWC_SIMPLEQ_FOREACH(var, head, field) \
10394 + for((var) = SIMPLEQ_FIRST(head); \
10395 + (var) != SIMPLEQ_END(head); \
10396 + (var) = SIMPLEQ_NEXT(var, field))
10397 +
10398 +/*
10399 + * Simple queue functions.
10400 + */
10401 +#define DWC_SIMPLEQ_INIT(head) do { \
10402 + (head)->sqh_first = NULL; \
10403 + (head)->sqh_last = &(head)->sqh_first; \
10404 +} while (0)
10405 +
10406 +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
10407 + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
10408 + (head)->sqh_last = &(elm)->field.sqe_next; \
10409 + (head)->sqh_first = (elm); \
10410 +} while (0)
10411 +
10412 +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
10413 + (elm)->field.sqe_next = NULL; \
10414 + *(head)->sqh_last = (elm); \
10415 + (head)->sqh_last = &(elm)->field.sqe_next; \
10416 +} while (0)
10417 +
10418 +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
10419 + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
10420 + (head)->sqh_last = &(elm)->field.sqe_next; \
10421 + (listelm)->field.sqe_next = (elm); \
10422 +} while (0)
10423 +
10424 +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \
10425 + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
10426 + (head)->sqh_last = &(head)->sqh_first; \
10427 +} while (0)
10428 +
10429 +/*
10430 + * Tail queue definitions.
10431 + */
10432 +#define DWC_TAILQ_HEAD(name, type) \
10433 +struct name { \
10434 + struct type *tqh_first; /* first element */ \
10435 + struct type **tqh_last; /* addr of last next element */ \
10436 +}
10437 +
10438 +#define DWC_TAILQ_HEAD_INITIALIZER(head) \
10439 + { NULL, &(head).tqh_first }
10440 +
10441 +#define DWC_TAILQ_ENTRY(type) \
10442 +struct { \
10443 + struct type *tqe_next; /* next element */ \
10444 + struct type **tqe_prev; /* address of previous next element */ \
10445 +}
10446 +
10447 +/*
10448 + * tail queue access methods
10449 + */
10450 +#define DWC_TAILQ_FIRST(head) ((head)->tqh_first)
10451 +#define DWC_TAILQ_END(head) NULL
10452 +#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
10453 +#define DWC_TAILQ_LAST(head, headname) \
10454 + (*(((struct headname *)((head)->tqh_last))->tqh_last))
10455 +/* XXX */
10456 +#define DWC_TAILQ_PREV(elm, headname, field) \
10457 + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
10458 +#define DWC_TAILQ_EMPTY(head) \
10459 + (DWC_TAILQ_FIRST(head) == DWC_TAILQ_END(head))
10460 +
10461 +#define DWC_TAILQ_FOREACH(var, head, field) \
10462 + for ((var) = DWC_TAILQ_FIRST(head); \
10463 + (var) != DWC_TAILQ_END(head); \
10464 + (var) = DWC_TAILQ_NEXT(var, field))
10465 +
10466 +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
10467 + for ((var) = DWC_TAILQ_LAST(head, headname); \
10468 + (var) != DWC_TAILQ_END(head); \
10469 + (var) = DWC_TAILQ_PREV(var, headname, field))
10470 +
10471 +/*
10472 + * Tail queue functions.
10473 + */
10474 +#define DWC_TAILQ_INIT(head) do { \
10475 + (head)->tqh_first = NULL; \
10476 + (head)->tqh_last = &(head)->tqh_first; \
10477 +} while (0)
10478 +
10479 +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \
10480 + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
10481 + (head)->tqh_first->field.tqe_prev = \
10482 + &(elm)->field.tqe_next; \
10483 + else \
10484 + (head)->tqh_last = &(elm)->field.tqe_next; \
10485 + (head)->tqh_first = (elm); \
10486 + (elm)->field.tqe_prev = &(head)->tqh_first; \
10487 +} while (0)
10488 +
10489 +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \
10490 + (elm)->field.tqe_next = NULL; \
10491 + (elm)->field.tqe_prev = (head)->tqh_last; \
10492 + *(head)->tqh_last = (elm); \
10493 + (head)->tqh_last = &(elm)->field.tqe_next; \
10494 +} while (0)
10495 +
10496 +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
10497 + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
10498 + (elm)->field.tqe_next->field.tqe_prev = \
10499 + &(elm)->field.tqe_next; \
10500 + else \
10501 + (head)->tqh_last = &(elm)->field.tqe_next; \
10502 + (listelm)->field.tqe_next = (elm); \
10503 + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
10504 +} while (0)
10505 +
10506 +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
10507 + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
10508 + (elm)->field.tqe_next = (listelm); \
10509 + *(listelm)->field.tqe_prev = (elm); \
10510 + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
10511 +} while (0)
10512 +
10513 +#define DWC_TAILQ_REMOVE(head, elm, field) do { \
10514 + if (((elm)->field.tqe_next) != NULL) \
10515 + (elm)->field.tqe_next->field.tqe_prev = \
10516 + (elm)->field.tqe_prev; \
10517 + else \
10518 + (head)->tqh_last = (elm)->field.tqe_prev; \
10519 + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
10520 +} while (0)
10521 +
10522 +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \
10523 + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
10524 + (elm2)->field.tqe_next->field.tqe_prev = \
10525 + &(elm2)->field.tqe_next; \
10526 + else \
10527 + (head)->tqh_last = &(elm2)->field.tqe_next; \
10528 + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
10529 + *(elm2)->field.tqe_prev = (elm2); \
10530 +} while (0)
10531 +
10532 +/*
10533 + * Circular queue definitions.
10534 + */
10535 +#define DWC_CIRCLEQ_HEAD(name, type) \
10536 +struct name { \
10537 + struct type *cqh_first; /* first element */ \
10538 + struct type *cqh_last; /* last element */ \
10539 +}
10540 +
10541 +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \
10542 + { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
10543 +
10544 +#define DWC_CIRCLEQ_ENTRY(type) \
10545 +struct { \
10546 + struct type *cqe_next; /* next element */ \
10547 + struct type *cqe_prev; /* previous element */ \
10548 +}
10549 +
10550 +/*
10551 + * Circular queue access methods
10552 + */
10553 +#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first)
10554 +#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last)
10555 +#define DWC_CIRCLEQ_END(head) ((void *)(head))
10556 +#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
10557 +#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
10558 +#define DWC_CIRCLEQ_EMPTY(head) \
10559 + (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
10560 +
10561 +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
10562 +
10563 +#define DWC_CIRCLEQ_FOREACH(var, head, field) \
10564 + for((var) = DWC_CIRCLEQ_FIRST(head); \
10565 + (var) != DWC_CIRCLEQ_END(head); \
10566 + (var) = DWC_CIRCLEQ_NEXT(var, field))
10567 +
10568 +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \
10569 + for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \
10570 + (var) != DWC_CIRCLEQ_END(head); \
10571 + (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
10572 +
10573 +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \
10574 + for((var) = DWC_CIRCLEQ_LAST(head); \
10575 + (var) != DWC_CIRCLEQ_END(head); \
10576 + (var) = DWC_CIRCLEQ_PREV(var, field))
10577 +
10578 +/*
10579 + * Circular queue functions.
10580 + */
10581 +#define DWC_CIRCLEQ_INIT(head) do { \
10582 + (head)->cqh_first = DWC_CIRCLEQ_END(head); \
10583 + (head)->cqh_last = DWC_CIRCLEQ_END(head); \
10584 +} while (0)
10585 +
10586 +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \
10587 + (elm)->field.cqe_next = NULL; \
10588 + (elm)->field.cqe_prev = NULL; \
10589 +} while (0)
10590 +
10591 +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
10592 + (elm)->field.cqe_next = (listelm)->field.cqe_next; \
10593 + (elm)->field.cqe_prev = (listelm); \
10594 + if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \
10595 + (head)->cqh_last = (elm); \
10596 + else \
10597 + (listelm)->field.cqe_next->field.cqe_prev = (elm); \
10598 + (listelm)->field.cqe_next = (elm); \
10599 +} while (0)
10600 +
10601 +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
10602 + (elm)->field.cqe_next = (listelm); \
10603 + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
10604 + if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \
10605 + (head)->cqh_first = (elm); \
10606 + else \
10607 + (listelm)->field.cqe_prev->field.cqe_next = (elm); \
10608 + (listelm)->field.cqe_prev = (elm); \
10609 +} while (0)
10610 +
10611 +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
10612 + (elm)->field.cqe_next = (head)->cqh_first; \
10613 + (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \
10614 + if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \
10615 + (head)->cqh_last = (elm); \
10616 + else \
10617 + (head)->cqh_first->field.cqe_prev = (elm); \
10618 + (head)->cqh_first = (elm); \
10619 +} while (0)
10620 +
10621 +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
10622 + (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \
10623 + (elm)->field.cqe_prev = (head)->cqh_last; \
10624 + if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \
10625 + (head)->cqh_first = (elm); \
10626 + else \
10627 + (head)->cqh_last->field.cqe_next = (elm); \
10628 + (head)->cqh_last = (elm); \
10629 +} while (0)
10630 +
10631 +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \
10632 + if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \
10633 + (head)->cqh_last = (elm)->field.cqe_prev; \
10634 + else \
10635 + (elm)->field.cqe_next->field.cqe_prev = \
10636 + (elm)->field.cqe_prev; \
10637 + if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \
10638 + (head)->cqh_first = (elm)->field.cqe_next; \
10639 + else \
10640 + (elm)->field.cqe_prev->field.cqe_next = \
10641 + (elm)->field.cqe_next; \
10642 +} while (0)
10643 +
10644 +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \
10645 + DWC_CIRCLEQ_REMOVE(head, elm, field); \
10646 + DWC_CIRCLEQ_INIT_ENTRY(elm, field); \
10647 +} while (0)
10648 +
10649 +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
10650 + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
10651 + DWC_CIRCLEQ_END(head)) \
10652 + (head).cqh_last = (elm2); \
10653 + else \
10654 + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
10655 + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
10656 + DWC_CIRCLEQ_END(head)) \
10657 + (head).cqh_first = (elm2); \
10658 + else \
10659 + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
10660 +} while (0)
10661 +
10662 +#ifdef __cplusplus
10663 +}
10664 +#endif
10665 +
10666 +#endif /* _DWC_LIST_H_ */
10667 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_mem.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_mem.c
10668 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100
10669 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_mem.c 2013-07-06 15:25:50.000000000 +0100
10670 @@ -0,0 +1,245 @@
10671 +/* Memory Debugging */
10672 +#ifdef DWC_DEBUG_MEMORY
10673 +
10674 +#include "dwc_os.h"
10675 +#include "dwc_list.h"
10676 +
10677 +struct allocation {
10678 + void *addr;
10679 + void *ctx;
10680 + char *func;
10681 + int line;
10682 + uint32_t size;
10683 + int dma;
10684 + DWC_CIRCLEQ_ENTRY(allocation) entry;
10685 +};
10686 +
10687 +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
10688 +
10689 +struct allocation_manager {
10690 + void *mem_ctx;
10691 + struct allocation_queue allocations;
10692 +
10693 + /* statistics */
10694 + int num;
10695 + int num_freed;
10696 + int num_active;
10697 + uint32_t total;
10698 + uint32_t cur;
10699 + uint32_t max;
10700 +};
10701 +
10702 +static struct allocation_manager *manager = NULL;
10703 +
10704 +static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
10705 + int dma)
10706 +{
10707 + struct allocation *a;
10708 +
10709 + DWC_ASSERT(manager != NULL, "manager not allocated");
10710 +
10711 + a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
10712 + if (!a) {
10713 + return -DWC_E_NO_MEMORY;
10714 + }
10715 +
10716 + a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
10717 + if (!a->func) {
10718 + __DWC_FREE(manager->mem_ctx, a);
10719 + return -DWC_E_NO_MEMORY;
10720 + }
10721 +
10722 + DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
10723 + a->addr = addr;
10724 + a->ctx = ctx;
10725 + a->line = line;
10726 + a->size = size;
10727 + a->dma = dma;
10728 + DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
10729 +
10730 + /* Update stats */
10731 + manager->num++;
10732 + manager->num_active++;
10733 + manager->total += size;
10734 + manager->cur += size;
10735 +
10736 + if (manager->max < manager->cur) {
10737 + manager->max = manager->cur;
10738 + }
10739 +
10740 + return 0;
10741 +}
10742 +
10743 +static struct allocation *find_allocation(void *ctx, void *addr)
10744 +{
10745 + struct allocation *a;
10746 +
10747 + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
10748 + if (a->ctx == ctx && a->addr == addr) {
10749 + return a;
10750 + }
10751 + }
10752 +
10753 + return NULL;
10754 +}
10755 +
10756 +static void free_allocation(void *ctx, void *addr, char const *func, int line)
10757 +{
10758 + struct allocation *a = find_allocation(ctx, addr);
10759 +
10760 + if (!a) {
10761 + DWC_ASSERT(0,
10762 + "Free of address %p that was never allocated or already freed %s:%d",
10763 + addr, func, line);
10764 + return;
10765 + }
10766 +
10767 + DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
10768 +
10769 + manager->num_active--;
10770 + manager->num_freed++;
10771 + manager->cur -= a->size;
10772 + __DWC_FREE(manager->mem_ctx, a->func);
10773 + __DWC_FREE(manager->mem_ctx, a);
10774 +}
10775 +
10776 +int dwc_memory_debug_start(void *mem_ctx)
10777 +{
10778 + DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
10779 +
10780 + if (manager) {
10781 + return -DWC_E_BUSY;
10782 + }
10783 +
10784 + manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
10785 + if (!manager) {
10786 + return -DWC_E_NO_MEMORY;
10787 + }
10788 +
10789 + DWC_CIRCLEQ_INIT(&manager->allocations);
10790 + manager->mem_ctx = mem_ctx;
10791 + manager->num = 0;
10792 + manager->num_freed = 0;
10793 + manager->num_active = 0;
10794 + manager->total = 0;
10795 + manager->cur = 0;
10796 + manager->max = 0;
10797 +
10798 + return 0;
10799 +}
10800 +
10801 +void dwc_memory_debug_stop(void)
10802 +{
10803 + struct allocation *a;
10804 +
10805 + dwc_memory_debug_report();
10806 +
10807 + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
10808 + DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
10809 + free_allocation(a->ctx, a->addr, NULL, -1);
10810 + }
10811 +
10812 + __DWC_FREE(manager->mem_ctx, manager);
10813 +}
10814 +
10815 +void dwc_memory_debug_report(void)
10816 +{
10817 + struct allocation *a;
10818 +
10819 + DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
10820 + DWC_PRINTF("Num Allocations = %d\n", manager->num);
10821 + DWC_PRINTF("Freed = %d\n", manager->num_freed);
10822 + DWC_PRINTF("Active = %d\n", manager->num_active);
10823 + DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
10824 + DWC_PRINTF("Total Memory Used = %d\n", manager->total);
10825 + DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
10826 + DWC_PRINTF("Unfreed allocations:\n");
10827 +
10828 + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
10829 + DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n",
10830 + a->addr, a->size, a->func, a->line, a->dma);
10831 + }
10832 +}
10833 +
10834 +/* The replacement functions */
10835 +void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
10836 +{
10837 + void *addr = __DWC_ALLOC(mem_ctx, size);
10838 +
10839 + if (!addr) {
10840 + return NULL;
10841 + }
10842 +
10843 + if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
10844 + __DWC_FREE(mem_ctx, addr);
10845 + return NULL;
10846 + }
10847 +
10848 + return addr;
10849 +}
10850 +
10851 +void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
10852 + int line)
10853 +{
10854 + void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);
10855 +
10856 + if (!addr) {
10857 + return NULL;
10858 + }
10859 +
10860 + if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
10861 + __DWC_FREE(mem_ctx, addr);
10862 + return NULL;
10863 + }
10864 +
10865 + return addr;
10866 +}
10867 +
10868 +void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)
10869 +{
10870 + free_allocation(mem_ctx, addr, func, line);
10871 + __DWC_FREE(mem_ctx, addr);
10872 +}
10873 +
10874 +void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
10875 + char const *func, int line)
10876 +{
10877 + void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
10878 +
10879 + if (!addr) {
10880 + return NULL;
10881 + }
10882 +
10883 + if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
10884 + __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
10885 + return NULL;
10886 + }
10887 +
10888 + return addr;
10889 +}
10890 +
10891 +void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
10892 + dwc_dma_t *dma_addr, char const *func, int line)
10893 +{
10894 + void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);
10895 +
10896 + if (!addr) {
10897 + return NULL;
10898 + }
10899 +
10900 + if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
10901 + __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
10902 + return NULL;
10903 + }
10904 +
10905 + return addr;
10906 +}
10907 +
10908 +void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
10909 + dwc_dma_t dma_addr, char const *func, int line)
10910 +{
10911 + free_allocation(dma_ctx, virt_addr, func, line);
10912 + __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
10913 +}
10914 +
10915 +#endif /* DWC_DEBUG_MEMORY */
10916 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_modpow.c
10917 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_modpow.c 1970-01-01 01:00:00.000000000 +0100
10918 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_modpow.c 2013-07-06 15:25:50.000000000 +0100
10919 @@ -0,0 +1,636 @@
10920 +/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows.
10921 + *
10922 + * PuTTY is copyright 1997-2007 Simon Tatham.
10923 + *
10924 + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
10925 + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
10926 + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
10927 + * Kuhn, and CORE SDI S.A.
10928 + *
10929 + * Permission is hereby granted, free of charge, to any person
10930 + * obtaining a copy of this software and associated documentation files
10931 + * (the "Software"), to deal in the Software without restriction,
10932 + * including without limitation the rights to use, copy, modify, merge,
10933 + * publish, distribute, sublicense, and/or sell copies of the Software,
10934 + * and to permit persons to whom the Software is furnished to do so,
10935 + * subject to the following conditions:
10936 + *
10937 + * The above copyright notice and this permission notice shall be
10938 + * included in all copies or substantial portions of the Software.
10939 +
10940 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
10941 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10942 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
10943 + * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
10944 + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
10945 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
10946 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10947 + *
10948 + */
10949 +#ifdef DWC_CRYPTOLIB
10950 +
10951 +#ifndef CONFIG_MACH_IPMATE
10952 +
10953 +#include "dwc_modpow.h"
10954 +
10955 +#define BIGNUM_INT_MASK 0xFFFFFFFFUL
10956 +#define BIGNUM_TOP_BIT 0x80000000UL
10957 +#define BIGNUM_INT_BITS 32
10958 +
10959 +
10960 +static void *snmalloc(void *mem_ctx, size_t n, size_t size)
10961 +{
10962 + void *p;
10963 + size *= n;
10964 + if (size == 0) size = 1;
10965 + p = dwc_alloc(mem_ctx, size);
10966 + return p;
10967 +}
10968 +
10969 +#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))
10970 +#define sfree dwc_free
10971 +
10972 +/*
10973 + * Usage notes:
10974 + * * Do not call the DIVMOD_WORD macro with expressions such as array
10975 + * subscripts, as some implementations object to this (see below).
10976 + * * Note that none of the division methods below will cope if the
10977 + * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
10978 + * to avoid this case.
10979 + * If this condition occurs, in the case of the x86 DIV instruction,
10980 + * an overflow exception will occur, which (according to a correspondent)
10981 + * will manifest on Windows as something like
10982 + * 0xC0000095: Integer overflow
10983 + * The C variant won't give the right answer, either.
10984 + */
10985 +
10986 +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
10987 +
10988 +#if defined __GNUC__ && defined __i386__
10989 +#define DIVMOD_WORD(q, r, hi, lo, w) \
10990 + __asm__("div %2" : \
10991 + "=d" (r), "=a" (q) : \
10992 + "r" (w), "d" (hi), "a" (lo))
10993 +#else
10994 +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
10995 + BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
10996 + q = n / w; \
10997 + r = n % w; \
10998 +} while (0)
10999 +#endif
11000 +
11001 +// q = n / w;
11002 +// r = n % w;
11003 +
11004 +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
11005 +
11006 +#define BIGNUM_INTERNAL
11007 +
11008 +static Bignum newbn(void *mem_ctx, int length)
11009 +{
11010 + Bignum b = snewn(mem_ctx, length + 1, BignumInt);
11011 + //if (!b)
11012 + //abort(); /* FIXME */
11013 + DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
11014 + b[0] = length;
11015 + return b;
11016 +}
11017 +
11018 +void freebn(void *mem_ctx, Bignum b)
11019 +{
11020 + /*
11021 + * Burn the evidence, just in case.
11022 + */
11023 + DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
11024 + sfree(mem_ctx, b);
11025 +}
11026 +
11027 +/*
11028 + * Compute c = a * b.
11029 + * Input is in the first len words of a and b.
11030 + * Result is returned in the first 2*len words of c.
11031 + */
11032 +static void internal_mul(BignumInt *a, BignumInt *b,
11033 + BignumInt *c, int len)
11034 +{
11035 + int i, j;
11036 + BignumDblInt t;
11037 +
11038 + for (j = 0; j < 2 * len; j++)
11039 + c[j] = 0;
11040 +
11041 + for (i = len - 1; i >= 0; i--) {
11042 + t = 0;
11043 + for (j = len - 1; j >= 0; j--) {
11044 + t += MUL_WORD(a[i], (BignumDblInt) b[j]);
11045 + t += (BignumDblInt) c[i + j + 1];
11046 + c[i + j + 1] = (BignumInt) t;
11047 + t = t >> BIGNUM_INT_BITS;
11048 + }
11049 + c[i] = (BignumInt) t;
11050 + }
11051 +}
11052 +
11053 +static void internal_add_shifted(BignumInt *number,
11054 + unsigned n, int shift)
11055 +{
11056 + int word = 1 + (shift / BIGNUM_INT_BITS);
11057 + int bshift = shift % BIGNUM_INT_BITS;
11058 + BignumDblInt addend;
11059 +
11060 + addend = (BignumDblInt)n << bshift;
11061 +
11062 + while (addend) {
11063 + addend += number[word];
11064 + number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
11065 + addend >>= BIGNUM_INT_BITS;
11066 + word++;
11067 + }
11068 +}
11069 +
11070 +/*
11071 + * Compute a = a % m.
11072 + * Input in first alen words of a and first mlen words of m.
11073 + * Output in first alen words of a
11074 + * (of which first alen-mlen words will be zero).
11075 + * The MSW of m MUST have its high bit set.
11076 + * Quotient is accumulated in the `quotient' array, which is a Bignum
11077 + * rather than the internal bigendian format. Quotient parts are shifted
11078 + * left by `qshift' before adding into quot.
11079 + */
11080 +static void internal_mod(BignumInt *a, int alen,
11081 + BignumInt *m, int mlen,
11082 + BignumInt *quot, int qshift)
11083 +{
11084 + BignumInt m0, m1;
11085 + unsigned int h;
11086 + int i, k;
11087 +
11088 + m0 = m[0];
11089 + if (mlen > 1)
11090 + m1 = m[1];
11091 + else
11092 + m1 = 0;
11093 +
11094 + for (i = 0; i <= alen - mlen; i++) {
11095 + BignumDblInt t;
11096 + unsigned int q, r, c, ai1;
11097 +
11098 + if (i == 0) {
11099 + h = 0;
11100 + } else {
11101 + h = a[i - 1];
11102 + a[i - 1] = 0;
11103 + }
11104 +
11105 + if (i == alen - 1)
11106 + ai1 = 0;
11107 + else
11108 + ai1 = a[i + 1];
11109 +
11110 + /* Find q = h:a[i] / m0 */
11111 + if (h >= m0) {
11112 + /*
11113 + * Special case.
11114 + *
11115 + * To illustrate it, suppose a BignumInt is 8 bits, and
11116 + * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
11117 + * our initial division will be 0xA123 / 0xA1, which
11118 + * will give a quotient of 0x100 and a divide overflow.
11119 + * However, the invariants in this division algorithm
11120 + * are not violated, since the full number A1:23:... is
11121 + * _less_ than the quotient prefix A1:B2:... and so the
11122 + * following correction loop would have sorted it out.
11123 + *
11124 + * In this situation we set q to be the largest
11125 + * quotient we _can_ stomach (0xFF, of course).
11126 + */
11127 + q = BIGNUM_INT_MASK;
11128 + } else {
11129 + /* Macro doesn't want an array subscript expression passed
11130 + * into it (see definition), so use a temporary. */
11131 + BignumInt tmplo = a[i];
11132 + DIVMOD_WORD(q, r, h, tmplo, m0);
11133 +
11134 + /* Refine our estimate of q by looking at
11135 + h:a[i]:a[i+1] / m0:m1 */
11136 + t = MUL_WORD(m1, q);
11137 + if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
11138 + q--;
11139 + t -= m1;
11140 + r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */
11141 + if (r >= (BignumDblInt) m0 &&
11142 + t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
11143 + }
11144 + }
11145 +
11146 + /* Subtract q * m from a[i...] */
11147 + c = 0;
11148 + for (k = mlen - 1; k >= 0; k--) {
11149 + t = MUL_WORD(q, m[k]);
11150 + t += c;
11151 + c = (unsigned)(t >> BIGNUM_INT_BITS);
11152 + if ((BignumInt) t > a[i + k])
11153 + c++;
11154 + a[i + k] -= (BignumInt) t;
11155 + }
11156 +
11157 + /* Add back m in case of borrow */
11158 + if (c != h) {
11159 + t = 0;
11160 + for (k = mlen - 1; k >= 0; k--) {
11161 + t += m[k];
11162 + t += a[i + k];
11163 + a[i + k] = (BignumInt) t;
11164 + t = t >> BIGNUM_INT_BITS;
11165 + }
11166 + q--;
11167 + }
11168 + if (quot)
11169 + internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
11170 + }
11171 +}
11172 +
11173 +/*
11174 + * Compute p % mod.
11175 + * The most significant word of mod MUST be non-zero.
11176 + * We assume that the result array is the same size as the mod array.
11177 + * We optionally write out a quotient if `quotient' is non-NULL.
11178 + * We can avoid writing out the result if `result' is NULL.
11179 + */
11180 +void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)
11181 +{
11182 + BignumInt *n, *m;
11183 + int mshift;
11184 + int plen, mlen, i, j;
11185 +
11186 + /* Allocate m of size mlen, copy mod to m */
11187 + /* We use big endian internally */
11188 + mlen = mod[0];
11189 + m = snewn(mem_ctx, mlen, BignumInt);
11190 + //if (!m)
11191 + //abort(); /* FIXME */
11192 + for (j = 0; j < mlen; j++)
11193 + m[j] = mod[mod[0] - j];
11194 +
11195 + /* Shift m left to make msb bit set */
11196 + for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
11197 + if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11198 + break;
11199 + if (mshift) {
11200 + for (i = 0; i < mlen - 1; i++)
11201 + m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
11202 + m[mlen - 1] = m[mlen - 1] << mshift;
11203 + }
11204 +
11205 + plen = p[0];
11206 + /* Ensure plen > mlen */
11207 + if (plen <= mlen)
11208 + plen = mlen + 1;
11209 +
11210 + /* Allocate n of size plen, copy p to n */
11211 + n = snewn(mem_ctx, plen, BignumInt);
11212 + //if (!n)
11213 + //abort(); /* FIXME */
11214 + for (j = 0; j < plen; j++)
11215 + n[j] = 0;
11216 + for (j = 1; j <= (int)p[0]; j++)
11217 + n[plen - j] = p[j];
11218 +
11219 + /* Main computation */
11220 + internal_mod(n, plen, m, mlen, quotient, mshift);
11221 +
11222 + /* Fixup result in case the modulus was shifted */
11223 + if (mshift) {
11224 + for (i = plen - mlen - 1; i < plen - 1; i++)
11225 + n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
11226 + n[plen - 1] = n[plen - 1] << mshift;
11227 + internal_mod(n, plen, m, mlen, quotient, 0);
11228 + for (i = plen - 1; i >= plen - mlen; i--)
11229 + n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
11230 + }
11231 +
11232 + /* Copy result to buffer */
11233 + if (result) {
11234 + for (i = 1; i <= (int)result[0]; i++) {
11235 + int j = plen - i;
11236 + result[i] = j >= 0 ? n[j] : 0;
11237 + }
11238 + }
11239 +
11240 + /* Free temporary arrays */
11241 + for (i = 0; i < mlen; i++)
11242 + m[i] = 0;
11243 + sfree(mem_ctx, m);
11244 + for (i = 0; i < plen; i++)
11245 + n[i] = 0;
11246 + sfree(mem_ctx, n);
11247 +}
11248 +
11249 +/*
11250 + * Simple remainder.
11251 + */
11252 +Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)
11253 +{
11254 + Bignum r = newbn(mem_ctx, b[0]);
11255 + bigdivmod(mem_ctx, a, b, r, NULL);
11256 + return r;
11257 +}
11258 +
11259 +/*
11260 + * Compute (base ^ exp) % mod.
11261 + */
11262 +Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)
11263 +{
11264 + BignumInt *a, *b, *n, *m;
11265 + int mshift;
11266 + int mlen, i, j;
11267 + Bignum base, result;
11268 +
11269 + /*
11270 + * The most significant word of mod needs to be non-zero. It
11271 + * should already be, but let's make sure.
11272 + */
11273 + //assert(mod[mod[0]] != 0);
11274 +
11275 + /*
11276 + * Make sure the base is smaller than the modulus, by reducing
11277 + * it modulo the modulus if not.
11278 + */
11279 + base = bigmod(mem_ctx, base_in, mod);
11280 +
11281 + /* Allocate m of size mlen, copy mod to m */
11282 + /* We use big endian internally */
11283 + mlen = mod[0];
11284 + m = snewn(mem_ctx, mlen, BignumInt);
11285 + //if (!m)
11286 + //abort(); /* FIXME */
11287 + for (j = 0; j < mlen; j++)
11288 + m[j] = mod[mod[0] - j];
11289 +
11290 + /* Shift m left to make msb bit set */
11291 + for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
11292 + if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11293 + break;
11294 + if (mshift) {
11295 + for (i = 0; i < mlen - 1; i++)
11296 + m[i] =
11297 + (m[i] << mshift) | (m[i + 1] >>
11298 + (BIGNUM_INT_BITS - mshift));
11299 + m[mlen - 1] = m[mlen - 1] << mshift;
11300 + }
11301 +
11302 + /* Allocate n of size mlen, copy base to n */
11303 + n = snewn(mem_ctx, mlen, BignumInt);
11304 + //if (!n)
11305 + //abort(); /* FIXME */
11306 + i = mlen - base[0];
11307 + for (j = 0; j < i; j++)
11308 + n[j] = 0;
11309 + for (j = 0; j < base[0]; j++)
11310 + n[i + j] = base[base[0] - j];
11311 +
11312 + /* Allocate a and b of size 2*mlen. Set a = 1 */
11313 + a = snewn(mem_ctx, 2 * mlen, BignumInt);
11314 + //if (!a)
11315 + //abort(); /* FIXME */
11316 + b = snewn(mem_ctx, 2 * mlen, BignumInt);
11317 + //if (!b)
11318 + //abort(); /* FIXME */
11319 + for (i = 0; i < 2 * mlen; i++)
11320 + a[i] = 0;
11321 + a[2 * mlen - 1] = 1;
11322 +
11323 + /* Skip leading zero bits of exp. */
11324 + i = 0;
11325 + j = BIGNUM_INT_BITS - 1;
11326 + while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
11327 + j--;
11328 + if (j < 0) {
11329 + i++;
11330 + j = BIGNUM_INT_BITS - 1;
11331 + }
11332 + }
11333 +
11334 + /* Main computation */
11335 + while (i < exp[0]) {
11336 + while (j >= 0) {
11337 + internal_mul(a + mlen, a + mlen, b, mlen);
11338 + internal_mod(b, mlen * 2, m, mlen, NULL, 0);
11339 + if ((exp[exp[0] - i] & (1 << j)) != 0) {
11340 + internal_mul(b + mlen, n, a, mlen);
11341 + internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11342 + } else {
11343 + BignumInt *t;
11344 + t = a;
11345 + a = b;
11346 + b = t;
11347 + }
11348 + j--;
11349 + }
11350 + i++;
11351 + j = BIGNUM_INT_BITS - 1;
11352 + }
11353 +
11354 + /* Fixup result in case the modulus was shifted */
11355 + if (mshift) {
11356 + for (i = mlen - 1; i < 2 * mlen - 1; i++)
11357 + a[i] =
11358 + (a[i] << mshift) | (a[i + 1] >>
11359 + (BIGNUM_INT_BITS - mshift));
11360 + a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
11361 + internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11362 + for (i = 2 * mlen - 1; i >= mlen; i--)
11363 + a[i] =
11364 + (a[i] >> mshift) | (a[i - 1] <<
11365 + (BIGNUM_INT_BITS - mshift));
11366 + }
11367 +
11368 + /* Copy result to buffer */
11369 + result = newbn(mem_ctx, mod[0]);
11370 + for (i = 0; i < mlen; i++)
11371 + result[result[0] - i] = a[i + mlen];
11372 + while (result[0] > 1 && result[result[0]] == 0)
11373 + result[0]--;
11374 +
11375 + /* Free temporary arrays */
11376 + for (i = 0; i < 2 * mlen; i++)
11377 + a[i] = 0;
11378 + sfree(mem_ctx, a);
11379 + for (i = 0; i < 2 * mlen; i++)
11380 + b[i] = 0;
11381 + sfree(mem_ctx, b);
11382 + for (i = 0; i < mlen; i++)
11383 + m[i] = 0;
11384 + sfree(mem_ctx, m);
11385 + for (i = 0; i < mlen; i++)
11386 + n[i] = 0;
11387 + sfree(mem_ctx, n);
11388 +
11389 + freebn(mem_ctx, base);
11390 +
11391 + return result;
11392 +}
11393 +
11394 +
11395 +#ifdef UNITTEST
11396 +
11397 +static __u32 dh_p[] = {
11398 + 96,
11399 + 0xFFFFFFFF,
11400 + 0xFFFFFFFF,
11401 + 0xA93AD2CA,
11402 + 0x4B82D120,
11403 + 0xE0FD108E,
11404 + 0x43DB5BFC,
11405 + 0x74E5AB31,
11406 + 0x08E24FA0,
11407 + 0xBAD946E2,
11408 + 0x770988C0,
11409 + 0x7A615D6C,
11410 + 0xBBE11757,
11411 + 0x177B200C,
11412 + 0x521F2B18,
11413 + 0x3EC86A64,
11414 + 0xD8760273,
11415 + 0xD98A0864,
11416 + 0xF12FFA06,
11417 + 0x1AD2EE6B,
11418 + 0xCEE3D226,
11419 + 0x4A25619D,
11420 + 0x1E8C94E0,
11421 + 0xDB0933D7,
11422 + 0xABF5AE8C,
11423 + 0xA6E1E4C7,
11424 + 0xB3970F85,
11425 + 0x5D060C7D,
11426 + 0x8AEA7157,
11427 + 0x58DBEF0A,
11428 + 0xECFB8504,
11429 + 0xDF1CBA64,
11430 + 0xA85521AB,
11431 + 0x04507A33,
11432 + 0xAD33170D,
11433 + 0x8AAAC42D,
11434 + 0x15728E5A,
11435 + 0x98FA0510,
11436 + 0x15D22618,
11437 + 0xEA956AE5,
11438 + 0x3995497C,
11439 + 0x95581718,
11440 + 0xDE2BCBF6,
11441 + 0x6F4C52C9,
11442 + 0xB5C55DF0,
11443 + 0xEC07A28F,
11444 + 0x9B2783A2,
11445 + 0x180E8603,
11446 + 0xE39E772C,
11447 + 0x2E36CE3B,
11448 + 0x32905E46,
11449 + 0xCA18217C,
11450 + 0xF1746C08,
11451 + 0x4ABC9804,
11452 + 0x670C354E,
11453 + 0x7096966D,
11454 + 0x9ED52907,
11455 + 0x208552BB,
11456 + 0x1C62F356,
11457 + 0xDCA3AD96,
11458 + 0x83655D23,
11459 + 0xFD24CF5F,
11460 + 0x69163FA8,
11461 + 0x1C55D39A,
11462 + 0x98DA4836,
11463 + 0xA163BF05,
11464 + 0xC2007CB8,
11465 + 0xECE45B3D,
11466 + 0x49286651,
11467 + 0x7C4B1FE6,
11468 + 0xAE9F2411,
11469 + 0x5A899FA5,
11470 + 0xEE386BFB,
11471 + 0xF406B7ED,
11472 + 0x0BFF5CB6,
11473 + 0xA637ED6B,
11474 + 0xF44C42E9,
11475 + 0x625E7EC6,
11476 + 0xE485B576,
11477 + 0x6D51C245,
11478 + 0x4FE1356D,
11479 + 0xF25F1437,
11480 + 0x302B0A6D,
11481 + 0xCD3A431B,
11482 + 0xEF9519B3,
11483 + 0x8E3404DD,
11484 + 0x514A0879,
11485 + 0x3B139B22,
11486 + 0x020BBEA6,
11487 + 0x8A67CC74,
11488 + 0x29024E08,
11489 + 0x80DC1CD1,
11490 + 0xC4C6628B,
11491 + 0x2168C234,
11492 + 0xC90FDAA2,
11493 + 0xFFFFFFFF,
11494 + 0xFFFFFFFF,
11495 +};
11496 +
11497 +static __u32 dh_a[] = {
11498 + 8,
11499 + 0xdf367516,
11500 + 0x86459caa,
11501 + 0xe2d459a4,
11502 + 0xd910dae0,
11503 + 0x8a8b5e37,
11504 + 0x67ab31c6,
11505 + 0xf0b55ea9,
11506 + 0x440051d6,
11507 +};
11508 +
11509 +static __u32 dh_b[] = {
11510 + 8,
11511 + 0xded92656,
11512 + 0xe07a048a,
11513 + 0x6fa452cd,
11514 + 0x2df89d30,
11515 + 0xc75f1b0f,
11516 + 0x8ce3578f,
11517 + 0x7980a324,
11518 + 0x5daec786,
11519 +};
11520 +
11521 +static __u32 dh_g[] = {
11522 + 1,
11523 + 2,
11524 +};
11525 +
11526 +int main(void)
11527 +{
11528 + int i;
11529 + __u32 *k;
11530 + k = dwc_modpow(NULL, dh_g, dh_a, dh_p);
11531 +
11532 + printf("\n\n");
11533 + for (i=0; i<k[0]; i++) {
11534 + __u32 word32 = k[k[0] - i];
11535 + __u16 l = word32 & 0xffff;
11536 + __u16 m = (word32 & 0xffff0000) >> 16;
11537 + printf("%04x %04x ", m, l);
11538 + if (!((i + 1)%13)) printf("\n");
11539 + }
11540 + printf("\n\n");
11541 +
11542 + if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
11543 + printf("PASS\n\n");
11544 + }
11545 + else {
11546 + printf("FAIL\n\n");
11547 + }
11548 +
11549 +}
11550 +
11551 +#endif /* UNITTEST */
11552 +
11553 +#endif /* CONFIG_MACH_IPMATE */
11554 +
11555 +#endif /*DWC_CRYPTOLIB */
11556 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_modpow.h
11557 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_modpow.h 1970-01-01 01:00:00.000000000 +0100
11558 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_modpow.h 2013-07-06 15:25:50.000000000 +0100
11559 @@ -0,0 +1,34 @@
11560 +/*
11561 + * dwc_modpow.h
11562 + * See dwc_modpow.c for license and changes
11563 + */
11564 +#ifndef _DWC_MODPOW_H
11565 +#define _DWC_MODPOW_H
11566 +
11567 +#ifdef __cplusplus
11568 +extern "C" {
11569 +#endif
11570 +
11571 +#include "dwc_os.h"
11572 +
11573 +/** @file
11574 + *
11575 + * This file defines the module exponentiation function which is only used
11576 + * internally by the DWC UWB modules for calculation of PKs during numeric
11577 + * association. The routine is taken from the PUTTY, an open source terminal
11578 + * emulator. The PUTTY License is preserved in the dwc_modpow.c file.
11579 + *
11580 + */
11581 +
11582 +typedef uint32_t BignumInt;
11583 +typedef uint64_t BignumDblInt;
11584 +typedef BignumInt *Bignum;
11585 +
11586 +/* Compute modular exponentiaion */
11587 +extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);
11588 +
11589 +#ifdef __cplusplus
11590 +}
11591 +#endif
11592 +
11593 +#endif /* _LINUX_BIGNUM_H */
11594 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_notifier.c
11595 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100
11596 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_notifier.c 2013-07-06 15:25:50.000000000 +0100
11597 @@ -0,0 +1,319 @@
11598 +#ifdef DWC_NOTIFYLIB
11599 +
11600 +#include "dwc_notifier.h"
11601 +#include "dwc_list.h"
11602 +
11603 +typedef struct dwc_observer {
11604 + void *observer;
11605 + dwc_notifier_callback_t callback;
11606 + void *data;
11607 + char *notification;
11608 + DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
11609 +} observer_t;
11610 +
11611 +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
11612 +
11613 +typedef struct dwc_notifier {
11614 + void *mem_ctx;
11615 + void *object;
11616 + struct observer_queue observers;
11617 + DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
11618 +} notifier_t;
11619 +
11620 +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
11621 +
11622 +typedef struct manager {
11623 + void *mem_ctx;
11624 + void *wkq_ctx;
11625 + dwc_workq_t *wq;
11626 +// dwc_mutex_t *mutex;
11627 + struct notifier_queue notifiers;
11628 +} manager_t;
11629 +
11630 +static manager_t *manager = NULL;
11631 +
11632 +static int create_manager(void *mem_ctx, void *wkq_ctx)
11633 +{
11634 + manager = dwc_alloc(mem_ctx, sizeof(manager_t));
11635 + if (!manager) {
11636 + return -DWC_E_NO_MEMORY;
11637 + }
11638 +
11639 + DWC_CIRCLEQ_INIT(&manager->notifiers);
11640 +
11641 + manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");
11642 + if (!manager->wq) {
11643 + return -DWC_E_NO_MEMORY;
11644 + }
11645 +
11646 + return 0;
11647 +}
11648 +
11649 +static void free_manager(void)
11650 +{
11651 + dwc_workq_free(manager->wq);
11652 +
11653 + /* All notifiers must have unregistered themselves before this module
11654 + * can be removed. Hitting this assertion indicates a programmer
11655 + * error. */
11656 + DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),
11657 + "Notification manager being freed before all notifiers have been removed");
11658 + dwc_free(manager->mem_ctx, manager);
11659 +}
11660 +
11661 +#ifdef DEBUG
11662 +static void dump_manager(void)
11663 +{
11664 + notifier_t *n;
11665 + observer_t *o;
11666 +
11667 + DWC_ASSERT(manager, "Notification manager not found");
11668 +
11669 + DWC_DEBUG("List of all notifiers and observers:\n");
11670 + DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
11671 + DWC_DEBUG("Notifier %p has observers:\n", n->object);
11672 + DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
11673 + DWC_DEBUG(" %p watching %s\n", o->observer, o->notification);
11674 + }
11675 + }
11676 +}
11677 +#else
11678 +#define dump_manager(...)
11679 +#endif
11680 +
11681 +static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,
11682 + dwc_notifier_callback_t callback, void *data)
11683 +{
11684 + observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));
11685 +
11686 + if (!new_observer) {
11687 + return NULL;
11688 + }
11689 +
11690 + DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
11691 + new_observer->observer = observer;
11692 + new_observer->notification = notification;
11693 + new_observer->callback = callback;
11694 + new_observer->data = data;
11695 + return new_observer;
11696 +}
11697 +
11698 +static void free_observer(void *mem_ctx, observer_t *observer)
11699 +{
11700 + dwc_free(mem_ctx, observer);
11701 +}
11702 +
11703 +static notifier_t *alloc_notifier(void *mem_ctx, void *object)
11704 +{
11705 + notifier_t *notifier;
11706 +
11707 + if (!object) {
11708 + return NULL;
11709 + }
11710 +
11711 + notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));
11712 + if (!notifier) {
11713 + return NULL;
11714 + }
11715 +
11716 + DWC_CIRCLEQ_INIT(&notifier->observers);
11717 + DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
11718 +
11719 + notifier->mem_ctx = mem_ctx;
11720 + notifier->object = object;
11721 + return notifier;
11722 +}
11723 +
11724 +static void free_notifier(notifier_t *notifier)
11725 +{
11726 + observer_t *observer;
11727 +
11728 + DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
11729 + free_observer(notifier->mem_ctx, observer);
11730 + }
11731 +
11732 + dwc_free(notifier->mem_ctx, notifier);
11733 +}
11734 +
11735 +static notifier_t *find_notifier(void *object)
11736 +{
11737 + notifier_t *notifier;
11738 +
11739 + DWC_ASSERT(manager, "Notification manager not found");
11740 +
11741 + if (!object) {
11742 + return NULL;
11743 + }
11744 +
11745 + DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
11746 + if (notifier->object == object) {
11747 + return notifier;
11748 + }
11749 + }
11750 +
11751 + return NULL;
11752 +}
11753 +
11754 +int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)
11755 +{
11756 + return create_manager(mem_ctx, wkq_ctx);
11757 +}
11758 +
11759 +void dwc_free_notification_manager(void)
11760 +{
11761 + free_manager();
11762 +}
11763 +
11764 +dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)
11765 +{
11766 + notifier_t *notifier;
11767 +
11768 + DWC_ASSERT(manager, "Notification manager not found");
11769 +
11770 + notifier = find_notifier(object);
11771 + if (notifier) {
11772 + DWC_ERROR("Notifier %p is already registered\n", object);
11773 + return NULL;
11774 + }
11775 +
11776 + notifier = alloc_notifier(mem_ctx, object);
11777 + if (!notifier) {
11778 + return NULL;
11779 + }
11780 +
11781 + DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
11782 +
11783 + DWC_INFO("Notifier %p registered", object);
11784 + dump_manager();
11785 +
11786 + return notifier;
11787 +}
11788 +
11789 +void dwc_unregister_notifier(dwc_notifier_t *notifier)
11790 +{
11791 + DWC_ASSERT(manager, "Notification manager not found");
11792 +
11793 + if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
11794 + observer_t *o;
11795 +
11796 + DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);
11797 + DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
11798 + DWC_DEBUGC(" %p watching %s\n", o->observer, o->notification);
11799 + }
11800 +
11801 + DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers),
11802 + "Notifier %p has active observers when removing", notifier);
11803 + }
11804 +
11805 + DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
11806 + free_notifier(notifier);
11807 +
11808 + DWC_INFO("Notifier unregistered");
11809 + dump_manager();
11810 +}
11811 +
11812 +/* Add an observer to observe the notifier for a particular state, event, or notification. */
11813 +int dwc_add_observer(void *observer, void *object, char *notification,
11814 + dwc_notifier_callback_t callback, void *data)
11815 +{
11816 + notifier_t *notifier = find_notifier(object);
11817 + observer_t *new_observer;
11818 +
11819 + if (!notifier) {
11820 + DWC_ERROR("Notifier %p is not found when adding observer\n", object);
11821 + return -DWC_E_INVALID;
11822 + }
11823 +
11824 + new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);
11825 + if (!new_observer) {
11826 + return -DWC_E_NO_MEMORY;
11827 + }
11828 +
11829 + DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
11830 +
11831 + DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
11832 + observer, object, notification, callback, data);
11833 +
11834 + dump_manager();
11835 + return 0;
11836 +}
11837 +
11838 +int dwc_remove_observer(void *observer)
11839 +{
11840 + notifier_t *n;
11841 +
11842 + DWC_ASSERT(manager, "Notification manager not found");
11843 +
11844 + DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
11845 + observer_t *o;
11846 + observer_t *o2;
11847 +
11848 + DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
11849 + if (o->observer == observer) {
11850 + DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
11851 + DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
11852 + o->observer, n->object, o->notification);
11853 + free_observer(n->mem_ctx, o);
11854 + }
11855 + }
11856 + }
11857 +
11858 + dump_manager();
11859 + return 0;
11860 +}
11861 +
11862 +typedef struct callback_data {
11863 + void *mem_ctx;
11864 + dwc_notifier_callback_t cb;
11865 + void *observer;
11866 + void *data;
11867 + void *object;
11868 + char *notification;
11869 + void *notification_data;
11870 +} cb_data_t;
11871 +
11872 +static void cb_task(void *data)
11873 +{
11874 + cb_data_t *cb = (cb_data_t *)data;
11875 +
11876 + cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
11877 + dwc_free(cb->mem_ctx, cb);
11878 +}
11879 +
11880 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
11881 +{
11882 + observer_t *o;
11883 +
11884 + DWC_ASSERT(manager, "Notification manager not found");
11885 +
11886 + DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
11887 + int len = DWC_STRLEN(notification);
11888 +
11889 + if (DWC_STRLEN(o->notification) != len) {
11890 + continue;
11891 + }
11892 +
11893 + if (DWC_STRNCMP(o->notification, notification, len) == 0) {
11894 + cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));
11895 +
11896 + if (!cb_data) {
11897 + DWC_ERROR("Failed to allocate callback data\n");
11898 + return;
11899 + }
11900 +
11901 + cb_data->mem_ctx = notifier->mem_ctx;
11902 + cb_data->cb = o->callback;
11903 + cb_data->observer = o->observer;
11904 + cb_data->data = o->data;
11905 + cb_data->object = notifier->object;
11906 + cb_data->notification = notification;
11907 + cb_data->notification_data = notification_data;
11908 + DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);
11909 + DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
11910 + "Notify callback from %p for Notification %s, to observer %p",
11911 + cb_data->object, notification, cb_data->observer);
11912 + }
11913 + }
11914 +}
11915 +
11916 +#endif /* DWC_NOTIFYLIB */
11917 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_notifier.h
11918 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100
11919 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_notifier.h 2013-07-06 15:25:50.000000000 +0100
11920 @@ -0,0 +1,122 @@
11921 +
11922 +#ifndef __DWC_NOTIFIER_H__
11923 +#define __DWC_NOTIFIER_H__
11924 +
11925 +#ifdef __cplusplus
11926 +extern "C" {
11927 +#endif
11928 +
11929 +#include "dwc_os.h"
11930 +
11931 +/** @file
11932 + *
11933 + * A simple implementation of the Observer pattern. Any "module" can
11934 + * register as an observer or notifier. The notion of "module" is abstract and
11935 + * can mean anything used to identify either an observer or notifier. Usually
11936 + * it will be a pointer to a data structure which contains some state, ie an
11937 + * object.
11938 + *
11939 + * Before any notifiers can be added, the global notification manager must be
11940 + * brought up with dwc_alloc_notification_manager().
11941 + * dwc_free_notification_manager() will bring it down and free all resources.
11942 + * These would typically be called upon module load and unload. The
11943 + * notification manager is a single global instance that handles all registered
11944 + * observable modules and observers so this should be done only once.
11945 + *
11946 + * A module can be observable by using Notifications to publicize some general
11947 + * information about it's state or operation. It does not care who listens, or
11948 + * even if anyone listens, or what they do with the information. The observable
11949 + * modules do not need to know any information about it's observers or their
11950 + * interface, or their state or data.
11951 + *
11952 + * Any module can register to emit Notifications. It should publish a list of
11953 + * notifications that it can emit and their behavior, such as when they will get
11954 + * triggered, and what information will be provided to the observer. Then it
11955 + * should register itself as an observable module. See dwc_register_notifier().
11956 + *
11957 + * Any module can observe any observable, registered module, provided it has a
11958 + * handle to the other module and knows what notifications to observe. See
11959 + * dwc_add_observer().
11960 + *
11961 + * A function of type dwc_notifier_callback_t is called whenever a notification
11962 + * is triggered with one or more observers observing it. This function is
11963 + * called in it's own process so it may sleep or block if needed. It is
11964 + * guaranteed to be called sometime after the notification has occurred and will
11965 + * be called once per each time the notification is triggered. It will NOT be
11966 + * called in the same process context used to trigger the notification.
11967 + *
11968 + * @section Limitiations
11969 + *
11970 + * Keep in mind that Notifications that can be triggered in rapid sucession may
11971 + * schedule too many processes too handle. Be aware of this limitation when
11972 + * designing to use notifications, and only add notifications for appropriate
11973 + * observable information.
11974 + *
11975 + * Also Notification callbacks are not synchronous. If you need to synchronize
11976 + * the behavior between module/observer you must use other means. And perhaps
11977 + * that will mean Notifications are not the proper solution.
11978 + */
11979 +
11980 +struct dwc_notifier;
11981 +typedef struct dwc_notifier dwc_notifier_t;
11982 +
11983 +/** The callback function must be of this type.
11984 + *
11985 + * @param object This is the object that is being observed.
11986 + * @param notification This is the notification that was triggered.
11987 + * @param observer This is the observer
11988 + * @param notification_data This is notification-specific data that the notifier
11989 + * has included in this notification. The value of this should be published in
11990 + * the documentation of the observable module with the notifications.
11991 + * @param user_data This is any custom data that the observer provided when
11992 + * adding itself as an observer to the notification. */
11993 +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
11994 + void *notification_data, void *user_data);
11995 +
11996 +/** Brings up the notification manager. */
11997 +extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
11998 +/** Brings down the notification manager. */
11999 +extern void dwc_free_notification_manager(void);
12000 +
12001 +/** This function registers an observable module. A dwc_notifier_t object is
12002 + * returned to the observable module. This is an opaque object that is used by
12003 + * the observable module to trigger notifications. This object should only be
12004 + * accessible to functions that are authorized to trigger notifications for this
12005 + * module. Observers do not need this object. */
12006 +extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
12007 +
12008 +/** This function unregisters an observable module. All observers have to be
12009 + * removed prior to unregistration. */
12010 +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
12011 +
12012 +/** Add a module as an observer to the observable module. The observable module
12013 + * needs to have previously registered with the notification manager.
12014 + *
12015 + * @param observer The observer module
12016 + * @param object The module to observe
12017 + * @param notification The notification to observe
12018 + * @param callback The callback function to call
12019 + * @param user_data Any additional user data to pass into the callback function */
12020 +extern int dwc_add_observer(void *observer, void *object, char *notification,
12021 + dwc_notifier_callback_t callback, void *user_data);
12022 +
12023 +/** Removes the specified observer from all notifications that it is currently
12024 + * observing. */
12025 +extern int dwc_remove_observer(void *observer);
12026 +
12027 +/** This function triggers a Notification. It should be called by the
12028 + * observable module, or any module or library which the observable module
12029 + * allows to trigger notification on it's behalf. Such as the dwc_cc_t.
12030 + *
12031 + * dwc_notify is a non-blocking function. Callbacks are scheduled called in
12032 + * their own process context for each trigger. Callbacks can be blocking.
12033 + * dwc_notify can be called from interrupt context if needed.
12034 + *
12035 + */
12036 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
12037 +
12038 +#ifdef __cplusplus
12039 +}
12040 +#endif
12041 +
12042 +#endif /* __DWC_NOTIFIER_H__ */
12043 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_os.h
12044 --- linux-3.10/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100
12045 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/dwc_os.h 2013-07-06 15:25:50.000000000 +0100
12046 @@ -0,0 +1,1262 @@
12047 +/* =========================================================================
12048 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
12049 + * $Revision: #14 $
12050 + * $Date: 2010/11/04 $
12051 + * $Change: 1621695 $
12052 + *
12053 + * Synopsys Portability Library Software and documentation
12054 + * (hereinafter, "Software") is an Unsupported proprietary work of
12055 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
12056 + * between Synopsys and you.
12057 + *
12058 + * The Software IS NOT an item of Licensed Software or Licensed Product
12059 + * under any End User Software License Agreement or Agreement for
12060 + * Licensed Product with Synopsys or any supplement thereto. You are
12061 + * permitted to use and redistribute this Software in source and binary
12062 + * forms, with or without modification, provided that redistributions
12063 + * of source code must retain this notice. You may not view, use,
12064 + * disclose, copy or distribute this file or any information contained
12065 + * herein except pursuant to this license grant from Synopsys. If you
12066 + * do not agree with this notice, including the disclaimer below, then
12067 + * you are not authorized to use the Software.
12068 + *
12069 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
12070 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12071 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12072 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
12073 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
12074 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
12075 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
12076 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
12077 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12078 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
12079 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12080 + * DAMAGE.
12081 + * ========================================================================= */
12082 +#ifndef _DWC_OS_H_
12083 +#define _DWC_OS_H_
12084 +
12085 +#ifdef __cplusplus
12086 +extern "C" {
12087 +#endif
12088 +
12089 +/** @file
12090 + *
12091 + * DWC portability library, low level os-wrapper functions
12092 + *
12093 + */
12094 +
12095 +/* These basic types need to be defined by some OS header file or custom header
12096 + * file for your specific target architecture.
12097 + *
12098 + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
12099 + *
12100 + * Any custom or alternate header file must be added and enabled here.
12101 + */
12102 +
12103 +#ifdef DWC_LINUX
12104 +# include <linux/types.h>
12105 +# ifdef CONFIG_DEBUG_MUTEXES
12106 +# include <linux/mutex.h>
12107 +# endif
12108 +# include <linux/errno.h>
12109 +# include <stdarg.h>
12110 +#endif
12111 +
12112 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12113 +# include <os_dep.h>
12114 +#endif
12115 +
12116 +
12117 +/** @name Primitive Types and Values */
12118 +
12119 +/** We define a boolean type for consistency. Can be either YES or NO */
12120 +typedef uint8_t dwc_bool_t;
12121 +#define YES 1
12122 +#define NO 0
12123 +
12124 +#ifdef DWC_LINUX
12125 +
12126 +/** @name Error Codes */
12127 +#define DWC_E_INVALID EINVAL
12128 +#define DWC_E_NO_MEMORY ENOMEM
12129 +#define DWC_E_NO_DEVICE ENODEV
12130 +#define DWC_E_NOT_SUPPORTED EOPNOTSUPP
12131 +#define DWC_E_TIMEOUT ETIMEDOUT
12132 +#define DWC_E_BUSY EBUSY
12133 +#define DWC_E_AGAIN EAGAIN
12134 +#define DWC_E_RESTART ERESTART
12135 +#define DWC_E_ABORT ECONNABORTED
12136 +#define DWC_E_SHUTDOWN ESHUTDOWN
12137 +#define DWC_E_NO_DATA ENODATA
12138 +#define DWC_E_DISCONNECT ECONNRESET
12139 +#define DWC_E_UNKNOWN EINVAL
12140 +#define DWC_E_NO_STREAM_RES ENOSR
12141 +#define DWC_E_COMMUNICATION ECOMM
12142 +#define DWC_E_OVERFLOW EOVERFLOW
12143 +#define DWC_E_PROTOCOL EPROTO
12144 +#define DWC_E_IN_PROGRESS EINPROGRESS
12145 +#define DWC_E_PIPE EPIPE
12146 +#define DWC_E_IO EIO
12147 +#define DWC_E_NO_SPACE ENOSPC
12148 +
12149 +#else
12150 +
12151 +/** @name Error Codes */
12152 +#define DWC_E_INVALID 1001
12153 +#define DWC_E_NO_MEMORY 1002
12154 +#define DWC_E_NO_DEVICE 1003
12155 +#define DWC_E_NOT_SUPPORTED 1004
12156 +#define DWC_E_TIMEOUT 1005
12157 +#define DWC_E_BUSY 1006
12158 +#define DWC_E_AGAIN 1007
12159 +#define DWC_E_RESTART 1008
12160 +#define DWC_E_ABORT 1009
12161 +#define DWC_E_SHUTDOWN 1010
12162 +#define DWC_E_NO_DATA 1011
12163 +#define DWC_E_DISCONNECT 2000
12164 +#define DWC_E_UNKNOWN 3000
12165 +#define DWC_E_NO_STREAM_RES 4001
12166 +#define DWC_E_COMMUNICATION 4002
12167 +#define DWC_E_OVERFLOW 4003
12168 +#define DWC_E_PROTOCOL 4004
12169 +#define DWC_E_IN_PROGRESS 4005
12170 +#define DWC_E_PIPE 4006
12171 +#define DWC_E_IO 4007
12172 +#define DWC_E_NO_SPACE 4008
12173 +
12174 +#endif
12175 +
12176 +
12177 +/** @name Tracing/Logging Functions
12178 + *
12179 + * These function provide the capability to add tracing, debugging, and error
12180 + * messages, as well exceptions as assertions. The WUDEV uses these
12181 + * extensively. These could be logged to the main console, the serial port, an
12182 + * internal buffer, etc. These functions could also be no-op if they are too
12183 + * expensive on your system. By default undefining the DEBUG macro already
12184 + * no-ops some of these functions. */
12185 +
12186 +/** Returns non-zero if in interrupt context. */
12187 +extern dwc_bool_t DWC_IN_IRQ(void);
12188 +#define dwc_in_irq DWC_IN_IRQ
12189 +
12190 +/** Returns "IRQ" if DWC_IN_IRQ is true. */
12191 +static inline char *dwc_irq(void) {
12192 + return DWC_IN_IRQ() ? "IRQ" : "";
12193 +}
12194 +
12195 +/** Returns non-zero if in bottom-half context. */
12196 +extern dwc_bool_t DWC_IN_BH(void);
12197 +#define dwc_in_bh DWC_IN_BH
12198 +
12199 +/** Returns "BH" if DWC_IN_BH is true. */
12200 +static inline char *dwc_bh(void) {
12201 + return DWC_IN_BH() ? "BH" : "";
12202 +}
12203 +
12204 +/**
12205 + * A vprintf() clone. Just call vprintf if you've got it.
12206 + */
12207 +extern void DWC_VPRINTF(char *format, va_list args);
12208 +#define dwc_vprintf DWC_VPRINTF
12209 +
12210 +/**
12211 + * A vsnprintf() clone. Just call vprintf if you've got it.
12212 + */
12213 +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
12214 +#define dwc_vsnprintf DWC_VSNPRINTF
12215 +
12216 +/**
12217 + * printf() clone. Just call printf if you've go it.
12218 + */
12219 +extern void DWC_PRINTF(char *format, ...)
12220 +/* This provides compiler level static checking of the parameters if you're
12221 + * using GCC. */
12222 +#ifdef __GNUC__
12223 + __attribute__ ((format(printf, 1, 2)));
12224 +#else
12225 + ;
12226 +#endif
12227 +#define dwc_printf DWC_PRINTF
12228 +
12229 +/**
12230 + * sprintf() clone. Just call sprintf if you've got it.
12231 + */
12232 +extern int DWC_SPRINTF(char *string, char *format, ...)
12233 +#ifdef __GNUC__
12234 + __attribute__ ((format(printf, 2, 3)));
12235 +#else
12236 + ;
12237 +#endif
12238 +#define dwc_sprintf DWC_SPRINTF
12239 +
12240 +/**
12241 + * snprintf() clone. Just call snprintf if you've got it.
12242 + */
12243 +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
12244 +#ifdef __GNUC__
12245 + __attribute__ ((format(printf, 3, 4)));
12246 +#else
12247 + ;
12248 +#endif
12249 +#define dwc_snprintf DWC_SNPRINTF
12250 +
12251 +/**
12252 + * Prints a WARNING message. On systems that don't differentiate between
12253 + * warnings and regular log messages, just print it. Indicates that something
12254 + * may be wrong with the driver. Works like printf().
12255 + *
12256 + * Use the DWC_WARN macro to call this function.
12257 + */
12258 +extern void __DWC_WARN(char *format, ...)
12259 +#ifdef __GNUC__
12260 + __attribute__ ((format(printf, 1, 2)));
12261 +#else
12262 + ;
12263 +#endif
12264 +
12265 +/**
12266 + * Prints an error message. On systems that don't differentiate between errors
12267 + * and regular log messages, just print it. Indicates that something went wrong
12268 + * with the driver. Works like printf().
12269 + *
12270 + * Use the DWC_ERROR macro to call this function.
12271 + */
12272 +extern void __DWC_ERROR(char *format, ...)
12273 +#ifdef __GNUC__
12274 + __attribute__ ((format(printf, 1, 2)));
12275 +#else
12276 + ;
12277 +#endif
12278 +
12279 +/**
12280 + * Prints an exception error message and takes some user-defined action such as
12281 + * print out a backtrace or trigger a breakpoint. Indicates that something went
12282 + * abnormally wrong with the driver such as programmer error, or other
12283 + * exceptional condition. It should not be ignored so even on systems without
12284 + * printing capability, some action should be taken to notify the developer of
12285 + * it. Works like printf().
12286 + */
12287 +extern void DWC_EXCEPTION(char *format, ...)
12288 +#ifdef __GNUC__
12289 + __attribute__ ((format(printf, 1, 2)));
12290 +#else
12291 + ;
12292 +#endif
12293 +#define dwc_exception DWC_EXCEPTION
12294 +
12295 +#ifndef DWC_OTG_DEBUG_LEV
12296 +#define DWC_OTG_DEBUG_LEV 0
12297 +#endif
12298 +
12299 +#ifdef DEBUG
12300 +/**
12301 + * Prints out a debug message. Used for logging/trace messages.
12302 + *
12303 + * Use the DWC_DEBUG macro to call this function
12304 + */
12305 +extern void __DWC_DEBUG(char *format, ...)
12306 +#ifdef __GNUC__
12307 + __attribute__ ((format(printf, 1, 2)));
12308 +#else
12309 + ;
12310 +#endif
12311 +#else
12312 +#define __DWC_DEBUG printk
12313 +#endif
12314 +
12315 +/**
12316 + * Prints out a Debug message.
12317 + */
12318 +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
12319 + __func__, dwc_irq(), ## _args)
12320 +#define dwc_debug DWC_DEBUG
12321 +/**
12322 + * Prints out a Debug message if enabled at compile time.
12323 + */
12324 +#if DWC_OTG_DEBUG_LEV > 0
12325 +#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
12326 +#else
12327 +#define DWC_DEBUGC(_format, _args...)
12328 +#endif
12329 +#define dwc_debugc DWC_DEBUGC
12330 +/**
12331 + * Prints out an informative message.
12332 + */
12333 +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
12334 + dwc_irq(), ## _args)
12335 +#define dwc_info DWC_INFO
12336 +/**
12337 + * Prints out an informative message if enabled at compile time.
12338 + */
12339 +#if DWC_OTG_DEBUG_LEV > 1
12340 +#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
12341 +#else
12342 +#define DWC_INFOC(_format, _args...)
12343 +#endif
12344 +#define dwc_infoc DWC_INFOC
12345 +/**
12346 + * Prints out a warning message.
12347 + */
12348 +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
12349 + dwc_irq(), __func__, __LINE__, ## _args)
12350 +#define dwc_warn DWC_WARN
12351 +/**
12352 + * Prints out an error message.
12353 + */
12354 +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
12355 + dwc_irq(), __func__, __LINE__, ## _args)
12356 +#define dwc_error DWC_ERROR
12357 +
12358 +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
12359 + dwc_irq(), __func__, __LINE__, ## _args)
12360 +#define dwc_proto_error DWC_PROTO_ERROR
12361 +
12362 +#ifdef DEBUG
12363 +/** Prints out a exception error message if the _expr expression fails. Disabled
12364 + * if DEBUG is not enabled. */
12365 +#define DWC_ASSERT(_expr, _format, _args...) do { \
12366 + if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
12367 + __FILE__, __LINE__, ## _args); } \
12368 + } while (0)
12369 +#else
12370 +#define DWC_ASSERT(_x...)
12371 +#endif
12372 +#define dwc_assert DWC_ASSERT
12373 +
12374 +
12375 +/** @name Byte Ordering
12376 + * The following functions are for conversions between processor's byte ordering
12377 + * and specific ordering you want.
12378 + */
12379 +
12380 +/** Converts 32 bit data in CPU byte ordering to little endian. */
12381 +extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
12382 +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
12383 +
12384 +/** Converts 32 bit data in CPU byte orderint to big endian. */
12385 +extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
12386 +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
12387 +
12388 +/** Converts 32 bit little endian data to CPU byte ordering. */
12389 +extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
12390 +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
12391 +
12392 +/** Converts 32 bit big endian data to CPU byte ordering. */
12393 +extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
12394 +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
12395 +
12396 +/** Converts 16 bit data in CPU byte ordering to little endian. */
12397 +extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
12398 +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
12399 +
12400 +/** Converts 16 bit data in CPU byte orderint to big endian. */
12401 +extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
12402 +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
12403 +
12404 +/** Converts 16 bit little endian data to CPU byte ordering. */
12405 +extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
12406 +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
12407 +
12408 +/** Converts 16 bit bi endian data to CPU byte ordering. */
12409 +extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
12410 +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
12411 +
12412 +
12413 +/** @name Register Read/Write
12414 + *
12415 + * The following six functions should be implemented to read/write registers of
12416 + * 32-bit and 64-bit sizes. All modules use this to read/write register values.
12417 + * The reg value is a pointer to the register calculated from the void *base
12418 + * variable passed into the driver when it is started. */
12419 +
12420 +#ifdef DWC_LINUX
12421 +/* Linux doesn't need any extra parameters for register read/write, so we
12422 + * just throw away the IO context parameter.
12423 + */
12424 +/** Reads the content of a 32-bit register. */
12425 +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
12426 +#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
12427 +
12428 +/** Reads the content of a 64-bit register. */
12429 +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
12430 +#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
12431 +
12432 +/** Writes to a 32-bit register. */
12433 +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
12434 +#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
12435 +
12436 +/** Writes to a 64-bit register. */
12437 +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
12438 +#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
12439 +
12440 +/**
12441 + * Modify bit values in a register. Using the
12442 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12443 + */
12444 +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12445 +#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
12446 +extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12447 +#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
12448 +
12449 +#endif /* DWC_LINUX */
12450 +
12451 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12452 +typedef struct dwc_ioctx {
12453 + struct device *dev;
12454 + bus_space_tag_t iot;
12455 + bus_space_handle_t ioh;
12456 +} dwc_ioctx_t;
12457 +
12458 +/** BSD needs two extra parameters for register read/write, so we pass
12459 + * them in using the IO context parameter.
12460 + */
12461 +/** Reads the content of a 32-bit register. */
12462 +extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
12463 +#define dwc_read_reg32 DWC_READ_REG32
12464 +
12465 +/** Reads the content of a 64-bit register. */
12466 +extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
12467 +#define dwc_read_reg64 DWC_READ_REG64
12468 +
12469 +/** Writes to a 32-bit register. */
12470 +extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
12471 +#define dwc_write_reg32 DWC_WRITE_REG32
12472 +
12473 +/** Writes to a 64-bit register. */
12474 +extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
12475 +#define dwc_write_reg64 DWC_WRITE_REG64
12476 +
12477 +/**
12478 + * Modify bit values in a register. Using the
12479 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12480 + */
12481 +extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12482 +#define dwc_modify_reg32 DWC_MODIFY_REG32
12483 +extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12484 +#define dwc_modify_reg64 DWC_MODIFY_REG64
12485 +
12486 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12487 +
12488 +/** @cond */
12489 +
12490 +/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the
12491 + * register writes. */
12492 +
12493 +#ifdef DWC_LINUX
12494 +
12495 +# ifdef DWC_DEBUG_REGS
12496 +
12497 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12498 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12499 + return DWC_READ_REG32(&container->regs->_reg[num]); \
12500 +} \
12501 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12502 + DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12503 + &(((uint32_t*)container->regs->_reg)[num]), data); \
12504 + DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12505 +}
12506 +
12507 +#define dwc_define_read_write_reg(_reg,_container_type) \
12508 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12509 + return DWC_READ_REG32(&container->regs->_reg); \
12510 +} \
12511 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12512 + DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12513 + DWC_WRITE_REG32(&container->regs->_reg, data); \
12514 +}
12515 +
12516 +# else /* DWC_DEBUG_REGS */
12517 +
12518 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12519 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12520 + return DWC_READ_REG32(&container->regs->_reg[num]); \
12521 +} \
12522 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12523 + DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12524 +}
12525 +
12526 +#define dwc_define_read_write_reg(_reg,_container_type) \
12527 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12528 + return DWC_READ_REG32(&container->regs->_reg); \
12529 +} \
12530 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12531 + DWC_WRITE_REG32(&container->regs->_reg, data); \
12532 +}
12533 +
12534 +# endif /* DWC_DEBUG_REGS */
12535 +
12536 +#endif /* DWC_LINUX */
12537 +
12538 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12539 +
12540 +# ifdef DWC_DEBUG_REGS
12541 +
12542 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12543 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12544 + return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12545 +} \
12546 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12547 + DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12548 + &(((uint32_t*)container->regs->_reg)[num]), data); \
12549 + DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12550 +}
12551 +
12552 +#define dwc_define_read_write_reg(_reg,_container_type) \
12553 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12554 + return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12555 +} \
12556 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12557 + DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12558 + DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12559 +}
12560 +
12561 +# else /* DWC_DEBUG_REGS */
12562 +
12563 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12564 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12565 + return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12566 +} \
12567 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12568 + DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12569 +}
12570 +
12571 +#define dwc_define_read_write_reg(_reg,_container_type) \
12572 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12573 + return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12574 +} \
12575 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12576 + DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12577 +}
12578 +
12579 +# endif /* DWC_DEBUG_REGS */
12580 +
12581 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12582 +
12583 +/** @endcond */
12584 +
12585 +
12586 +#ifdef DWC_CRYPTOLIB
12587 +/** @name Crypto Functions
12588 + *
12589 + * These are the low-level cryptographic functions used by the driver. */
12590 +
12591 +/** Perform AES CBC */
12592 +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
12593 +#define dwc_aes_cbc DWC_AES_CBC
12594 +
12595 +/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */
12596 +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
12597 +#define dwc_random_bytes DWC_RANDOM_BYTES
12598 +
12599 +/** Perform the SHA-256 hash function */
12600 +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
12601 +#define dwc_sha256 DWC_SHA256
12602 +
12603 +/** Calculated the HMAC-SHA256 */
12604 +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
12605 +#define dwc_hmac_sha256 DWC_HMAC_SHA256
12606 +
12607 +#endif /* DWC_CRYPTOLIB */
12608 +
12609 +
12610 +/** @name Memory Allocation
12611 + *
12612 + * These function provide access to memory allocation. There are only 2 DMA
12613 + * functions and 3 Regular memory functions that need to be implemented. None
12614 + * of the memory debugging routines need to be implemented. The allocation
12615 + * routines all ZERO the contents of the memory.
12616 + *
12617 + * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
12618 + * This checks for memory leaks, keeping track of alloc/free pairs. It also
12619 + * keeps track of how much memory the driver is using at any given time. */
12620 +
12621 +#define DWC_PAGE_SIZE 4096
12622 +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
12623 +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
12624 +
12625 +#define DWC_INVALID_DMA_ADDR 0x0
12626 +
12627 +#ifdef DWC_LINUX
12628 +/** Type for a DMA address */
12629 +typedef dma_addr_t dwc_dma_t;
12630 +#endif
12631 +
12632 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12633 +typedef bus_addr_t dwc_dma_t;
12634 +#endif
12635 +
12636 +#ifdef DWC_FREEBSD
12637 +typedef struct dwc_dmactx {
12638 + struct device *dev;
12639 + bus_dma_tag_t dma_tag;
12640 + bus_dmamap_t dma_map;
12641 + bus_addr_t dma_paddr;
12642 + void *dma_vaddr;
12643 +} dwc_dmactx_t;
12644 +#endif
12645 +
12646 +#ifdef DWC_NETBSD
12647 +typedef struct dwc_dmactx {
12648 + struct device *dev;
12649 + bus_dma_tag_t dma_tag;
12650 + bus_dmamap_t dma_map;
12651 + bus_dma_segment_t segs[1];
12652 + int nsegs;
12653 + bus_addr_t dma_paddr;
12654 + void *dma_vaddr;
12655 +} dwc_dmactx_t;
12656 +#endif
12657 +
12658 +/* @todo these functions will be added in the future */
12659 +#if 0
12660 +/**
12661 + * Creates a DMA pool from which you can allocate DMA buffers. Buffers
12662 + * allocated from this pool will be guaranteed to meet the size, alignment, and
12663 + * boundary requirements specified.
12664 + *
12665 + * @param[in] size Specifies the size of the buffers that will be allocated from
12666 + * this pool.
12667 + * @param[in] align Specifies the byte alignment requirements of the buffers
12668 + * allocated from this pool. Must be a power of 2.
12669 + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
12670 + * this pool must not cross.
12671 + *
12672 + * @returns A pointer to an internal opaque structure which is not to be
12673 + * accessed outside of these library functions. Use this handle to specify
12674 + * which pools to allocate/free DMA buffers from and also to destroy the pool,
12675 + * when you are done with it.
12676 + */
12677 +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
12678 +
12679 +/**
12680 + * Destroy a DMA pool. All buffers allocated from that pool must be freed first.
12681 + */
12682 +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
12683 +
12684 +/**
12685 + * Allocate a buffer from the specified DMA pool and zeros its contents.
12686 + */
12687 +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
12688 +
12689 +/**
12690 + * Free a previously allocated buffer from the DMA pool.
12691 + */
12692 +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
12693 +#endif
12694 +
12695 +/** Allocates a DMA capable buffer and zeroes its contents. */
12696 +extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
12697 +
12698 +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
12699 +extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
12700 +
12701 +/** Frees a previously allocated buffer. */
12702 +extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
12703 +
12704 +/** Allocates a block of memory and zeroes its contents. */
12705 +extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
12706 +
12707 +/** Allocates a block of memory and zeroes its contents, in an atomic manner
12708 + * which can be used inside interrupt context. The size should be sufficiently
12709 + * small, a few KB at most, such that failures are not likely to occur. Can just call
12710 + * __DWC_ALLOC if it is atomic. */
12711 +extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
12712 +
12713 +/** Frees a previously allocated buffer. */
12714 +extern void __DWC_FREE(void *mem_ctx, void *addr);
12715 +
12716 +#ifndef DWC_DEBUG_MEMORY
12717 +
12718 +#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
12719 +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
12720 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
12721 +
12722 +# ifdef DWC_LINUX
12723 +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)
12724 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)
12725 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)
12726 +# endif
12727 +
12728 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12729 +#define DWC_DMA_ALLOC __DWC_DMA_ALLOC
12730 +#define DWC_DMA_FREE __DWC_DMA_FREE
12731 +# endif
12732 +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
12733 +
12734 +#else /* DWC_DEBUG_MEMORY */
12735 +
12736 +extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
12737 +extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
12738 +extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
12739 +extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
12740 + char const *func, int line);
12741 +extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
12742 + char const *func, int line);
12743 +extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
12744 + dwc_dma_t dma_addr, char const *func, int line);
12745 +
12746 +extern int dwc_memory_debug_start(void *mem_ctx);
12747 +extern void dwc_memory_debug_stop(void);
12748 +extern void dwc_memory_debug_report(void);
12749 +
12750 +#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
12751 +#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
12752 + __func__, __LINE__)
12753 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
12754 +
12755 +# ifdef DWC_LINUX
12756 +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \
12757 + _dma_, __func__, __LINE__)
12758 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \
12759 + _dma_, __func__, __LINE__)
12760 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \
12761 + _virt_, _dma_, __func__, __LINE__)
12762 +# endif
12763 +
12764 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12765 +#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
12766 + _dma_, __func__, __LINE__)
12767 +#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
12768 + _virt_, _dma_, __func__, __LINE__)
12769 +# endif
12770 +
12771 +#endif /* DWC_DEBUG_MEMORY */
12772 +
12773 +#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
12774 +#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
12775 +#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
12776 +
12777 +#ifdef DWC_LINUX
12778 +/* Linux doesn't need any extra parameters for DMA buffer allocation, so we
12779 + * just throw away the DMA context parameter.
12780 + */
12781 +#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
12782 +#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
12783 +#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
12784 +#endif
12785 +
12786 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12787 +/** BSD needs several extra parameters for DMA buffer allocation, so we pass
12788 + * them in using the DMA context parameter.
12789 + */
12790 +#define dwc_dma_alloc DWC_DMA_ALLOC
12791 +#define dwc_dma_free DWC_DMA_FREE
12792 +#endif
12793 +
12794 +
12795 +/** @name Memory and String Processing */
12796 +
12797 +/** memset() clone */
12798 +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
12799 +#define dwc_memset DWC_MEMSET
12800 +
12801 +/** memcpy() clone */
12802 +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
12803 +#define dwc_memcpy DWC_MEMCPY
12804 +
12805 +/** memmove() clone */
12806 +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
12807 +#define dwc_memmove DWC_MEMMOVE
12808 +
12809 +/** memcmp() clone */
12810 +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
12811 +#define dwc_memcmp DWC_MEMCMP
12812 +
12813 +/** strcmp() clone */
12814 +extern int DWC_STRCMP(void *s1, void *s2);
12815 +#define dwc_strcmp DWC_STRCMP
12816 +
12817 +/** strncmp() clone */
12818 +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
12819 +#define dwc_strncmp DWC_STRNCMP
12820 +
12821 +/** strlen() clone, for NULL terminated ASCII strings */
12822 +extern int DWC_STRLEN(char const *str);
12823 +#define dwc_strlen DWC_STRLEN
12824 +
12825 +/** strcpy() clone, for NULL terminated ASCII strings */
12826 +extern char *DWC_STRCPY(char *to, const char *from);
12827 +#define dwc_strcpy DWC_STRCPY
12828 +
12829 +/** strdup() clone. If you wish to use memory allocation debugging, this
12830 + * implementation of strdup should use the DWC_* memory routines instead of
12831 + * calling a predefined strdup. Otherwise the memory allocated by this routine
12832 + * will not be seen by the debugging routines. */
12833 +extern char *DWC_STRDUP(char const *str);
12834 +#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
12835 +
12836 +/** NOT an atoi() clone. Read the description carefully. Returns an integer
12837 + * converted from the string str in base 10 unless the string begins with a "0x"
12838 + * in which case it is base 16. String must be a NULL terminated sequence of
12839 + * ASCII characters and may optionally begin with whitespace, a + or -, and a
12840 + * "0x" prefix if base 16. The remaining characters must be valid digits for
12841 + * the number and end with a NULL character. If any invalid characters are
12842 + * encountered or it returns with a negative error code and the results of the
12843 + * conversion are undefined. On sucess it returns 0. Overflow conditions are
12844 + * undefined. An example implementation using atoi() can be referenced from the
12845 + * Linux implementation. */
12846 +extern int DWC_ATOI(const char *str, int32_t *value);
12847 +#define dwc_atoi DWC_ATOI
12848 +
12849 +/** Same as above but for unsigned. */
12850 +extern int DWC_ATOUI(const char *str, uint32_t *value);
12851 +#define dwc_atoui DWC_ATOUI
12852 +
12853 +#ifdef DWC_UTFLIB
12854 +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
12855 +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
12856 +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
12857 +#endif
12858 +
12859 +
12860 +/** @name Wait queues
12861 + *
12862 + * Wait queues provide a means of synchronizing between threads or processes. A
12863 + * process can block on a waitq if some condition is not true, waiting for it to
12864 + * become true. When the waitq is triggered all waiting process will get
12865 + * unblocked and the condition will be check again. Waitqs should be triggered
12866 + * every time a condition can potentially change.*/
12867 +struct dwc_waitq;
12868 +
12869 +/** Type for a waitq */
12870 +typedef struct dwc_waitq dwc_waitq_t;
12871 +
12872 +/** The type of waitq condition callback function. This is called every time
12873 + * condition is evaluated. */
12874 +typedef int (*dwc_waitq_condition_t)(void *data);
12875 +
12876 +/** Allocate a waitq */
12877 +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
12878 +#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
12879 +
12880 +/** Free a waitq */
12881 +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
12882 +#define dwc_waitq_free DWC_WAITQ_FREE
12883 +
12884 +/** Check the condition and if it is false, block on the waitq. When unblocked, check the
12885 + * condition again. The function returns when the condition becomes true. The return value
12886 + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
12887 +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
12888 +#define dwc_waitq_wait DWC_WAITQ_WAIT
12889 +
12890 +/** Check the condition and if it is false, block on the waitq. When unblocked,
12891 + * check the condition again. The function returns when the condition become
12892 + * true or the timeout has passed. The return value is 0 on condition true or
12893 + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
12894 + * error. */
12895 +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
12896 + void *data, int32_t msecs);
12897 +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
12898 +
12899 +/** Trigger a waitq, unblocking all processes. This should be called whenever a condition
12900 + * has potentially changed. */
12901 +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
12902 +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
12903 +
12904 +/** Unblock all processes waiting on the waitq with an ABORTED result. */
12905 +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
12906 +#define dwc_waitq_abort DWC_WAITQ_ABORT
12907 +
12908 +
12909 +/** @name Threads
12910 + *
12911 + * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP
12912 + * whenever it is woken up, and then return. The DWC_THREAD_STOP function
12913 + * returns the value from the thread.
12914 + */
12915 +
12916 +struct dwc_thread;
12917 +
12918 +/** Type for a thread */
12919 +typedef struct dwc_thread dwc_thread_t;
12920 +
12921 +/** The thread function */
12922 +typedef int (*dwc_thread_function_t)(void *data);
12923 +
12924 +/** Create a thread and start it running the thread_function. Returns a handle
12925 + * to the thread */
12926 +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
12927 +#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
12928 +
12929 +/** Stops a thread. Return the value returned by the thread. Or will return
12930 + * DWC_ABORT if the thread never started. */
12931 +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
12932 +#define dwc_thread_stop DWC_THREAD_STOP
12933 +
12934 +/** Signifies to the thread that it must stop. */
12935 +#ifdef DWC_LINUX
12936 +/* Linux doesn't need any parameters for kthread_should_stop() */
12937 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
12938 +#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
12939 +
12940 +/* No thread_exit function in Linux */
12941 +#define dwc_thread_exit(_thrd_)
12942 +#endif
12943 +
12944 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12945 +/** BSD needs the thread pointer for kthread_suspend_check() */
12946 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
12947 +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
12948 +
12949 +/** The thread must call this to exit. */
12950 +extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
12951 +#define dwc_thread_exit DWC_THREAD_EXIT
12952 +#endif
12953 +
12954 +
12955 +/** @name Work queues
12956 + *
12957 + * Workqs are used to queue a callback function to be called at some later time,
12958 + * in another thread. */
12959 +struct dwc_workq;
12960 +
12961 +/** Type for a workq */
12962 +typedef struct dwc_workq dwc_workq_t;
12963 +
12964 +/** The type of the callback function to be called. */
12965 +typedef void (*dwc_work_callback_t)(void *data);
12966 +
12967 +/** Allocate a workq */
12968 +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
12969 +#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
12970 +
12971 +/** Free a workq. All work must be completed before being freed. */
12972 +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
12973 +#define dwc_workq_free DWC_WORKQ_FREE
12974 +
12975 +/** Schedule a callback on the workq, passing in data. The function will be
12976 + * scheduled at some later time. */
12977 +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
12978 + void *data, char *format, ...)
12979 +#ifdef __GNUC__
12980 + __attribute__ ((format(printf, 4, 5)));
12981 +#else
12982 + ;
12983 +#endif
12984 +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
12985 +
12986 +/** Schedule a callback on the workq, that will be called until at least
12987 + * given number miliseconds have passed. */
12988 +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
12989 + void *data, uint32_t time, char *format, ...)
12990 +#ifdef __GNUC__
12991 + __attribute__ ((format(printf, 5, 6)));
12992 +#else
12993 + ;
12994 +#endif
12995 +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
12996 +
12997 +/** The number of processes in the workq */
12998 +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
12999 +#define dwc_workq_pending DWC_WORKQ_PENDING
13000 +
13001 +/** Blocks until all the work in the workq is complete or timed out. Returns <
13002 + * 0 on timeout. */
13003 +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
13004 +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
13005 +
13006 +
13007 +/** @name Tasklets
13008 + *
13009 + */
13010 +struct dwc_tasklet;
13011 +
13012 +/** Type for a tasklet */
13013 +typedef struct dwc_tasklet dwc_tasklet_t;
13014 +
13015 +/** The type of the callback function to be called */
13016 +typedef void (*dwc_tasklet_callback_t)(void *data);
13017 +
13018 +/** Allocates a tasklet */
13019 +extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
13020 +#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
13021 +
13022 +/** Frees a tasklet */
13023 +extern void DWC_TASK_FREE(dwc_tasklet_t *task);
13024 +#define dwc_task_free DWC_TASK_FREE
13025 +
13026 +/** Schedules a tasklet to run */
13027 +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
13028 +#define dwc_task_schedule DWC_TASK_SCHEDULE
13029 +
13030 +extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);
13031 +#define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE
13032 +
13033 +/** @name Timer
13034 + *
13035 + * Callbacks must be small and atomic.
13036 + */
13037 +struct dwc_timer;
13038 +
13039 +/** Type for a timer */
13040 +typedef struct dwc_timer dwc_timer_t;
13041 +
13042 +/** The type of the callback function to be called */
13043 +typedef void (*dwc_timer_callback_t)(void *data);
13044 +
13045 +/** Allocates a timer */
13046 +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
13047 +#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
13048 +
13049 +/** Frees a timer */
13050 +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
13051 +#define dwc_timer_free DWC_TIMER_FREE
13052 +
13053 +/** Schedules the timer to run at time ms from now. And will repeat at every
13054 + * repeat_interval msec therafter
13055 + *
13056 + * Modifies a timer that is still awaiting execution to a new expiration time.
13057 + * The mod_time is added to the old time. */
13058 +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
13059 +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
13060 +
13061 +/** Disables the timer from execution. */
13062 +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
13063 +#define dwc_timer_cancel DWC_TIMER_CANCEL
13064 +
13065 +
13066 +/** @name Spinlocks
13067 + *
13068 + * These locks are used when the work between the lock/unlock is atomic and
13069 + * short. Interrupts are also disabled during the lock/unlock and thus they are
13070 + * suitable to lock between interrupt/non-interrupt context. They also lock
13071 + * between processes if you have multiple CPUs or Preemption. If you don't have
13072 + * multiple CPUS or Preemption, then the you can simply implement the
13073 + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because
13074 + * the work between the lock/unlock is atomic, the process context will never
13075 + * change, and so you never have to lock between processes. */
13076 +
13077 +struct dwc_spinlock;
13078 +
13079 +/** Type for a spinlock */
13080 +typedef struct dwc_spinlock dwc_spinlock_t;
13081 +
13082 +/** Type for the 'flags' argument to spinlock funtions */
13083 +typedef unsigned long dwc_irqflags_t;
13084 +
13085 +/** Returns an initialized lock variable. This function should allocate and
13086 + * initialize the OS-specific data structure used for locking. This data
13087 + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
13088 + * be freed by the DWC_FREE_LOCK when it is no longer used. */
13089 +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
13090 +#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
13091 +
13092 +/** Frees an initialized lock variable. */
13093 +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
13094 +#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
13095 +
13096 +/** Disables interrupts and blocks until it acquires the lock.
13097 + *
13098 + * @param lock Pointer to the spinlock.
13099 + * @param flags Unsigned long for irq flags storage.
13100 + */
13101 +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
13102 +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
13103 +
13104 +/** Re-enables the interrupt and releases the lock.
13105 + *
13106 + * @param lock Pointer to the spinlock.
13107 + * @param flags Unsigned long for irq flags storage. Must be the same as was
13108 + * passed into DWC_LOCK.
13109 + */
13110 +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
13111 +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
13112 +
13113 +/** Blocks until it acquires the lock.
13114 + *
13115 + * @param lock Pointer to the spinlock.
13116 + */
13117 +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
13118 +#define dwc_spinlock DWC_SPINLOCK
13119 +
13120 +/** Releases the lock.
13121 + *
13122 + * @param lock Pointer to the spinlock.
13123 + */
13124 +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
13125 +#define dwc_spinunlock DWC_SPINUNLOCK
13126 +
13127 +
13128 +/** @name Mutexes
13129 + *
13130 + * Unlike spinlocks Mutexes lock only between processes and the work between the
13131 + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
13132 + */
13133 +
13134 +struct dwc_mutex;
13135 +
13136 +/** Type for a mutex */
13137 +typedef struct dwc_mutex dwc_mutex_t;
13138 +
13139 +/* For Linux Mutex Debugging make it inline because the debugging routines use
13140 + * the symbol to determine recursive locking. This makes it falsely think
13141 + * recursive locking occurs. */
13142 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13143 +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
13144 + __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
13145 + mutex_init((struct mutex *)__mutexp); \
13146 +})
13147 +#endif
13148 +
13149 +/** Allocate a mutex */
13150 +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
13151 +#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
13152 +
13153 +/* For memory leak debugging when using Linux Mutex Debugging */
13154 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13155 +#define DWC_MUTEX_FREE(__mutexp) do { \
13156 + mutex_destroy((struct mutex *)__mutexp); \
13157 + DWC_FREE(__mutexp); \
13158 +} while(0)
13159 +#else
13160 +/** Free a mutex */
13161 +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
13162 +#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
13163 +#endif
13164 +
13165 +/** Lock a mutex */
13166 +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
13167 +#define dwc_mutex_lock DWC_MUTEX_LOCK
13168 +
13169 +/** Non-blocking lock returns 1 on successful lock. */
13170 +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
13171 +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
13172 +
13173 +/** Unlock a mutex */
13174 +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
13175 +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
13176 +
13177 +
13178 +/** @name Time */
13179 +
13180 +/** Microsecond delay.
13181 + *
13182 + * @param usecs Microseconds to delay.
13183 + */
13184 +extern void DWC_UDELAY(uint32_t usecs);
13185 +#define dwc_udelay DWC_UDELAY
13186 +
13187 +/** Millisecond delay.
13188 + *
13189 + * @param msecs Milliseconds to delay.
13190 + */
13191 +extern void DWC_MDELAY(uint32_t msecs);
13192 +#define dwc_mdelay DWC_MDELAY
13193 +
13194 +/** Non-busy waiting.
13195 + * Sleeps for specified number of milliseconds.
13196 + *
13197 + * @param msecs Milliseconds to sleep.
13198 + */
13199 +extern void DWC_MSLEEP(uint32_t msecs);
13200 +#define dwc_msleep DWC_MSLEEP
13201 +
13202 +/**
13203 + * Returns number of milliseconds since boot.
13204 + */
13205 +extern uint32_t DWC_TIME(void);
13206 +#define dwc_time DWC_TIME
13207 +
13208 +
13209 +
13210 +
13211 +/* @mainpage DWC Portability and Common Library
13212 + *
13213 + * This is the documentation for the DWC Portability and Common Library.
13214 + *
13215 + * @section intro Introduction
13216 + *
13217 + * The DWC Portability library consists of wrapper calls and data structures to
13218 + * all low-level functions which are typically provided by the OS. The WUDEV
13219 + * driver uses only these functions. In order to port the WUDEV driver, only
13220 + * the functions in this library need to be re-implemented, with the same
13221 + * behavior as documented here.
13222 + *
13223 + * The Common library consists of higher level functions, which rely only on
13224 + * calling the functions from the DWC Portability library. These common
13225 + * routines are shared across modules. Some of the common libraries need to be
13226 + * used directly by the driver programmer when porting WUDEV. Such as the
13227 + * parameter and notification libraries.
13228 + *
13229 + * @section low Portability Library OS Wrapper Functions
13230 + *
13231 + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
13232 + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of
13233 + * these functions are included in the dwc_os.h file.
13234 + *
13235 + * There are many functions here covering a wide array of OS services. Please
13236 + * see dwc_os.h for details, and implementation notes for each function.
13237 + *
13238 + * @section common Common Library Functions
13239 + *
13240 + * Any function starting with dwc and in all lowercase is a common library
13241 + * routine. These functions have a portable implementation and do not need to
13242 + * be reimplemented when porting. The common routines can be used by any
13243 + * driver, and some must be used by the end user to control the drivers. For
13244 + * example, you must use the Parameter common library in order to set the
13245 + * parameters in the WUDEV module.
13246 + *
13247 + * The common libraries consist of the following:
13248 + *
13249 + * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h
13250 + * - Parameters - Used internally and can be used by end-user. See dwc_params.h
13251 + * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h
13252 + * - Lists - Used internally and can be used by end-user. See dwc_list.h
13253 + * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h
13254 + * - Modpow - Used internally only. See dwc_modpow.h
13255 + * - DH - Used internally only. See dwc_dh.h
13256 + * - Crypto - Used internally only. See dwc_crypto.h
13257 + *
13258 + *
13259 + * @section prereq Prerequistes For dwc_os.h
13260 + * @subsection types Data Types
13261 + *
13262 + * The dwc_os.h file assumes that several low-level data types are pre defined for the
13263 + * compilation environment. These data types are:
13264 + *
13265 + * - uint8_t - unsigned 8-bit data type
13266 + * - int8_t - signed 8-bit data type
13267 + * - uint16_t - unsigned 16-bit data type
13268 + * - int16_t - signed 16-bit data type
13269 + * - uint32_t - unsigned 32-bit data type
13270 + * - int32_t - signed 32-bit data type
13271 + * - uint64_t - unsigned 64-bit data type
13272 + * - int64_t - signed 64-bit data type
13273 + *
13274 + * Ensure that these are defined before using dwc_os.h. The easiest way to do
13275 + * that is to modify the top of the file to include the appropriate header.
13276 + * This is already done for the Linux environment. If the DWC_LINUX macro is
13277 + * defined, the correct header will be added. A standard header <stdint.h> is
13278 + * also used for environments where standard C headers are available.
13279 + *
13280 + * @subsection stdarg Variable Arguments
13281 + *
13282 + * Variable arguments are provided by a standard C header <stdarg.h>. it is
13283 + * available in Both the Linux and ANSI C enviornment. An equivalent must be
13284 + * provided in your enviornment in order to use dwc_os.h with the debug and
13285 + * tracing message functionality.
13286 + *
13287 + * @subsection thread Threading
13288 + *
13289 + * WUDEV Core must be run on an operating system that provides for multiple
13290 + * threads/processes. Threading can be implemented in many ways, even in
13291 + * embedded systems without an operating system. At the bare minimum, the
13292 + * system should be able to start any number of processes at any time to handle
13293 + * special work. It need not be a pre-emptive system. Process context can
13294 + * change upon a call to a blocking function. The hardware interrupt context
13295 + * that calls the module's ISR() function must be differentiable from process
13296 + * context, even if your processes are impemented via a hardware interrupt.
13297 + * Further locking mechanism between process must exist (or be implemented), and
13298 + * process context must have a way to disable interrupts for a period of time to
13299 + * lock them out. If all of this exists, the functions in dwc_os.h related to
13300 + * threading should be able to be implemented with the defined behavior.
13301 + *
13302 + */
13303 +
13304 +#ifdef __cplusplus
13305 +}
13306 +#endif
13307 +
13308 +#endif /* _DWC_OS_H_ */
13309 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/Makefile linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/Makefile
13310 --- linux-3.10/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100
13311 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/Makefile 2013-07-06 15:25:50.000000000 +0100
13312 @@ -0,0 +1,58 @@
13313 +#
13314 +# Makefile for DWC_common library
13315 +#
13316 +
13317 +ifneq ($(KERNELRELEASE),)
13318 +
13319 +EXTRA_CFLAGS += -DDWC_LINUX
13320 +#EXTRA_CFLAGS += -DDEBUG
13321 +#EXTRA_CFLAGS += -DDWC_DEBUG_REGS
13322 +#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY
13323 +
13324 +EXTRA_CFLAGS += -DDWC_LIBMODULE
13325 +EXTRA_CFLAGS += -DDWC_CCLIB
13326 +#EXTRA_CFLAGS += -DDWC_CRYPTOLIB
13327 +EXTRA_CFLAGS += -DDWC_NOTIFYLIB
13328 +EXTRA_CFLAGS += -DDWC_UTFLIB
13329 +
13330 +obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o
13331 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
13332 + dwc_crypto.o dwc_notifier.o \
13333 + dwc_common_linux.o dwc_mem.o
13334 +
13335 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
13336 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
13337 +
13338 +ifneq ($(kernrel3),2.6.20)
13339 +# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually
13340 +EXTRA_CFLAGS += $(CPPFLAGS)
13341 +endif
13342 +
13343 +else
13344 +
13345 +#ifeq ($(KDIR),)
13346 +#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
13347 +#endif
13348 +
13349 +ifeq ($(ARCH),)
13350 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
13351 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
13352 +endif
13353 +
13354 +ifeq ($(DOXYGEN),)
13355 +DOXYGEN := doxygen
13356 +endif
13357 +
13358 +default:
13359 + $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
13360 +
13361 +docs: $(wildcard *.[hc]) doc/doxygen.cfg
13362 + $(DOXYGEN) doc/doxygen.cfg
13363 +
13364 +tags: $(wildcard *.[hc])
13365 + $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
13366 +
13367 +endif
13368 +
13369 +clean:
13370 + rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
13371 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/Makefile.fbsd
13372 --- linux-3.10/drivers/usb/host/dwc_common_port/Makefile.fbsd 1970-01-01 01:00:00.000000000 +0100
13373 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/Makefile.fbsd 2013-07-06 15:25:50.000000000 +0100
13374 @@ -0,0 +1,17 @@
13375 +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
13376 +CFLAGS += -DDWC_FREEBSD
13377 +CFLAGS += -DDEBUG
13378 +#CFLAGS += -DDWC_DEBUG_REGS
13379 +#CFLAGS += -DDWC_DEBUG_MEMORY
13380 +
13381 +#CFLAGS += -DDWC_LIBMODULE
13382 +#CFLAGS += -DDWC_CCLIB
13383 +#CFLAGS += -DDWC_CRYPTOLIB
13384 +#CFLAGS += -DDWC_NOTIFYLIB
13385 +#CFLAGS += -DDWC_UTFLIB
13386 +
13387 +KMOD = dwc_common_port_lib
13388 +SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \
13389 + dwc_common_fbsd.c dwc_mem.c
13390 +
13391 +.include <bsd.kmod.mk>
13392 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/Makefile.linux linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/Makefile.linux
13393 --- linux-3.10/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100
13394 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/Makefile.linux 2013-07-06 15:25:50.000000000 +0100
13395 @@ -0,0 +1,49 @@
13396 +#
13397 +# Makefile for DWC_common library
13398 +#
13399 +ifneq ($(KERNELRELEASE),)
13400 +
13401 +EXTRA_CFLAGS += -DDWC_LINUX
13402 +#EXTRA_CFLAGS += -DDEBUG
13403 +#EXTRA_CFLAGS += -DDWC_DEBUG_REGS
13404 +#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY
13405 +
13406 +EXTRA_CFLAGS += -DDWC_LIBMODULE
13407 +EXTRA_CFLAGS += -DDWC_CCLIB
13408 +EXTRA_CFLAGS += -DDWC_CRYPTOLIB
13409 +EXTRA_CFLAGS += -DDWC_NOTIFYLIB
13410 +EXTRA_CFLAGS += -DDWC_UTFLIB
13411 +
13412 +obj-m := dwc_common_port_lib.o
13413 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
13414 + dwc_crypto.o dwc_notifier.o \
13415 + dwc_common_linux.o dwc_mem.o
13416 +
13417 +else
13418 +
13419 +ifeq ($(KDIR),)
13420 +$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
13421 +endif
13422 +
13423 +ifeq ($(ARCH),)
13424 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
13425 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
13426 +endif
13427 +
13428 +ifeq ($(DOXYGEN),)
13429 +DOXYGEN := doxygen
13430 +endif
13431 +
13432 +default:
13433 + $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
13434 +
13435 +docs: $(wildcard *.[hc]) doc/doxygen.cfg
13436 + $(DOXYGEN) doc/doxygen.cfg
13437 +
13438 +tags: $(wildcard *.[hc])
13439 + $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
13440 +
13441 +endif
13442 +
13443 +clean:
13444 + rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
13445 diff -urN linux-3.10/drivers/usb/host/dwc_common_port/usb.h linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/usb.h
13446 --- linux-3.10/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100
13447 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_common_port/usb.h 2013-07-06 15:25:50.000000000 +0100
13448 @@ -0,0 +1,946 @@
13449 +/*
13450 + * Copyright (c) 1998 The NetBSD Foundation, Inc.
13451 + * All rights reserved.
13452 + *
13453 + * This code is derived from software contributed to The NetBSD Foundation
13454 + * by Lennart Augustsson (lennart@augustsson.net) at
13455 + * Carlstedt Research & Technology.
13456 + *
13457 + * Redistribution and use in source and binary forms, with or without
13458 + * modification, are permitted provided that the following conditions
13459 + * are met:
13460 + * 1. Redistributions of source code must retain the above copyright
13461 + * notice, this list of conditions and the following disclaimer.
13462 + * 2. Redistributions in binary form must reproduce the above copyright
13463 + * notice, this list of conditions and the following disclaimer in the
13464 + * documentation and/or other materials provided with the distribution.
13465 + * 3. All advertising materials mentioning features or use of this software
13466 + * must display the following acknowledgement:
13467 + * This product includes software developed by the NetBSD
13468 + * Foundation, Inc. and its contributors.
13469 + * 4. Neither the name of The NetBSD Foundation nor the names of its
13470 + * contributors may be used to endorse or promote products derived
13471 + * from this software without specific prior written permission.
13472 + *
13473 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
13474 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13475 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13476 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
13477 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13478 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13479 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13480 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13481 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13482 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13483 + * POSSIBILITY OF SUCH DAMAGE.
13484 + */
13485 +
13486 +/* Modified by Synopsys, Inc, 12/12/2007 */
13487 +
13488 +
13489 +#ifndef _USB_H_
13490 +#define _USB_H_
13491 +
13492 +#ifdef __cplusplus
13493 +extern "C" {
13494 +#endif
13495 +
13496 +/*
13497 + * The USB records contain some unaligned little-endian word
13498 + * components. The U[SG]ETW macros take care of both the alignment
13499 + * and endian problem and should always be used to access non-byte
13500 + * values.
13501 + */
13502 +typedef u_int8_t uByte;
13503 +typedef u_int8_t uWord[2];
13504 +typedef u_int8_t uDWord[4];
13505 +
13506 +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
13507 +#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff }
13508 +#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \
13509 + ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
13510 +
13511 +#if 1
13512 +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
13513 +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
13514 +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
13515 +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
13516 + (w)[1] = (u_int8_t)((v) >> 8), \
13517 + (w)[2] = (u_int8_t)((v) >> 16), \
13518 + (w)[3] = (u_int8_t)((v) >> 24))
13519 +#else
13520 +/*
13521 + * On little-endian machines that can handle unanliged accesses
13522 + * (e.g. i386) these macros can be replaced by the following.
13523 + */
13524 +#define UGETW(w) (*(u_int16_t *)(w))
13525 +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
13526 +#define UGETDW(w) (*(u_int32_t *)(w))
13527 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
13528 +#endif
13529 +
13530 +/*
13531 + * Macros for accessing UAS IU fields, which are big-endian
13532 + */
13533 +#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
13534 +#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff }
13535 +#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
13536 + ((x) >> 8) & 0xff, (x) & 0xff }
13537 +#define IUGETW(w) (((w)[0] << 8) | (w)[1])
13538 +#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
13539 +#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
13540 +#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
13541 + (w)[1] = (u_int8_t)((v) >> 16), \
13542 + (w)[2] = (u_int8_t)((v) >> 8), \
13543 + (w)[3] = (u_int8_t)(v))
13544 +
13545 +#define UPACKED __attribute__((__packed__))
13546 +
13547 +typedef struct {
13548 + uByte bmRequestType;
13549 + uByte bRequest;
13550 + uWord wValue;
13551 + uWord wIndex;
13552 + uWord wLength;
13553 +} UPACKED usb_device_request_t;
13554 +
13555 +#define UT_GET_DIR(a) ((a) & 0x80)
13556 +#define UT_WRITE 0x00
13557 +#define UT_READ 0x80
13558 +
13559 +#define UT_GET_TYPE(a) ((a) & 0x60)
13560 +#define UT_STANDARD 0x00
13561 +#define UT_CLASS 0x20
13562 +#define UT_VENDOR 0x40
13563 +
13564 +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
13565 +#define UT_DEVICE 0x00
13566 +#define UT_INTERFACE 0x01
13567 +#define UT_ENDPOINT 0x02
13568 +#define UT_OTHER 0x03
13569 +
13570 +#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE)
13571 +#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE)
13572 +#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT)
13573 +#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE)
13574 +#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE)
13575 +#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
13576 +#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE)
13577 +#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE)
13578 +#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER)
13579 +#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT)
13580 +#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE)
13581 +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
13582 +#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER)
13583 +#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT)
13584 +#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE)
13585 +#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE)
13586 +#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER)
13587 +#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT)
13588 +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
13589 +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
13590 +#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER)
13591 +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
13592 +
13593 +/* Requests */
13594 +#define UR_GET_STATUS 0x00
13595 +#define USTAT_STANDARD_STATUS 0x00
13596 +#define WUSTAT_WUSB_FEATURE 0x01
13597 +#define WUSTAT_CHANNEL_INFO 0x02
13598 +#define WUSTAT_RECEIVED_DATA 0x03
13599 +#define WUSTAT_MAS_AVAILABILITY 0x04
13600 +#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05
13601 +#define UR_CLEAR_FEATURE 0x01
13602 +#define UR_SET_FEATURE 0x03
13603 +#define UR_SET_AND_TEST_FEATURE 0x0c
13604 +#define UR_SET_ADDRESS 0x05
13605 +#define UR_GET_DESCRIPTOR 0x06
13606 +#define UDESC_DEVICE 0x01
13607 +#define UDESC_CONFIG 0x02
13608 +#define UDESC_STRING 0x03
13609 +#define UDESC_INTERFACE 0x04
13610 +#define UDESC_ENDPOINT 0x05
13611 +#define UDESC_SS_USB_COMPANION 0x30
13612 +#define UDESC_DEVICE_QUALIFIER 0x06
13613 +#define UDESC_OTHER_SPEED_CONFIGURATION 0x07
13614 +#define UDESC_INTERFACE_POWER 0x08
13615 +#define UDESC_OTG 0x09
13616 +#define WUDESC_SECURITY 0x0c
13617 +#define WUDESC_KEY 0x0d
13618 +#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
13619 +#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
13620 +#define WUD_KEY_TYPE_ASSOC 0x01
13621 +#define WUD_KEY_TYPE_GTK 0x02
13622 +#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
13623 +#define WUD_KEY_ORIGIN_HOST 0x00
13624 +#define WUD_KEY_ORIGIN_DEVICE 0x01
13625 +#define WUDESC_ENCRYPTION_TYPE 0x0e
13626 +#define WUDESC_BOS 0x0f
13627 +#define WUDESC_DEVICE_CAPABILITY 0x10
13628 +#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
13629 +#define UDESC_BOS 0x0f
13630 +#define UDESC_DEVICE_CAPABILITY 0x10
13631 +#define UDESC_CS_DEVICE 0x21 /* class specific */
13632 +#define UDESC_CS_CONFIG 0x22
13633 +#define UDESC_CS_STRING 0x23
13634 +#define UDESC_CS_INTERFACE 0x24
13635 +#define UDESC_CS_ENDPOINT 0x25
13636 +#define UDESC_HUB 0x29
13637 +#define UR_SET_DESCRIPTOR 0x07
13638 +#define UR_GET_CONFIG 0x08
13639 +#define UR_SET_CONFIG 0x09
13640 +#define UR_GET_INTERFACE 0x0a
13641 +#define UR_SET_INTERFACE 0x0b
13642 +#define UR_SYNCH_FRAME 0x0c
13643 +#define WUR_SET_ENCRYPTION 0x0d
13644 +#define WUR_GET_ENCRYPTION 0x0e
13645 +#define WUR_SET_HANDSHAKE 0x0f
13646 +#define WUR_GET_HANDSHAKE 0x10
13647 +#define WUR_SET_CONNECTION 0x11
13648 +#define WUR_SET_SECURITY_DATA 0x12
13649 +#define WUR_GET_SECURITY_DATA 0x13
13650 +#define WUR_SET_WUSB_DATA 0x14
13651 +#define WUDATA_DRPIE_INFO 0x01
13652 +#define WUDATA_TRANSMIT_DATA 0x02
13653 +#define WUDATA_TRANSMIT_PARAMS 0x03
13654 +#define WUDATA_RECEIVE_PARAMS 0x04
13655 +#define WUDATA_TRANSMIT_POWER 0x05
13656 +#define WUR_LOOPBACK_DATA_WRITE 0x15
13657 +#define WUR_LOOPBACK_DATA_READ 0x16
13658 +#define WUR_SET_INTERFACE_DS 0x17
13659 +
13660 +/* Feature numbers */
13661 +#define UF_ENDPOINT_HALT 0
13662 +#define UF_DEVICE_REMOTE_WAKEUP 1
13663 +#define UF_TEST_MODE 2
13664 +#define UF_DEVICE_B_HNP_ENABLE 3
13665 +#define UF_DEVICE_A_HNP_SUPPORT 4
13666 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
13667 +#define WUF_WUSB 3
13668 +#define WUF_TX_DRPIE 0x0
13669 +#define WUF_DEV_XMIT_PACKET 0x1
13670 +#define WUF_COUNT_PACKETS 0x2
13671 +#define WUF_CAPTURE_PACKETS 0x3
13672 +#define UF_FUNCTION_SUSPEND 0
13673 +#define UF_U1_ENABLE 48
13674 +#define UF_U2_ENABLE 49
13675 +#define UF_LTM_ENABLE 50
13676 +
13677 +/* Class requests from the USB 2.0 hub spec, table 11-15 */
13678 +#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE)
13679 +#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE)
13680 +#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR)
13681 +#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS)
13682 +#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS)
13683 +#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE)
13684 +#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE)
13685 +#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE)
13686 +
13687 +#ifdef _MSC_VER
13688 +#include <pshpack1.h>
13689 +#endif
13690 +
13691 +typedef struct {
13692 + uByte bLength;
13693 + uByte bDescriptorType;
13694 + uByte bDescriptorSubtype;
13695 +} UPACKED usb_descriptor_t;
13696 +
13697 +typedef struct {
13698 + uByte bLength;
13699 + uByte bDescriptorType;
13700 +} UPACKED usb_descriptor_header_t;
13701 +
13702 +typedef struct {
13703 + uByte bLength;
13704 + uByte bDescriptorType;
13705 + uWord bcdUSB;
13706 +#define UD_USB_2_0 0x0200
13707 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
13708 + uByte bDeviceClass;
13709 + uByte bDeviceSubClass;
13710 + uByte bDeviceProtocol;
13711 + uByte bMaxPacketSize;
13712 + /* The fields below are not part of the initial descriptor. */
13713 + uWord idVendor;
13714 + uWord idProduct;
13715 + uWord bcdDevice;
13716 + uByte iManufacturer;
13717 + uByte iProduct;
13718 + uByte iSerialNumber;
13719 + uByte bNumConfigurations;
13720 +} UPACKED usb_device_descriptor_t;
13721 +#define USB_DEVICE_DESCRIPTOR_SIZE 18
13722 +
13723 +typedef struct {
13724 + uByte bLength;
13725 + uByte bDescriptorType;
13726 + uWord wTotalLength;
13727 + uByte bNumInterface;
13728 + uByte bConfigurationValue;
13729 + uByte iConfiguration;
13730 +#define UC_ATT_ONE (1 << 7) /* must be set */
13731 +#define UC_ATT_SELFPOWER (1 << 6) /* self powered */
13732 +#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */
13733 +#define UC_ATT_BATTERY (1 << 4) /* battery powered */
13734 + uByte bmAttributes;
13735 +#define UC_BUS_POWERED 0x80
13736 +#define UC_SELF_POWERED 0x40
13737 +#define UC_REMOTE_WAKEUP 0x20
13738 + uByte bMaxPower; /* max current in 2 mA units */
13739 +#define UC_POWER_FACTOR 2
13740 +} UPACKED usb_config_descriptor_t;
13741 +#define USB_CONFIG_DESCRIPTOR_SIZE 9
13742 +
13743 +typedef struct {
13744 + uByte bLength;
13745 + uByte bDescriptorType;
13746 + uByte bInterfaceNumber;
13747 + uByte bAlternateSetting;
13748 + uByte bNumEndpoints;
13749 + uByte bInterfaceClass;
13750 + uByte bInterfaceSubClass;
13751 + uByte bInterfaceProtocol;
13752 + uByte iInterface;
13753 +} UPACKED usb_interface_descriptor_t;
13754 +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
13755 +
13756 +typedef struct {
13757 + uByte bLength;
13758 + uByte bDescriptorType;
13759 + uByte bEndpointAddress;
13760 +#define UE_GET_DIR(a) ((a) & 0x80)
13761 +#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7))
13762 +#define UE_DIR_IN 0x80
13763 +#define UE_DIR_OUT 0x00
13764 +#define UE_ADDR 0x0f
13765 +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
13766 + uByte bmAttributes;
13767 +#define UE_XFERTYPE 0x03
13768 +#define UE_CONTROL 0x00
13769 +#define UE_ISOCHRONOUS 0x01
13770 +#define UE_BULK 0x02
13771 +#define UE_INTERRUPT 0x03
13772 +#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE)
13773 +#define UE_ISO_TYPE 0x0c
13774 +#define UE_ISO_ASYNC 0x04
13775 +#define UE_ISO_ADAPT 0x08
13776 +#define UE_ISO_SYNC 0x0c
13777 +#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE)
13778 + uWord wMaxPacketSize;
13779 + uByte bInterval;
13780 +} UPACKED usb_endpoint_descriptor_t;
13781 +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
13782 +
13783 +typedef struct ss_endpoint_companion_descriptor {
13784 + uByte bLength;
13785 + uByte bDescriptorType;
13786 + uByte bMaxBurst;
13787 +#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f)
13788 +#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f))
13789 +#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03)
13790 +#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03))
13791 + uByte bmAttributes;
13792 + uWord wBytesPerInterval;
13793 +} UPACKED ss_endpoint_companion_descriptor_t;
13794 +#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
13795 +
13796 +typedef struct {
13797 + uByte bLength;
13798 + uByte bDescriptorType;
13799 + uWord bString[127];
13800 +} UPACKED usb_string_descriptor_t;
13801 +#define USB_MAX_STRING_LEN 128
13802 +#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */
13803 +
13804 +/* Hub specific request */
13805 +#define UR_GET_BUS_STATE 0x02
13806 +#define UR_CLEAR_TT_BUFFER 0x08
13807 +#define UR_RESET_TT 0x09
13808 +#define UR_GET_TT_STATE 0x0a
13809 +#define UR_STOP_TT 0x0b
13810 +
13811 +/* Hub features */
13812 +#define UHF_C_HUB_LOCAL_POWER 0
13813 +#define UHF_C_HUB_OVER_CURRENT 1
13814 +#define UHF_PORT_CONNECTION 0
13815 +#define UHF_PORT_ENABLE 1
13816 +#define UHF_PORT_SUSPEND 2
13817 +#define UHF_PORT_OVER_CURRENT 3
13818 +#define UHF_PORT_RESET 4
13819 +#define UHF_PORT_L1 5
13820 +#define UHF_PORT_POWER 8
13821 +#define UHF_PORT_LOW_SPEED 9
13822 +#define UHF_PORT_HIGH_SPEED 10
13823 +#define UHF_C_PORT_CONNECTION 16
13824 +#define UHF_C_PORT_ENABLE 17
13825 +#define UHF_C_PORT_SUSPEND 18
13826 +#define UHF_C_PORT_OVER_CURRENT 19
13827 +#define UHF_C_PORT_RESET 20
13828 +#define UHF_C_PORT_L1 23
13829 +#define UHF_PORT_TEST 21
13830 +#define UHF_PORT_INDICATOR 22
13831 +
13832 +typedef struct {
13833 + uByte bDescLength;
13834 + uByte bDescriptorType;
13835 + uByte bNbrPorts;
13836 + uWord wHubCharacteristics;
13837 +#define UHD_PWR 0x0003
13838 +#define UHD_PWR_GANGED 0x0000
13839 +#define UHD_PWR_INDIVIDUAL 0x0001
13840 +#define UHD_PWR_NO_SWITCH 0x0002
13841 +#define UHD_COMPOUND 0x0004
13842 +#define UHD_OC 0x0018
13843 +#define UHD_OC_GLOBAL 0x0000
13844 +#define UHD_OC_INDIVIDUAL 0x0008
13845 +#define UHD_OC_NONE 0x0010
13846 +#define UHD_TT_THINK 0x0060
13847 +#define UHD_TT_THINK_8 0x0000
13848 +#define UHD_TT_THINK_16 0x0020
13849 +#define UHD_TT_THINK_24 0x0040
13850 +#define UHD_TT_THINK_32 0x0060
13851 +#define UHD_PORT_IND 0x0080
13852 + uByte bPwrOn2PwrGood; /* delay in 2 ms units */
13853 +#define UHD_PWRON_FACTOR 2
13854 + uByte bHubContrCurrent;
13855 + uByte DeviceRemovable[32]; /* max 255 ports */
13856 +#define UHD_NOT_REMOV(desc, i) \
13857 + (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
13858 + /* deprecated */ uByte PortPowerCtrlMask[1];
13859 +} UPACKED usb_hub_descriptor_t;
13860 +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
13861 +
13862 +typedef struct {
13863 + uByte bLength;
13864 + uByte bDescriptorType;
13865 + uWord bcdUSB;
13866 + uByte bDeviceClass;
13867 + uByte bDeviceSubClass;
13868 + uByte bDeviceProtocol;
13869 + uByte bMaxPacketSize0;
13870 + uByte bNumConfigurations;
13871 + uByte bReserved;
13872 +} UPACKED usb_device_qualifier_t;
13873 +#define USB_DEVICE_QUALIFIER_SIZE 10
13874 +
13875 +typedef struct {
13876 + uByte bLength;
13877 + uByte bDescriptorType;
13878 + uByte bmAttributes;
13879 +#define UOTG_SRP 0x01
13880 +#define UOTG_HNP 0x02
13881 +} UPACKED usb_otg_descriptor_t;
13882 +
13883 +/* OTG feature selectors */
13884 +#define UOTG_B_HNP_ENABLE 3
13885 +#define UOTG_A_HNP_SUPPORT 4
13886 +#define UOTG_A_ALT_HNP_SUPPORT 5
13887 +
13888 +typedef struct {
13889 + uWord wStatus;
13890 +/* Device status flags */
13891 +#define UDS_SELF_POWERED 0x0001
13892 +#define UDS_REMOTE_WAKEUP 0x0002
13893 +/* Endpoint status flags */
13894 +#define UES_HALT 0x0001
13895 +} UPACKED usb_status_t;
13896 +
13897 +typedef struct {
13898 + uWord wHubStatus;
13899 +#define UHS_LOCAL_POWER 0x0001
13900 +#define UHS_OVER_CURRENT 0x0002
13901 + uWord wHubChange;
13902 +} UPACKED usb_hub_status_t;
13903 +
13904 +typedef struct {
13905 + uWord wPortStatus;
13906 +#define UPS_CURRENT_CONNECT_STATUS 0x0001
13907 +#define UPS_PORT_ENABLED 0x0002
13908 +#define UPS_SUSPEND 0x0004
13909 +#define UPS_OVERCURRENT_INDICATOR 0x0008
13910 +#define UPS_RESET 0x0010
13911 +#define UPS_PORT_POWER 0x0100
13912 +#define UPS_LOW_SPEED 0x0200
13913 +#define UPS_HIGH_SPEED 0x0400
13914 +#define UPS_PORT_TEST 0x0800
13915 +#define UPS_PORT_INDICATOR 0x1000
13916 + uWord wPortChange;
13917 +#define UPS_C_CONNECT_STATUS 0x0001
13918 +#define UPS_C_PORT_ENABLED 0x0002
13919 +#define UPS_C_SUSPEND 0x0004
13920 +#define UPS_C_OVERCURRENT_INDICATOR 0x0008
13921 +#define UPS_C_PORT_RESET 0x0010
13922 +} UPACKED usb_port_status_t;
13923 +
13924 +#ifdef _MSC_VER
13925 +#include <poppack.h>
13926 +#endif
13927 +
13928 +/* Device class codes */
13929 +#define UDCLASS_IN_INTERFACE 0x00
13930 +#define UDCLASS_COMM 0x02
13931 +#define UDCLASS_HUB 0x09
13932 +#define UDSUBCLASS_HUB 0x00
13933 +#define UDPROTO_FSHUB 0x00
13934 +#define UDPROTO_HSHUBSTT 0x01
13935 +#define UDPROTO_HSHUBMTT 0x02
13936 +#define UDCLASS_DIAGNOSTIC 0xdc
13937 +#define UDCLASS_WIRELESS 0xe0
13938 +#define UDSUBCLASS_RF 0x01
13939 +#define UDPROTO_BLUETOOTH 0x01
13940 +#define UDCLASS_VENDOR 0xff
13941 +
13942 +/* Interface class codes */
13943 +#define UICLASS_UNSPEC 0x00
13944 +
13945 +#define UICLASS_AUDIO 0x01
13946 +#define UISUBCLASS_AUDIOCONTROL 1
13947 +#define UISUBCLASS_AUDIOSTREAM 2
13948 +#define UISUBCLASS_MIDISTREAM 3
13949 +
13950 +#define UICLASS_CDC 0x02 /* communication */
13951 +#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1
13952 +#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2
13953 +#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3
13954 +#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
13955 +#define UISUBCLASS_CAPI_CONTROLMODEL 5
13956 +#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
13957 +#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
13958 +#define UIPROTO_CDC_AT 1
13959 +
13960 +#define UICLASS_HID 0x03
13961 +#define UISUBCLASS_BOOT 1
13962 +#define UIPROTO_BOOT_KEYBOARD 1
13963 +
13964 +#define UICLASS_PHYSICAL 0x05
13965 +
13966 +#define UICLASS_IMAGE 0x06
13967 +
13968 +#define UICLASS_PRINTER 0x07
13969 +#define UISUBCLASS_PRINTER 1
13970 +#define UIPROTO_PRINTER_UNI 1
13971 +#define UIPROTO_PRINTER_BI 2
13972 +#define UIPROTO_PRINTER_1284 3
13973 +
13974 +#define UICLASS_MASS 0x08
13975 +#define UISUBCLASS_RBC 1
13976 +#define UISUBCLASS_SFF8020I 2
13977 +#define UISUBCLASS_QIC157 3
13978 +#define UISUBCLASS_UFI 4
13979 +#define UISUBCLASS_SFF8070I 5
13980 +#define UISUBCLASS_SCSI 6
13981 +#define UIPROTO_MASS_CBI_I 0
13982 +#define UIPROTO_MASS_CBI 1
13983 +#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */
13984 +#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */
13985 +
13986 +#define UICLASS_HUB 0x09
13987 +#define UISUBCLASS_HUB 0
13988 +#define UIPROTO_FSHUB 0
13989 +#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */
13990 +#define UIPROTO_HSHUBMTT 1
13991 +
13992 +#define UICLASS_CDC_DATA 0x0a
13993 +#define UISUBCLASS_DATA 0
13994 +#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */
13995 +#define UIPROTO_DATA_HDLC 0x31 /* HDLC */
13996 +#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */
13997 +#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */
13998 +#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */
13999 +#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */
14000 +#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */
14001 +#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */
14002 +#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */
14003 +#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */
14004 +#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */
14005 +#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/
14006 +#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */
14007 +
14008 +#define UICLASS_SMARTCARD 0x0b
14009 +
14010 +/*#define UICLASS_FIRM_UPD 0x0c*/
14011 +
14012 +#define UICLASS_SECURITY 0x0d
14013 +
14014 +#define UICLASS_DIAGNOSTIC 0xdc
14015 +
14016 +#define UICLASS_WIRELESS 0xe0
14017 +#define UISUBCLASS_RF 0x01
14018 +#define UIPROTO_BLUETOOTH 0x01
14019 +
14020 +#define UICLASS_APPL_SPEC 0xfe
14021 +#define UISUBCLASS_FIRMWARE_DOWNLOAD 1
14022 +#define UISUBCLASS_IRDA 2
14023 +#define UIPROTO_IRDA 0
14024 +
14025 +#define UICLASS_VENDOR 0xff
14026 +
14027 +#define USB_HUB_MAX_DEPTH 5
14028 +
14029 +/*
14030 + * Minimum time a device needs to be powered down to go through
14031 + * a power cycle. XXX Are these time in the spec?
14032 + */
14033 +#define USB_POWER_DOWN_TIME 200 /* ms */
14034 +#define USB_PORT_POWER_DOWN_TIME 100 /* ms */
14035 +
14036 +#if 0
14037 +/* These are the values from the spec. */
14038 +#define USB_PORT_RESET_DELAY 10 /* ms */
14039 +#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */
14040 +#define USB_PORT_RESET_RECOVERY 10 /* ms */
14041 +#define USB_PORT_POWERUP_DELAY 100 /* ms */
14042 +#define USB_SET_ADDRESS_SETTLE 2 /* ms */
14043 +#define USB_RESUME_DELAY (20*5) /* ms */
14044 +#define USB_RESUME_WAIT 10 /* ms */
14045 +#define USB_RESUME_RECOVERY 10 /* ms */
14046 +#define USB_EXTRA_POWER_UP_TIME 0 /* ms */
14047 +#else
14048 +/* Allow for marginal (i.e. non-conforming) devices. */
14049 +#define USB_PORT_RESET_DELAY 50 /* ms */
14050 +#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
14051 +#define USB_PORT_RESET_RECOVERY 250 /* ms */
14052 +#define USB_PORT_POWERUP_DELAY 300 /* ms */
14053 +#define USB_SET_ADDRESS_SETTLE 10 /* ms */
14054 +#define USB_RESUME_DELAY (50*5) /* ms */
14055 +#define USB_RESUME_WAIT 50 /* ms */
14056 +#define USB_RESUME_RECOVERY 50 /* ms */
14057 +#define USB_EXTRA_POWER_UP_TIME 20 /* ms */
14058 +#endif
14059 +
14060 +#define USB_MIN_POWER 100 /* mA */
14061 +#define USB_MAX_POWER 500 /* mA */
14062 +
14063 +#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/
14064 +
14065 +#define USB_UNCONFIG_NO 0
14066 +#define USB_UNCONFIG_INDEX (-1)
14067 +
14068 +/*** ioctl() related stuff ***/
14069 +
14070 +struct usb_ctl_request {
14071 + int ucr_addr;
14072 + usb_device_request_t ucr_request;
14073 + void *ucr_data;
14074 + int ucr_flags;
14075 +#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */
14076 + int ucr_actlen; /* actual length transferred */
14077 +};
14078 +
14079 +struct usb_alt_interface {
14080 + int uai_config_index;
14081 + int uai_interface_index;
14082 + int uai_alt_no;
14083 +};
14084 +
14085 +#define USB_CURRENT_CONFIG_INDEX (-1)
14086 +#define USB_CURRENT_ALT_INDEX (-1)
14087 +
14088 +struct usb_config_desc {
14089 + int ucd_config_index;
14090 + usb_config_descriptor_t ucd_desc;
14091 +};
14092 +
14093 +struct usb_interface_desc {
14094 + int uid_config_index;
14095 + int uid_interface_index;
14096 + int uid_alt_index;
14097 + usb_interface_descriptor_t uid_desc;
14098 +};
14099 +
14100 +struct usb_endpoint_desc {
14101 + int ued_config_index;
14102 + int ued_interface_index;
14103 + int ued_alt_index;
14104 + int ued_endpoint_index;
14105 + usb_endpoint_descriptor_t ued_desc;
14106 +};
14107 +
14108 +struct usb_full_desc {
14109 + int ufd_config_index;
14110 + u_int ufd_size;
14111 + u_char *ufd_data;
14112 +};
14113 +
14114 +struct usb_string_desc {
14115 + int usd_string_index;
14116 + int usd_language_id;
14117 + usb_string_descriptor_t usd_desc;
14118 +};
14119 +
14120 +struct usb_ctl_report_desc {
14121 + int ucrd_size;
14122 + u_char ucrd_data[1024]; /* filled data size will vary */
14123 +};
14124 +
14125 +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
14126 +
14127 +#define USB_MAX_DEVNAMES 4
14128 +#define USB_MAX_DEVNAMELEN 16
14129 +struct usb_device_info {
14130 + u_int8_t udi_bus;
14131 + u_int8_t udi_addr; /* device address */
14132 + usb_event_cookie_t udi_cookie;
14133 + char udi_product[USB_MAX_STRING_LEN];
14134 + char udi_vendor[USB_MAX_STRING_LEN];
14135 + char udi_release[8];
14136 + u_int16_t udi_productNo;
14137 + u_int16_t udi_vendorNo;
14138 + u_int16_t udi_releaseNo;
14139 + u_int8_t udi_class;
14140 + u_int8_t udi_subclass;
14141 + u_int8_t udi_protocol;
14142 + u_int8_t udi_config;
14143 + u_int8_t udi_speed;
14144 +#define USB_SPEED_UNKNOWN 0
14145 +#define USB_SPEED_LOW 1
14146 +#define USB_SPEED_FULL 2
14147 +#define USB_SPEED_HIGH 3
14148 +#define USB_SPEED_VARIABLE 4
14149 +#define USB_SPEED_SUPER 5
14150 + int udi_power; /* power consumption in mA, 0 if selfpowered */
14151 + int udi_nports;
14152 + char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
14153 + u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */
14154 +#define USB_PORT_ENABLED 0xff
14155 +#define USB_PORT_SUSPENDED 0xfe
14156 +#define USB_PORT_POWERED 0xfd
14157 +#define USB_PORT_DISABLED 0xfc
14158 +};
14159 +
14160 +struct usb_ctl_report {
14161 + int ucr_report;
14162 + u_char ucr_data[1024]; /* filled data size will vary */
14163 +};
14164 +
14165 +struct usb_device_stats {
14166 + u_long uds_requests[4]; /* indexed by transfer type UE_* */
14167 +};
14168 +
14169 +#define WUSB_MIN_IE 0x80
14170 +#define WUSB_WCTA_IE 0x80
14171 +#define WUSB_WCONNECTACK_IE 0x81
14172 +#define WUSB_WHOSTINFO_IE 0x82
14173 +#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
14174 +#define WUHI_CA_RECONN 0x00
14175 +#define WUHI_CA_LIMITED 0x01
14176 +#define WUHI_CA_ALL 0x03
14177 +#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
14178 +#define WUSB_WCHCHANGEANNOUNCE_IE 0x83
14179 +#define WUSB_WDEV_DISCONNECT_IE 0x84
14180 +#define WUSB_WHOST_DISCONNECT_IE 0x85
14181 +#define WUSB_WRELEASE_CHANNEL_IE 0x86
14182 +#define WUSB_WWORK_IE 0x87
14183 +#define WUSB_WCHANNEL_STOP_IE 0x88
14184 +#define WUSB_WDEV_KEEPALIVE_IE 0x89
14185 +#define WUSB_WISOCH_DISCARD_IE 0x8A
14186 +#define WUSB_WRESETDEVICE_IE 0x8B
14187 +#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C
14188 +#define WUSB_MAX_IE 0x8C
14189 +
14190 +/* Device Notification Types */
14191 +
14192 +#define WUSB_DN_MIN 0x01
14193 +#define WUSB_DN_CONNECT 0x01
14194 +# define WUSB_DA_OLDCONN 0x00
14195 +# define WUSB_DA_NEWCONN 0x01
14196 +# define WUSB_DA_SELF_BEACON 0x02
14197 +# define WUSB_DA_DIR_BEACON 0x04
14198 +# define WUSB_DA_NO_BEACON 0x06
14199 +#define WUSB_DN_DISCONNECT 0x02
14200 +#define WUSB_DN_EPRDY 0x03
14201 +#define WUSB_DN_MASAVAILCHANGED 0x04
14202 +#define WUSB_DN_REMOTEWAKEUP 0x05
14203 +#define WUSB_DN_SLEEP 0x06
14204 +#define WUSB_DN_ALIVE 0x07
14205 +#define WUSB_DN_MAX 0x07
14206 +
14207 +#ifdef _MSC_VER
14208 +#include <pshpack1.h>
14209 +#endif
14210 +
14211 +/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */
14212 +typedef struct wusb_hndshk_data {
14213 + uByte bMessageNumber;
14214 + uByte bStatus;
14215 + uByte tTKID[3];
14216 + uByte bReserved;
14217 + uByte CDID[16];
14218 + uByte Nonce[16];
14219 + uByte MIC[8];
14220 +} UPACKED wusb_hndshk_data_t;
14221 +#define WUSB_HANDSHAKE_LEN_FOR_MIC 38
14222 +
14223 +/* WUSB Connection Context */
14224 +typedef struct wusb_conn_context {
14225 + uByte CHID [16];
14226 + uByte CDID [16];
14227 + uByte CK [16];
14228 +} UPACKED wusb_conn_context_t;
14229 +
14230 +/* WUSB Security Descriptor */
14231 +typedef struct wusb_security_desc {
14232 + uByte bLength;
14233 + uByte bDescriptorType;
14234 + uWord wTotalLength;
14235 + uByte bNumEncryptionTypes;
14236 +} UPACKED wusb_security_desc_t;
14237 +
14238 +/* WUSB Encryption Type Descriptor */
14239 +typedef struct wusb_encrypt_type_desc {
14240 + uByte bLength;
14241 + uByte bDescriptorType;
14242 +
14243 + uByte bEncryptionType;
14244 +#define WUETD_UNSECURE 0
14245 +#define WUETD_WIRED 1
14246 +#define WUETD_CCM_1 2
14247 +#define WUETD_RSA_1 3
14248 +
14249 + uByte bEncryptionValue;
14250 + uByte bAuthKeyIndex;
14251 +} UPACKED wusb_encrypt_type_desc_t;
14252 +
14253 +/* WUSB Key Descriptor */
14254 +typedef struct wusb_key_desc {
14255 + uByte bLength;
14256 + uByte bDescriptorType;
14257 + uByte tTKID[3];
14258 + uByte bReserved;
14259 + uByte KeyData[1]; /* variable length */
14260 +} UPACKED wusb_key_desc_t;
14261 +
14262 +/* WUSB BOS Descriptor (Binary device Object Store) */
14263 +typedef struct wusb_bos_desc {
14264 + uByte bLength;
14265 + uByte bDescriptorType;
14266 + uWord wTotalLength;
14267 + uByte bNumDeviceCaps;
14268 +} UPACKED wusb_bos_desc_t;
14269 +
14270 +#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02
14271 +typedef struct usb_dev_cap_20_ext_desc {
14272 + uByte bLength;
14273 + uByte bDescriptorType;
14274 + uByte bDevCapabilityType;
14275 +#define USB_20_EXT_LPM 0x02
14276 + uDWord bmAttributes;
14277 +} UPACKED usb_dev_cap_20_ext_desc_t;
14278 +
14279 +#define USB_DEVICE_CAPABILITY_SS_USB 0x03
14280 +typedef struct usb_dev_cap_ss_usb {
14281 + uByte bLength;
14282 + uByte bDescriptorType;
14283 + uByte bDevCapabilityType;
14284 +#define USB_DC_SS_USB_LTM_CAPABLE 0x02
14285 + uByte bmAttributes;
14286 +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01
14287 +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02
14288 +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04
14289 +#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08
14290 + uWord wSpeedsSupported;
14291 + uByte bFunctionalitySupport;
14292 + uByte bU1DevExitLat;
14293 + uWord wU2DevExitLat;
14294 +} UPACKED usb_dev_cap_ss_usb_t;
14295 +
14296 +#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04
14297 +typedef struct usb_dev_cap_container_id {
14298 + uByte bLength;
14299 + uByte bDescriptorType;
14300 + uByte bDevCapabilityType;
14301 + uByte bReserved;
14302 + uByte containerID[16];
14303 +} UPACKED usb_dev_cap_container_id_t;
14304 +
14305 +/* Device Capability Type Codes */
14306 +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
14307 +
14308 +/* Device Capability Descriptor */
14309 +typedef struct wusb_dev_cap_desc {
14310 + uByte bLength;
14311 + uByte bDescriptorType;
14312 + uByte bDevCapabilityType;
14313 + uByte caps[1]; /* Variable length */
14314 +} UPACKED wusb_dev_cap_desc_t;
14315 +
14316 +/* Device Capability Descriptor */
14317 +typedef struct wusb_dev_cap_uwb_desc {
14318 + uByte bLength;
14319 + uByte bDescriptorType;
14320 + uByte bDevCapabilityType;
14321 + uByte bmAttributes;
14322 + uWord wPHYRates; /* Bitmap */
14323 + uByte bmTFITXPowerInfo;
14324 + uByte bmFFITXPowerInfo;
14325 + uWord bmBandGroup;
14326 + uByte bReserved;
14327 +} UPACKED wusb_dev_cap_uwb_desc_t;
14328 +
14329 +/* Wireless USB Endpoint Companion Descriptor */
14330 +typedef struct wusb_endpoint_companion_desc {
14331 + uByte bLength;
14332 + uByte bDescriptorType;
14333 + uByte bMaxBurst;
14334 + uByte bMaxSequence;
14335 + uWord wMaxStreamDelay;
14336 + uWord wOverTheAirPacketSize;
14337 + uByte bOverTheAirInterval;
14338 + uByte bmCompAttributes;
14339 +} UPACKED wusb_endpoint_companion_desc_t;
14340 +
14341 +/* Wireless USB Numeric Association M1 Data Structure */
14342 +typedef struct wusb_m1_data {
14343 + uByte version;
14344 + uWord langId;
14345 + uByte deviceFriendlyNameLength;
14346 + uByte sha_256_m3[32];
14347 + uByte deviceFriendlyName[256];
14348 +} UPACKED wusb_m1_data_t;
14349 +
14350 +typedef struct wusb_m2_data {
14351 + uByte version;
14352 + uWord langId;
14353 + uByte hostFriendlyNameLength;
14354 + uByte pkh[384];
14355 + uByte hostFriendlyName[256];
14356 +} UPACKED wusb_m2_data_t;
14357 +
14358 +typedef struct wusb_m3_data {
14359 + uByte pkd[384];
14360 + uByte nd;
14361 +} UPACKED wusb_m3_data_t;
14362 +
14363 +typedef struct wusb_m4_data {
14364 + uDWord _attributeTypeIdAndLength_1;
14365 + uWord associationTypeId;
14366 +
14367 + uDWord _attributeTypeIdAndLength_2;
14368 + uWord associationSubTypeId;
14369 +
14370 + uDWord _attributeTypeIdAndLength_3;
14371 + uDWord length;
14372 +
14373 + uDWord _attributeTypeIdAndLength_4;
14374 + uDWord associationStatus;
14375 +
14376 + uDWord _attributeTypeIdAndLength_5;
14377 + uByte chid[16];
14378 +
14379 + uDWord _attributeTypeIdAndLength_6;
14380 + uByte cdid[16];
14381 +
14382 + uDWord _attributeTypeIdAndLength_7;
14383 + uByte bandGroups[2];
14384 +} UPACKED wusb_m4_data_t;
14385 +
14386 +#ifdef _MSC_VER
14387 +#include <poppack.h>
14388 +#endif
14389 +
14390 +#ifdef __cplusplus
14391 +}
14392 +#endif
14393 +
14394 +#endif /* _USB_H_ */
14395 diff -urN linux-3.10/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-rpi-3.10.y/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14396 --- linux-3.10/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
14397 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2013-07-06 15:25:50.000000000 +0100
14398 @@ -0,0 +1,224 @@
14399 +# Doxyfile 1.3.9.1
14400 +
14401 +#---------------------------------------------------------------------------
14402 +# Project related configuration options
14403 +#---------------------------------------------------------------------------
14404 +PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"
14405 +PROJECT_NUMBER = v3.00a
14406 +OUTPUT_DIRECTORY = ./doc/
14407 +CREATE_SUBDIRS = NO
14408 +OUTPUT_LANGUAGE = English
14409 +BRIEF_MEMBER_DESC = YES
14410 +REPEAT_BRIEF = YES
14411 +ABBREVIATE_BRIEF = "The $name class" \
14412 + "The $name widget" \
14413 + "The $name file" \
14414 + is \
14415 + provides \
14416 + specifies \
14417 + contains \
14418 + represents \
14419 + a \
14420 + an \
14421 + the
14422 +ALWAYS_DETAILED_SEC = NO
14423 +INLINE_INHERITED_MEMB = NO
14424 +FULL_PATH_NAMES = NO
14425 +STRIP_FROM_PATH =
14426 +STRIP_FROM_INC_PATH =
14427 +SHORT_NAMES = NO
14428 +JAVADOC_AUTOBRIEF = YES
14429 +MULTILINE_CPP_IS_BRIEF = NO
14430 +INHERIT_DOCS = YES
14431 +DISTRIBUTE_GROUP_DOC = NO
14432 +TAB_SIZE = 8
14433 +ALIASES =
14434 +OPTIMIZE_OUTPUT_FOR_C = YES
14435 +OPTIMIZE_OUTPUT_JAVA = NO
14436 +SUBGROUPING = YES
14437 +#---------------------------------------------------------------------------
14438 +# Build related configuration options
14439 +#---------------------------------------------------------------------------
14440 +EXTRACT_ALL = NO
14441 +EXTRACT_PRIVATE = YES
14442 +EXTRACT_STATIC = YES
14443 +EXTRACT_LOCAL_CLASSES = YES
14444 +EXTRACT_LOCAL_METHODS = NO
14445 +HIDE_UNDOC_MEMBERS = NO
14446 +HIDE_UNDOC_CLASSES = NO
14447 +HIDE_FRIEND_COMPOUNDS = NO
14448 +HIDE_IN_BODY_DOCS = NO
14449 +INTERNAL_DOCS = NO
14450 +CASE_SENSE_NAMES = NO
14451 +HIDE_SCOPE_NAMES = NO
14452 +SHOW_INCLUDE_FILES = YES
14453 +INLINE_INFO = YES
14454 +SORT_MEMBER_DOCS = NO
14455 +SORT_BRIEF_DOCS = NO
14456 +SORT_BY_SCOPE_NAME = NO
14457 +GENERATE_TODOLIST = YES
14458 +GENERATE_TESTLIST = YES
14459 +GENERATE_BUGLIST = YES
14460 +GENERATE_DEPRECATEDLIST= YES
14461 +ENABLED_SECTIONS =
14462 +MAX_INITIALIZER_LINES = 30
14463 +SHOW_USED_FILES = YES
14464 +SHOW_DIRECTORIES = YES
14465 +#---------------------------------------------------------------------------
14466 +# configuration options related to warning and progress messages
14467 +#---------------------------------------------------------------------------
14468 +QUIET = YES
14469 +WARNINGS = YES
14470 +WARN_IF_UNDOCUMENTED = NO
14471 +WARN_IF_DOC_ERROR = YES
14472 +WARN_FORMAT = "$file:$line: $text"
14473 +WARN_LOGFILE =
14474 +#---------------------------------------------------------------------------
14475 +# configuration options related to the input files
14476 +#---------------------------------------------------------------------------
14477 +INPUT = .
14478 +FILE_PATTERNS = *.c \
14479 + *.h \
14480 + ./linux/*.c \
14481 + ./linux/*.h
14482 +RECURSIVE = NO
14483 +EXCLUDE = ./test/ \
14484 + ./dwc_otg/.AppleDouble/
14485 +EXCLUDE_SYMLINKS = YES
14486 +EXCLUDE_PATTERNS = *.mod.*
14487 +EXAMPLE_PATH =
14488 +EXAMPLE_PATTERNS = *
14489 +EXAMPLE_RECURSIVE = NO
14490 +IMAGE_PATH =
14491 +INPUT_FILTER =
14492 +FILTER_PATTERNS =
14493 +FILTER_SOURCE_FILES = NO
14494 +#---------------------------------------------------------------------------
14495 +# configuration options related to source browsing
14496 +#---------------------------------------------------------------------------
14497 +SOURCE_BROWSER = YES
14498 +INLINE_SOURCES = NO
14499 +STRIP_CODE_COMMENTS = YES
14500 +REFERENCED_BY_RELATION = NO
14501 +REFERENCES_RELATION = NO
14502 +VERBATIM_HEADERS = NO
14503 +#---------------------------------------------------------------------------
14504 +# configuration options related to the alphabetical class index
14505 +#---------------------------------------------------------------------------
14506 +ALPHABETICAL_INDEX = NO
14507 +COLS_IN_ALPHA_INDEX = 5
14508 +IGNORE_PREFIX =
14509 +#---------------------------------------------------------------------------
14510 +# configuration options related to the HTML output
14511 +#---------------------------------------------------------------------------
14512 +GENERATE_HTML = YES
14513 +HTML_OUTPUT = html
14514 +HTML_FILE_EXTENSION = .html
14515 +HTML_HEADER =
14516 +HTML_FOOTER =
14517 +HTML_STYLESHEET =
14518 +HTML_ALIGN_MEMBERS = YES
14519 +GENERATE_HTMLHELP = NO
14520 +CHM_FILE =
14521 +HHC_LOCATION =
14522 +GENERATE_CHI = NO
14523 +BINARY_TOC = NO
14524 +TOC_EXPAND = NO
14525 +DISABLE_INDEX = NO
14526 +ENUM_VALUES_PER_LINE = 4
14527 +GENERATE_TREEVIEW = YES
14528 +TREEVIEW_WIDTH = 250
14529 +#---------------------------------------------------------------------------
14530 +# configuration options related to the LaTeX output
14531 +#---------------------------------------------------------------------------
14532 +GENERATE_LATEX = NO
14533 +LATEX_OUTPUT = latex
14534 +LATEX_CMD_NAME = latex
14535 +MAKEINDEX_CMD_NAME = makeindex
14536 +COMPACT_LATEX = NO
14537 +PAPER_TYPE = a4wide
14538 +EXTRA_PACKAGES =
14539 +LATEX_HEADER =
14540 +PDF_HYPERLINKS = NO
14541 +USE_PDFLATEX = NO
14542 +LATEX_BATCHMODE = NO
14543 +LATEX_HIDE_INDICES = NO
14544 +#---------------------------------------------------------------------------
14545 +# configuration options related to the RTF output
14546 +#---------------------------------------------------------------------------
14547 +GENERATE_RTF = NO
14548 +RTF_OUTPUT = rtf
14549 +COMPACT_RTF = NO
14550 +RTF_HYPERLINKS = NO
14551 +RTF_STYLESHEET_FILE =
14552 +RTF_EXTENSIONS_FILE =
14553 +#---------------------------------------------------------------------------
14554 +# configuration options related to the man page output
14555 +#---------------------------------------------------------------------------
14556 +GENERATE_MAN = NO
14557 +MAN_OUTPUT = man
14558 +MAN_EXTENSION = .3
14559 +MAN_LINKS = NO
14560 +#---------------------------------------------------------------------------
14561 +# configuration options related to the XML output
14562 +#---------------------------------------------------------------------------
14563 +GENERATE_XML = NO
14564 +XML_OUTPUT = xml
14565 +XML_SCHEMA =
14566 +XML_DTD =
14567 +XML_PROGRAMLISTING = YES
14568 +#---------------------------------------------------------------------------
14569 +# configuration options for the AutoGen Definitions output
14570 +#---------------------------------------------------------------------------
14571 +GENERATE_AUTOGEN_DEF = NO
14572 +#---------------------------------------------------------------------------
14573 +# configuration options related to the Perl module output
14574 +#---------------------------------------------------------------------------
14575 +GENERATE_PERLMOD = NO
14576 +PERLMOD_LATEX = NO
14577 +PERLMOD_PRETTY = YES
14578 +PERLMOD_MAKEVAR_PREFIX =
14579 +#---------------------------------------------------------------------------
14580 +# Configuration options related to the preprocessor
14581 +#---------------------------------------------------------------------------
14582 +ENABLE_PREPROCESSING = YES
14583 +MACRO_EXPANSION = YES
14584 +EXPAND_ONLY_PREDEF = YES
14585 +SEARCH_INCLUDES = YES
14586 +INCLUDE_PATH =
14587 +INCLUDE_FILE_PATTERNS =
14588 +PREDEFINED = DEVICE_ATTR DWC_EN_ISOC
14589 +EXPAND_AS_DEFINED = DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW DWC_OTG_DEVICE_ATTR_BITFIELD_STORE DWC_OTG_DEVICE_ATTR_BITFIELD_RW DWC_OTG_DEVICE_ATTR_BITFIELD_RO DWC_OTG_DEVICE_ATTR_REG_SHOW DWC_OTG_DEVICE_ATTR_REG_STORE DWC_OTG_DEVICE_ATTR_REG32_RW DWC_OTG_DEVICE_ATTR_REG32_RO DWC_EN_ISOC
14590 +SKIP_FUNCTION_MACROS = NO
14591 +#---------------------------------------------------------------------------
14592 +# Configuration::additions related to external references
14593 +#---------------------------------------------------------------------------
14594 +TAGFILES =
14595 +GENERATE_TAGFILE =
14596 +ALLEXTERNALS = NO
14597 +EXTERNAL_GROUPS = YES
14598 +PERL_PATH = /usr/bin/perl
14599 +#---------------------------------------------------------------------------
14600 +# Configuration options related to the dot tool
14601 +#---------------------------------------------------------------------------
14602 +CLASS_DIAGRAMS = YES
14603 +HIDE_UNDOC_RELATIONS = YES
14604 +HAVE_DOT = NO
14605 +CLASS_GRAPH = YES
14606 +COLLABORATION_GRAPH = YES
14607 +UML_LOOK = NO
14608 +TEMPLATE_RELATIONS = NO
14609 +INCLUDE_GRAPH = YES
14610 +INCLUDED_BY_GRAPH = YES
14611 +CALL_GRAPH = NO
14612 +GRAPHICAL_HIERARCHY = YES
14613 +DOT_IMAGE_FORMAT = png
14614 +DOT_PATH =
14615 +DOTFILE_DIRS =
14616 +MAX_DOT_GRAPH_DEPTH = 1000
14617 +GENERATE_LEGEND = YES
14618 +DOT_CLEANUP = YES
14619 +#---------------------------------------------------------------------------
14620 +# Configuration::additions related to the search engine
14621 +#---------------------------------------------------------------------------
14622 +SEARCHENGINE = NO
14623 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dummy_audio.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dummy_audio.c
14624 --- linux-3.10/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100
14625 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dummy_audio.c 2013-07-06 15:25:50.000000000 +0100
14626 @@ -0,0 +1,1575 @@
14627 +/*
14628 + * zero.c -- Gadget Zero, for USB development
14629 + *
14630 + * Copyright (C) 2003-2004 David Brownell
14631 + * All rights reserved.
14632 + *
14633 + * Redistribution and use in source and binary forms, with or without
14634 + * modification, are permitted provided that the following conditions
14635 + * are met:
14636 + * 1. Redistributions of source code must retain the above copyright
14637 + * notice, this list of conditions, and the following disclaimer,
14638 + * without modification.
14639 + * 2. Redistributions in binary form must reproduce the above copyright
14640 + * notice, this list of conditions and the following disclaimer in the
14641 + * documentation and/or other materials provided with the distribution.
14642 + * 3. The names of the above-listed copyright holders may not be used
14643 + * to endorse or promote products derived from this software without
14644 + * specific prior written permission.
14645 + *
14646 + * ALTERNATIVELY, this software may be distributed under the terms of the
14647 + * GNU General Public License ("GPL") as published by the Free Software
14648 + * Foundation, either version 2 of that License or (at your option) any
14649 + * later version.
14650 + *
14651 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
14652 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14653 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14654 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14655 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14656 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14657 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14658 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14659 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14660 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14661 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14662 + */
14663 +
14664 +
14665 +/*
14666 + * Gadget Zero only needs two bulk endpoints, and is an example of how you
14667 + * can write a hardware-agnostic gadget driver running inside a USB device.
14668 + *
14669 + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
14670 + * affect most of the driver.
14671 + *
14672 + * Use it with the Linux host/master side "usbtest" driver to get a basic
14673 + * functional test of your device-side usb stack, or with "usb-skeleton".
14674 + *
14675 + * It supports two similar configurations. One sinks whatever the usb host
14676 + * writes, and in return sources zeroes. The other loops whatever the host
14677 + * writes back, so the host can read it. Module options include:
14678 + *
14679 + * buflen=N default N=4096, buffer size used
14680 + * qlen=N default N=32, how many buffers in the loopback queue
14681 + * loopdefault default false, list loopback config first
14682 + *
14683 + * Many drivers will only have one configuration, letting them be much
14684 + * simpler if they also don't support high speed operation (like this
14685 + * driver does).
14686 + */
14687 +
14688 +#include <linux/config.h>
14689 +#include <linux/module.h>
14690 +#include <linux/kernel.h>
14691 +#include <linux/delay.h>
14692 +#include <linux/ioport.h>
14693 +#include <linux/sched.h>
14694 +#include <linux/slab.h>
14695 +#include <linux/smp_lock.h>
14696 +#include <linux/errno.h>
14697 +#include <linux/init.h>
14698 +#include <linux/timer.h>
14699 +#include <linux/list.h>
14700 +#include <linux/interrupt.h>
14701 +#include <linux/uts.h>
14702 +#include <linux/version.h>
14703 +#include <linux/device.h>
14704 +#include <linux/moduleparam.h>
14705 +#include <linux/proc_fs.h>
14706 +
14707 +#include <asm/byteorder.h>
14708 +#include <asm/io.h>
14709 +#include <asm/irq.h>
14710 +#include <asm/system.h>
14711 +#include <asm/unaligned.h>
14712 +
14713 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
14714 +# include <linux/usb/ch9.h>
14715 +#else
14716 +# include <linux/usb_ch9.h>
14717 +#endif
14718 +
14719 +#include <linux/usb_gadget.h>
14720 +
14721 +
14722 +/*-------------------------------------------------------------------------*/
14723 +/*-------------------------------------------------------------------------*/
14724 +
14725 +
14726 +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
14727 +{
14728 + int count = 0;
14729 + u8 c;
14730 + u16 uchar;
14731 +
14732 + /* this insists on correct encodings, though not minimal ones.
14733 + * BUT it currently rejects legit 4-byte UTF-8 code points,
14734 + * which need surrogate pairs. (Unicode 3.1 can use them.)
14735 + */
14736 + while (len != 0 && (c = (u8) *s++) != 0) {
14737 + if (unlikely(c & 0x80)) {
14738 + // 2-byte sequence:
14739 + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
14740 + if ((c & 0xe0) == 0xc0) {
14741 + uchar = (c & 0x1f) << 6;
14742 +
14743 + c = (u8) *s++;
14744 + if ((c & 0xc0) != 0xc0)
14745 + goto fail;
14746 + c &= 0x3f;
14747 + uchar |= c;
14748 +
14749 + // 3-byte sequence (most CJKV characters):
14750 + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
14751 + } else if ((c & 0xf0) == 0xe0) {
14752 + uchar = (c & 0x0f) << 12;
14753 +
14754 + c = (u8) *s++;
14755 + if ((c & 0xc0) != 0xc0)
14756 + goto fail;
14757 + c &= 0x3f;
14758 + uchar |= c << 6;
14759 +
14760 + c = (u8) *s++;
14761 + if ((c & 0xc0) != 0xc0)
14762 + goto fail;
14763 + c &= 0x3f;
14764 + uchar |= c;
14765 +
14766 + /* no bogus surrogates */
14767 + if (0xd800 <= uchar && uchar <= 0xdfff)
14768 + goto fail;
14769 +
14770 + // 4-byte sequence (surrogate pairs, currently rare):
14771 + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
14772 + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
14773 + // (uuuuu = wwww + 1)
14774 + // FIXME accept the surrogate code points (only)
14775 +
14776 + } else
14777 + goto fail;
14778 + } else
14779 + uchar = c;
14780 + put_unaligned (cpu_to_le16 (uchar), cp++);
14781 + count++;
14782 + len--;
14783 + }
14784 + return count;
14785 +fail:
14786 + return -1;
14787 +}
14788 +
14789 +
14790 +/**
14791 + * usb_gadget_get_string - fill out a string descriptor
14792 + * @table: of c strings encoded using UTF-8
14793 + * @id: string id, from low byte of wValue in get string descriptor
14794 + * @buf: at least 256 bytes
14795 + *
14796 + * Finds the UTF-8 string matching the ID, and converts it into a
14797 + * string descriptor in utf16-le.
14798 + * Returns length of descriptor (always even) or negative errno
14799 + *
14800 + * If your driver needs stings in multiple languages, you'll probably
14801 + * "switch (wIndex) { ... }" in your ep0 string descriptor logic,
14802 + * using this routine after choosing which set of UTF-8 strings to use.
14803 + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
14804 + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
14805 + * characters (which are also widely used in C strings).
14806 + */
14807 +int
14808 +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
14809 +{
14810 + struct usb_string *s;
14811 + int len;
14812 +
14813 + /* descriptor 0 has the language id */
14814 + if (id == 0) {
14815 + buf [0] = 4;
14816 + buf [1] = USB_DT_STRING;
14817 + buf [2] = (u8) table->language;
14818 + buf [3] = (u8) (table->language >> 8);
14819 + return 4;
14820 + }
14821 + for (s = table->strings; s && s->s; s++)
14822 + if (s->id == id)
14823 + break;
14824 +
14825 + /* unrecognized: stall. */
14826 + if (!s || !s->s)
14827 + return -EINVAL;
14828 +
14829 + /* string descriptors have length, tag, then UTF16-LE text */
14830 + len = min ((size_t) 126, strlen (s->s));
14831 + memset (buf + 2, 0, 2 * len); /* zero all the bytes */
14832 + len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
14833 + if (len < 0)
14834 + return -EINVAL;
14835 + buf [0] = (len + 1) * 2;
14836 + buf [1] = USB_DT_STRING;
14837 + return buf [0];
14838 +}
14839 +
14840 +
14841 +/*-------------------------------------------------------------------------*/
14842 +/*-------------------------------------------------------------------------*/
14843 +
14844 +
14845 +/**
14846 + * usb_descriptor_fillbuf - fill buffer with descriptors
14847 + * @buf: Buffer to be filled
14848 + * @buflen: Size of buf
14849 + * @src: Array of descriptor pointers, terminated by null pointer.
14850 + *
14851 + * Copies descriptors into the buffer, returning the length or a
14852 + * negative error code if they can't all be copied. Useful when
14853 + * assembling descriptors for an associated set of interfaces used
14854 + * as part of configuring a composite device; or in other cases where
14855 + * sets of descriptors need to be marshaled.
14856 + */
14857 +int
14858 +usb_descriptor_fillbuf(void *buf, unsigned buflen,
14859 + const struct usb_descriptor_header **src)
14860 +{
14861 + u8 *dest = buf;
14862 +
14863 + if (!src)
14864 + return -EINVAL;
14865 +
14866 + /* fill buffer from src[] until null descriptor ptr */
14867 + for (; 0 != *src; src++) {
14868 + unsigned len = (*src)->bLength;
14869 +
14870 + if (len > buflen)
14871 + return -EINVAL;
14872 + memcpy(dest, *src, len);
14873 + buflen -= len;
14874 + dest += len;
14875 + }
14876 + return dest - (u8 *)buf;
14877 +}
14878 +
14879 +
14880 +/**
14881 + * usb_gadget_config_buf - builts a complete configuration descriptor
14882 + * @config: Header for the descriptor, including characteristics such
14883 + * as power requirements and number of interfaces.
14884 + * @desc: Null-terminated vector of pointers to the descriptors (interface,
14885 + * endpoint, etc) defining all functions in this device configuration.
14886 + * @buf: Buffer for the resulting configuration descriptor.
14887 + * @length: Length of buffer. If this is not big enough to hold the
14888 + * entire configuration descriptor, an error code will be returned.
14889 + *
14890 + * This copies descriptors into the response buffer, building a descriptor
14891 + * for that configuration. It returns the buffer length or a negative
14892 + * status code. The config.wTotalLength field is set to match the length
14893 + * of the result, but other descriptor fields (including power usage and
14894 + * interface count) must be set by the caller.
14895 + *
14896 + * Gadget drivers could use this when constructing a config descriptor
14897 + * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the
14898 + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
14899 + */
14900 +int usb_gadget_config_buf(
14901 + const struct usb_config_descriptor *config,
14902 + void *buf,
14903 + unsigned length,
14904 + const struct usb_descriptor_header **desc
14905 +)
14906 +{
14907 + struct usb_config_descriptor *cp = buf;
14908 + int len;
14909 +
14910 + /* config descriptor first */
14911 + if (length < USB_DT_CONFIG_SIZE || !desc)
14912 + return -EINVAL;
14913 + *cp = *config;
14914 +
14915 + /* then interface/endpoint/class/vendor/... */
14916 + len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
14917 + length - USB_DT_CONFIG_SIZE, desc);
14918 + if (len < 0)
14919 + return len;
14920 + len += USB_DT_CONFIG_SIZE;
14921 + if (len > 0xffff)
14922 + return -EINVAL;
14923 +
14924 + /* patch up the config descriptor */
14925 + cp->bLength = USB_DT_CONFIG_SIZE;
14926 + cp->bDescriptorType = USB_DT_CONFIG;
14927 + cp->wTotalLength = cpu_to_le16(len);
14928 + cp->bmAttributes |= USB_CONFIG_ATT_ONE;
14929 + return len;
14930 +}
14931 +
14932 +/*-------------------------------------------------------------------------*/
14933 +/*-------------------------------------------------------------------------*/
14934 +
14935 +
14936 +#define RBUF_LEN (1024*1024)
14937 +static int rbuf_start;
14938 +static int rbuf_len;
14939 +static __u8 rbuf[RBUF_LEN];
14940 +
14941 +/*-------------------------------------------------------------------------*/
14942 +
14943 +#define DRIVER_VERSION "St Patrick's Day 2004"
14944 +
14945 +static const char shortname [] = "zero";
14946 +static const char longname [] = "YAMAHA YST-MS35D USB Speaker ";
14947 +
14948 +static const char source_sink [] = "source and sink data";
14949 +static const char loopback [] = "loop input to output";
14950 +
14951 +/*-------------------------------------------------------------------------*/
14952 +
14953 +/*
14954 + * driver assumes self-powered hardware, and
14955 + * has no way for users to trigger remote wakeup.
14956 + *
14957 + * this version autoconfigures as much as possible,
14958 + * which is reasonable for most "bulk-only" drivers.
14959 + */
14960 +static const char *EP_IN_NAME; /* source */
14961 +static const char *EP_OUT_NAME; /* sink */
14962 +
14963 +/*-------------------------------------------------------------------------*/
14964 +
14965 +/* big enough to hold our biggest descriptor */
14966 +#define USB_BUFSIZ 512
14967 +
14968 +struct zero_dev {
14969 + spinlock_t lock;
14970 + struct usb_gadget *gadget;
14971 + struct usb_request *req; /* for control responses */
14972 +
14973 + /* when configured, we have one of two configs:
14974 + * - source data (in to host) and sink it (out from host)
14975 + * - or loop it back (out from host back in to host)
14976 + */
14977 + u8 config;
14978 + struct usb_ep *in_ep, *out_ep;
14979 +
14980 + /* autoresume timer */
14981 + struct timer_list resume;
14982 +};
14983 +
14984 +#define xprintk(d,level,fmt,args...) \
14985 + dev_printk(level , &(d)->gadget->dev , fmt , ## args)
14986 +
14987 +#ifdef DEBUG
14988 +#define DBG(dev,fmt,args...) \
14989 + xprintk(dev , KERN_DEBUG , fmt , ## args)
14990 +#else
14991 +#define DBG(dev,fmt,args...) \
14992 + do { } while (0)
14993 +#endif /* DEBUG */
14994 +
14995 +#ifdef VERBOSE
14996 +#define VDBG DBG
14997 +#else
14998 +#define VDBG(dev,fmt,args...) \
14999 + do { } while (0)
15000 +#endif /* VERBOSE */
15001 +
15002 +#define ERROR(dev,fmt,args...) \
15003 + xprintk(dev , KERN_ERR , fmt , ## args)
15004 +#define WARN(dev,fmt,args...) \
15005 + xprintk(dev , KERN_WARNING , fmt , ## args)
15006 +#define INFO(dev,fmt,args...) \
15007 + xprintk(dev , KERN_INFO , fmt , ## args)
15008 +
15009 +/*-------------------------------------------------------------------------*/
15010 +
15011 +static unsigned buflen = 4096;
15012 +static unsigned qlen = 32;
15013 +static unsigned pattern = 0;
15014 +
15015 +module_param (buflen, uint, S_IRUGO|S_IWUSR);
15016 +module_param (qlen, uint, S_IRUGO|S_IWUSR);
15017 +module_param (pattern, uint, S_IRUGO|S_IWUSR);
15018 +
15019 +/*
15020 + * if it's nonzero, autoresume says how many seconds to wait
15021 + * before trying to wake up the host after suspend.
15022 + */
15023 +static unsigned autoresume = 0;
15024 +module_param (autoresume, uint, 0);
15025 +
15026 +/*
15027 + * Normally the "loopback" configuration is second (index 1) so
15028 + * it's not the default. Here's where to change that order, to
15029 + * work better with hosts where config changes are problematic.
15030 + * Or controllers (like superh) that only support one config.
15031 + */
15032 +static int loopdefault = 0;
15033 +
15034 +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
15035 +
15036 +/*-------------------------------------------------------------------------*/
15037 +
15038 +/* Thanks to NetChip Technologies for donating this product ID.
15039 + *
15040 + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
15041 + * Instead: allocate your own, using normal USB-IF procedures.
15042 + */
15043 +#ifndef CONFIG_USB_ZERO_HNPTEST
15044 +#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
15045 +#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */
15046 +#else
15047 +#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */
15048 +#define DRIVER_PRODUCT_NUM 0xbadd
15049 +#endif
15050 +
15051 +/*-------------------------------------------------------------------------*/
15052 +
15053 +/*
15054 + * DESCRIPTORS ... most are static, but strings and (full)
15055 + * configuration descriptors are built on demand.
15056 + */
15057 +
15058 +/*
15059 +#define STRING_MANUFACTURER 25
15060 +#define STRING_PRODUCT 42
15061 +#define STRING_SERIAL 101
15062 +*/
15063 +#define STRING_MANUFACTURER 1
15064 +#define STRING_PRODUCT 2
15065 +#define STRING_SERIAL 3
15066 +
15067 +#define STRING_SOURCE_SINK 250
15068 +#define STRING_LOOPBACK 251
15069 +
15070 +/*
15071 + * This device advertises two configurations; these numbers work
15072 + * on a pxa250 as well as more flexible hardware.
15073 + */
15074 +#define CONFIG_SOURCE_SINK 3
15075 +#define CONFIG_LOOPBACK 2
15076 +
15077 +/*
15078 +static struct usb_device_descriptor
15079 +device_desc = {
15080 + .bLength = sizeof device_desc,
15081 + .bDescriptorType = USB_DT_DEVICE,
15082 +
15083 + .bcdUSB = __constant_cpu_to_le16 (0x0200),
15084 + .bDeviceClass = USB_CLASS_VENDOR_SPEC,
15085 +
15086 + .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
15087 + .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
15088 + .iManufacturer = STRING_MANUFACTURER,
15089 + .iProduct = STRING_PRODUCT,
15090 + .iSerialNumber = STRING_SERIAL,
15091 + .bNumConfigurations = 2,
15092 +};
15093 +*/
15094 +static struct usb_device_descriptor
15095 +device_desc = {
15096 + .bLength = sizeof device_desc,
15097 + .bDescriptorType = USB_DT_DEVICE,
15098 + .bcdUSB = __constant_cpu_to_le16 (0x0100),
15099 + .bDeviceClass = USB_CLASS_PER_INTERFACE,
15100 + .bDeviceSubClass = 0,
15101 + .bDeviceProtocol = 0,
15102 + .bMaxPacketSize0 = 64,
15103 + .bcdDevice = __constant_cpu_to_le16 (0x0100),
15104 + .idVendor = __constant_cpu_to_le16 (0x0499),
15105 + .idProduct = __constant_cpu_to_le16 (0x3002),
15106 + .iManufacturer = STRING_MANUFACTURER,
15107 + .iProduct = STRING_PRODUCT,
15108 + .iSerialNumber = STRING_SERIAL,
15109 + .bNumConfigurations = 1,
15110 +};
15111 +
15112 +static struct usb_config_descriptor
15113 +z_config = {
15114 + .bLength = sizeof z_config,
15115 + .bDescriptorType = USB_DT_CONFIG,
15116 +
15117 + /* compute wTotalLength on the fly */
15118 + .bNumInterfaces = 2,
15119 + .bConfigurationValue = 1,
15120 + .iConfiguration = 0,
15121 + .bmAttributes = 0x40,
15122 + .bMaxPower = 0, /* self-powered */
15123 +};
15124 +
15125 +
15126 +static struct usb_otg_descriptor
15127 +otg_descriptor = {
15128 + .bLength = sizeof otg_descriptor,
15129 + .bDescriptorType = USB_DT_OTG,
15130 +
15131 + .bmAttributes = USB_OTG_SRP,
15132 +};
15133 +
15134 +/* one interface in each configuration */
15135 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15136 +
15137 +/*
15138 + * usb 2.0 devices need to expose both high speed and full speed
15139 + * descriptors, unless they only run at full speed.
15140 + *
15141 + * that means alternate endpoint descriptors (bigger packets)
15142 + * and a "device qualifier" ... plus more construction options
15143 + * for the config descriptor.
15144 + */
15145 +
15146 +static struct usb_qualifier_descriptor
15147 +dev_qualifier = {
15148 + .bLength = sizeof dev_qualifier,
15149 + .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
15150 +
15151 + .bcdUSB = __constant_cpu_to_le16 (0x0200),
15152 + .bDeviceClass = USB_CLASS_VENDOR_SPEC,
15153 +
15154 + .bNumConfigurations = 2,
15155 +};
15156 +
15157 +
15158 +struct usb_cs_as_general_descriptor {
15159 + __u8 bLength;
15160 + __u8 bDescriptorType;
15161 +
15162 + __u8 bDescriptorSubType;
15163 + __u8 bTerminalLink;
15164 + __u8 bDelay;
15165 + __u16 wFormatTag;
15166 +} __attribute__ ((packed));
15167 +
15168 +struct usb_cs_as_format_descriptor {
15169 + __u8 bLength;
15170 + __u8 bDescriptorType;
15171 +
15172 + __u8 bDescriptorSubType;
15173 + __u8 bFormatType;
15174 + __u8 bNrChannels;
15175 + __u8 bSubframeSize;
15176 + __u8 bBitResolution;
15177 + __u8 bSamfreqType;
15178 + __u8 tLowerSamFreq[3];
15179 + __u8 tUpperSamFreq[3];
15180 +} __attribute__ ((packed));
15181 +
15182 +static const struct usb_interface_descriptor
15183 +z_audio_control_if_desc = {
15184 + .bLength = sizeof z_audio_control_if_desc,
15185 + .bDescriptorType = USB_DT_INTERFACE,
15186 + .bInterfaceNumber = 0,
15187 + .bAlternateSetting = 0,
15188 + .bNumEndpoints = 0,
15189 + .bInterfaceClass = USB_CLASS_AUDIO,
15190 + .bInterfaceSubClass = 0x1,
15191 + .bInterfaceProtocol = 0,
15192 + .iInterface = 0,
15193 +};
15194 +
15195 +static const struct usb_interface_descriptor
15196 +z_audio_if_desc = {
15197 + .bLength = sizeof z_audio_if_desc,
15198 + .bDescriptorType = USB_DT_INTERFACE,
15199 + .bInterfaceNumber = 1,
15200 + .bAlternateSetting = 0,
15201 + .bNumEndpoints = 0,
15202 + .bInterfaceClass = USB_CLASS_AUDIO,
15203 + .bInterfaceSubClass = 0x2,
15204 + .bInterfaceProtocol = 0,
15205 + .iInterface = 0,
15206 +};
15207 +
15208 +static const struct usb_interface_descriptor
15209 +z_audio_if_desc2 = {
15210 + .bLength = sizeof z_audio_if_desc,
15211 + .bDescriptorType = USB_DT_INTERFACE,
15212 + .bInterfaceNumber = 1,
15213 + .bAlternateSetting = 1,
15214 + .bNumEndpoints = 1,
15215 + .bInterfaceClass = USB_CLASS_AUDIO,
15216 + .bInterfaceSubClass = 0x2,
15217 + .bInterfaceProtocol = 0,
15218 + .iInterface = 0,
15219 +};
15220 +
15221 +static const struct usb_cs_as_general_descriptor
15222 +z_audio_cs_as_if_desc = {
15223 + .bLength = 7,
15224 + .bDescriptorType = 0x24,
15225 +
15226 + .bDescriptorSubType = 0x01,
15227 + .bTerminalLink = 0x01,
15228 + .bDelay = 0x0,
15229 + .wFormatTag = __constant_cpu_to_le16 (0x0001)
15230 +};
15231 +
15232 +
15233 +static const struct usb_cs_as_format_descriptor
15234 +z_audio_cs_as_format_desc = {
15235 + .bLength = 0xe,
15236 + .bDescriptorType = 0x24,
15237 +
15238 + .bDescriptorSubType = 2,
15239 + .bFormatType = 1,
15240 + .bNrChannels = 1,
15241 + .bSubframeSize = 1,
15242 + .bBitResolution = 8,
15243 + .bSamfreqType = 0,
15244 + .tLowerSamFreq = {0x7e, 0x13, 0x00},
15245 + .tUpperSamFreq = {0xe2, 0xd6, 0x00},
15246 +};
15247 +
15248 +static const struct usb_endpoint_descriptor
15249 +z_iso_ep = {
15250 + .bLength = 0x09,
15251 + .bDescriptorType = 0x05,
15252 + .bEndpointAddress = 0x04,
15253 + .bmAttributes = 0x09,
15254 + .wMaxPacketSize = 0x0038,
15255 + .bInterval = 0x01,
15256 + .bRefresh = 0x00,
15257 + .bSynchAddress = 0x00,
15258 +};
15259 +
15260 +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15261 +
15262 +// 9 bytes
15263 +static char z_ac_interface_header_desc[] =
15264 +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
15265 +
15266 +// 12 bytes
15267 +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
15268 + 0x03, 0x00, 0x00, 0x00};
15269 +// 13 bytes
15270 +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00,
15271 + 0x02, 0x00, 0x02, 0x00, 0x00};
15272 +// 9 bytes
15273 +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02,
15274 + 0x00};
15275 +
15276 +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,
15277 + 0x00};
15278 +
15279 +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15280 +
15281 +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00,
15282 + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15283 +
15284 +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15285 + 0x00};
15286 +
15287 +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15288 +
15289 +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
15290 + 0x00};
15291 +
15292 +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15293 +
15294 +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
15295 + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15296 +
15297 +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15298 + 0x00};
15299 +
15300 +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15301 +
15302 +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
15303 + 0x00};
15304 +
15305 +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15306 +
15307 +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
15308 + 0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15309 +
15310 +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
15311 + 0x00};
15312 +
15313 +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15314 +
15315 +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00,
15316 + 0x00};
15317 +
15318 +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15319 +
15320 +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00,
15321 + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15322 +
15323 +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
15324 + 0x00};
15325 +
15326 +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15327 +
15328 +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
15329 + 0x00};
15330 +
15331 +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15332 +
15333 +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00,
15334 + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15335 +
15336 +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
15337 + 0x00};
15338 +
15339 +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15340 +
15341 +
15342 +
15343 +static const struct usb_descriptor_header *z_function [] = {
15344 + (struct usb_descriptor_header *) &z_audio_control_if_desc,
15345 + (struct usb_descriptor_header *) &z_ac_interface_header_desc,
15346 + (struct usb_descriptor_header *) &z_0,
15347 + (struct usb_descriptor_header *) &z_1,
15348 + (struct usb_descriptor_header *) &z_2,
15349 + (struct usb_descriptor_header *) &z_audio_if_desc,
15350 + (struct usb_descriptor_header *) &z_audio_if_desc2,
15351 + (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
15352 + (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
15353 + (struct usb_descriptor_header *) &z_iso_ep,
15354 + (struct usb_descriptor_header *) &z_iso_ep2,
15355 + (struct usb_descriptor_header *) &za_0,
15356 + (struct usb_descriptor_header *) &za_1,
15357 + (struct usb_descriptor_header *) &za_2,
15358 + (struct usb_descriptor_header *) &za_3,
15359 + (struct usb_descriptor_header *) &za_4,
15360 + (struct usb_descriptor_header *) &za_5,
15361 + (struct usb_descriptor_header *) &za_6,
15362 + (struct usb_descriptor_header *) &za_7,
15363 + (struct usb_descriptor_header *) &za_8,
15364 + (struct usb_descriptor_header *) &za_9,
15365 + (struct usb_descriptor_header *) &za_10,
15366 + (struct usb_descriptor_header *) &za_11,
15367 + (struct usb_descriptor_header *) &za_12,
15368 + (struct usb_descriptor_header *) &za_13,
15369 + (struct usb_descriptor_header *) &za_14,
15370 + (struct usb_descriptor_header *) &za_15,
15371 + (struct usb_descriptor_header *) &za_16,
15372 + (struct usb_descriptor_header *) &za_17,
15373 + (struct usb_descriptor_header *) &za_18,
15374 + (struct usb_descriptor_header *) &za_19,
15375 + (struct usb_descriptor_header *) &za_20,
15376 + (struct usb_descriptor_header *) &za_21,
15377 + (struct usb_descriptor_header *) &za_22,
15378 + (struct usb_descriptor_header *) &za_23,
15379 + (struct usb_descriptor_header *) &za_24,
15380 + NULL,
15381 +};
15382 +
15383 +/* maxpacket and other transfer characteristics vary by speed. */
15384 +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
15385 +
15386 +#else
15387 +
15388 +/* if there's no high speed support, maxpacket doesn't change. */
15389 +#define ep_desc(g,hs,fs) fs
15390 +
15391 +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
15392 +
15393 +static char manufacturer [40];
15394 +//static char serial [40];
15395 +static char serial [] = "Ser 00 em";
15396 +
15397 +/* static strings, in UTF-8 */
15398 +static struct usb_string strings [] = {
15399 + { STRING_MANUFACTURER, manufacturer, },
15400 + { STRING_PRODUCT, longname, },
15401 + { STRING_SERIAL, serial, },
15402 + { STRING_LOOPBACK, loopback, },
15403 + { STRING_SOURCE_SINK, source_sink, },
15404 + { } /* end of list */
15405 +};
15406 +
15407 +static struct usb_gadget_strings stringtab = {
15408 + .language = 0x0409, /* en-us */
15409 + .strings = strings,
15410 +};
15411 +
15412 +/*
15413 + * config descriptors are also handcrafted. these must agree with code
15414 + * that sets configurations, and with code managing interfaces and their
15415 + * altsettings. other complexity may come from:
15416 + *
15417 + * - high speed support, including "other speed config" rules
15418 + * - multiple configurations
15419 + * - interfaces with alternate settings
15420 + * - embedded class or vendor-specific descriptors
15421 + *
15422 + * this handles high speed, and has a second config that could as easily
15423 + * have been an alternate interface setting (on most hardware).
15424 + *
15425 + * NOTE: to demonstrate (and test) more USB capabilities, this driver
15426 + * should include an altsetting to test interrupt transfers, including
15427 + * high bandwidth modes at high speed. (Maybe work like Intel's test
15428 + * device?)
15429 + */
15430 +static int
15431 +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
15432 +{
15433 + int len;
15434 + const struct usb_descriptor_header **function;
15435 +
15436 + function = z_function;
15437 + len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
15438 + if (len < 0)
15439 + return len;
15440 + ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
15441 + return len;
15442 +}
15443 +
15444 +/*-------------------------------------------------------------------------*/
15445 +
15446 +static struct usb_request *
15447 +alloc_ep_req (struct usb_ep *ep, unsigned length)
15448 +{
15449 + struct usb_request *req;
15450 +
15451 + req = usb_ep_alloc_request (ep, GFP_ATOMIC);
15452 + if (req) {
15453 + req->length = length;
15454 + req->buf = usb_ep_alloc_buffer (ep, length,
15455 + &req->dma, GFP_ATOMIC);
15456 + if (!req->buf) {
15457 + usb_ep_free_request (ep, req);
15458 + req = NULL;
15459 + }
15460 + }
15461 + return req;
15462 +}
15463 +
15464 +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
15465 +{
15466 + if (req->buf)
15467 + usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
15468 + usb_ep_free_request (ep, req);
15469 +}
15470 +
15471 +/*-------------------------------------------------------------------------*/
15472 +
15473 +/* optionally require specific source/sink data patterns */
15474 +
15475 +static int
15476 +check_read_data (
15477 + struct zero_dev *dev,
15478 + struct usb_ep *ep,
15479 + struct usb_request *req
15480 +)
15481 +{
15482 + unsigned i;
15483 + u8 *buf = req->buf;
15484 +
15485 + for (i = 0; i < req->actual; i++, buf++) {
15486 + switch (pattern) {
15487 + /* all-zeroes has no synchronization issues */
15488 + case 0:
15489 + if (*buf == 0)
15490 + continue;
15491 + break;
15492 + /* mod63 stays in sync with short-terminated transfers,
15493 + * or otherwise when host and gadget agree on how large
15494 + * each usb transfer request should be. resync is done
15495 + * with set_interface or set_config.
15496 + */
15497 + case 1:
15498 + if (*buf == (u8)(i % 63))
15499 + continue;
15500 + break;
15501 + }
15502 + ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
15503 + usb_ep_set_halt (ep);
15504 + return -EINVAL;
15505 + }
15506 + return 0;
15507 +}
15508 +
15509 +/*-------------------------------------------------------------------------*/
15510 +
15511 +static void zero_reset_config (struct zero_dev *dev)
15512 +{
15513 + if (dev->config == 0)
15514 + return;
15515 +
15516 + DBG (dev, "reset config\n");
15517 +
15518 + /* just disable endpoints, forcing completion of pending i/o.
15519 + * all our completion handlers free their requests in this case.
15520 + */
15521 + if (dev->in_ep) {
15522 + usb_ep_disable (dev->in_ep);
15523 + dev->in_ep = NULL;
15524 + }
15525 + if (dev->out_ep) {
15526 + usb_ep_disable (dev->out_ep);
15527 + dev->out_ep = NULL;
15528 + }
15529 + dev->config = 0;
15530 + del_timer (&dev->resume);
15531 +}
15532 +
15533 +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
15534 +
15535 +static void
15536 +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
15537 +{
15538 + struct zero_dev *dev = ep->driver_data;
15539 + int status = req->status;
15540 + int i, j;
15541 +
15542 + switch (status) {
15543 +
15544 + case 0: /* normal completion? */
15545 + //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
15546 + for (i=0, j=rbuf_start; i<req->actual; i++) {
15547 + //printk ("%02x ", ((__u8*)req->buf)[i]);
15548 + rbuf[j] = ((__u8*)req->buf)[i];
15549 + j++;
15550 + if (j >= RBUF_LEN) j=0;
15551 + }
15552 + rbuf_start = j;
15553 + //printk ("\n\n");
15554 +
15555 + if (rbuf_len < RBUF_LEN) {
15556 + rbuf_len += req->actual;
15557 + if (rbuf_len > RBUF_LEN) {
15558 + rbuf_len = RBUF_LEN;
15559 + }
15560 + }
15561 +
15562 + break;
15563 +
15564 + /* this endpoint is normally active while we're configured */
15565 + case -ECONNABORTED: /* hardware forced ep reset */
15566 + case -ECONNRESET: /* request dequeued */
15567 + case -ESHUTDOWN: /* disconnect from host */
15568 + VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
15569 + req->actual, req->length);
15570 + if (ep == dev->out_ep)
15571 + check_read_data (dev, ep, req);
15572 + free_ep_req (ep, req);
15573 + return;
15574 +
15575 + case -EOVERFLOW: /* buffer overrun on read means that
15576 + * we didn't provide a big enough
15577 + * buffer.
15578 + */
15579 + default:
15580 +#if 1
15581 + DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
15582 + status, req->actual, req->length);
15583 +#endif
15584 + case -EREMOTEIO: /* short read */
15585 + break;
15586 + }
15587 +
15588 + status = usb_ep_queue (ep, req, GFP_ATOMIC);
15589 + if (status) {
15590 + ERROR (dev, "kill %s: resubmit %d bytes --> %d\n",
15591 + ep->name, req->length, status);
15592 + usb_ep_set_halt (ep);
15593 + /* FIXME recover later ... somehow */
15594 + }
15595 +}
15596 +
15597 +static struct usb_request *
15598 +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
15599 +{
15600 + struct usb_request *req;
15601 + int status;
15602 +
15603 + req = alloc_ep_req (ep, 512);
15604 + if (!req)
15605 + return NULL;
15606 +
15607 + req->complete = zero_isoc_complete;
15608 +
15609 + status = usb_ep_queue (ep, req, gfp_flags);
15610 + if (status) {
15611 + struct zero_dev *dev = ep->driver_data;
15612 +
15613 + ERROR (dev, "start %s --> %d\n", ep->name, status);
15614 + free_ep_req (ep, req);
15615 + req = NULL;
15616 + }
15617 +
15618 + return req;
15619 +}
15620 +
15621 +/* change our operational config. this code must agree with the code
15622 + * that returns config descriptors, and altsetting code.
15623 + *
15624 + * it's also responsible for power management interactions. some
15625 + * configurations might not work with our current power sources.
15626 + *
15627 + * note that some device controller hardware will constrain what this
15628 + * code can do, perhaps by disallowing more than one configuration or
15629 + * by limiting configuration choices (like the pxa2xx).
15630 + */
15631 +static int
15632 +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
15633 +{
15634 + int result = 0;
15635 + struct usb_gadget *gadget = dev->gadget;
15636 + const struct usb_endpoint_descriptor *d;
15637 + struct usb_ep *ep;
15638 +
15639 + if (number == dev->config)
15640 + return 0;
15641 +
15642 + zero_reset_config (dev);
15643 +
15644 + gadget_for_each_ep (ep, gadget) {
15645 +
15646 + if (strcmp (ep->name, "ep4") == 0) {
15647 +
15648 + d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
15649 + result = usb_ep_enable (ep, d);
15650 +
15651 + if (result == 0) {
15652 + ep->driver_data = dev;
15653 + dev->in_ep = ep;
15654 +
15655 + if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
15656 +
15657 + dev->in_ep = ep;
15658 + continue;
15659 + }
15660 +
15661 + usb_ep_disable (ep);
15662 + result = -EIO;
15663 + }
15664 + }
15665 +
15666 + }
15667 +
15668 + dev->config = number;
15669 + return result;
15670 +}
15671 +
15672 +/*-------------------------------------------------------------------------*/
15673 +
15674 +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
15675 +{
15676 + if (req->status || req->actual != req->length)
15677 + DBG ((struct zero_dev *) ep->driver_data,
15678 + "setup complete --> %d, %d/%d\n",
15679 + req->status, req->actual, req->length);
15680 +}
15681 +
15682 +/*
15683 + * The setup() callback implements all the ep0 functionality that's
15684 + * not handled lower down, in hardware or the hardware driver (like
15685 + * device and endpoint feature flags, and their status). It's all
15686 + * housekeeping for the gadget function we're implementing. Most of
15687 + * the work is in config-specific setup.
15688 + */
15689 +static int
15690 +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
15691 +{
15692 + struct zero_dev *dev = get_gadget_data (gadget);
15693 + struct usb_request *req = dev->req;
15694 + int value = -EOPNOTSUPP;
15695 +
15696 + /* usually this stores reply data in the pre-allocated ep0 buffer,
15697 + * but config change events will reconfigure hardware.
15698 + */
15699 + req->zero = 0;
15700 + switch (ctrl->bRequest) {
15701 +
15702 + case USB_REQ_GET_DESCRIPTOR:
15703 +
15704 + switch (ctrl->wValue >> 8) {
15705 +
15706 + case USB_DT_DEVICE:
15707 + value = min (ctrl->wLength, (u16) sizeof device_desc);
15708 + memcpy (req->buf, &device_desc, value);
15709 + break;
15710 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15711 + case USB_DT_DEVICE_QUALIFIER:
15712 + if (!gadget->is_dualspeed)
15713 + break;
15714 + value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
15715 + memcpy (req->buf, &dev_qualifier, value);
15716 + break;
15717 +
15718 + case USB_DT_OTHER_SPEED_CONFIG:
15719 + if (!gadget->is_dualspeed)
15720 + break;
15721 + // FALLTHROUGH
15722 +#endif /* CONFIG_USB_GADGET_DUALSPEED */
15723 + case USB_DT_CONFIG:
15724 + value = config_buf (gadget, req->buf,
15725 + ctrl->wValue >> 8,
15726 + ctrl->wValue & 0xff);
15727 + if (value >= 0)
15728 + value = min (ctrl->wLength, (u16) value);
15729 + break;
15730 +
15731 + case USB_DT_STRING:
15732 + /* wIndex == language code.
15733 + * this driver only handles one language, you can
15734 + * add string tables for other languages, using
15735 + * any UTF-8 characters
15736 + */
15737 + value = usb_gadget_get_string (&stringtab,
15738 + ctrl->wValue & 0xff, req->buf);
15739 + if (value >= 0) {
15740 + value = min (ctrl->wLength, (u16) value);
15741 + }
15742 + break;
15743 + }
15744 + break;
15745 +
15746 + /* currently two configs, two speeds */
15747 + case USB_REQ_SET_CONFIGURATION:
15748 + if (ctrl->bRequestType != 0)
15749 + goto unknown;
15750 +
15751 + spin_lock (&dev->lock);
15752 + value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
15753 + spin_unlock (&dev->lock);
15754 + break;
15755 + case USB_REQ_GET_CONFIGURATION:
15756 + if (ctrl->bRequestType != USB_DIR_IN)
15757 + goto unknown;
15758 + *(u8 *)req->buf = dev->config;
15759 + value = min (ctrl->wLength, (u16) 1);
15760 + break;
15761 +
15762 + /* until we add altsetting support, or other interfaces,
15763 + * only 0/0 are possible. pxa2xx only supports 0/0 (poorly)
15764 + * and already killed pending endpoint I/O.
15765 + */
15766 + case USB_REQ_SET_INTERFACE:
15767 +
15768 + if (ctrl->bRequestType != USB_RECIP_INTERFACE)
15769 + goto unknown;
15770 + spin_lock (&dev->lock);
15771 + if (dev->config) {
15772 + u8 config = dev->config;
15773 +
15774 + /* resets interface configuration, forgets about
15775 + * previous transaction state (queued bufs, etc)
15776 + * and re-inits endpoint state (toggle etc)
15777 + * no response queued, just zero status == success.
15778 + * if we had more than one interface we couldn't
15779 + * use this "reset the config" shortcut.
15780 + */
15781 + zero_reset_config (dev);
15782 + zero_set_config (dev, config, GFP_ATOMIC);
15783 + value = 0;
15784 + }
15785 + spin_unlock (&dev->lock);
15786 + break;
15787 + case USB_REQ_GET_INTERFACE:
15788 + if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
15789 + value = ctrl->wLength;
15790 + break;
15791 + }
15792 + else {
15793 + if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
15794 + goto unknown;
15795 + if (!dev->config)
15796 + break;
15797 + if (ctrl->wIndex != 0) {
15798 + value = -EDOM;
15799 + break;
15800 + }
15801 + *(u8 *)req->buf = 0;
15802 + value = min (ctrl->wLength, (u16) 1);
15803 + }
15804 + break;
15805 +
15806 + /*
15807 + * These are the same vendor-specific requests supported by
15808 + * Intel's USB 2.0 compliance test devices. We exceed that
15809 + * device spec by allowing multiple-packet requests.
15810 + */
15811 + case 0x5b: /* control WRITE test -- fill the buffer */
15812 + if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
15813 + goto unknown;
15814 + if (ctrl->wValue || ctrl->wIndex)
15815 + break;
15816 + /* just read that many bytes into the buffer */
15817 + if (ctrl->wLength > USB_BUFSIZ)
15818 + break;
15819 + value = ctrl->wLength;
15820 + break;
15821 + case 0x5c: /* control READ test -- return the buffer */
15822 + if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
15823 + goto unknown;
15824 + if (ctrl->wValue || ctrl->wIndex)
15825 + break;
15826 + /* expect those bytes are still in the buffer; send back */
15827 + if (ctrl->wLength > USB_BUFSIZ
15828 + || ctrl->wLength != req->length)
15829 + break;
15830 + value = ctrl->wLength;
15831 + break;
15832 +
15833 + case 0x01: // SET_CUR
15834 + case 0x02:
15835 + case 0x03:
15836 + case 0x04:
15837 + case 0x05:
15838 + value = ctrl->wLength;
15839 + break;
15840 + case 0x81:
15841 + switch (ctrl->wValue) {
15842 + case 0x0201:
15843 + case 0x0202:
15844 + ((u8*)req->buf)[0] = 0x00;
15845 + ((u8*)req->buf)[1] = 0xe3;
15846 + break;
15847 + case 0x0300:
15848 + case 0x0500:
15849 + ((u8*)req->buf)[0] = 0x00;
15850 + break;
15851 + }
15852 + //((u8*)req->buf)[0] = 0x81;
15853 + //((u8*)req->buf)[1] = 0x81;
15854 + value = ctrl->wLength;
15855 + break;
15856 + case 0x82:
15857 + switch (ctrl->wValue) {
15858 + case 0x0201:
15859 + case 0x0202:
15860 + ((u8*)req->buf)[0] = 0x00;
15861 + ((u8*)req->buf)[1] = 0xc3;
15862 + break;
15863 + case 0x0300:
15864 + case 0x0500:
15865 + ((u8*)req->buf)[0] = 0x00;
15866 + break;
15867 + }
15868 + //((u8*)req->buf)[0] = 0x82;
15869 + //((u8*)req->buf)[1] = 0x82;
15870 + value = ctrl->wLength;
15871 + break;
15872 + case 0x83:
15873 + switch (ctrl->wValue) {
15874 + case 0x0201:
15875 + case 0x0202:
15876 + ((u8*)req->buf)[0] = 0x00;
15877 + ((u8*)req->buf)[1] = 0x00;
15878 + break;
15879 + case 0x0300:
15880 + ((u8*)req->buf)[0] = 0x60;
15881 + break;
15882 + case 0x0500:
15883 + ((u8*)req->buf)[0] = 0x18;
15884 + break;
15885 + }
15886 + //((u8*)req->buf)[0] = 0x83;
15887 + //((u8*)req->buf)[1] = 0x83;
15888 + value = ctrl->wLength;
15889 + break;
15890 + case 0x84:
15891 + switch (ctrl->wValue) {
15892 + case 0x0201:
15893 + case 0x0202:
15894 + ((u8*)req->buf)[0] = 0x00;
15895 + ((u8*)req->buf)[1] = 0x01;
15896 + break;
15897 + case 0x0300:
15898 + case 0x0500:
15899 + ((u8*)req->buf)[0] = 0x08;
15900 + break;
15901 + }
15902 + //((u8*)req->buf)[0] = 0x84;
15903 + //((u8*)req->buf)[1] = 0x84;
15904 + value = ctrl->wLength;
15905 + break;
15906 + case 0x85:
15907 + ((u8*)req->buf)[0] = 0x85;
15908 + ((u8*)req->buf)[1] = 0x85;
15909 + value = ctrl->wLength;
15910 + break;
15911 +
15912 +
15913 + default:
15914 +unknown:
15915 + printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
15916 + ctrl->bRequestType, ctrl->bRequest,
15917 + ctrl->wValue, ctrl->wIndex, ctrl->wLength);
15918 + }
15919 +
15920 + /* respond with data transfer before status phase? */
15921 + if (value >= 0) {
15922 + req->length = value;
15923 + req->zero = value < ctrl->wLength
15924 + && (value % gadget->ep0->maxpacket) == 0;
15925 + value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
15926 + if (value < 0) {
15927 + DBG (dev, "ep_queue < 0 --> %d\n", value);
15928 + req->status = 0;
15929 + zero_setup_complete (gadget->ep0, req);
15930 + }
15931 + }
15932 +
15933 + /* device either stalls (value < 0) or reports success */
15934 + return value;
15935 +}
15936 +
15937 +static void
15938 +zero_disconnect (struct usb_gadget *gadget)
15939 +{
15940 + struct zero_dev *dev = get_gadget_data (gadget);
15941 + unsigned long flags;
15942 +
15943 + spin_lock_irqsave (&dev->lock, flags);
15944 + zero_reset_config (dev);
15945 +
15946 + /* a more significant application might have some non-usb
15947 + * activities to quiesce here, saving resources like power
15948 + * or pushing the notification up a network stack.
15949 + */
15950 + spin_unlock_irqrestore (&dev->lock, flags);
15951 +
15952 + /* next we may get setup() calls to enumerate new connections;
15953 + * or an unbind() during shutdown (including removing module).
15954 + */
15955 +}
15956 +
15957 +static void
15958 +zero_autoresume (unsigned long _dev)
15959 +{
15960 + struct zero_dev *dev = (struct zero_dev *) _dev;
15961 + int status;
15962 +
15963 + /* normally the host would be woken up for something
15964 + * more significant than just a timer firing...
15965 + */
15966 + if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
15967 + status = usb_gadget_wakeup (dev->gadget);
15968 + DBG (dev, "wakeup --> %d\n", status);
15969 + }
15970 +}
15971 +
15972 +/*-------------------------------------------------------------------------*/
15973 +
15974 +static void
15975 +zero_unbind (struct usb_gadget *gadget)
15976 +{
15977 + struct zero_dev *dev = get_gadget_data (gadget);
15978 +
15979 + DBG (dev, "unbind\n");
15980 +
15981 + /* we've already been disconnected ... no i/o is active */
15982 + if (dev->req)
15983 + free_ep_req (gadget->ep0, dev->req);
15984 + del_timer_sync (&dev->resume);
15985 + kfree (dev);
15986 + set_gadget_data (gadget, NULL);
15987 +}
15988 +
15989 +static int
15990 +zero_bind (struct usb_gadget *gadget)
15991 +{
15992 + struct zero_dev *dev;
15993 + //struct usb_ep *ep;
15994 +
15995 + printk("binding\n");
15996 + /*
15997 + * DRIVER POLICY CHOICE: you may want to do this differently.
15998 + * One thing to avoid is reusing a bcdDevice revision code
15999 + * with different host-visible configurations or behavior
16000 + * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
16001 + */
16002 + //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
16003 +
16004 +
16005 + /* ok, we made sense of the hardware ... */
16006 + dev = kmalloc (sizeof *dev, SLAB_KERNEL);
16007 + if (!dev)
16008 + return -ENOMEM;
16009 + memset (dev, 0, sizeof *dev);
16010 + spin_lock_init (&dev->lock);
16011 + dev->gadget = gadget;
16012 + set_gadget_data (gadget, dev);
16013 +
16014 + /* preallocate control response and buffer */
16015 + dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
16016 + if (!dev->req)
16017 + goto enomem;
16018 + dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
16019 + &dev->req->dma, GFP_KERNEL);
16020 + if (!dev->req->buf)
16021 + goto enomem;
16022 +
16023 + dev->req->complete = zero_setup_complete;
16024 +
16025 + device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
16026 +
16027 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16028 + /* assume ep0 uses the same value for both speeds ... */
16029 + dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
16030 +
16031 + /* and that all endpoints are dual-speed */
16032 + //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
16033 + //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
16034 +#endif
16035 +
16036 + usb_gadget_set_selfpowered (gadget);
16037 +
16038 + init_timer (&dev->resume);
16039 + dev->resume.function = zero_autoresume;
16040 + dev->resume.data = (unsigned long) dev;
16041 +
16042 + gadget->ep0->driver_data = dev;
16043 +
16044 + INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
16045 + INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
16046 + EP_OUT_NAME, EP_IN_NAME);
16047 +
16048 + snprintf (manufacturer, sizeof manufacturer,
16049 + UTS_SYSNAME " " UTS_RELEASE " with %s",
16050 + gadget->name);
16051 +
16052 + return 0;
16053 +
16054 +enomem:
16055 + zero_unbind (gadget);
16056 + return -ENOMEM;
16057 +}
16058 +
16059 +/*-------------------------------------------------------------------------*/
16060 +
16061 +static void
16062 +zero_suspend (struct usb_gadget *gadget)
16063 +{
16064 + struct zero_dev *dev = get_gadget_data (gadget);
16065 +
16066 + if (gadget->speed == USB_SPEED_UNKNOWN)
16067 + return;
16068 +
16069 + if (autoresume) {
16070 + mod_timer (&dev->resume, jiffies + (HZ * autoresume));
16071 + DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
16072 + } else
16073 + DBG (dev, "suspend\n");
16074 +}
16075 +
16076 +static void
16077 +zero_resume (struct usb_gadget *gadget)
16078 +{
16079 + struct zero_dev *dev = get_gadget_data (gadget);
16080 +
16081 + DBG (dev, "resume\n");
16082 + del_timer (&dev->resume);
16083 +}
16084 +
16085 +
16086 +/*-------------------------------------------------------------------------*/
16087 +
16088 +static struct usb_gadget_driver zero_driver = {
16089 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16090 + .speed = USB_SPEED_HIGH,
16091 +#else
16092 + .speed = USB_SPEED_FULL,
16093 +#endif
16094 + .function = (char *) longname,
16095 + .bind = zero_bind,
16096 + .unbind = zero_unbind,
16097 +
16098 + .setup = zero_setup,
16099 + .disconnect = zero_disconnect,
16100 +
16101 + .suspend = zero_suspend,
16102 + .resume = zero_resume,
16103 +
16104 + .driver = {
16105 + .name = (char *) shortname,
16106 + // .shutdown = ...
16107 + // .suspend = ...
16108 + // .resume = ...
16109 + },
16110 +};
16111 +
16112 +MODULE_AUTHOR ("David Brownell");
16113 +MODULE_LICENSE ("Dual BSD/GPL");
16114 +
16115 +static struct proc_dir_entry *pdir, *pfile;
16116 +
16117 +static int isoc_read_data (char *page, char **start,
16118 + off_t off, int count,
16119 + int *eof, void *data)
16120 +{
16121 + int i;
16122 + static int c = 0;
16123 + static int done = 0;
16124 + static int s = 0;
16125 +
16126 +/*
16127 + printk ("\ncount: %d\n", count);
16128 + printk ("rbuf_start: %d\n", rbuf_start);
16129 + printk ("rbuf_len: %d\n", rbuf_len);
16130 + printk ("off: %d\n", off);
16131 + printk ("start: %p\n\n", *start);
16132 +*/
16133 + if (done) {
16134 + c = 0;
16135 + done = 0;
16136 + *eof = 1;
16137 + return 0;
16138 + }
16139 +
16140 + if (c == 0) {
16141 + if (rbuf_len == RBUF_LEN)
16142 + s = rbuf_start;
16143 + else s = 0;
16144 + }
16145 +
16146 + for (i=0; i<count && c<rbuf_len; i++, c++) {
16147 + page[i] = rbuf[(c+s) % RBUF_LEN];
16148 + }
16149 + *start = page;
16150 +
16151 + if (c >= rbuf_len) {
16152 + *eof = 1;
16153 + done = 1;
16154 + }
16155 +
16156 +
16157 + return i;
16158 +}
16159 +
16160 +static int __init init (void)
16161 +{
16162 +
16163 + int retval = 0;
16164 +
16165 + pdir = proc_mkdir("isoc_test", NULL);
16166 + if(pdir == NULL) {
16167 + retval = -ENOMEM;
16168 + printk("Error creating dir\n");
16169 + goto done;
16170 + }
16171 + pdir->owner = THIS_MODULE;
16172 +
16173 + pfile = create_proc_read_entry("isoc_data",
16174 + 0444, pdir,
16175 + isoc_read_data,
16176 + NULL);
16177 + if (pfile == NULL) {
16178 + retval = -ENOMEM;
16179 + printk("Error creating file\n");
16180 + goto no_file;
16181 + }
16182 + pfile->owner = THIS_MODULE;
16183 +
16184 + return usb_gadget_register_driver (&zero_driver);
16185 +
16186 + no_file:
16187 + remove_proc_entry("isoc_data", NULL);
16188 + done:
16189 + return retval;
16190 +}
16191 +module_init (init);
16192 +
16193 +static void __exit cleanup (void)
16194 +{
16195 +
16196 + usb_gadget_unregister_driver (&zero_driver);
16197 +
16198 + remove_proc_entry("isoc_data", pdir);
16199 + remove_proc_entry("isoc_test", NULL);
16200 +}
16201 +module_exit (cleanup);
16202 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16203 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100
16204 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2013-07-06 15:25:50.000000000 +0100
16205 @@ -0,0 +1,142 @@
16206 +/* ==========================================================================
16207 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16208 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16209 + * otherwise expressly agreed to in writing between Synopsys and you.
16210 + *
16211 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16212 + * any End User Software License Agreement or Agreement for Licensed Product
16213 + * with Synopsys or any supplement thereto. You are permitted to use and
16214 + * redistribute this Software in source and binary forms, with or without
16215 + * modification, provided that redistributions of source code must retain this
16216 + * notice. You may not view, use, disclose, copy or distribute this file or
16217 + * any information contained herein except pursuant to this license grant from
16218 + * Synopsys. If you do not agree with this notice, including the disclaimer
16219 + * below, then you are not authorized to use the Software.
16220 + *
16221 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16222 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16223 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16224 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16225 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16226 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16227 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16228 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16229 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16230 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16231 + * DAMAGE.
16232 + * ========================================================================== */
16233 +
16234 +#if !defined(__DWC_CFI_COMMON_H__)
16235 +#define __DWC_CFI_COMMON_H__
16236 +
16237 +//#include <linux/types.h>
16238 +
16239 +/**
16240 + * @file
16241 + *
16242 + * This file contains the CFI specific common constants, interfaces
16243 + * (functions and macros) and structures for Linux. No PCD specific
16244 + * data structure or definition is to be included in this file.
16245 + *
16246 + */
16247 +
16248 +/** This is a request for all Core Features */
16249 +#define VEN_CORE_GET_FEATURES 0xB1
16250 +
16251 +/** This is a request to get the value of a specific Core Feature */
16252 +#define VEN_CORE_GET_FEATURE 0xB2
16253 +
16254 +/** This command allows the host to set the value of a specific Core Feature */
16255 +#define VEN_CORE_SET_FEATURE 0xB3
16256 +
16257 +/** This command allows the host to set the default values of
16258 + * either all or any specific Core Feature
16259 + */
16260 +#define VEN_CORE_RESET_FEATURES 0xB4
16261 +
16262 +/** This command forces the PCD to write the deferred values of a Core Features */
16263 +#define VEN_CORE_ACTIVATE_FEATURES 0xB5
16264 +
16265 +/** This request reads a DWORD value from a register at the specified offset */
16266 +#define VEN_CORE_READ_REGISTER 0xB6
16267 +
16268 +/** This request writes a DWORD value into a register at the specified offset */
16269 +#define VEN_CORE_WRITE_REGISTER 0xB7
16270 +
16271 +/** This structure is the header of the Core Features dataset returned to
16272 + * the Host
16273 + */
16274 +struct cfi_all_features_header {
16275 +/** The features header structure length is */
16276 +#define CFI_ALL_FEATURES_HDR_LEN 8
16277 + /**
16278 + * The total length of the features dataset returned to the Host
16279 + */
16280 + uint16_t wTotalLen;
16281 +
16282 + /**
16283 + * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
16284 + * This field identifies the version of the CFI Specification with which
16285 + * the device is compliant.
16286 + */
16287 + uint16_t wVersion;
16288 +
16289 + /** The ID of the Core */
16290 + uint16_t wCoreID;
16291 +#define CFI_CORE_ID_UDC 1
16292 +#define CFI_CORE_ID_OTG 2
16293 +#define CFI_CORE_ID_WUDEV 3
16294 +
16295 + /** Number of features returned by VEN_CORE_GET_FEATURES request */
16296 + uint16_t wNumFeatures;
16297 +} UPACKED;
16298 +
16299 +typedef struct cfi_all_features_header cfi_all_features_header_t;
16300 +
16301 +/** This structure is a header of the Core Feature descriptor dataset returned to
16302 + * the Host after the VEN_CORE_GET_FEATURES request
16303 + */
16304 +struct cfi_feature_desc_header {
16305 +#define CFI_FEATURE_DESC_HDR_LEN 8
16306 +
16307 + /** The feature ID */
16308 + uint16_t wFeatureID;
16309 +
16310 + /** Length of this feature descriptor in bytes - including the
16311 + * length of the feature name string
16312 + */
16313 + uint16_t wLength;
16314 +
16315 + /** The data length of this feature in bytes */
16316 + uint16_t wDataLength;
16317 +
16318 + /**
16319 + * Attributes of this features
16320 + * D0: Access rights
16321 + * 0 - Read/Write
16322 + * 1 - Read only
16323 + */
16324 + uint8_t bmAttributes;
16325 +#define CFI_FEATURE_ATTR_RO 1
16326 +#define CFI_FEATURE_ATTR_RW 0
16327 +
16328 + /** Length of the feature name in bytes */
16329 + uint8_t bNameLen;
16330 +
16331 + /** The feature name buffer */
16332 + //uint8_t *name;
16333 +} UPACKED;
16334 +
16335 +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
16336 +
16337 +/**
16338 + * This structure describes a NULL terminated string referenced by its id field.
16339 + * It is very similar to usb_string structure but has the id field type set to 16-bit.
16340 + */
16341 +struct cfi_string {
16342 + uint16_t id;
16343 + const uint8_t *s;
16344 +};
16345 +typedef struct cfi_string cfi_string_t;
16346 +
16347 +#endif
16348 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16349 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1970-01-01 01:00:00.000000000 +0100
16350 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2013-07-06 15:25:50.000000000 +0100
16351 @@ -0,0 +1,854 @@
16352 +/* ==========================================================================
16353 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
16354 + * $Revision: #12 $
16355 + * $Date: 2011/10/26 $
16356 + * $Change: 1873028 $
16357 + *
16358 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16359 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16360 + * otherwise expressly agreed to in writing between Synopsys and you.
16361 + *
16362 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16363 + * any End User Software License Agreement or Agreement for Licensed Product
16364 + * with Synopsys or any supplement thereto. You are permitted to use and
16365 + * redistribute this Software in source and binary forms, with or without
16366 + * modification, provided that redistributions of source code must retain this
16367 + * notice. You may not view, use, disclose, copy or distribute this file or
16368 + * any information contained herein except pursuant to this license grant from
16369 + * Synopsys. If you do not agree with this notice, including the disclaimer
16370 + * below, then you are not authorized to use the Software.
16371 + *
16372 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16373 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16374 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16375 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16376 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16377 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16378 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16379 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16380 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16381 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16382 + * DAMAGE.
16383 + * ========================================================================== */
16384 +
16385 +#include "dwc_os.h"
16386 +#include "dwc_otg_regs.h"
16387 +#include "dwc_otg_cil.h"
16388 +#include "dwc_otg_adp.h"
16389 +
16390 +/** @file
16391 + *
16392 + * This file contains the most of the Attach Detect Protocol implementation for
16393 + * the driver to support OTG Rev2.0.
16394 + *
16395 + */
16396 +
16397 +void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
16398 +{
16399 + adpctl_data_t adpctl;
16400 +
16401 + adpctl.d32 = value;
16402 + adpctl.b.ar = 0x2;
16403 +
16404 + DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16405 +
16406 + while (adpctl.b.ar) {
16407 + adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16408 + }
16409 +
16410 +}
16411 +
16412 +/**
16413 + * Function is called to read ADP registers
16414 + */
16415 +uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
16416 +{
16417 + adpctl_data_t adpctl;
16418 +
16419 + adpctl.d32 = 0;
16420 + adpctl.b.ar = 0x1;
16421 +
16422 + DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16423 +
16424 + while (adpctl.b.ar) {
16425 + adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16426 + }
16427 +
16428 + return adpctl.d32;
16429 +}
16430 +
16431 +/**
16432 + * Function is called to read ADPCTL register and filter Write-clear bits
16433 + */
16434 +uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
16435 +{
16436 + adpctl_data_t adpctl;
16437 +
16438 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16439 + adpctl.b.adp_tmout_int = 0;
16440 + adpctl.b.adp_prb_int = 0;
16441 + adpctl.b.adp_tmout_int = 0;
16442 +
16443 + return adpctl.d32;
16444 +}
16445 +
16446 +/**
16447 + * Function is called to write ADP registers
16448 + */
16449 +void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
16450 + uint32_t set)
16451 +{
16452 + dwc_otg_adp_write_reg(core_if,
16453 + (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
16454 +}
16455 +
16456 +static void adp_sense_timeout(void *ptr)
16457 +{
16458 + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16459 + core_if->adp.sense_timer_started = 0;
16460 + DWC_PRINTF("ADP SENSE TIMEOUT\n");
16461 + if (core_if->adp_enable) {
16462 + dwc_otg_adp_sense_stop(core_if);
16463 + dwc_otg_adp_probe_start(core_if);
16464 + }
16465 +}
16466 +
16467 +/**
16468 + * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
16469 + */
16470 +static void adp_vbuson_timeout(void *ptr)
16471 +{
16472 + gpwrdn_data_t gpwrdn;
16473 + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16474 + hprt0_data_t hprt0 = {.d32 = 0 };
16475 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
16476 + DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
16477 + if (core_if) {
16478 + core_if->adp.vbuson_timer_started = 0;
16479 + /* Turn off vbus */
16480 + hprt0.b.prtpwr = 1;
16481 + DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
16482 + gpwrdn.d32 = 0;
16483 +
16484 + /* Power off the core */
16485 + if (core_if->power_down == 2) {
16486 + /* Enable Wakeup Logic */
16487 +// gpwrdn.b.wkupactiv = 1;
16488 + gpwrdn.b.pmuactv = 0;
16489 + gpwrdn.b.pwrdnrstn = 1;
16490 + gpwrdn.b.pwrdnclmp = 1;
16491 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16492 + gpwrdn.d32);
16493 +
16494 + /* Suspend the Phy Clock */
16495 + pcgcctl.b.stoppclk = 1;
16496 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
16497 +
16498 + /* Switch on VDD */
16499 +// gpwrdn.b.wkupactiv = 1;
16500 + gpwrdn.b.pmuactv = 1;
16501 + gpwrdn.b.pwrdnrstn = 1;
16502 + gpwrdn.b.pwrdnclmp = 1;
16503 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16504 + gpwrdn.d32);
16505 + } else {
16506 + /* Enable Power Down Logic */
16507 + gpwrdn.b.pmuintsel = 1;
16508 + gpwrdn.b.pmuactv = 1;
16509 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16510 + }
16511 +
16512 + /* Power off the core */
16513 + if (core_if->power_down == 2) {
16514 + gpwrdn.d32 = 0;
16515 + gpwrdn.b.pwrdnswtch = 1;
16516 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
16517 + gpwrdn.d32, 0);
16518 + }
16519 +
16520 + /* Unmask SRP detected interrupt from Power Down Logic */
16521 + gpwrdn.d32 = 0;
16522 + gpwrdn.b.srp_det_msk = 1;
16523 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16524 +
16525 + dwc_otg_adp_probe_start(core_if);
16526 + dwc_otg_dump_global_registers(core_if);
16527 + dwc_otg_dump_host_registers(core_if);
16528 + }
16529 +
16530 +}
16531 +
16532 +/**
16533 + * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
16534 + * not asserted within 1.1 seconds.
16535 + *
16536 + * @param core_if the pointer to core_if strucure.
16537 + */
16538 +void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
16539 +{
16540 + core_if->adp.vbuson_timer_started = 1;
16541 + if (core_if->adp.vbuson_timer)
16542 + {
16543 + DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
16544 + /* 1.1 secs + 60ms necessary for cil_hcd_start*/
16545 + DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
16546 + } else {
16547 + DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
16548 + }
16549 +}
16550 +
16551 +#if 0
16552 +/**
16553 + * Masks all DWC OTG core interrupts
16554 + *
16555 + */
16556 +static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
16557 +{
16558 + int i;
16559 + gahbcfg_data_t ahbcfg = {.d32 = 0 };
16560 +
16561 + /* Mask Host Interrupts */
16562 +
16563 + /* Clear and disable HCINTs */
16564 + for (i = 0; i < core_if->core_params->host_channels; i++) {
16565 + DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
16566 + DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
16567 +
16568 + }
16569 +
16570 + /* Clear and disable HAINT */
16571 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
16572 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
16573 +
16574 + /* Mask Device Interrupts */
16575 + if (!core_if->multiproc_int_enable) {
16576 + /* Clear and disable IN Endpoint interrupts */
16577 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
16578 + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16579 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16580 + diepint, 0xFFFFFFFF);
16581 + }
16582 +
16583 + /* Clear and disable OUT Endpoint interrupts */
16584 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
16585 + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16586 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16587 + doepint, 0xFFFFFFFF);
16588 + }
16589 +
16590 + /* Clear and disable DAINT */
16591 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
16592 + 0xFFFFFFFF);
16593 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
16594 + } else {
16595 + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
16596 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16597 + diepeachintmsk[i], 0);
16598 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16599 + diepint, 0xFFFFFFFF);
16600 + }
16601 +
16602 + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
16603 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16604 + doepeachintmsk[i], 0);
16605 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16606 + doepint, 0xFFFFFFFF);
16607 + }
16608 +
16609 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
16610 + 0);
16611 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
16612 + 0xFFFFFFFF);
16613 +
16614 + }
16615 +
16616 + /* Disable interrupts */
16617 + ahbcfg.b.glblintrmsk = 1;
16618 + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
16619 +
16620 + /* Disable all interrupts. */
16621 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
16622 +
16623 + /* Clear any pending interrupts */
16624 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16625 +
16626 + /* Clear any pending OTG Interrupts */
16627 + DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
16628 +}
16629 +
16630 +/**
16631 + * Unmask Port Connection Detected interrupt
16632 + *
16633 + */
16634 +static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
16635 +{
16636 + gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
16637 +
16638 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
16639 +}
16640 +#endif
16641 +
16642 +/**
16643 + * Starts the ADP Probing
16644 + *
16645 + * @param core_if the pointer to core_if structure.
16646 + */
16647 +uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
16648 +{
16649 +
16650 + adpctl_data_t adpctl = {.d32 = 0};
16651 + gpwrdn_data_t gpwrdn;
16652 +#if 0
16653 + adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
16654 + .b.adp_sns_int = 1, b.adp_tmout_int};
16655 +#endif
16656 + dwc_otg_disable_global_interrupts(core_if);
16657 + DWC_PRINTF("ADP Probe Start\n");
16658 + core_if->adp.probe_enabled = 1;
16659 +
16660 + adpctl.b.adpres = 1;
16661 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16662 +
16663 + while (adpctl.b.adpres) {
16664 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16665 + }
16666 +
16667 + adpctl.d32 = 0;
16668 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16669 +
16670 + /* In Host mode unmask SRP detected interrupt */
16671 + gpwrdn.d32 = 0;
16672 + gpwrdn.b.sts_chngint_msk = 1;
16673 + if (!gpwrdn.b.idsts) {
16674 + gpwrdn.b.srp_det_msk = 1;
16675 + }
16676 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16677 +
16678 + adpctl.b.adp_tmout_int_msk = 1;
16679 + adpctl.b.adp_prb_int_msk = 1;
16680 + adpctl.b.prb_dschg = 1;
16681 + adpctl.b.prb_delta = 1;
16682 + adpctl.b.prb_per = 1;
16683 + adpctl.b.adpen = 1;
16684 + adpctl.b.enaprb = 1;
16685 +
16686 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16687 + DWC_PRINTF("ADP Probe Finish\n");
16688 + return 0;
16689 +}
16690 +
16691 +/**
16692 + * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
16693 + * within 3 seconds.
16694 + *
16695 + * @param core_if the pointer to core_if strucure.
16696 + */
16697 +void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
16698 +{
16699 + core_if->adp.sense_timer_started = 1;
16700 + DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
16701 +}
16702 +
16703 +/**
16704 + * Starts the ADP Sense
16705 + *
16706 + * @param core_if the pointer to core_if strucure.
16707 + */
16708 +uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
16709 +{
16710 + adpctl_data_t adpctl;
16711 +
16712 + DWC_PRINTF("ADP Sense Start\n");
16713 +
16714 + /* Unmask ADP sense interrupt and mask all other from the core */
16715 + adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16716 + adpctl.b.adp_sns_int_msk = 1;
16717 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16718 + dwc_otg_disable_global_interrupts(core_if); // vahrama
16719 +
16720 + /* Set ADP reset bit*/
16721 + adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16722 + adpctl.b.adpres = 1;
16723 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16724 +
16725 + while (adpctl.b.adpres) {
16726 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16727 + }
16728 +
16729 + adpctl.b.adpres = 0;
16730 + adpctl.b.adpen = 1;
16731 + adpctl.b.enasns = 1;
16732 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16733 +
16734 + dwc_otg_adp_sense_timer_start(core_if);
16735 +
16736 + return 0;
16737 +}
16738 +
16739 +/**
16740 + * Stops the ADP Probing
16741 + *
16742 + * @param core_if the pointer to core_if strucure.
16743 + */
16744 +uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
16745 +{
16746 +
16747 + adpctl_data_t adpctl;
16748 + DWC_PRINTF("Stop ADP probe\n");
16749 + core_if->adp.probe_enabled = 0;
16750 + core_if->adp.probe_counter = 0;
16751 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16752 +
16753 + adpctl.b.adpen = 0;
16754 + adpctl.b.adp_prb_int = 1;
16755 + adpctl.b.adp_tmout_int = 1;
16756 + adpctl.b.adp_sns_int = 1;
16757 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16758 +
16759 + return 0;
16760 +}
16761 +
16762 +/**
16763 + * Stops the ADP Sensing
16764 + *
16765 + * @param core_if the pointer to core_if strucure.
16766 + */
16767 +uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
16768 +{
16769 + adpctl_data_t adpctl;
16770 +
16771 + core_if->adp.sense_enabled = 0;
16772 +
16773 + adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16774 + adpctl.b.enasns = 0;
16775 + adpctl.b.adp_sns_int = 1;
16776 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
16777 +
16778 + return 0;
16779 +}
16780 +
16781 +/**
16782 + * Called to turn on the VBUS after initial ADP probe in host mode.
16783 + * If port power was already enabled in cil_hcd_start function then
16784 + * only schedule a timer.
16785 + *
16786 + * @param core_if the pointer to core_if structure.
16787 + */
16788 +void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
16789 +{
16790 + hprt0_data_t hprt0 = {.d32 = 0 };
16791 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
16792 + DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
16793 +
16794 + if (hprt0.b.prtpwr == 0) {
16795 + hprt0.b.prtpwr = 1;
16796 + //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
16797 + }
16798 +
16799 + dwc_otg_adp_vbuson_timer_start(core_if);
16800 +}
16801 +
16802 +/**
16803 + * Called right after driver is loaded
16804 + * to perform initial actions for ADP
16805 + *
16806 + * @param core_if the pointer to core_if structure.
16807 + * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
16808 + */
16809 +void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
16810 +{
16811 + gpwrdn_data_t gpwrdn;
16812 +
16813 + DWC_PRINTF("ADP Initial Start\n");
16814 + core_if->adp.adp_started = 1;
16815 +
16816 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16817 + dwc_otg_disable_global_interrupts(core_if);
16818 + if (is_host) {
16819 + DWC_PRINTF("HOST MODE\n");
16820 + /* Enable Power Down Logic Interrupt*/
16821 + gpwrdn.d32 = 0;
16822 + gpwrdn.b.pmuintsel = 1;
16823 + gpwrdn.b.pmuactv = 1;
16824 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16825 + /* Initialize first ADP probe to obtain Ramp Time value */
16826 + core_if->adp.initial_probe = 1;
16827 + dwc_otg_adp_probe_start(core_if);
16828 + } else {
16829 + gotgctl_data_t gotgctl;
16830 + gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
16831 + DWC_PRINTF("DEVICE MODE\n");
16832 + if (gotgctl.b.bsesvld == 0) {
16833 + /* Enable Power Down Logic Interrupt*/
16834 + gpwrdn.d32 = 0;
16835 + DWC_PRINTF("VBUS is not valid - start ADP probe\n");
16836 + gpwrdn.b.pmuintsel = 1;
16837 + gpwrdn.b.pmuactv = 1;
16838 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16839 + core_if->adp.initial_probe = 1;
16840 + dwc_otg_adp_probe_start(core_if);
16841 + } else {
16842 + DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
16843 + core_if->op_state = B_PERIPHERAL;
16844 + dwc_otg_core_init(core_if);
16845 + dwc_otg_enable_global_interrupts(core_if);
16846 + cil_pcd_start(core_if);
16847 + dwc_otg_dump_global_registers(core_if);
16848 + dwc_otg_dump_dev_registers(core_if);
16849 + }
16850 + }
16851 +}
16852 +
16853 +void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
16854 +{
16855 + core_if->adp.adp_started = 0;
16856 + core_if->adp.initial_probe = 0;
16857 + core_if->adp.probe_timer_values[0] = -1;
16858 + core_if->adp.probe_timer_values[1] = -1;
16859 + core_if->adp.probe_enabled = 0;
16860 + core_if->adp.sense_enabled = 0;
16861 + core_if->adp.sense_timer_started = 0;
16862 + core_if->adp.vbuson_timer_started = 0;
16863 + core_if->adp.probe_counter = 0;
16864 + core_if->adp.gpwrdn = 0;
16865 + core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
16866 + /* Initialize timers */
16867 + core_if->adp.sense_timer =
16868 + DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
16869 + core_if->adp.vbuson_timer =
16870 + DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
16871 + if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
16872 + {
16873 + DWC_ERROR("Could not allocate memory for ADP timers\n");
16874 + }
16875 +}
16876 +
16877 +void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
16878 +{
16879 + gpwrdn_data_t gpwrdn = { .d32 = 0 };
16880 + gpwrdn.b.pmuintsel = 1;
16881 + gpwrdn.b.pmuactv = 1;
16882 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
16883 +
16884 + if (core_if->adp.probe_enabled)
16885 + dwc_otg_adp_probe_stop(core_if);
16886 + if (core_if->adp.sense_enabled)
16887 + dwc_otg_adp_sense_stop(core_if);
16888 + if (core_if->adp.sense_timer_started)
16889 + DWC_TIMER_CANCEL(core_if->adp.sense_timer);
16890 + if (core_if->adp.vbuson_timer_started)
16891 + DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
16892 + DWC_TIMER_FREE(core_if->adp.sense_timer);
16893 + DWC_TIMER_FREE(core_if->adp.vbuson_timer);
16894 +}
16895 +
16896 +/////////////////////////////////////////////////////////////////////
16897 +////////////// ADP Interrupt Handlers ///////////////////////////////
16898 +/////////////////////////////////////////////////////////////////////
16899 +/**
16900 + * This function sets Ramp Timer values
16901 + */
16902 +static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
16903 +{
16904 + if (core_if->adp.probe_timer_values[0] == -1) {
16905 + core_if->adp.probe_timer_values[0] = val;
16906 + core_if->adp.probe_timer_values[1] = -1;
16907 + return 1;
16908 + } else {
16909 + core_if->adp.probe_timer_values[1] =
16910 + core_if->adp.probe_timer_values[0];
16911 + core_if->adp.probe_timer_values[0] = val;
16912 + return 0;
16913 + }
16914 +}
16915 +
16916 +/**
16917 + * This function compares Ramp Timer values
16918 + */
16919 +static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
16920 +{
16921 + uint32_t diff;
16922 + if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
16923 + diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
16924 + else
16925 + diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];
16926 + if(diff < 2) {
16927 + return 0;
16928 + } else {
16929 + return 1;
16930 + }
16931 +}
16932 +
16933 +/**
16934 + * This function handles ADP Probe Interrupts
16935 + */
16936 +static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
16937 + uint32_t val)
16938 +{
16939 + adpctl_data_t adpctl = {.d32 = 0 };
16940 + gpwrdn_data_t gpwrdn, temp;
16941 + adpctl.d32 = val;
16942 +
16943 + temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16944 + core_if->adp.probe_counter++;
16945 + core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16946 + if (adpctl.b.rtim == 0 && !temp.b.idsts){
16947 + DWC_PRINTF("RTIM value is 0\n");
16948 + goto exit;
16949 + }
16950 + if (set_timer_value(core_if, adpctl.b.rtim) &&
16951 + core_if->adp.initial_probe) {
16952 + core_if->adp.initial_probe = 0;
16953 + dwc_otg_adp_probe_stop(core_if);
16954 + gpwrdn.d32 = 0;
16955 + gpwrdn.b.pmuactv = 1;
16956 + gpwrdn.b.pmuintsel = 1;
16957 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
16958 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16959 +
16960 + /* check which value is for device mode and which for Host mode */
16961 + if (!temp.b.idsts) { /* considered host mode value is 0 */
16962 + /*
16963 + * Turn on VBUS after initial ADP probe.
16964 + */
16965 + core_if->op_state = A_HOST;
16966 + dwc_otg_enable_global_interrupts(core_if);
16967 + DWC_SPINUNLOCK(core_if->lock);
16968 + cil_hcd_start(core_if);
16969 + dwc_otg_adp_turnon_vbus(core_if);
16970 + DWC_SPINLOCK(core_if->lock);
16971 + } else {
16972 + /*
16973 + * Initiate SRP after initial ADP probe.
16974 + */
16975 + dwc_otg_enable_global_interrupts(core_if);
16976 + dwc_otg_initiate_srp(core_if);
16977 + }
16978 + } else if (core_if->adp.probe_counter > 2){
16979 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16980 + if (compare_timer_values(core_if)) {
16981 + DWC_PRINTF("Difference in timer values !!! \n");
16982 +// core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
16983 + dwc_otg_adp_probe_stop(core_if);
16984 +
16985 + /* Power on the core */
16986 + if (core_if->power_down == 2) {
16987 + gpwrdn.b.pwrdnswtch = 1;
16988 + DWC_MODIFY_REG32(&core_if->core_global_regs->
16989 + gpwrdn, 0, gpwrdn.d32);
16990 + }
16991 +
16992 + /* check which value is for device mode and which for Host mode */
16993 + if (!temp.b.idsts) { /* considered host mode value is 0 */
16994 + /* Disable Interrupt from Power Down Logic */
16995 + gpwrdn.d32 = 0;
16996 + gpwrdn.b.pmuintsel = 1;
16997 + gpwrdn.b.pmuactv = 1;
16998 + DWC_MODIFY_REG32(&core_if->core_global_regs->
16999 + gpwrdn, gpwrdn.d32, 0);
17000 +
17001 + /*
17002 + * Initialize the Core for Host mode.
17003 + */
17004 + core_if->op_state = A_HOST;
17005 + dwc_otg_core_init(core_if);
17006 + dwc_otg_enable_global_interrupts(core_if);
17007 + cil_hcd_start(core_if);
17008 + } else {
17009 + gotgctl_data_t gotgctl;
17010 + /* Mask SRP detected interrupt from Power Down Logic */
17011 + gpwrdn.d32 = 0;
17012 + gpwrdn.b.srp_det_msk = 1;
17013 + DWC_MODIFY_REG32(&core_if->core_global_regs->
17014 + gpwrdn, gpwrdn.d32, 0);
17015 +
17016 + /* Disable Power Down Logic */
17017 + gpwrdn.d32 = 0;
17018 + gpwrdn.b.pmuintsel = 1;
17019 + gpwrdn.b.pmuactv = 1;
17020 + DWC_MODIFY_REG32(&core_if->core_global_regs->
17021 + gpwrdn, gpwrdn.d32, 0);
17022 +
17023 + /*
17024 + * Initialize the Core for Device mode.
17025 + */
17026 + core_if->op_state = B_PERIPHERAL;
17027 + dwc_otg_core_init(core_if);
17028 + dwc_otg_enable_global_interrupts(core_if);
17029 + cil_pcd_start(core_if);
17030 +
17031 + gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17032 + if (!gotgctl.b.bsesvld) {
17033 + dwc_otg_initiate_srp(core_if);
17034 + }
17035 + }
17036 + }
17037 + if (core_if->power_down == 2) {
17038 + if (gpwrdn.b.bsessvld) {
17039 + /* Mask SRP detected interrupt from Power Down Logic */
17040 + gpwrdn.d32 = 0;
17041 + gpwrdn.b.srp_det_msk = 1;
17042 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17043 +
17044 + /* Disable Power Down Logic */
17045 + gpwrdn.d32 = 0;
17046 + gpwrdn.b.pmuactv = 1;
17047 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17048 +
17049 + /*
17050 + * Initialize the Core for Device mode.
17051 + */
17052 + core_if->op_state = B_PERIPHERAL;
17053 + dwc_otg_core_init(core_if);
17054 + dwc_otg_enable_global_interrupts(core_if);
17055 + cil_pcd_start(core_if);
17056 + }
17057 + }
17058 + }
17059 +exit:
17060 + /* Clear interrupt */
17061 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17062 + adpctl.b.adp_prb_int = 1;
17063 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
17064 +
17065 + return 0;
17066 +}
17067 +
17068 +/**
17069 + * This function hadles ADP Sense Interrupt
17070 + */
17071 +static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
17072 +{
17073 + adpctl_data_t adpctl;
17074 + /* Stop ADP Sense timer */
17075 + DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17076 +
17077 + /* Restart ADP Sense timer */
17078 + dwc_otg_adp_sense_timer_start(core_if);
17079 +
17080 + /* Clear interrupt */
17081 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17082 + adpctl.b.adp_sns_int = 1;
17083 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
17084 +
17085 + return 0;
17086 +}
17087 +
17088 +/**
17089 + * This function handles ADP Probe Interrupts
17090 + */
17091 +static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
17092 + uint32_t val)
17093 +{
17094 + adpctl_data_t adpctl = {.d32 = 0 };
17095 + adpctl.d32 = val;
17096 + set_timer_value(core_if, adpctl.b.rtim);
17097 +
17098 + /* Clear interrupt */
17099 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17100 + adpctl.b.adp_tmout_int = 1;
17101 + dwc_otg_adp_write_reg(core_if, adpctl.d32);
17102 +
17103 + return 0;
17104 +}
17105 +
17106 +/**
17107 + * ADP Interrupt handler.
17108 + *
17109 + */
17110 +int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
17111 +{
17112 + int retval = 0;
17113 + adpctl_data_t adpctl = {.d32 = 0};
17114 +
17115 + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17116 + DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
17117 +
17118 + if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
17119 + DWC_PRINTF("ADP Sense interrupt\n");
17120 + retval |= dwc_otg_adp_handle_sns_intr(core_if);
17121 + }
17122 + if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
17123 + DWC_PRINTF("ADP timeout interrupt\n");
17124 + retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
17125 + }
17126 + if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
17127 + DWC_PRINTF("ADP Probe interrupt\n");
17128 + adpctl.b.adp_prb_int = 1;
17129 + retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
17130 + }
17131 +
17132 +// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
17133 + //dwc_otg_adp_write_reg(core_if, adpctl.d32);
17134 + DWC_PRINTF("RETURN FROM ADP ISR\n");
17135 +
17136 + return retval;
17137 +}
17138 +
17139 +/**
17140 + *
17141 + * @param core_if Programming view of DWC_otg controller.
17142 + */
17143 +int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
17144 +{
17145 +
17146 +#ifndef DWC_HOST_ONLY
17147 + hprt0_data_t hprt0;
17148 + gpwrdn_data_t gpwrdn;
17149 + DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
17150 +
17151 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17152 + /* check which value is for device mode and which for Host mode */
17153 + if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */
17154 + DWC_PRINTF("SRP: Host mode\n");
17155 +
17156 + if (core_if->adp_enable) {
17157 + dwc_otg_adp_probe_stop(core_if);
17158 +
17159 + /* Power on the core */
17160 + if (core_if->power_down == 2) {
17161 + gpwrdn.b.pwrdnswtch = 1;
17162 + DWC_MODIFY_REG32(&core_if->core_global_regs->
17163 + gpwrdn, 0, gpwrdn.d32);
17164 + }
17165 +
17166 + core_if->op_state = A_HOST;
17167 + dwc_otg_core_init(core_if);
17168 + dwc_otg_enable_global_interrupts(core_if);
17169 + cil_hcd_start(core_if);
17170 + }
17171 +
17172 + /* Turn on the port power bit. */
17173 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
17174 + hprt0.b.prtpwr = 1;
17175 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17176 +
17177 + /* Start the Connection timer. So a message can be displayed
17178 + * if connect does not occur within 10 seconds. */
17179 + cil_hcd_session_start(core_if);
17180 + } else {
17181 + DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
17182 + if (core_if->adp_enable) {
17183 + dwc_otg_adp_probe_stop(core_if);
17184 +
17185 + /* Power on the core */
17186 + if (core_if->power_down == 2) {
17187 + gpwrdn.b.pwrdnswtch = 1;
17188 + DWC_MODIFY_REG32(&core_if->core_global_regs->
17189 + gpwrdn, 0, gpwrdn.d32);
17190 + }
17191 +
17192 + gpwrdn.d32 = 0;
17193 + gpwrdn.b.pmuactv = 0;
17194 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
17195 + gpwrdn.d32);
17196 +
17197 + core_if->op_state = B_PERIPHERAL;
17198 + dwc_otg_core_init(core_if);
17199 + dwc_otg_enable_global_interrupts(core_if);
17200 + cil_pcd_start(core_if);
17201 + }
17202 + }
17203 +#endif
17204 + return 1;
17205 +}
17206 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17207 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1970-01-01 01:00:00.000000000 +0100
17208 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2013-07-06 15:25:50.000000000 +0100
17209 @@ -0,0 +1,80 @@
17210 +/* ==========================================================================
17211 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
17212 + * $Revision: #7 $
17213 + * $Date: 2011/10/24 $
17214 + * $Change: 1871159 $
17215 + *
17216 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17217 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17218 + * otherwise expressly agreed to in writing between Synopsys and you.
17219 + *
17220 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17221 + * any End User Software License Agreement or Agreement for Licensed Product
17222 + * with Synopsys or any supplement thereto. You are permitted to use and
17223 + * redistribute this Software in source and binary forms, with or without
17224 + * modification, provided that redistributions of source code must retain this
17225 + * notice. You may not view, use, disclose, copy or distribute this file or
17226 + * any information contained herein except pursuant to this license grant from
17227 + * Synopsys. If you do not agree with this notice, including the disclaimer
17228 + * below, then you are not authorized to use the Software.
17229 + *
17230 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17231 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17232 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17233 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17234 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17235 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17236 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17237 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17238 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17239 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17240 + * DAMAGE.
17241 + * ========================================================================== */
17242 +
17243 +#ifndef __DWC_OTG_ADP_H__
17244 +#define __DWC_OTG_ADP_H__
17245 +
17246 +/**
17247 + * @file
17248 + *
17249 + * This file contains the Attach Detect Protocol interfaces and defines
17250 + * (functions) and structures for Linux.
17251 + *
17252 + */
17253 +
17254 +#define DWC_OTG_ADP_UNATTACHED 0
17255 +#define DWC_OTG_ADP_ATTACHED 1
17256 +#define DWC_OTG_ADP_UNKOWN 2
17257 +
17258 +typedef struct dwc_otg_adp {
17259 + uint32_t adp_started;
17260 + uint32_t initial_probe;
17261 + int32_t probe_timer_values[2];
17262 + uint32_t probe_enabled;
17263 + uint32_t sense_enabled;
17264 + dwc_timer_t *sense_timer;
17265 + uint32_t sense_timer_started;
17266 + dwc_timer_t *vbuson_timer;
17267 + uint32_t vbuson_timer_started;
17268 + uint32_t attached;
17269 + uint32_t probe_counter;
17270 + uint32_t gpwrdn;
17271 +} dwc_otg_adp_t;
17272 +
17273 +/**
17274 + * Attach Detect Protocol functions
17275 + */
17276 +
17277 +extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);
17278 +extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);
17279 +extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);
17280 +extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
17281 +extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
17282 +extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
17283 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
17284 +extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
17285 +extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
17286 +extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
17287 +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
17288 +
17289 +#endif //__DWC_OTG_ADP_H__
17290 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17291 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100
17292 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2013-07-06 15:25:50.000000000 +0100
17293 @@ -0,0 +1,1210 @@
17294 +/* ==========================================================================
17295 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
17296 + * $Revision: #44 $
17297 + * $Date: 2010/11/29 $
17298 + * $Change: 1636033 $
17299 + *
17300 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17301 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17302 + * otherwise expressly agreed to in writing between Synopsys and you.
17303 + *
17304 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17305 + * any End User Software License Agreement or Agreement for Licensed Product
17306 + * with Synopsys or any supplement thereto. You are permitted to use and
17307 + * redistribute this Software in source and binary forms, with or without
17308 + * modification, provided that redistributions of source code must retain this
17309 + * notice. You may not view, use, disclose, copy or distribute this file or
17310 + * any information contained herein except pursuant to this license grant from
17311 + * Synopsys. If you do not agree with this notice, including the disclaimer
17312 + * below, then you are not authorized to use the Software.
17313 + *
17314 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17315 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17316 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17317 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17318 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17319 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17320 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17321 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17322 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17323 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17324 + * DAMAGE.
17325 + * ========================================================================== */
17326 +
17327 +/** @file
17328 + *
17329 + * The diagnostic interface will provide access to the controller for
17330 + * bringing up the hardware and testing. The Linux driver attributes
17331 + * feature will be used to provide the Linux Diagnostic
17332 + * Interface. These attributes are accessed through sysfs.
17333 + */
17334 +
17335 +/** @page "Linux Module Attributes"
17336 + *
17337 + * The Linux module attributes feature is used to provide the Linux
17338 + * Diagnostic Interface. These attributes are accessed through sysfs.
17339 + * The diagnostic interface will provide access to the controller for
17340 + * bringing up the hardware and testing.
17341 +
17342 + The following table shows the attributes.
17343 + <table>
17344 + <tr>
17345 + <td><b> Name</b></td>
17346 + <td><b> Description</b></td>
17347 + <td><b> Access</b></td>
17348 + </tr>
17349 +
17350 + <tr>
17351 + <td> mode </td>
17352 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
17353 + <td> Read</td>
17354 + </tr>
17355 +
17356 + <tr>
17357 + <td> hnpcapable </td>
17358 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
17359 + Read returns the current value.</td>
17360 + <td> Read/Write</td>
17361 + </tr>
17362 +
17363 + <tr>
17364 + <td> srpcapable </td>
17365 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
17366 + Read returns the current value.</td>
17367 + <td> Read/Write</td>
17368 + </tr>
17369 +
17370 + <tr>
17371 + <td> hsic_connect </td>
17372 + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
17373 + Read returns the current value.</td>
17374 + <td> Read/Write</td>
17375 + </tr>
17376 +
17377 + <tr>
17378 + <td> inv_sel_hsic </td>
17379 + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
17380 + Read returns the current value.</td>
17381 + <td> Read/Write</td>
17382 + </tr>
17383 +
17384 + <tr>
17385 + <td> hnp </td>
17386 + <td> Initiates the Host Negotiation Protocol. Read returns the status.</td>
17387 + <td> Read/Write</td>
17388 + </tr>
17389 +
17390 + <tr>
17391 + <td> srp </td>
17392 + <td> Initiates the Session Request Protocol. Read returns the status.</td>
17393 + <td> Read/Write</td>
17394 + </tr>
17395 +
17396 + <tr>
17397 + <td> buspower </td>
17398 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
17399 + <td> Read/Write</td>
17400 + </tr>
17401 +
17402 + <tr>
17403 + <td> bussuspend </td>
17404 + <td> Suspends the USB bus.</td>
17405 + <td> Read/Write</td>
17406 + </tr>
17407 +
17408 + <tr>
17409 + <td> busconnected </td>
17410 + <td> Gets the connection status of the bus</td>
17411 + <td> Read</td>
17412 + </tr>
17413 +
17414 + <tr>
17415 + <td> gotgctl </td>
17416 + <td> Gets or sets the Core Control Status Register.</td>
17417 + <td> Read/Write</td>
17418 + </tr>
17419 +
17420 + <tr>
17421 + <td> gusbcfg </td>
17422 + <td> Gets or sets the Core USB Configuration Register</td>
17423 + <td> Read/Write</td>
17424 + </tr>
17425 +
17426 + <tr>
17427 + <td> grxfsiz </td>
17428 + <td> Gets or sets the Receive FIFO Size Register</td>
17429 + <td> Read/Write</td>
17430 + </tr>
17431 +
17432 + <tr>
17433 + <td> gnptxfsiz </td>
17434 + <td> Gets or sets the non-periodic Transmit Size Register</td>
17435 + <td> Read/Write</td>
17436 + </tr>
17437 +
17438 + <tr>
17439 + <td> gpvndctl </td>
17440 + <td> Gets or sets the PHY Vendor Control Register</td>
17441 + <td> Read/Write</td>
17442 + </tr>
17443 +
17444 + <tr>
17445 + <td> ggpio </td>
17446 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
17447 + or sets the upper 16 bits.</td>
17448 + <td> Read/Write</td>
17449 + </tr>
17450 +
17451 + <tr>
17452 + <td> guid </td>
17453 + <td> Gets or sets the value of the User ID Register</td>
17454 + <td> Read/Write</td>
17455 + </tr>
17456 +
17457 + <tr>
17458 + <td> gsnpsid </td>
17459 + <td> Gets the value of the Synopsys ID Regester</td>
17460 + <td> Read</td>
17461 + </tr>
17462 +
17463 + <tr>
17464 + <td> devspeed </td>
17465 + <td> Gets or sets the device speed setting in the DCFG register</td>
17466 + <td> Read/Write</td>
17467 + </tr>
17468 +
17469 + <tr>
17470 + <td> enumspeed </td>
17471 + <td> Gets the device enumeration Speed.</td>
17472 + <td> Read</td>
17473 + </tr>
17474 +
17475 + <tr>
17476 + <td> hptxfsiz </td>
17477 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
17478 + <td> Read</td>
17479 + </tr>
17480 +
17481 + <tr>
17482 + <td> hprt0 </td>
17483 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
17484 + <td> Read/Write</td>
17485 + </tr>
17486 +
17487 + <tr>
17488 + <td> regoffset </td>
17489 + <td> Sets the register offset for the next Register Access</td>
17490 + <td> Read/Write</td>
17491 + </tr>
17492 +
17493 + <tr>
17494 + <td> regvalue </td>
17495 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
17496 + <td> Read/Write</td>
17497 + </tr>
17498 +
17499 + <tr>
17500 + <td> remote_wakeup </td>
17501 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
17502 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
17503 + Wakeup signalling bit in the Device Control Register is set for 1
17504 + milli-second.</td>
17505 + <td> Read/Write</td>
17506 + </tr>
17507 +
17508 + <tr>
17509 + <td> rem_wakeup_pwrdn </td>
17510 + <td> On read, shows the status core - hibernated or not. On write, initiates
17511 + a remote wakeup of the device from Hibernation. </td>
17512 + <td> Read/Write</td>
17513 + </tr>
17514 +
17515 + <tr>
17516 + <td> mode_ch_tim_en </td>
17517 + <td> This bit is used to enable or disable the host core to wait for 200 PHY
17518 + clock cycles at the end of Resume to change the opmode signal to the PHY to 00
17519 + after Suspend or LPM. </td>
17520 + <td> Read/Write</td>
17521 + </tr>
17522 +
17523 + <tr>
17524 + <td> fr_interval </td>
17525 + <td> On read, shows the value of HFIR Frame Interval. On write, dynamically
17526 + reload HFIR register during runtime. The application can write a value to this
17527 + register only after the Port Enable bit of the Host Port Control and Status
17528 + register (HPRT.PrtEnaPort) has been set </td>
17529 + <td> Read/Write</td>
17530 + </tr>
17531 +
17532 + <tr>
17533 + <td> disconnect_us </td>
17534 + <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
17535 + which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>
17536 + <td> Read/Write</td>
17537 + </tr>
17538 +
17539 + <tr>
17540 + <td> regdump </td>
17541 + <td> Dumps the contents of core registers.</td>
17542 + <td> Read</td>
17543 + </tr>
17544 +
17545 + <tr>
17546 + <td> spramdump </td>
17547 + <td> Dumps the contents of core registers.</td>
17548 + <td> Read</td>
17549 + </tr>
17550 +
17551 + <tr>
17552 + <td> hcddump </td>
17553 + <td> Dumps the current HCD state.</td>
17554 + <td> Read</td>
17555 + </tr>
17556 +
17557 + <tr>
17558 + <td> hcd_frrem </td>
17559 + <td> Shows the average value of the Frame Remaining
17560 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
17561 + occurs. This can be used to determine the average interrupt latency. Also
17562 + shows the average Frame Remaining value for start_transfer and the "a" and
17563 + "b" sample points. The "a" and "b" sample points may be used during debugging
17564 + bto determine how long it takes to execute a section of the HCD code.</td>
17565 + <td> Read</td>
17566 + </tr>
17567 +
17568 + <tr>
17569 + <td> rd_reg_test </td>
17570 + <td> Displays the time required to read the GNPTXFSIZ register many times
17571 + (the output shows the number of times the register is read).
17572 + <td> Read</td>
17573 + </tr>
17574 +
17575 + <tr>
17576 + <td> wr_reg_test </td>
17577 + <td> Displays the time required to write the GNPTXFSIZ register many times
17578 + (the output shows the number of times the register is written).
17579 + <td> Read</td>
17580 + </tr>
17581 +
17582 + <tr>
17583 + <td> lpm_response </td>
17584 + <td> Gets or sets lpm_response mode. Applicable only in device mode.
17585 + <td> Write</td>
17586 + </tr>
17587 +
17588 + <tr>
17589 + <td> sleep_status </td>
17590 + <td> Shows sleep status of device.
17591 + <td> Read</td>
17592 + </tr>
17593 +
17594 + </table>
17595 +
17596 + Example usage:
17597 + To get the current mode:
17598 + cat /sys/devices/lm0/mode
17599 +
17600 + To power down the USB:
17601 + echo 0 > /sys/devices/lm0/buspower
17602 + */
17603 +
17604 +#include "dwc_otg_os_dep.h"
17605 +#include "dwc_os.h"
17606 +#include "dwc_otg_driver.h"
17607 +#include "dwc_otg_attr.h"
17608 +#include "dwc_otg_core_if.h"
17609 +#include "dwc_otg_pcd_if.h"
17610 +#include "dwc_otg_hcd_if.h"
17611 +
17612 +/*
17613 + * MACROs for defining sysfs attribute
17614 + */
17615 +#ifdef LM_INTERFACE
17616 +
17617 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17618 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17619 +{ \
17620 + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17621 + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17622 + uint32_t val; \
17623 + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17624 + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17625 +}
17626 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17627 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17628 + const char *buf, size_t count) \
17629 +{ \
17630 + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17631 + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17632 + uint32_t set = simple_strtoul(buf, NULL, 16); \
17633 + dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17634 + return count; \
17635 +}
17636 +
17637 +#elif defined(PCI_INTERFACE)
17638 +
17639 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17640 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17641 +{ \
17642 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
17643 + uint32_t val; \
17644 + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17645 + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17646 +}
17647 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17648 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17649 + const char *buf, size_t count) \
17650 +{ \
17651 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
17652 + uint32_t set = simple_strtoul(buf, NULL, 16); \
17653 + dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17654 + return count; \
17655 +}
17656 +
17657 +#elif defined(PLATFORM_INTERFACE)
17658 +
17659 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17660 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17661 +{ \
17662 + struct platform_device *platform_dev = \
17663 + container_of(_dev, struct platform_device, dev); \
17664 + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17665 + uint32_t val; \
17666 + DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17667 + __func__, _dev, platform_dev, otg_dev); \
17668 + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17669 + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17670 +}
17671 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17672 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17673 + const char *buf, size_t count) \
17674 +{ \
17675 + struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17676 + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17677 + uint32_t set = simple_strtoul(buf, NULL, 16); \
17678 + dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17679 + return count; \
17680 +}
17681 +#endif
17682 +
17683 +/*
17684 + * MACROs for defining sysfs attribute for 32-bit registers
17685 + */
17686 +#ifdef LM_INTERFACE
17687 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17688 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17689 +{ \
17690 + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17691 + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17692 + uint32_t val; \
17693 + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17694 + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17695 +}
17696 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17697 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17698 + const char *buf, size_t count) \
17699 +{ \
17700 + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17701 + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17702 + uint32_t val = simple_strtoul(buf, NULL, 16); \
17703 + dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17704 + return count; \
17705 +}
17706 +#elif defined(PCI_INTERFACE)
17707 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17708 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17709 +{ \
17710 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
17711 + uint32_t val; \
17712 + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17713 + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17714 +}
17715 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17716 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17717 + const char *buf, size_t count) \
17718 +{ \
17719 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
17720 + uint32_t val = simple_strtoul(buf, NULL, 16); \
17721 + dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17722 + return count; \
17723 +}
17724 +
17725 +#elif defined(PLATFORM_INTERFACE)
17726 +#include "dwc_otg_dbg.h"
17727 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17728 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17729 +{ \
17730 + struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17731 + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17732 + uint32_t val; \
17733 + DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17734 + __func__, _dev, platform_dev, otg_dev); \
17735 + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17736 + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17737 +}
17738 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17739 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17740 + const char *buf, size_t count) \
17741 +{ \
17742 + struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17743 + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17744 + uint32_t val = simple_strtoul(buf, NULL, 16); \
17745 + dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17746 + return count; \
17747 +}
17748 +
17749 +#endif
17750 +
17751 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
17752 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17753 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17754 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
17755 +
17756 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
17757 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17758 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
17759 +
17760 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
17761 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17762 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17763 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
17764 +
17765 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
17766 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17767 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
17768 +
17769 +/** @name Functions for Show/Store of Attributes */
17770 +/**@{*/
17771 +
17772 +/**
17773 + * Helper function returning the otg_device structure of the given device
17774 + */
17775 +static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
17776 +{
17777 + dwc_otg_device_t *otg_dev;
17778 + DWC_OTG_GETDRVDEV(otg_dev, _dev);
17779 + return otg_dev;
17780 +}
17781 +
17782 +/**
17783 + * Show the register offset of the Register Access.
17784 + */
17785 +static ssize_t regoffset_show(struct device *_dev,
17786 + struct device_attribute *attr, char *buf)
17787 +{
17788 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17789 + return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
17790 + otg_dev->os_dep.reg_offset);
17791 +}
17792 +
17793 +/**
17794 + * Set the register offset for the next Register Access Read/Write
17795 + */
17796 +static ssize_t regoffset_store(struct device *_dev,
17797 + struct device_attribute *attr,
17798 + const char *buf, size_t count)
17799 +{
17800 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17801 + uint32_t offset = simple_strtoul(buf, NULL, 16);
17802 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
17803 + if (offset < SZ_256K) {
17804 +#elif defined(PCI_INTERFACE)
17805 + if (offset < 0x00040000) {
17806 +#endif
17807 + otg_dev->os_dep.reg_offset = offset;
17808 + } else {
17809 + dev_err(_dev, "invalid offset\n");
17810 + }
17811 +
17812 + return count;
17813 +}
17814 +
17815 +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
17816 +
17817 +/**
17818 + * Show the value of the register at the offset in the reg_offset
17819 + * attribute.
17820 + */
17821 +static ssize_t regvalue_show(struct device *_dev,
17822 + struct device_attribute *attr, char *buf)
17823 +{
17824 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17825 + uint32_t val;
17826 + volatile uint32_t *addr;
17827 +
17828 + if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
17829 + /* Calculate the address */
17830 + addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
17831 + (uint8_t *) otg_dev->os_dep.base);
17832 + val = DWC_READ_REG32(addr);
17833 + return snprintf(buf,
17834 + sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
17835 + "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,
17836 + val);
17837 + } else {
17838 + dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);
17839 + return sprintf(buf, "invalid offset\n");
17840 + }
17841 +}
17842 +
17843 +/**
17844 + * Store the value in the register at the offset in the reg_offset
17845 + * attribute.
17846 + *
17847 + */
17848 +static ssize_t regvalue_store(struct device *_dev,
17849 + struct device_attribute *attr,
17850 + const char *buf, size_t count)
17851 +{
17852 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17853 + volatile uint32_t *addr;
17854 + uint32_t val = simple_strtoul(buf, NULL, 16);
17855 + //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
17856 + if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
17857 + /* Calculate the address */
17858 + addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
17859 + (uint8_t *) otg_dev->os_dep.base);
17860 + DWC_WRITE_REG32(addr, val);
17861 + } else {
17862 + dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
17863 + otg_dev->os_dep.reg_offset);
17864 + }
17865 + return count;
17866 +}
17867 +
17868 +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
17869 +
17870 +/*
17871 + * Attributes
17872 + */
17873 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
17874 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
17875 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");
17876 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
17877 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
17878 +
17879 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
17880 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
17881 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
17882 +
17883 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
17884 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
17885 + &(otg_dev->core_if->core_global_regs->gusbcfg),
17886 + "GUSBCFG");
17887 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
17888 + &(otg_dev->core_if->core_global_regs->grxfsiz),
17889 + "GRXFSIZ");
17890 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
17891 + &(otg_dev->core_if->core_global_regs->gnptxfsiz),
17892 + "GNPTXFSIZ");
17893 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
17894 + &(otg_dev->core_if->core_global_regs->gpvndctl),
17895 + "GPVNDCTL");
17896 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
17897 + &(otg_dev->core_if->core_global_regs->ggpio),
17898 + "GGPIO");
17899 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
17900 + "GUID");
17901 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
17902 + &(otg_dev->core_if->core_global_regs->gsnpsid),
17903 + "GSNPSID");
17904 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
17905 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
17906 +
17907 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
17908 + &(otg_dev->core_if->core_global_regs->hptxfsiz),
17909 + "HPTXFSIZ");
17910 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
17911 +
17912 +/**
17913 + * @todo Add code to initiate the HNP.
17914 + */
17915 +/**
17916 + * Show the HNP status bit
17917 + */
17918 +static ssize_t hnp_show(struct device *_dev,
17919 + struct device_attribute *attr, char *buf)
17920 +{
17921 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17922 + return sprintf(buf, "HstNegScs = 0x%x\n",
17923 + dwc_otg_get_hnpstatus(otg_dev->core_if));
17924 +}
17925 +
17926 +/**
17927 + * Set the HNP Request bit
17928 + */
17929 +static ssize_t hnp_store(struct device *_dev,
17930 + struct device_attribute *attr,
17931 + const char *buf, size_t count)
17932 +{
17933 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17934 + uint32_t in = simple_strtoul(buf, NULL, 16);
17935 + dwc_otg_set_hnpreq(otg_dev->core_if, in);
17936 + return count;
17937 +}
17938 +
17939 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
17940 +
17941 +/**
17942 + * @todo Add code to initiate the SRP.
17943 + */
17944 +/**
17945 + * Show the SRP status bit
17946 + */
17947 +static ssize_t srp_show(struct device *_dev,
17948 + struct device_attribute *attr, char *buf)
17949 +{
17950 +#ifndef DWC_HOST_ONLY
17951 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17952 + return sprintf(buf, "SesReqScs = 0x%x\n",
17953 + dwc_otg_get_srpstatus(otg_dev->core_if));
17954 +#else
17955 + return sprintf(buf, "Host Only Mode!\n");
17956 +#endif
17957 +}
17958 +
17959 +/**
17960 + * Set the SRP Request bit
17961 + */
17962 +static ssize_t srp_store(struct device *_dev,
17963 + struct device_attribute *attr,
17964 + const char *buf, size_t count)
17965 +{
17966 +#ifndef DWC_HOST_ONLY
17967 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17968 + dwc_otg_pcd_initiate_srp(otg_dev->pcd);
17969 +#endif
17970 + return count;
17971 +}
17972 +
17973 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
17974 +
17975 +/**
17976 + * @todo Need to do more for power on/off?
17977 + */
17978 +/**
17979 + * Show the Bus Power status
17980 + */
17981 +static ssize_t buspower_show(struct device *_dev,
17982 + struct device_attribute *attr, char *buf)
17983 +{
17984 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17985 + return sprintf(buf, "Bus Power = 0x%x\n",
17986 + dwc_otg_get_prtpower(otg_dev->core_if));
17987 +}
17988 +
17989 +/**
17990 + * Set the Bus Power status
17991 + */
17992 +static ssize_t buspower_store(struct device *_dev,
17993 + struct device_attribute *attr,
17994 + const char *buf, size_t count)
17995 +{
17996 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17997 + uint32_t on = simple_strtoul(buf, NULL, 16);
17998 + dwc_otg_set_prtpower(otg_dev->core_if, on);
17999 + return count;
18000 +}
18001 +
18002 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
18003 +
18004 +/**
18005 + * @todo Need to do more for suspend?
18006 + */
18007 +/**
18008 + * Show the Bus Suspend status
18009 + */
18010 +static ssize_t bussuspend_show(struct device *_dev,
18011 + struct device_attribute *attr, char *buf)
18012 +{
18013 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18014 + return sprintf(buf, "Bus Suspend = 0x%x\n",
18015 + dwc_otg_get_prtsuspend(otg_dev->core_if));
18016 +}
18017 +
18018 +/**
18019 + * Set the Bus Suspend status
18020 + */
18021 +static ssize_t bussuspend_store(struct device *_dev,
18022 + struct device_attribute *attr,
18023 + const char *buf, size_t count)
18024 +{
18025 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18026 + uint32_t in = simple_strtoul(buf, NULL, 16);
18027 + dwc_otg_set_prtsuspend(otg_dev->core_if, in);
18028 + return count;
18029 +}
18030 +
18031 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
18032 +
18033 +/**
18034 + * Show the Mode Change Ready Timer status
18035 + */
18036 +static ssize_t mode_ch_tim_en_show(struct device *_dev,
18037 + struct device_attribute *attr, char *buf)
18038 +{
18039 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18040 + return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
18041 + dwc_otg_get_mode_ch_tim(otg_dev->core_if));
18042 +}
18043 +
18044 +/**
18045 + * Set the Mode Change Ready Timer status
18046 + */
18047 +static ssize_t mode_ch_tim_en_store(struct device *_dev,
18048 + struct device_attribute *attr,
18049 + const char *buf, size_t count)
18050 +{
18051 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18052 + uint32_t in = simple_strtoul(buf, NULL, 16);
18053 + dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);
18054 + return count;
18055 +}
18056 +
18057 +DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);
18058 +
18059 +/**
18060 + * Show the value of HFIR Frame Interval bitfield
18061 + */
18062 +static ssize_t fr_interval_show(struct device *_dev,
18063 + struct device_attribute *attr, char *buf)
18064 +{
18065 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18066 + return sprintf(buf, "Frame Interval = 0x%x\n",
18067 + dwc_otg_get_fr_interval(otg_dev->core_if));
18068 +}
18069 +
18070 +/**
18071 + * Set the HFIR Frame Interval value
18072 + */
18073 +static ssize_t fr_interval_store(struct device *_dev,
18074 + struct device_attribute *attr,
18075 + const char *buf, size_t count)
18076 +{
18077 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18078 + uint32_t in = simple_strtoul(buf, NULL, 10);
18079 + dwc_otg_set_fr_interval(otg_dev->core_if, in);
18080 + return count;
18081 +}
18082 +
18083 +DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);
18084 +
18085 +/**
18086 + * Show the status of Remote Wakeup.
18087 + */
18088 +static ssize_t remote_wakeup_show(struct device *_dev,
18089 + struct device_attribute *attr, char *buf)
18090 +{
18091 +#ifndef DWC_HOST_ONLY
18092 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18093 +
18094 + return sprintf(buf,
18095 + "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
18096 + dwc_otg_get_remotewakesig(otg_dev->core_if),
18097 + dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
18098 + dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
18099 +#else
18100 + return sprintf(buf, "Host Only Mode!\n");
18101 +#endif /* DWC_HOST_ONLY */
18102 +}
18103 +
18104 +/**
18105 + * Initiate a remote wakeup of the host. The Device control register
18106 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
18107 + * flag is set.
18108 + *
18109 + */
18110 +static ssize_t remote_wakeup_store(struct device *_dev,
18111 + struct device_attribute *attr,
18112 + const char *buf, size_t count)
18113 +{
18114 +#ifndef DWC_HOST_ONLY
18115 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18116 + uint32_t val = simple_strtoul(buf, NULL, 16);
18117 +
18118 + if (val & 1) {
18119 + dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
18120 + } else {
18121 + dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
18122 + }
18123 +#endif /* DWC_HOST_ONLY */
18124 + return count;
18125 +}
18126 +
18127 +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
18128 + remote_wakeup_store);
18129 +
18130 +/**
18131 + * Show the whether core is hibernated or not.
18132 + */
18133 +static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
18134 + struct device_attribute *attr, char *buf)
18135 +{
18136 +#ifndef DWC_HOST_ONLY
18137 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18138 +
18139 + if (dwc_otg_get_core_state(otg_dev->core_if)) {
18140 + DWC_PRINTF("Core is in hibernation\n");
18141 + } else {
18142 + DWC_PRINTF("Core is not in hibernation\n");
18143 + }
18144 +#endif /* DWC_HOST_ONLY */
18145 + return 0;
18146 +}
18147 +
18148 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
18149 + int rem_wakeup, int reset);
18150 +
18151 +/**
18152 + * Initiate a remote wakeup of the device to exit from hibernation.
18153 + */
18154 +static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,
18155 + struct device_attribute *attr,
18156 + const char *buf, size_t count)
18157 +{
18158 +#ifndef DWC_HOST_ONLY
18159 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18160 + dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
18161 +#endif
18162 + return count;
18163 +}
18164 +
18165 +DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,
18166 + rem_wakeup_pwrdn_store);
18167 +
18168 +static ssize_t disconnect_us(struct device *_dev,
18169 + struct device_attribute *attr,
18170 + const char *buf, size_t count)
18171 +{
18172 +
18173 +#ifndef DWC_HOST_ONLY
18174 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18175 + uint32_t val = simple_strtoul(buf, NULL, 16);
18176 + DWC_PRINTF("The Passed value is %04x\n", val);
18177 +
18178 + dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);
18179 +
18180 +#endif /* DWC_HOST_ONLY */
18181 + return count;
18182 +}
18183 +
18184 +DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);
18185 +
18186 +/**
18187 + * Dump global registers and either host or device registers (depending on the
18188 + * current mode of the core).
18189 + */
18190 +static ssize_t regdump_show(struct device *_dev,
18191 + struct device_attribute *attr, char *buf)
18192 +{
18193 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18194 +
18195 + dwc_otg_dump_global_registers(otg_dev->core_if);
18196 + if (dwc_otg_is_host_mode(otg_dev->core_if)) {
18197 + dwc_otg_dump_host_registers(otg_dev->core_if);
18198 + } else {
18199 + dwc_otg_dump_dev_registers(otg_dev->core_if);
18200 +
18201 + }
18202 + return sprintf(buf, "Register Dump\n");
18203 +}
18204 +
18205 +DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0);
18206 +
18207 +/**
18208 + * Dump global registers and either host or device registers (depending on the
18209 + * current mode of the core).
18210 + */
18211 +static ssize_t spramdump_show(struct device *_dev,
18212 + struct device_attribute *attr, char *buf)
18213 +{
18214 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18215 +
18216 + dwc_otg_dump_spram(otg_dev->core_if);
18217 +
18218 + return sprintf(buf, "SPRAM Dump\n");
18219 +}
18220 +
18221 +DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0);
18222 +
18223 +/**
18224 + * Dump the current hcd state.
18225 + */
18226 +static ssize_t hcddump_show(struct device *_dev,
18227 + struct device_attribute *attr, char *buf)
18228 +{
18229 +#ifndef DWC_DEVICE_ONLY
18230 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18231 + dwc_otg_hcd_dump_state(otg_dev->hcd);
18232 +#endif /* DWC_DEVICE_ONLY */
18233 + return sprintf(buf, "HCD Dump\n");
18234 +}
18235 +
18236 +DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0);
18237 +
18238 +/**
18239 + * Dump the average frame remaining at SOF. This can be used to
18240 + * determine average interrupt latency. Frame remaining is also shown for
18241 + * start transfer and two additional sample points.
18242 + */
18243 +static ssize_t hcd_frrem_show(struct device *_dev,
18244 + struct device_attribute *attr, char *buf)
18245 +{
18246 +#ifndef DWC_DEVICE_ONLY
18247 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18248 +
18249 + dwc_otg_hcd_dump_frrem(otg_dev->hcd);
18250 +#endif /* DWC_DEVICE_ONLY */
18251 + return sprintf(buf, "HCD Dump Frame Remaining\n");
18252 +}
18253 +
18254 +DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0);
18255 +
18256 +/**
18257 + * Displays the time required to read the GNPTXFSIZ register many times (the
18258 + * output shows the number of times the register is read).
18259 + */
18260 +#define RW_REG_COUNT 10000000
18261 +#define MSEC_PER_JIFFIE 1000/HZ
18262 +static ssize_t rd_reg_test_show(struct device *_dev,
18263 + struct device_attribute *attr, char *buf)
18264 +{
18265 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18266 + int i;
18267 + int time;
18268 + int start_jiffies;
18269 +
18270 + printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18271 + HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18272 + start_jiffies = jiffies;
18273 + for (i = 0; i < RW_REG_COUNT; i++) {
18274 + dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18275 + }
18276 + time = jiffies - start_jiffies;
18277 + return sprintf(buf,
18278 + "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18279 + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18280 +}
18281 +
18282 +DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0);
18283 +
18284 +/**
18285 + * Displays the time required to write the GNPTXFSIZ register many times (the
18286 + * output shows the number of times the register is written).
18287 + */
18288 +static ssize_t wr_reg_test_show(struct device *_dev,
18289 + struct device_attribute *attr, char *buf)
18290 +{
18291 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18292 + uint32_t reg_val;
18293 + int i;
18294 + int time;
18295 + int start_jiffies;
18296 +
18297 + printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18298 + HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18299 + reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18300 + start_jiffies = jiffies;
18301 + for (i = 0; i < RW_REG_COUNT; i++) {
18302 + dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
18303 + }
18304 + time = jiffies - start_jiffies;
18305 + return sprintf(buf,
18306 + "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18307 + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18308 +}
18309 +
18310 +DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0);
18311 +
18312 +#ifdef CONFIG_USB_DWC_OTG_LPM
18313 +
18314 +/**
18315 +* Show the lpm_response attribute.
18316 +*/
18317 +static ssize_t lpmresp_show(struct device *_dev,
18318 + struct device_attribute *attr, char *buf)
18319 +{
18320 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18321 +
18322 + if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
18323 + return sprintf(buf, "** LPM is DISABLED **\n");
18324 +
18325 + if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18326 + return sprintf(buf, "** Current mode is not device mode\n");
18327 + }
18328 + return sprintf(buf, "lpm_response = %d\n",
18329 + dwc_otg_get_lpmresponse(otg_dev->core_if));
18330 +}
18331 +
18332 +/**
18333 +* Store the lpm_response attribute.
18334 +*/
18335 +static ssize_t lpmresp_store(struct device *_dev,
18336 + struct device_attribute *attr,
18337 + const char *buf, size_t count)
18338 +{
18339 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18340 + uint32_t val = simple_strtoul(buf, NULL, 16);
18341 +
18342 + if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
18343 + return 0;
18344 + }
18345 +
18346 + if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18347 + return 0;
18348 + }
18349 +
18350 + dwc_otg_set_lpmresponse(otg_dev->core_if, val);
18351 + return count;
18352 +}
18353 +
18354 +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
18355 +
18356 +/**
18357 +* Show the sleep_status attribute.
18358 +*/
18359 +static ssize_t sleepstatus_show(struct device *_dev,
18360 + struct device_attribute *attr, char *buf)
18361 +{
18362 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18363 + return sprintf(buf, "Sleep Status = %d\n",
18364 + dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
18365 +}
18366 +
18367 +/**
18368 + * Store the sleep_status attribure.
18369 + */
18370 +static ssize_t sleepstatus_store(struct device *_dev,
18371 + struct device_attribute *attr,
18372 + const char *buf, size_t count)
18373 +{
18374 + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18375 + dwc_otg_core_if_t *core_if = otg_dev->core_if;
18376 +
18377 + if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
18378 + if (dwc_otg_is_host_mode(core_if)) {
18379 +
18380 + DWC_PRINTF("Host initiated resume\n");
18381 + dwc_otg_set_prtresume(otg_dev->core_if, 1);
18382 + }
18383 + }
18384 +
18385 + return count;
18386 +}
18387 +
18388 +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
18389 + sleepstatus_store);
18390 +
18391 +#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
18392 +
18393 +/**@}*/
18394 +
18395 +/**
18396 + * Create the device files
18397 + */
18398 +void dwc_otg_attr_create(
18399 +#ifdef LM_INTERFACE
18400 + struct lm_device *dev
18401 +#elif defined(PCI_INTERFACE)
18402 + struct pci_dev *dev
18403 +#elif defined(PLATFORM_INTERFACE)
18404 + struct platform_device *dev
18405 +#endif
18406 + )
18407 +{
18408 + int error;
18409 +
18410 + error = device_create_file(&dev->dev, &dev_attr_regoffset);
18411 + error = device_create_file(&dev->dev, &dev_attr_regvalue);
18412 + error = device_create_file(&dev->dev, &dev_attr_mode);
18413 + error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
18414 + error = device_create_file(&dev->dev, &dev_attr_srpcapable);
18415 + error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
18416 + error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
18417 + error = device_create_file(&dev->dev, &dev_attr_hnp);
18418 + error = device_create_file(&dev->dev, &dev_attr_srp);
18419 + error = device_create_file(&dev->dev, &dev_attr_buspower);
18420 + error = device_create_file(&dev->dev, &dev_attr_bussuspend);
18421 + error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18422 + error = device_create_file(&dev->dev, &dev_attr_fr_interval);
18423 + error = device_create_file(&dev->dev, &dev_attr_busconnected);
18424 + error = device_create_file(&dev->dev, &dev_attr_gotgctl);
18425 + error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
18426 + error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
18427 + error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
18428 + error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
18429 + error = device_create_file(&dev->dev, &dev_attr_ggpio);
18430 + error = device_create_file(&dev->dev, &dev_attr_guid);
18431 + error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
18432 + error = device_create_file(&dev->dev, &dev_attr_devspeed);
18433 + error = device_create_file(&dev->dev, &dev_attr_enumspeed);
18434 + error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
18435 + error = device_create_file(&dev->dev, &dev_attr_hprt0);
18436 + error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
18437 + error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18438 + error = device_create_file(&dev->dev, &dev_attr_disconnect_us);
18439 + error = device_create_file(&dev->dev, &dev_attr_regdump);
18440 + error = device_create_file(&dev->dev, &dev_attr_spramdump);
18441 + error = device_create_file(&dev->dev, &dev_attr_hcddump);
18442 + error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
18443 + error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
18444 + error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
18445 +#ifdef CONFIG_USB_DWC_OTG_LPM
18446 + error = device_create_file(&dev->dev, &dev_attr_lpm_response);
18447 + error = device_create_file(&dev->dev, &dev_attr_sleep_status);
18448 +#endif
18449 +}
18450 +
18451 +/**
18452 + * Remove the device files
18453 + */
18454 +void dwc_otg_attr_remove(
18455 +#ifdef LM_INTERFACE
18456 + struct lm_device *dev
18457 +#elif defined(PCI_INTERFACE)
18458 + struct pci_dev *dev
18459 +#elif defined(PLATFORM_INTERFACE)
18460 + struct platform_device *dev
18461 +#endif
18462 + )
18463 +{
18464 + device_remove_file(&dev->dev, &dev_attr_regoffset);
18465 + device_remove_file(&dev->dev, &dev_attr_regvalue);
18466 + device_remove_file(&dev->dev, &dev_attr_mode);
18467 + device_remove_file(&dev->dev, &dev_attr_hnpcapable);
18468 + device_remove_file(&dev->dev, &dev_attr_srpcapable);
18469 + device_remove_file(&dev->dev, &dev_attr_hsic_connect);
18470 + device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
18471 + device_remove_file(&dev->dev, &dev_attr_hnp);
18472 + device_remove_file(&dev->dev, &dev_attr_srp);
18473 + device_remove_file(&dev->dev, &dev_attr_buspower);
18474 + device_remove_file(&dev->dev, &dev_attr_bussuspend);
18475 + device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18476 + device_remove_file(&dev->dev, &dev_attr_fr_interval);
18477 + device_remove_file(&dev->dev, &dev_attr_busconnected);
18478 + device_remove_file(&dev->dev, &dev_attr_gotgctl);
18479 + device_remove_file(&dev->dev, &dev_attr_gusbcfg);
18480 + device_remove_file(&dev->dev, &dev_attr_grxfsiz);
18481 + device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
18482 + device_remove_file(&dev->dev, &dev_attr_gpvndctl);
18483 + device_remove_file(&dev->dev, &dev_attr_ggpio);
18484 + device_remove_file(&dev->dev, &dev_attr_guid);
18485 + device_remove_file(&dev->dev, &dev_attr_gsnpsid);
18486 + device_remove_file(&dev->dev, &dev_attr_devspeed);
18487 + device_remove_file(&dev->dev, &dev_attr_enumspeed);
18488 + device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
18489 + device_remove_file(&dev->dev, &dev_attr_hprt0);
18490 + device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
18491 + device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18492 + device_remove_file(&dev->dev, &dev_attr_disconnect_us);
18493 + device_remove_file(&dev->dev, &dev_attr_regdump);
18494 + device_remove_file(&dev->dev, &dev_attr_spramdump);
18495 + device_remove_file(&dev->dev, &dev_attr_hcddump);
18496 + device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
18497 + device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
18498 + device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
18499 +#ifdef CONFIG_USB_DWC_OTG_LPM
18500 + device_remove_file(&dev->dev, &dev_attr_lpm_response);
18501 + device_remove_file(&dev->dev, &dev_attr_sleep_status);
18502 +#endif
18503 +}
18504 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18505 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100
18506 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2013-07-06 15:25:50.000000000 +0100
18507 @@ -0,0 +1,89 @@
18508 +/* ==========================================================================
18509 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
18510 + * $Revision: #13 $
18511 + * $Date: 2010/06/21 $
18512 + * $Change: 1532021 $
18513 + *
18514 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18515 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18516 + * otherwise expressly agreed to in writing between Synopsys and you.
18517 + *
18518 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18519 + * any End User Software License Agreement or Agreement for Licensed Product
18520 + * with Synopsys or any supplement thereto. You are permitted to use and
18521 + * redistribute this Software in source and binary forms, with or without
18522 + * modification, provided that redistributions of source code must retain this
18523 + * notice. You may not view, use, disclose, copy or distribute this file or
18524 + * any information contained herein except pursuant to this license grant from
18525 + * Synopsys. If you do not agree with this notice, including the disclaimer
18526 + * below, then you are not authorized to use the Software.
18527 + *
18528 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18529 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18530 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18531 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18532 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18533 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18534 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18535 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18536 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18537 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18538 + * DAMAGE.
18539 + * ========================================================================== */
18540 +
18541 +#if !defined(__DWC_OTG_ATTR_H__)
18542 +#define __DWC_OTG_ATTR_H__
18543 +
18544 +/** @file
18545 + * This file contains the interface to the Linux device attributes.
18546 + */
18547 +extern struct device_attribute dev_attr_regoffset;
18548 +extern struct device_attribute dev_attr_regvalue;
18549 +
18550 +extern struct device_attribute dev_attr_mode;
18551 +extern struct device_attribute dev_attr_hnpcapable;
18552 +extern struct device_attribute dev_attr_srpcapable;
18553 +extern struct device_attribute dev_attr_hnp;
18554 +extern struct device_attribute dev_attr_srp;
18555 +extern struct device_attribute dev_attr_buspower;
18556 +extern struct device_attribute dev_attr_bussuspend;
18557 +extern struct device_attribute dev_attr_mode_ch_tim_en;
18558 +extern struct device_attribute dev_attr_fr_interval;
18559 +extern struct device_attribute dev_attr_busconnected;
18560 +extern struct device_attribute dev_attr_gotgctl;
18561 +extern struct device_attribute dev_attr_gusbcfg;
18562 +extern struct device_attribute dev_attr_grxfsiz;
18563 +extern struct device_attribute dev_attr_gnptxfsiz;
18564 +extern struct device_attribute dev_attr_gpvndctl;
18565 +extern struct device_attribute dev_attr_ggpio;
18566 +extern struct device_attribute dev_attr_guid;
18567 +extern struct device_attribute dev_attr_gsnpsid;
18568 +extern struct device_attribute dev_attr_devspeed;
18569 +extern struct device_attribute dev_attr_enumspeed;
18570 +extern struct device_attribute dev_attr_hptxfsiz;
18571 +extern struct device_attribute dev_attr_hprt0;
18572 +#ifdef CONFIG_USB_DWC_OTG_LPM
18573 +extern struct device_attribute dev_attr_lpm_response;
18574 +extern struct device_attribute devi_attr_sleep_status;
18575 +#endif
18576 +
18577 +void dwc_otg_attr_create(
18578 +#ifdef LM_INTERFACE
18579 + struct lm_device *dev
18580 +#elif defined(PCI_INTERFACE)
18581 + struct pci_dev *dev
18582 +#elif defined(PLATFORM_INTERFACE)
18583 + struct platform_device *dev
18584 +#endif
18585 + );
18586 +
18587 +void dwc_otg_attr_remove(
18588 +#ifdef LM_INTERFACE
18589 + struct lm_device *dev
18590 +#elif defined(PCI_INTERFACE)
18591 + struct pci_dev *dev
18592 +#elif defined(PLATFORM_INTERFACE)
18593 + struct platform_device *dev
18594 +#endif
18595 + );
18596 +#endif
18597 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18598 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100
18599 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2013-07-06 15:25:50.000000000 +0100
18600 @@ -0,0 +1,1876 @@
18601 +/* ==========================================================================
18602 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18603 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18604 + * otherwise expressly agreed to in writing between Synopsys and you.
18605 + *
18606 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18607 + * any End User Software License Agreement or Agreement for Licensed Product
18608 + * with Synopsys or any supplement thereto. You are permitted to use and
18609 + * redistribute this Software in source and binary forms, with or without
18610 + * modification, provided that redistributions of source code must retain this
18611 + * notice. You may not view, use, disclose, copy or distribute this file or
18612 + * any information contained herein except pursuant to this license grant from
18613 + * Synopsys. If you do not agree with this notice, including the disclaimer
18614 + * below, then you are not authorized to use the Software.
18615 + *
18616 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18617 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18618 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18619 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18620 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18621 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18622 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18623 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18624 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18625 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18626 + * DAMAGE.
18627 + * ========================================================================== */
18628 +
18629 +/** @file
18630 + *
18631 + * This file contains the most of the CFI(Core Feature Interface)
18632 + * implementation for the OTG.
18633 + */
18634 +
18635 +#ifdef DWC_UTE_CFI
18636 +
18637 +#include "dwc_otg_pcd.h"
18638 +#include "dwc_otg_cfi.h"
18639 +
18640 +/** This definition should actually migrate to the Portability Library */
18641 +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
18642 +
18643 +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
18644 +
18645 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
18646 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
18647 + struct dwc_otg_pcd *pcd,
18648 + struct cfi_usb_ctrlrequest *ctrl_req);
18649 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
18650 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18651 + struct cfi_usb_ctrlrequest *req);
18652 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18653 + struct cfi_usb_ctrlrequest *req);
18654 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18655 + struct cfi_usb_ctrlrequest *req);
18656 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
18657 + struct cfi_usb_ctrlrequest *req);
18658 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
18659 +
18660 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
18661 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
18662 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
18663 +
18664 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
18665 +
18666 +/** This is the header of the all features descriptor */
18667 +static cfi_all_features_header_t all_props_desc_header = {
18668 + .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
18669 + .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
18670 + .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
18671 +};
18672 +
18673 +/** This is an array of statically allocated feature descriptors */
18674 +static cfi_feature_desc_header_t prop_descs[] = {
18675 +
18676 + /* FT_ID_DMA_MODE */
18677 + {
18678 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
18679 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18680 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
18681 + },
18682 +
18683 + /* FT_ID_DMA_BUFFER_SETUP */
18684 + {
18685 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
18686 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18687 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18688 + },
18689 +
18690 + /* FT_ID_DMA_BUFF_ALIGN */
18691 + {
18692 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
18693 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18694 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18695 + },
18696 +
18697 + /* FT_ID_DMA_CONCAT_SETUP */
18698 + {
18699 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
18700 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18701 + //.wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18702 + },
18703 +
18704 + /* FT_ID_DMA_CIRCULAR */
18705 + {
18706 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
18707 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18708 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18709 + },
18710 +
18711 + /* FT_ID_THRESHOLD_SETUP */
18712 + {
18713 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
18714 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18715 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18716 + },
18717 +
18718 + /* FT_ID_DFIFO_DEPTH */
18719 + {
18720 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
18721 + .bmAttributes = CFI_FEATURE_ATTR_RO,
18722 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18723 + },
18724 +
18725 + /* FT_ID_TX_FIFO_DEPTH */
18726 + {
18727 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
18728 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18729 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18730 + },
18731 +
18732 + /* FT_ID_RX_FIFO_DEPTH */
18733 + {
18734 + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
18735 + .bmAttributes = CFI_FEATURE_ATTR_RW,
18736 + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18737 + }
18738 +};
18739 +
18740 +/** The table of feature names */
18741 +cfi_string_t prop_name_table[] = {
18742 + {FT_ID_DMA_MODE, "dma_mode"},
18743 + {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
18744 + {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
18745 + {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
18746 + {FT_ID_DMA_CIRCULAR, "buffer_circular"},
18747 + {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
18748 + {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
18749 + {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
18750 + {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
18751 + {}
18752 +};
18753 +
18754 +/************************************************************************/
18755 +
18756 +/**
18757 + * Returns the name of the feature by its ID
18758 + * or NULL if no featute ID matches.
18759 + *
18760 + */
18761 +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
18762 +{
18763 + cfi_string_t *pstr;
18764 + *len = 0;
18765 +
18766 + for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
18767 + if (pstr->id == prop_id) {
18768 + *len = DWC_STRLEN(pstr->s);
18769 + return pstr->s;
18770 + }
18771 + }
18772 + return NULL;
18773 +}
18774 +
18775 +/**
18776 + * This function handles all CFI specific control requests.
18777 + *
18778 + * Return a negative value to stall the DCE.
18779 + */
18780 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
18781 +{
18782 + int retval = 0;
18783 + dwc_otg_pcd_ep_t *ep = NULL;
18784 + cfiobject_t *cfi = pcd->cfi;
18785 + struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
18786 + uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
18787 + uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
18788 + uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
18789 + uint32_t regaddr = 0;
18790 + uint32_t regval = 0;
18791 +
18792 + /* Save this Control Request in the CFI object.
18793 + * The data field will be assigned in the data stage completion CB function.
18794 + */
18795 + cfi->ctrl_req = *ctrl;
18796 + cfi->ctrl_req.data = NULL;
18797 +
18798 + cfi->need_gadget_att = 0;
18799 + cfi->need_status_in_complete = 0;
18800 +
18801 + switch (ctrl->bRequest) {
18802 + case VEN_CORE_GET_FEATURES:
18803 + retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
18804 + if (retval >= 0) {
18805 + //dump_msg(cfi->buf_in.buf, retval);
18806 + ep = &pcd->ep0;
18807 +
18808 + retval = min((uint16_t) retval, wLen);
18809 + /* Transfer this buffer to the host through the EP0-IN EP */
18810 + ep->dwc_ep.dma_addr = cfi->buf_in.addr;
18811 + ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
18812 + ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
18813 + ep->dwc_ep.xfer_len = retval;
18814 + ep->dwc_ep.xfer_count = 0;
18815 + ep->dwc_ep.sent_zlp = 0;
18816 + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
18817 +
18818 + pcd->ep0_pending = 1;
18819 + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
18820 + }
18821 + retval = 0;
18822 + break;
18823 +
18824 + case VEN_CORE_GET_FEATURE:
18825 + CFI_INFO("VEN_CORE_GET_FEATURE\n");
18826 + retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
18827 + pcd, ctrl);
18828 + if (retval >= 0) {
18829 + ep = &pcd->ep0;
18830 +
18831 + retval = min((uint16_t) retval, wLen);
18832 + /* Transfer this buffer to the host through the EP0-IN EP */
18833 + ep->dwc_ep.dma_addr = cfi->buf_in.addr;
18834 + ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
18835 + ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
18836 + ep->dwc_ep.xfer_len = retval;
18837 + ep->dwc_ep.xfer_count = 0;
18838 + ep->dwc_ep.sent_zlp = 0;
18839 + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
18840 +
18841 + pcd->ep0_pending = 1;
18842 + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
18843 + }
18844 + CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
18845 + dump_msg(cfi->buf_in.buf, retval);
18846 + break;
18847 +
18848 + case VEN_CORE_SET_FEATURE:
18849 + CFI_INFO("VEN_CORE_SET_FEATURE\n");
18850 + /* Set up an XFER to get the data stage of the control request,
18851 + * which is the new value of the feature to be modified.
18852 + */
18853 + ep = &pcd->ep0;
18854 + ep->dwc_ep.is_in = 0;
18855 + ep->dwc_ep.dma_addr = cfi->buf_out.addr;
18856 + ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
18857 + ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
18858 + ep->dwc_ep.xfer_len = wLen;
18859 + ep->dwc_ep.xfer_count = 0;
18860 + ep->dwc_ep.sent_zlp = 0;
18861 + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
18862 +
18863 + pcd->ep0_pending = 1;
18864 + /* Read the control write's data stage */
18865 + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
18866 + retval = 0;
18867 + break;
18868 +
18869 + case VEN_CORE_RESET_FEATURES:
18870 + CFI_INFO("VEN_CORE_RESET_FEATURES\n");
18871 + cfi->need_gadget_att = 1;
18872 + cfi->need_status_in_complete = 1;
18873 + retval = cfi_preproc_reset(pcd, ctrl);
18874 + CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
18875 + break;
18876 +
18877 + case VEN_CORE_ACTIVATE_FEATURES:
18878 + CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
18879 + break;
18880 +
18881 + case VEN_CORE_READ_REGISTER:
18882 + CFI_INFO("VEN_CORE_READ_REGISTER\n");
18883 + /* wValue optionally contains the HI WORD of the register offset and
18884 + * wIndex contains the LOW WORD of the register offset
18885 + */
18886 + if (wValue == 0) {
18887 + /* @TODO - MAS - fix the access to the base field */
18888 + regaddr = 0;
18889 + //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
18890 + //GET_CORE_IF(pcd)->co
18891 + regaddr |= wIndex;
18892 + } else {
18893 + regaddr = (wValue << 16) | wIndex;
18894 + }
18895 +
18896 + /* Read a 32-bit value of the memory at the regaddr */
18897 + regval = DWC_READ_REG32((uint32_t *) regaddr);
18898 +
18899 + ep = &pcd->ep0;
18900 + dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
18901 + ep->dwc_ep.is_in = 1;
18902 + ep->dwc_ep.dma_addr = cfi->buf_in.addr;
18903 + ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
18904 + ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
18905 + ep->dwc_ep.xfer_len = wLen;
18906 + ep->dwc_ep.xfer_count = 0;
18907 + ep->dwc_ep.sent_zlp = 0;
18908 + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
18909 +
18910 + pcd->ep0_pending = 1;
18911 + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
18912 + cfi->need_gadget_att = 0;
18913 + retval = 0;
18914 + break;
18915 +
18916 + case VEN_CORE_WRITE_REGISTER:
18917 + CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
18918 + /* Set up an XFER to get the data stage of the control request,
18919 + * which is the new value of the register to be modified.
18920 + */
18921 + ep = &pcd->ep0;
18922 + ep->dwc_ep.is_in = 0;
18923 + ep->dwc_ep.dma_addr = cfi->buf_out.addr;
18924 + ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
18925 + ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
18926 + ep->dwc_ep.xfer_len = wLen;
18927 + ep->dwc_ep.xfer_count = 0;
18928 + ep->dwc_ep.sent_zlp = 0;
18929 + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
18930 +
18931 + pcd->ep0_pending = 1;
18932 + /* Read the control write's data stage */
18933 + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
18934 + retval = 0;
18935 + break;
18936 +
18937 + default:
18938 + retval = -DWC_E_NOT_SUPPORTED;
18939 + break;
18940 + }
18941 +
18942 + return retval;
18943 +}
18944 +
18945 +/**
18946 + * This function prepares the core features descriptors and copies its
18947 + * raw representation into the buffer <buf>.
18948 + *
18949 + * The buffer structure is as follows:
18950 + * all_features_header (8 bytes)
18951 + * features_#1 (8 bytes + feature name string length)
18952 + * features_#2 (8 bytes + feature name string length)
18953 + * .....
18954 + * features_#n - where n=the total count of feature descriptors
18955 + */
18956 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
18957 +{
18958 + cfi_feature_desc_header_t *prop_hdr = prop_descs;
18959 + cfi_feature_desc_header_t *prop;
18960 + cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
18961 + cfi_all_features_header_t *tmp;
18962 + uint8_t *tmpbuf = buf;
18963 + const uint8_t *pname = NULL;
18964 + int i, j, namelen = 0, totlen;
18965 +
18966 + /* Prepare and copy the core features into the buffer */
18967 + CFI_INFO("%s:\n", __func__);
18968 +
18969 + tmp = (cfi_all_features_header_t *) tmpbuf;
18970 + *tmp = *all_props_hdr;
18971 + tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
18972 +
18973 + j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
18974 + for (i = 0; i < j; i++, prop_hdr++) {
18975 + pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
18976 + prop = (cfi_feature_desc_header_t *) tmpbuf;
18977 + *prop = *prop_hdr;
18978 +
18979 + prop->bNameLen = namelen;
18980 + prop->wLength =
18981 + DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
18982 + namelen);
18983 +
18984 + tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
18985 + dwc_memcpy(tmpbuf, pname, namelen);
18986 + tmpbuf += namelen;
18987 + }
18988 +
18989 + totlen = tmpbuf - buf;
18990 +
18991 + if (totlen > 0) {
18992 + tmp = (cfi_all_features_header_t *) buf;
18993 + tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
18994 + }
18995 +
18996 + return totlen;
18997 +}
18998 +
18999 +/**
19000 + * This function releases all the dynamic memory in the CFI object.
19001 + */
19002 +static void cfi_release(cfiobject_t * cfiobj)
19003 +{
19004 + cfi_ep_t *cfiep;
19005 + dwc_list_link_t *tmp;
19006 +
19007 + CFI_INFO("%s\n", __func__);
19008 +
19009 + if (cfiobj->buf_in.buf) {
19010 + DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
19011 + cfiobj->buf_in.addr);
19012 + cfiobj->buf_in.buf = NULL;
19013 + }
19014 +
19015 + if (cfiobj->buf_out.buf) {
19016 + DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
19017 + cfiobj->buf_out.addr);
19018 + cfiobj->buf_out.buf = NULL;
19019 + }
19020 +
19021 + /* Free the Buffer Setup values for each EP */
19022 + //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
19023 + DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
19024 + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19025 + cfi_free_ep_bs_dyn_data(cfiep);
19026 + }
19027 +}
19028 +
19029 +/**
19030 + * This function frees the dynamically allocated EP buffer setup data.
19031 + */
19032 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
19033 +{
19034 + if (cfiep->bm_sg) {
19035 + DWC_FREE(cfiep->bm_sg);
19036 + cfiep->bm_sg = NULL;
19037 + }
19038 +
19039 + if (cfiep->bm_align) {
19040 + DWC_FREE(cfiep->bm_align);
19041 + cfiep->bm_align = NULL;
19042 + }
19043 +
19044 + if (cfiep->bm_concat) {
19045 + if (NULL != cfiep->bm_concat->wTxBytes) {
19046 + DWC_FREE(cfiep->bm_concat->wTxBytes);
19047 + cfiep->bm_concat->wTxBytes = NULL;
19048 + }
19049 + DWC_FREE(cfiep->bm_concat);
19050 + cfiep->bm_concat = NULL;
19051 + }
19052 +}
19053 +
19054 +/**
19055 + * This function initializes the default values of the features
19056 + * for a specific endpoint and should be called only once when
19057 + * the EP is enabled first time.
19058 + */
19059 +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
19060 +{
19061 + int retval = 0;
19062 +
19063 + cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
19064 + if (NULL == cfiep->bm_sg) {
19065 + CFI_INFO("Failed to allocate memory for SG feature value\n");
19066 + return -DWC_E_NO_MEMORY;
19067 + }
19068 + dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19069 +
19070 + /* For the Concatenation feature's default value we do not allocate
19071 + * memory for the wTxBytes field - it will be done in the set_feature_value
19072 + * request handler.
19073 + */
19074 + cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
19075 + if (NULL == cfiep->bm_concat) {
19076 + CFI_INFO
19077 + ("Failed to allocate memory for CONCATENATION feature value\n");
19078 + DWC_FREE(cfiep->bm_sg);
19079 + return -DWC_E_NO_MEMORY;
19080 + }
19081 + dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19082 +
19083 + cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
19084 + if (NULL == cfiep->bm_align) {
19085 + CFI_INFO
19086 + ("Failed to allocate memory for Alignment feature value\n");
19087 + DWC_FREE(cfiep->bm_sg);
19088 + DWC_FREE(cfiep->bm_concat);
19089 + return -DWC_E_NO_MEMORY;
19090 + }
19091 + dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
19092 +
19093 + return retval;
19094 +}
19095 +
19096 +/**
19097 + * The callback function that notifies the CFI on the activation of
19098 + * an endpoint in the PCD. The following steps are done in this function:
19099 + *
19100 + * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's
19101 + * active endpoint)
19102 + * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
19103 + * Set the Buffer Mode to standard
19104 + * Initialize the default values for all EP modes (SG, Circular, Concat, Align)
19105 + * Add the cfi_ep_t object to the list of active endpoints in the CFI object
19106 + */
19107 +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19108 + struct dwc_otg_pcd_ep *ep)
19109 +{
19110 + cfi_ep_t *cfiep;
19111 + int retval = -DWC_E_NOT_SUPPORTED;
19112 +
19113 + CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
19114 + "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
19115 + /* MAS - Check whether this endpoint already is in the list */
19116 + cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19117 +
19118 + if (NULL == cfiep) {
19119 + /* Allocate a cfi_ep_t object */
19120 + cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
19121 + if (NULL == cfiep) {
19122 + CFI_INFO
19123 + ("Unable to allocate memory for <cfiep> in function %s\n",
19124 + __func__);
19125 + return -DWC_E_NO_MEMORY;
19126 + }
19127 + dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
19128 +
19129 + /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
19130 + cfiep->ep = ep;
19131 +
19132 + /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
19133 + ep->dwc_ep.descs =
19134 + DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
19135 + sizeof(dwc_otg_dma_desc_t),
19136 + &ep->dwc_ep.descs_dma_addr);
19137 +
19138 + if (NULL == ep->dwc_ep.descs) {
19139 + DWC_FREE(cfiep);
19140 + return -DWC_E_NO_MEMORY;
19141 + }
19142 +
19143 + DWC_LIST_INIT(&cfiep->lh);
19144 +
19145 + /* Set the buffer mode to BM_STANDARD. It will be modified
19146 + * when building descriptors for a specific buffer mode */
19147 + ep->dwc_ep.buff_mode = BM_STANDARD;
19148 +
19149 + /* Create and initialize the default values for this EP's Buffer modes */
19150 + if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
19151 + return retval;
19152 +
19153 + /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
19154 + DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
19155 + retval = 0;
19156 + } else { /* The sought EP already is in the list */
19157 + CFI_INFO("%s: The sought EP already is in the list\n",
19158 + __func__);
19159 + }
19160 +
19161 + return retval;
19162 +}
19163 +
19164 +/**
19165 + * This function is called when the data stage of a 3-stage Control Write request
19166 + * is complete.
19167 + *
19168 + */
19169 +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
19170 + struct dwc_otg_pcd *pcd)
19171 +{
19172 + uint32_t addr, reg_value;
19173 + uint16_t wIndex, wValue;
19174 + uint8_t bRequest;
19175 + uint8_t *buf = cfi->buf_out.buf;
19176 + //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
19177 + struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
19178 + int retval = -DWC_E_NOT_SUPPORTED;
19179 +
19180 + CFI_INFO("%s\n", __func__);
19181 +
19182 + bRequest = ctrl_req->bRequest;
19183 + wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
19184 + wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
19185 +
19186 + /*
19187 + * Save the pointer to the data stage in the ctrl_req's <data> field.
19188 + * The request should be already saved in the command stage by now.
19189 + */
19190 + ctrl_req->data = cfi->buf_out.buf;
19191 + cfi->need_status_in_complete = 0;
19192 + cfi->need_gadget_att = 0;
19193 +
19194 + switch (bRequest) {
19195 + case VEN_CORE_WRITE_REGISTER:
19196 + /* The buffer contains raw data of the new value for the register */
19197 + reg_value = *((uint32_t *) buf);
19198 + if (wValue == 0) {
19199 + addr = 0;
19200 + //addr = (uint32_t) pcd->otg_dev->os_dep.base;
19201 + addr += wIndex;
19202 + } else {
19203 + addr = (wValue << 16) | wIndex;
19204 + }
19205 +
19206 + //writel(reg_value, addr);
19207 +
19208 + retval = 0;
19209 + cfi->need_status_in_complete = 1;
19210 + break;
19211 +
19212 + case VEN_CORE_SET_FEATURE:
19213 + /* The buffer contains raw data of the new value of the feature */
19214 + retval = cfi_set_feature_value(pcd);
19215 + if (retval < 0)
19216 + return retval;
19217 +
19218 + cfi->need_status_in_complete = 1;
19219 + break;
19220 +
19221 + default:
19222 + break;
19223 + }
19224 +
19225 + return retval;
19226 +}
19227 +
19228 +/**
19229 + * This function builds the DMA descriptors for the SG buffer mode.
19230 + */
19231 +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19232 + dwc_otg_pcd_request_t * req)
19233 +{
19234 + struct dwc_otg_pcd_ep *ep = cfiep->ep;
19235 + ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
19236 + struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19237 + struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19238 + dma_addr_t buff_addr = req->dma;
19239 + int i;
19240 + uint32_t txsize, off;
19241 +
19242 + txsize = sgval->wSize;
19243 + off = sgval->bOffset;
19244 +
19245 +// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n",
19246 +// __func__, cfiep->ep->ep.name, txsize, off);
19247 +
19248 + for (i = 0; i < sgval->bCount; i++) {
19249 + desc->status.b.bs = BS_HOST_BUSY;
19250 + desc->buf = buff_addr;
19251 + desc->status.b.l = 0;
19252 + desc->status.b.ioc = 0;
19253 + desc->status.b.sp = 0;
19254 + desc->status.b.bytes = txsize;
19255 + desc->status.b.bs = BS_HOST_READY;
19256 +
19257 + /* Set the next address of the buffer */
19258 + buff_addr += txsize + off;
19259 + desc_last = desc;
19260 + desc++;
19261 + }
19262 +
19263 + /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19264 + desc_last->status.b.l = 1;
19265 + desc_last->status.b.ioc = 1;
19266 + desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19267 + /* Save the last DMA descriptor pointer */
19268 + cfiep->dma_desc_last = desc_last;
19269 + cfiep->desc_count = sgval->bCount;
19270 +}
19271 +
19272 +/**
19273 + * This function builds the DMA descriptors for the Concatenation buffer mode.
19274 + */
19275 +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19276 + dwc_otg_pcd_request_t * req)
19277 +{
19278 + struct dwc_otg_pcd_ep *ep = cfiep->ep;
19279 + ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
19280 + struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19281 + struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19282 + dma_addr_t buff_addr = req->dma;
19283 + int i;
19284 + uint16_t *txsize;
19285 +
19286 + txsize = concatval->wTxBytes;
19287 +
19288 + for (i = 0; i < concatval->hdr.bDescCount; i++) {
19289 + desc->buf = buff_addr;
19290 + desc->status.b.bs = BS_HOST_BUSY;
19291 + desc->status.b.l = 0;
19292 + desc->status.b.ioc = 0;
19293 + desc->status.b.sp = 0;
19294 + desc->status.b.bytes = *txsize;
19295 + desc->status.b.bs = BS_HOST_READY;
19296 +
19297 + txsize++;
19298 + /* Set the next address of the buffer */
19299 + buff_addr += UGETW(ep->desc->wMaxPacketSize);
19300 + desc_last = desc;
19301 + desc++;
19302 + }
19303 +
19304 + /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19305 + desc_last->status.b.l = 1;
19306 + desc_last->status.b.ioc = 1;
19307 + desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19308 + cfiep->dma_desc_last = desc_last;
19309 + cfiep->desc_count = concatval->hdr.bDescCount;
19310 +}
19311 +
19312 +/**
19313 + * This function builds the DMA descriptors for the Circular buffer mode
19314 + */
19315 +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19316 + dwc_otg_pcd_request_t * req)
19317 +{
19318 + /* @todo: MAS - add implementation when this feature needs to be tested */
19319 +}
19320 +
19321 +/**
19322 + * This function builds the DMA descriptors for the Alignment buffer mode
19323 + */
19324 +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19325 + dwc_otg_pcd_request_t * req)
19326 +{
19327 + struct dwc_otg_pcd_ep *ep = cfiep->ep;
19328 + ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
19329 + struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19330 + dma_addr_t buff_addr = req->dma;
19331 +
19332 + desc->status.b.bs = BS_HOST_BUSY;
19333 + desc->status.b.l = 1;
19334 + desc->status.b.ioc = 1;
19335 + desc->status.b.sp = ep->dwc_ep.sent_zlp;
19336 + desc->status.b.bytes = req->length;
19337 + /* Adjust the buffer alignment */
19338 + desc->buf = (buff_addr + alignval->bAlign);
19339 + desc->status.b.bs = BS_HOST_READY;
19340 + cfiep->dma_desc_last = desc;
19341 + cfiep->desc_count = 1;
19342 +}
19343 +
19344 +/**
19345 + * This function builds the DMA descriptors chain for different modes of the
19346 + * buffer setup of an endpoint.
19347 + */
19348 +static void cfi_build_descriptors(struct cfiobject *cfi,
19349 + struct dwc_otg_pcd *pcd,
19350 + struct dwc_otg_pcd_ep *ep,
19351 + dwc_otg_pcd_request_t * req)
19352 +{
19353 + cfi_ep_t *cfiep;
19354 +
19355 + /* Get the cfiep by the dwc_otg_pcd_ep */
19356 + cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19357 + if (NULL == cfiep) {
19358 + CFI_INFO("%s: Unable to find a matching active endpoint\n",
19359 + __func__);
19360 + return;
19361 + }
19362 +
19363 + cfiep->xfer_len = req->length;
19364 +
19365 + /* Iterate through all the DMA descriptors */
19366 + switch (cfiep->ep->dwc_ep.buff_mode) {
19367 + case BM_SG:
19368 + cfi_build_sg_descs(cfi, cfiep, req);
19369 + break;
19370 +
19371 + case BM_CONCAT:
19372 + cfi_build_concat_descs(cfi, cfiep, req);
19373 + break;
19374 +
19375 + case BM_CIRCULAR:
19376 + cfi_build_circ_descs(cfi, cfiep, req);
19377 + break;
19378 +
19379 + case BM_ALIGN:
19380 + cfi_build_align_descs(cfi, cfiep, req);
19381 + break;
19382 +
19383 + default:
19384 + break;
19385 + }
19386 +}
19387 +
19388 +/**
19389 + * Allocate DMA buffer for different Buffer modes.
19390 + */
19391 +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19392 + struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
19393 + unsigned size, gfp_t flags)
19394 +{
19395 + return DWC_DMA_ALLOC(size, dma);
19396 +}
19397 +
19398 +/**
19399 + * This function initializes the CFI object.
19400 + */
19401 +int init_cfi(cfiobject_t * cfiobj)
19402 +{
19403 + CFI_INFO("%s\n", __func__);
19404 +
19405 + /* Allocate a buffer for IN XFERs */
19406 + cfiobj->buf_in.buf =
19407 + DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
19408 + if (NULL == cfiobj->buf_in.buf) {
19409 + CFI_INFO("Unable to allocate buffer for INs\n");
19410 + return -DWC_E_NO_MEMORY;
19411 + }
19412 +
19413 + /* Allocate a buffer for OUT XFERs */
19414 + cfiobj->buf_out.buf =
19415 + DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
19416 + if (NULL == cfiobj->buf_out.buf) {
19417 + CFI_INFO("Unable to allocate buffer for OUT\n");
19418 + return -DWC_E_NO_MEMORY;
19419 + }
19420 +
19421 + /* Initialize the callback function pointers */
19422 + cfiobj->ops.release = cfi_release;
19423 + cfiobj->ops.ep_enable = cfi_ep_enable;
19424 + cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
19425 + cfiobj->ops.build_descriptors = cfi_build_descriptors;
19426 + cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
19427 +
19428 + /* Initialize the list of active endpoints in the CFI object */
19429 + DWC_LIST_INIT(&cfiobj->active_eps);
19430 +
19431 + return 0;
19432 +}
19433 +
19434 +/**
19435 + * This function reads the required feature's current value into the buffer
19436 + *
19437 + * @retval: Returns negative as error, or the data length of the feature
19438 + */
19439 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
19440 + struct dwc_otg_pcd *pcd,
19441 + struct cfi_usb_ctrlrequest *ctrl_req)
19442 +{
19443 + int retval = -DWC_E_NOT_SUPPORTED;
19444 + struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19445 + uint16_t dfifo, rxfifo, txfifo;
19446 +
19447 + switch (ctrl_req->wIndex) {
19448 + /* Whether the DDMA is enabled or not */
19449 + case FT_ID_DMA_MODE:
19450 + *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
19451 + retval = 1;
19452 + break;
19453 +
19454 + case FT_ID_DMA_BUFFER_SETUP:
19455 + retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
19456 + break;
19457 +
19458 + case FT_ID_DMA_BUFF_ALIGN:
19459 + retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
19460 + break;
19461 +
19462 + case FT_ID_DMA_CONCAT_SETUP:
19463 + retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
19464 + break;
19465 +
19466 + case FT_ID_DMA_CIRCULAR:
19467 + CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
19468 + break;
19469 +
19470 + case FT_ID_THRESHOLD_SETUP:
19471 + CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
19472 + break;
19473 +
19474 + case FT_ID_DFIFO_DEPTH:
19475 + dfifo = get_dfifo_size(coreif);
19476 + *((uint16_t *) buf) = dfifo;
19477 + retval = sizeof(uint16_t);
19478 + break;
19479 +
19480 + case FT_ID_TX_FIFO_DEPTH:
19481 + retval = get_txfifo_size(pcd, ctrl_req->wValue);
19482 + if (retval >= 0) {
19483 + txfifo = retval;
19484 + *((uint16_t *) buf) = txfifo;
19485 + retval = sizeof(uint16_t);
19486 + }
19487 + break;
19488 +
19489 + case FT_ID_RX_FIFO_DEPTH:
19490 + retval = get_rxfifo_size(coreif, ctrl_req->wValue);
19491 + if (retval >= 0) {
19492 + rxfifo = retval;
19493 + *((uint16_t *) buf) = rxfifo;
19494 + retval = sizeof(uint16_t);
19495 + }
19496 + break;
19497 + }
19498 +
19499 + return retval;
19500 +}
19501 +
19502 +/**
19503 + * This function resets the SG for the specified EP to its default value
19504 + */
19505 +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
19506 +{
19507 + dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19508 + return 0;
19509 +}
19510 +
19511 +/**
19512 + * This function resets the Alignment for the specified EP to its default value
19513 + */
19514 +static int cfi_reset_align_val(cfi_ep_t * cfiep)
19515 +{
19516 + dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19517 + return 0;
19518 +}
19519 +
19520 +/**
19521 + * This function resets the Concatenation for the specified EP to its default value
19522 + * This function will also set the value of the wTxBytes field to NULL after
19523 + * freeing the memory previously allocated for this field.
19524 + */
19525 +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
19526 +{
19527 + /* First we need to free the wTxBytes field */
19528 + if (cfiep->bm_concat->wTxBytes) {
19529 + DWC_FREE(cfiep->bm_concat->wTxBytes);
19530 + cfiep->bm_concat->wTxBytes = NULL;
19531 + }
19532 +
19533 + dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19534 + return 0;
19535 +}
19536 +
19537 +/**
19538 + * This function resets all the buffer setups of the specified endpoint
19539 + */
19540 +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
19541 +{
19542 + cfi_reset_sg_val(cfiep);
19543 + cfi_reset_align_val(cfiep);
19544 + cfi_reset_concat_val(cfiep);
19545 + return 0;
19546 +}
19547 +
19548 +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
19549 + uint8_t rx_rst, uint8_t tx_rst)
19550 +{
19551 + int retval = -DWC_E_INVALID;
19552 + uint16_t tx_siz[15];
19553 + uint16_t rx_siz = 0;
19554 + dwc_otg_pcd_ep_t *ep = NULL;
19555 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
19556 + dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
19557 +
19558 + if (rx_rst) {
19559 + rx_siz = params->dev_rx_fifo_size;
19560 + params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
19561 + }
19562 +
19563 + if (tx_rst) {
19564 + if (ep_addr == 0) {
19565 + int i;
19566 +
19567 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
19568 + tx_siz[i] =
19569 + core_if->core_params->dev_tx_fifo_size[i];
19570 + core_if->core_params->dev_tx_fifo_size[i] =
19571 + core_if->init_txfsiz[i];
19572 + }
19573 + } else {
19574 +
19575 + ep = get_ep_by_addr(pcd, ep_addr);
19576 +
19577 + if (NULL == ep) {
19578 + CFI_INFO
19579 + ("%s: Unable to get the endpoint addr=0x%02x\n",
19580 + __func__, ep_addr);
19581 + return -DWC_E_INVALID;
19582 + }
19583 +
19584 + tx_siz[0] =
19585 + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
19586 + 1];
19587 + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
19588 + GET_CORE_IF(pcd)->init_txfsiz[ep->
19589 + dwc_ep.tx_fifo_num -
19590 + 1];
19591 + }
19592 + }
19593 +
19594 + if (resize_fifos(GET_CORE_IF(pcd))) {
19595 + retval = 0;
19596 + } else {
19597 + CFI_INFO
19598 + ("%s: Error resetting the feature Reset All(FIFO size)\n",
19599 + __func__);
19600 + if (rx_rst) {
19601 + params->dev_rx_fifo_size = rx_siz;
19602 + }
19603 +
19604 + if (tx_rst) {
19605 + if (ep_addr == 0) {
19606 + int i;
19607 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
19608 + i++) {
19609 + core_if->
19610 + core_params->dev_tx_fifo_size[i] =
19611 + tx_siz[i];
19612 + }
19613 + } else {
19614 + params->dev_tx_fifo_size[ep->
19615 + dwc_ep.tx_fifo_num -
19616 + 1] = tx_siz[0];
19617 + }
19618 + }
19619 + retval = -DWC_E_INVALID;
19620 + }
19621 + return retval;
19622 +}
19623 +
19624 +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
19625 +{
19626 + int retval = 0;
19627 + cfi_ep_t *cfiep;
19628 + cfiobject_t *cfi = pcd->cfi;
19629 + dwc_list_link_t *tmp;
19630 +
19631 + retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
19632 + if (retval < 0) {
19633 + return retval;
19634 + }
19635 +
19636 + /* If the EP address is known then reset the features for only that EP */
19637 + if (addr) {
19638 + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19639 + if (NULL == cfiep) {
19640 + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19641 + __func__, addr);
19642 + return -DWC_E_INVALID;
19643 + }
19644 + retval = cfi_ep_reset_all_setup_vals(cfiep);
19645 + cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19646 + }
19647 + /* Otherwise (wValue == 0), reset all features of all EP's */
19648 + else {
19649 + /* Traverse all the active EP's and reset the feature(s) value(s) */
19650 + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19651 + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19652 + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19653 + retval = cfi_ep_reset_all_setup_vals(cfiep);
19654 + cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19655 + if (retval < 0) {
19656 + CFI_INFO
19657 + ("%s: Error resetting the feature Reset All\n",
19658 + __func__);
19659 + return retval;
19660 + }
19661 + }
19662 + }
19663 + return retval;
19664 +}
19665 +
19666 +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
19667 + uint8_t addr)
19668 +{
19669 + int retval = 0;
19670 + cfi_ep_t *cfiep;
19671 + cfiobject_t *cfi = pcd->cfi;
19672 + dwc_list_link_t *tmp;
19673 +
19674 + /* If the EP address is known then reset the features for only that EP */
19675 + if (addr) {
19676 + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19677 + if (NULL == cfiep) {
19678 + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19679 + __func__, addr);
19680 + return -DWC_E_INVALID;
19681 + }
19682 + retval = cfi_reset_sg_val(cfiep);
19683 + }
19684 + /* Otherwise (wValue == 0), reset all features of all EP's */
19685 + else {
19686 + /* Traverse all the active EP's and reset the feature(s) value(s) */
19687 + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19688 + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19689 + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19690 + retval = cfi_reset_sg_val(cfiep);
19691 + if (retval < 0) {
19692 + CFI_INFO
19693 + ("%s: Error resetting the feature Buffer Setup\n",
19694 + __func__);
19695 + return retval;
19696 + }
19697 + }
19698 + }
19699 + return retval;
19700 +}
19701 +
19702 +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19703 +{
19704 + int retval = 0;
19705 + cfi_ep_t *cfiep;
19706 + cfiobject_t *cfi = pcd->cfi;
19707 + dwc_list_link_t *tmp;
19708 +
19709 + /* If the EP address is known then reset the features for only that EP */
19710 + if (addr) {
19711 + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19712 + if (NULL == cfiep) {
19713 + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19714 + __func__, addr);
19715 + return -DWC_E_INVALID;
19716 + }
19717 + retval = cfi_reset_concat_val(cfiep);
19718 + }
19719 + /* Otherwise (wValue == 0), reset all features of all EP's */
19720 + else {
19721 + /* Traverse all the active EP's and reset the feature(s) value(s) */
19722 + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19723 + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19724 + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19725 + retval = cfi_reset_concat_val(cfiep);
19726 + if (retval < 0) {
19727 + CFI_INFO
19728 + ("%s: Error resetting the feature Concatenation Value\n",
19729 + __func__);
19730 + return retval;
19731 + }
19732 + }
19733 + }
19734 + return retval;
19735 +}
19736 +
19737 +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19738 +{
19739 + int retval = 0;
19740 + cfi_ep_t *cfiep;
19741 + cfiobject_t *cfi = pcd->cfi;
19742 + dwc_list_link_t *tmp;
19743 +
19744 + /* If the EP address is known then reset the features for only that EP */
19745 + if (addr) {
19746 + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19747 + if (NULL == cfiep) {
19748 + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19749 + __func__, addr);
19750 + return -DWC_E_INVALID;
19751 + }
19752 + retval = cfi_reset_align_val(cfiep);
19753 + }
19754 + /* Otherwise (wValue == 0), reset all features of all EP's */
19755 + else {
19756 + /* Traverse all the active EP's and reset the feature(s) value(s) */
19757 + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19758 + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19759 + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19760 + retval = cfi_reset_align_val(cfiep);
19761 + if (retval < 0) {
19762 + CFI_INFO
19763 + ("%s: Error resetting the feature Aliignment Value\n",
19764 + __func__);
19765 + return retval;
19766 + }
19767 + }
19768 + }
19769 + return retval;
19770 +
19771 +}
19772 +
19773 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
19774 + struct cfi_usb_ctrlrequest *req)
19775 +{
19776 + int retval = 0;
19777 +
19778 + switch (req->wIndex) {
19779 + case 0:
19780 + /* Reset all features */
19781 + retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
19782 + break;
19783 +
19784 + case FT_ID_DMA_BUFFER_SETUP:
19785 + /* Reset the SG buffer setup */
19786 + retval =
19787 + cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
19788 + break;
19789 +
19790 + case FT_ID_DMA_CONCAT_SETUP:
19791 + /* Reset the Concatenation buffer setup */
19792 + retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
19793 + break;
19794 +
19795 + case FT_ID_DMA_BUFF_ALIGN:
19796 + /* Reset the Alignment buffer setup */
19797 + retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
19798 + break;
19799 +
19800 + case FT_ID_TX_FIFO_DEPTH:
19801 + retval =
19802 + cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
19803 + pcd->cfi->need_gadget_att = 0;
19804 + break;
19805 +
19806 + case FT_ID_RX_FIFO_DEPTH:
19807 + retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
19808 + pcd->cfi->need_gadget_att = 0;
19809 + break;
19810 + default:
19811 + break;
19812 + }
19813 + return retval;
19814 +}
19815 +
19816 +/**
19817 + * This function sets a new value for the SG buffer setup.
19818 + */
19819 +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
19820 +{
19821 + uint8_t inaddr, outaddr;
19822 + cfi_ep_t *epin, *epout;
19823 + ddma_sg_buffer_setup_t *psgval;
19824 + uint32_t desccount, size;
19825 +
19826 + CFI_INFO("%s\n", __func__);
19827 +
19828 + psgval = (ddma_sg_buffer_setup_t *) buf;
19829 + desccount = (uint32_t) psgval->bCount;
19830 + size = (uint32_t) psgval->wSize;
19831 +
19832 + /* Check the DMA descriptor count */
19833 + if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
19834 + CFI_INFO
19835 + ("%s: The count of DMA Descriptors should be between 1 and %d\n",
19836 + __func__, MAX_DMA_DESCS_PER_EP);
19837 + return -DWC_E_INVALID;
19838 + }
19839 +
19840 + /* Check the DMA descriptor count */
19841 +
19842 + if (size == 0) {
19843 +
19844 + CFI_INFO("%s: The transfer size should be at least 1 byte\n",
19845 + __func__);
19846 +
19847 + return -DWC_E_INVALID;
19848 +
19849 + }
19850 +
19851 + inaddr = psgval->bInEndpointAddress;
19852 + outaddr = psgval->bOutEndpointAddress;
19853 +
19854 + epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
19855 + epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
19856 +
19857 + if (NULL == epin || NULL == epout) {
19858 + CFI_INFO
19859 + ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
19860 + __func__, inaddr, outaddr);
19861 + return -DWC_E_INVALID;
19862 + }
19863 +
19864 + epin->ep->dwc_ep.buff_mode = BM_SG;
19865 + dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
19866 +
19867 + epout->ep->dwc_ep.buff_mode = BM_SG;
19868 + dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
19869 +
19870 + return 0;
19871 +}
19872 +
19873 +/**
19874 + * This function sets a new value for the buffer Alignment setup.
19875 + */
19876 +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
19877 +{
19878 + cfi_ep_t *ep;
19879 + uint8_t addr;
19880 + ddma_align_buffer_setup_t *palignval;
19881 +
19882 + palignval = (ddma_align_buffer_setup_t *) buf;
19883 + addr = palignval->bEndpointAddress;
19884 +
19885 + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
19886 +
19887 + if (NULL == ep) {
19888 + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
19889 + __func__, addr);
19890 + return -DWC_E_INVALID;
19891 + }
19892 +
19893 + ep->ep->dwc_ep.buff_mode = BM_ALIGN;
19894 + dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
19895 +
19896 + return 0;
19897 +}
19898 +
19899 +/**
19900 + * This function sets a new value for the Concatenation buffer setup.
19901 + */
19902 +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
19903 +{
19904 + uint8_t addr;
19905 + cfi_ep_t *ep;
19906 + struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
19907 + uint16_t *pVals;
19908 + uint32_t desccount;
19909 + int i;
19910 + uint16_t mps;
19911 +
19912 + pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
19913 + desccount = (uint32_t) pConcatValHdr->bDescCount;
19914 + pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
19915 +
19916 + /* Check the DMA descriptor count */
19917 + if (desccount > MAX_DMA_DESCS_PER_EP) {
19918 + CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
19919 + __func__, MAX_DMA_DESCS_PER_EP);
19920 + return -DWC_E_INVALID;
19921 + }
19922 +
19923 + addr = pConcatValHdr->bEndpointAddress;
19924 + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
19925 + if (NULL == ep) {
19926 + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
19927 + __func__, addr);
19928 + return -DWC_E_INVALID;
19929 + }
19930 +
19931 + mps = UGETW(ep->ep->desc->wMaxPacketSize);
19932 +
19933 +#if 0
19934 + for (i = 0; i < desccount; i++) {
19935 + CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
19936 + }
19937 + CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
19938 +#endif
19939 +
19940 + /* Check the wTxSizes to be less than or equal to the mps */
19941 + for (i = 0; i < desccount; i++) {
19942 + if (pVals[i] > mps) {
19943 + CFI_INFO
19944 + ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
19945 + __func__, i, pVals[i]);
19946 + return -DWC_E_INVALID;
19947 + }
19948 + }
19949 +
19950 + ep->ep->dwc_ep.buff_mode = BM_CONCAT;
19951 + dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
19952 +
19953 + /* Free the previously allocated storage for the wTxBytes */
19954 + if (ep->bm_concat->wTxBytes) {
19955 + DWC_FREE(ep->bm_concat->wTxBytes);
19956 + }
19957 +
19958 + /* Allocate a new storage for the wTxBytes field */
19959 + ep->bm_concat->wTxBytes =
19960 + DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
19961 + if (NULL == ep->bm_concat->wTxBytes) {
19962 + CFI_INFO("%s: Unable to allocate memory\n", __func__);
19963 + return -DWC_E_NO_MEMORY;
19964 + }
19965 +
19966 + /* Copy the new values into the wTxBytes filed */
19967 + dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
19968 + sizeof(uint16_t) * pConcatValHdr->bDescCount);
19969 +
19970 + return 0;
19971 +}
19972 +
19973 +/**
19974 + * This function calculates the total of all FIFO sizes
19975 + *
19976 + * @param core_if Programming view of DWC_otg controller
19977 + *
19978 + * @return The total of data FIFO sizes.
19979 + *
19980 + */
19981 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
19982 +{
19983 + dwc_otg_core_params_t *params = core_if->core_params;
19984 + uint16_t dfifo_total = 0;
19985 + int i;
19986 +
19987 + /* The shared RxFIFO size */
19988 + dfifo_total =
19989 + params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
19990 +
19991 + /* Add up each TxFIFO size to the total */
19992 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
19993 + dfifo_total += params->dev_tx_fifo_size[i];
19994 + }
19995 +
19996 + return dfifo_total;
19997 +}
19998 +
19999 +/**
20000 + * This function returns Rx FIFO size
20001 + *
20002 + * @param core_if Programming view of DWC_otg controller
20003 + *
20004 + * @return The total of data FIFO sizes.
20005 + *
20006 + */
20007 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
20008 +{
20009 + switch (wValue >> 8) {
20010 + case 0:
20011 + return (core_if->pwron_rxfsiz <
20012 + 32768) ? core_if->pwron_rxfsiz : 32768;
20013 + break;
20014 + case 1:
20015 + return core_if->core_params->dev_rx_fifo_size;
20016 + break;
20017 + default:
20018 + return -DWC_E_INVALID;
20019 + break;
20020 + }
20021 +}
20022 +
20023 +/**
20024 + * This function returns Tx FIFO size for IN EP
20025 + *
20026 + * @param core_if Programming view of DWC_otg controller
20027 + *
20028 + * @return The total of data FIFO sizes.
20029 + *
20030 + */
20031 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
20032 +{
20033 + dwc_otg_pcd_ep_t *ep;
20034 +
20035 + ep = get_ep_by_addr(pcd, wValue & 0xff);
20036 +
20037 + if (NULL == ep) {
20038 + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20039 + __func__, wValue & 0xff);
20040 + return -DWC_E_INVALID;
20041 + }
20042 +
20043 + if (!ep->dwc_ep.is_in) {
20044 + CFI_INFO
20045 + ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
20046 + __func__, wValue & 0xff);
20047 + return -DWC_E_INVALID;
20048 + }
20049 +
20050 + switch (wValue >> 8) {
20051 + case 0:
20052 + return (GET_CORE_IF(pcd)->pwron_txfsiz
20053 + [ep->dwc_ep.tx_fifo_num - 1] <
20054 + 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
20055 + dwc_ep.tx_fifo_num
20056 + - 1] : 32768;
20057 + break;
20058 + case 1:
20059 + return GET_CORE_IF(pcd)->core_params->
20060 + dev_tx_fifo_size[ep->dwc_ep.num - 1];
20061 + break;
20062 + default:
20063 + return -DWC_E_INVALID;
20064 + break;
20065 + }
20066 +}
20067 +
20068 +/**
20069 + * This function checks if the submitted combination of
20070 + * device mode FIFO sizes is possible or not.
20071 + *
20072 + * @param core_if Programming view of DWC_otg controller
20073 + *
20074 + * @return 1 if possible, 0 otherwise.
20075 + *
20076 + */
20077 +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
20078 +{
20079 + uint16_t dfifo_actual = 0;
20080 + dwc_otg_core_params_t *params = core_if->core_params;
20081 + uint16_t start_addr = 0;
20082 + int i;
20083 +
20084 + dfifo_actual =
20085 + params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20086 +
20087 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20088 + dfifo_actual += params->dev_tx_fifo_size[i];
20089 + }
20090 +
20091 + if (dfifo_actual > core_if->total_fifo_size) {
20092 + return 0;
20093 + }
20094 +
20095 + if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
20096 + return 0;
20097 +
20098 + if (params->dev_nperio_tx_fifo_size > 32768
20099 + || params->dev_nperio_tx_fifo_size < 16)
20100 + return 0;
20101 +
20102 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20103 +
20104 + if (params->dev_tx_fifo_size[i] > 768
20105 + || params->dev_tx_fifo_size[i] < 4)
20106 + return 0;
20107 + }
20108 +
20109 + if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
20110 + return 0;
20111 + start_addr = params->dev_rx_fifo_size;
20112 +
20113 + if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
20114 + return 0;
20115 + start_addr += params->dev_nperio_tx_fifo_size;
20116 +
20117 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20118 +
20119 + if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
20120 + return 0;
20121 + start_addr += params->dev_tx_fifo_size[i];
20122 + }
20123 +
20124 + return 1;
20125 +}
20126 +
20127 +/**
20128 + * This function resizes Device mode FIFOs
20129 + *
20130 + * @param core_if Programming view of DWC_otg controller
20131 + *
20132 + * @return 1 if successful, 0 otherwise
20133 + *
20134 + */
20135 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
20136 +{
20137 + int i = 0;
20138 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
20139 + dwc_otg_core_params_t *params = core_if->core_params;
20140 + uint32_t rx_fifo_size;
20141 + fifosize_data_t nptxfifosize;
20142 + fifosize_data_t txfifosize[15];
20143 +
20144 + uint32_t rx_fsz_bak;
20145 + uint32_t nptxfsz_bak;
20146 + uint32_t txfsz_bak[15];
20147 +
20148 + uint16_t start_address;
20149 + uint8_t retval = 1;
20150 +
20151 + if (!check_fifo_sizes(core_if)) {
20152 + return 0;
20153 + }
20154 +
20155 + /* Configure data FIFO sizes */
20156 + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
20157 + rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
20158 + rx_fifo_size = params->dev_rx_fifo_size;
20159 + DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
20160 +
20161 + /*
20162 + * Tx FIFOs These FIFOs are numbered from 1 to 15.
20163 + * Indexes of the FIFO size module parameters in the
20164 + * dev_tx_fifo_size array and the FIFO size registers in
20165 + * the dtxfsiz array run from 0 to 14.
20166 + */
20167 +
20168 + /* Non-periodic Tx FIFO */
20169 + nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
20170 + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
20171 + start_address = params->dev_rx_fifo_size;
20172 + nptxfifosize.b.startaddr = start_address;
20173 +
20174 + DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
20175 +
20176 + start_address += nptxfifosize.b.depth;
20177 +
20178 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20179 + txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
20180 +
20181 + txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
20182 + txfifosize[i].b.startaddr = start_address;
20183 + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20184 + txfifosize[i].d32);
20185 +
20186 + start_address += txfifosize[i].b.depth;
20187 + }
20188 +
20189 + /** Check if register values are set correctly */
20190 + if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
20191 + retval = 0;
20192 + }
20193 +
20194 + if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
20195 + retval = 0;
20196 + }
20197 +
20198 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20199 + if (txfifosize[i].d32 !=
20200 + DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
20201 + retval = 0;
20202 + }
20203 + }
20204 +
20205 + /** If register values are not set correctly, reset old values */
20206 + if (retval == 0) {
20207 + DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
20208 +
20209 + /* Non-periodic Tx FIFO */
20210 + DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
20211 +
20212 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20213 + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20214 + txfsz_bak[i]);
20215 + }
20216 + }
20217 + } else {
20218 + return 0;
20219 + }
20220 +
20221 + /* Flush the FIFOs */
20222 + dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
20223 + dwc_otg_flush_rx_fifo(core_if);
20224 +
20225 + return retval;
20226 +}
20227 +
20228 +/**
20229 + * This function sets a new value for the buffer Alignment setup.
20230 + */
20231 +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20232 +{
20233 + int retval;
20234 + uint32_t fsiz;
20235 + uint16_t size;
20236 + uint16_t ep_addr;
20237 + dwc_otg_pcd_ep_t *ep;
20238 + dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20239 + tx_fifo_size_setup_t *ptxfifoval;
20240 +
20241 + ptxfifoval = (tx_fifo_size_setup_t *) buf;
20242 + ep_addr = ptxfifoval->bEndpointAddress;
20243 + size = ptxfifoval->wDepth;
20244 +
20245 + ep = get_ep_by_addr(pcd, ep_addr);
20246 +
20247 + CFI_INFO
20248 + ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
20249 + __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
20250 +
20251 + if (NULL == ep) {
20252 + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20253 + __func__, ep_addr);
20254 + return -DWC_E_INVALID;
20255 + }
20256 +
20257 + fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
20258 + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
20259 +
20260 + if (resize_fifos(GET_CORE_IF(pcd))) {
20261 + retval = 0;
20262 + } else {
20263 + CFI_INFO
20264 + ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
20265 + __func__, ep_addr);
20266 + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
20267 + retval = -DWC_E_INVALID;
20268 + }
20269 +
20270 + return retval;
20271 +}
20272 +
20273 +/**
20274 + * This function sets a new value for the buffer Alignment setup.
20275 + */
20276 +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20277 +{
20278 + int retval;
20279 + uint32_t fsiz;
20280 + uint16_t size;
20281 + dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20282 + rx_fifo_size_setup_t *prxfifoval;
20283 +
20284 + prxfifoval = (rx_fifo_size_setup_t *) buf;
20285 + size = prxfifoval->wDepth;
20286 +
20287 + fsiz = params->dev_rx_fifo_size;
20288 + params->dev_rx_fifo_size = size;
20289 +
20290 + if (resize_fifos(GET_CORE_IF(pcd))) {
20291 + retval = 0;
20292 + } else {
20293 + CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
20294 + __func__);
20295 + params->dev_rx_fifo_size = fsiz;
20296 + retval = -DWC_E_INVALID;
20297 + }
20298 +
20299 + return retval;
20300 +}
20301 +
20302 +/**
20303 + * This function reads the SG of an EP's buffer setup into the buffer buf
20304 + */
20305 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20306 + struct cfi_usb_ctrlrequest *req)
20307 +{
20308 + int retval = -DWC_E_INVALID;
20309 + uint8_t addr;
20310 + cfi_ep_t *ep;
20311 +
20312 + /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20313 + addr = req->wValue & 0xFF;
20314 + if (addr == 0) /* The address should be non-zero */
20315 + return retval;
20316 +
20317 + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20318 + if (NULL == ep) {
20319 + CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20320 + __func__, addr);
20321 + return retval;
20322 + }
20323 +
20324 + dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
20325 + retval = BS_SG_VAL_DESC_LEN;
20326 + return retval;
20327 +}
20328 +
20329 +/**
20330 + * This function reads the Concatenation value of an EP's buffer mode into
20331 + * the buffer buf
20332 + */
20333 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20334 + struct cfi_usb_ctrlrequest *req)
20335 +{
20336 + int retval = -DWC_E_INVALID;
20337 + uint8_t addr;
20338 + cfi_ep_t *ep;
20339 + uint8_t desc_count;
20340 +
20341 + /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20342 + addr = req->wValue & 0xFF;
20343 + if (addr == 0) /* The address should be non-zero */
20344 + return retval;
20345 +
20346 + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20347 + if (NULL == ep) {
20348 + CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20349 + __func__, addr);
20350 + return retval;
20351 + }
20352 +
20353 + /* Copy the header to the buffer */
20354 + dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
20355 + /* Advance the buffer pointer by the header size */
20356 + buf += BS_CONCAT_VAL_HDR_LEN;
20357 +
20358 + desc_count = ep->bm_concat->hdr.bDescCount;
20359 + /* Copy alll the wTxBytes to the buffer */
20360 + dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
20361 +
20362 + retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
20363 + return retval;
20364 +}
20365 +
20366 +/**
20367 + * This function reads the buffer Alignment value of an EP's buffer mode into
20368 + * the buffer buf
20369 + *
20370 + * @return The total number of bytes copied to the buffer or negative error code.
20371 + */
20372 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20373 + struct cfi_usb_ctrlrequest *req)
20374 +{
20375 + int retval = -DWC_E_INVALID;
20376 + uint8_t addr;
20377 + cfi_ep_t *ep;
20378 +
20379 + /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20380 + addr = req->wValue & 0xFF;
20381 + if (addr == 0) /* The address should be non-zero */
20382 + return retval;
20383 +
20384 + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20385 + if (NULL == ep) {
20386 + CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20387 + __func__, addr);
20388 + return retval;
20389 + }
20390 +
20391 + dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
20392 + retval = BS_ALIGN_VAL_HDR_LEN;
20393 +
20394 + return retval;
20395 +}
20396 +
20397 +/**
20398 + * This function sets a new value for the specified feature
20399 + *
20400 + * @param pcd A pointer to the PCD object
20401 + *
20402 + * @return 0 if successful, negative error code otherwise to stall the DCE.
20403 + */
20404 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
20405 +{
20406 + int retval = -DWC_E_NOT_SUPPORTED;
20407 + uint16_t wIndex, wValue;
20408 + uint8_t bRequest;
20409 + struct dwc_otg_core_if *coreif;
20410 + cfiobject_t *cfi = pcd->cfi;
20411 + struct cfi_usb_ctrlrequest *ctrl_req;
20412 + uint8_t *buf;
20413 + ctrl_req = &cfi->ctrl_req;
20414 +
20415 + buf = pcd->cfi->ctrl_req.data;
20416 +
20417 + coreif = GET_CORE_IF(pcd);
20418 + bRequest = ctrl_req->bRequest;
20419 + wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
20420 + wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
20421 +
20422 + /* See which feature is to be modified */
20423 + switch (wIndex) {
20424 + case FT_ID_DMA_BUFFER_SETUP:
20425 + /* Modify the feature */
20426 + if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
20427 + return retval;
20428 +
20429 + /* And send this request to the gadget */
20430 + cfi->need_gadget_att = 1;
20431 + break;
20432 +
20433 + case FT_ID_DMA_BUFF_ALIGN:
20434 + if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
20435 + return retval;
20436 + cfi->need_gadget_att = 1;
20437 + break;
20438 +
20439 + case FT_ID_DMA_CONCAT_SETUP:
20440 + /* Modify the feature */
20441 + if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
20442 + return retval;
20443 + cfi->need_gadget_att = 1;
20444 + break;
20445 +
20446 + case FT_ID_DMA_CIRCULAR:
20447 + CFI_INFO("FT_ID_DMA_CIRCULAR\n");
20448 + break;
20449 +
20450 + case FT_ID_THRESHOLD_SETUP:
20451 + CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
20452 + break;
20453 +
20454 + case FT_ID_DFIFO_DEPTH:
20455 + CFI_INFO("FT_ID_DFIFO_DEPTH\n");
20456 + break;
20457 +
20458 + case FT_ID_TX_FIFO_DEPTH:
20459 + CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
20460 + if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
20461 + return retval;
20462 + cfi->need_gadget_att = 0;
20463 + break;
20464 +
20465 + case FT_ID_RX_FIFO_DEPTH:
20466 + CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
20467 + if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
20468 + return retval;
20469 + cfi->need_gadget_att = 0;
20470 + break;
20471 + }
20472 +
20473 + return retval;
20474 +}
20475 +
20476 +#endif //DWC_UTE_CFI
20477 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20478 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100
20479 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2013-07-06 15:25:50.000000000 +0100
20480 @@ -0,0 +1,320 @@
20481 +/* ==========================================================================
20482 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20483 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20484 + * otherwise expressly agreed to in writing between Synopsys and you.
20485 + *
20486 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20487 + * any End User Software License Agreement or Agreement for Licensed Product
20488 + * with Synopsys or any supplement thereto. You are permitted to use and
20489 + * redistribute this Software in source and binary forms, with or without
20490 + * modification, provided that redistributions of source code must retain this
20491 + * notice. You may not view, use, disclose, copy or distribute this file or
20492 + * any information contained herein except pursuant to this license grant from
20493 + * Synopsys. If you do not agree with this notice, including the disclaimer
20494 + * below, then you are not authorized to use the Software.
20495 + *
20496 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20497 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20498 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20499 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20500 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20501 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20502 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20503 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20504 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20505 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20506 + * DAMAGE.
20507 + * ========================================================================== */
20508 +
20509 +#if !defined(__DWC_OTG_CFI_H__)
20510 +#define __DWC_OTG_CFI_H__
20511 +
20512 +#include "dwc_otg_pcd.h"
20513 +#include "dwc_cfi_common.h"
20514 +
20515 +/**
20516 + * @file
20517 + * This file contains the CFI related OTG PCD specific common constants,
20518 + * interfaces(functions and macros) and data structures.The CFI Protocol is an
20519 + * optional interface for internal testing purposes that a DUT may implement to
20520 + * support testing of configurable features.
20521 + *
20522 + */
20523 +
20524 +struct dwc_otg_pcd;
20525 +struct dwc_otg_pcd_ep;
20526 +
20527 +/** OTG CFI Features (properties) ID constants */
20528 +/** This is a request for all Core Features */
20529 +#define FT_ID_DMA_MODE 0x0001
20530 +#define FT_ID_DMA_BUFFER_SETUP 0x0002
20531 +#define FT_ID_DMA_BUFF_ALIGN 0x0003
20532 +#define FT_ID_DMA_CONCAT_SETUP 0x0004
20533 +#define FT_ID_DMA_CIRCULAR 0x0005
20534 +#define FT_ID_THRESHOLD_SETUP 0x0006
20535 +#define FT_ID_DFIFO_DEPTH 0x0007
20536 +#define FT_ID_TX_FIFO_DEPTH 0x0008
20537 +#define FT_ID_RX_FIFO_DEPTH 0x0009
20538 +
20539 +/**********************************************************/
20540 +#define CFI_INFO_DEF
20541 +
20542 +#ifdef CFI_INFO_DEF
20543 +#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt);
20544 +#else
20545 +#define CFI_INFO(fmt...)
20546 +#endif
20547 +
20548 +#define min(x,y) ({ \
20549 + x < y ? x : y; })
20550 +
20551 +#define max(x,y) ({ \
20552 + x > y ? x : y; })
20553 +
20554 +/**
20555 + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
20556 + * also used for setting up a buffer for Circular DDMA.
20557 + */
20558 +struct _ddma_sg_buffer_setup {
20559 +#define BS_SG_VAL_DESC_LEN 6
20560 + /* The OUT EP address */
20561 + uint8_t bOutEndpointAddress;
20562 + /* The IN EP address */
20563 + uint8_t bInEndpointAddress;
20564 + /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
20565 + uint8_t bOffset;
20566 + /* The number of transfer segments (a DMA descriptors per each segment) */
20567 + uint8_t bCount;
20568 + /* Size (in byte) of each transfer segment */
20569 + uint16_t wSize;
20570 +} __attribute__ ((packed));
20571 +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
20572 +
20573 +/** Descriptor DMA Concatenation Buffer setup structure */
20574 +struct _ddma_concat_buffer_setup_hdr {
20575 +#define BS_CONCAT_VAL_HDR_LEN 4
20576 + /* The endpoint for which the buffer is to be set up */
20577 + uint8_t bEndpointAddress;
20578 + /* The count of descriptors to be used */
20579 + uint8_t bDescCount;
20580 + /* The total size of the transfer */
20581 + uint16_t wSize;
20582 +} __attribute__ ((packed));
20583 +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
20584 +
20585 +/** Descriptor DMA Concatenation Buffer setup structure */
20586 +struct _ddma_concat_buffer_setup {
20587 + /* The SG header */
20588 + ddma_concat_buffer_setup_hdr_t hdr;
20589 +
20590 + /* The XFER sizes pointer (allocated dynamically) */
20591 + uint16_t *wTxBytes;
20592 +} __attribute__ ((packed));
20593 +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
20594 +
20595 +/** Descriptor DMA Alignment Buffer setup structure */
20596 +struct _ddma_align_buffer_setup {
20597 +#define BS_ALIGN_VAL_HDR_LEN 2
20598 + uint8_t bEndpointAddress;
20599 + uint8_t bAlign;
20600 +} __attribute__ ((packed));
20601 +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
20602 +
20603 +/** Transmit FIFO Size setup structure */
20604 +struct _tx_fifo_size_setup {
20605 + uint8_t bEndpointAddress;
20606 + uint16_t wDepth;
20607 +} __attribute__ ((packed));
20608 +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
20609 +
20610 +/** Transmit FIFO Size setup structure */
20611 +struct _rx_fifo_size_setup {
20612 + uint16_t wDepth;
20613 +} __attribute__ ((packed));
20614 +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
20615 +
20616 +/**
20617 + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
20618 + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer
20619 + * to the data returned in the data stage of a 3-stage Control Write requests.
20620 + */
20621 +struct cfi_usb_ctrlrequest {
20622 + uint8_t bRequestType;
20623 + uint8_t bRequest;
20624 + uint16_t wValue;
20625 + uint16_t wIndex;
20626 + uint16_t wLength;
20627 + uint8_t *data;
20628 +} UPACKED;
20629 +
20630 +/*---------------------------------------------------------------------------*/
20631 +
20632 +/**
20633 + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
20634 + * This structure is used to store the buffer setup data for any
20635 + * enabled endpoint in the PCD.
20636 + */
20637 +struct cfi_ep {
20638 + /* Entry for the list container */
20639 + dwc_list_link_t lh;
20640 + /* Pointer to the active PCD endpoint structure */
20641 + struct dwc_otg_pcd_ep *ep;
20642 + /* The last descriptor in the chain of DMA descriptors of the endpoint */
20643 + struct dwc_otg_dma_desc *dma_desc_last;
20644 + /* The SG feature value */
20645 + ddma_sg_buffer_setup_t *bm_sg;
20646 + /* The Circular feature value */
20647 + ddma_sg_buffer_setup_t *bm_circ;
20648 + /* The Concatenation feature value */
20649 + ddma_concat_buffer_setup_t *bm_concat;
20650 + /* The Alignment feature value */
20651 + ddma_align_buffer_setup_t *bm_align;
20652 + /* XFER length */
20653 + uint32_t xfer_len;
20654 + /*
20655 + * Count of DMA descriptors currently used.
20656 + * The total should not exceed the MAX_DMA_DESCS_PER_EP value
20657 + * defined in the dwc_otg_cil.h
20658 + */
20659 + uint32_t desc_count;
20660 +};
20661 +typedef struct cfi_ep cfi_ep_t;
20662 +
20663 +typedef struct cfi_dma_buff {
20664 +#define CFI_IN_BUF_LEN 1024
20665 +#define CFI_OUT_BUF_LEN 1024
20666 + dma_addr_t addr;
20667 + uint8_t *buf;
20668 +} cfi_dma_buff_t;
20669 +
20670 +struct cfiobject;
20671 +
20672 +/**
20673 + * This is the interface for the CFI operations.
20674 + *
20675 + * @param ep_enable Called when any endpoint is enabled and activated.
20676 + * @param release Called when the CFI object is released and it needs to correctly
20677 + * deallocate the dynamic memory
20678 + * @param ctrl_write_complete Called when the data stage of the request is complete
20679 + */
20680 +typedef struct cfi_ops {
20681 + int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20682 + struct dwc_otg_pcd_ep * ep);
20683 + void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20684 + struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
20685 + unsigned size, gfp_t flags);
20686 + void (*release) (struct cfiobject * cfi);
20687 + int (*ctrl_write_complete) (struct cfiobject * cfi,
20688 + struct dwc_otg_pcd * pcd);
20689 + void (*build_descriptors) (struct cfiobject * cfi,
20690 + struct dwc_otg_pcd * pcd,
20691 + struct dwc_otg_pcd_ep * ep,
20692 + dwc_otg_pcd_request_t * req);
20693 +} cfi_ops_t;
20694 +
20695 +struct cfiobject {
20696 + cfi_ops_t ops;
20697 + struct dwc_otg_pcd *pcd;
20698 + struct usb_gadget *gadget;
20699 +
20700 + /* Buffers used to send/receive CFI-related request data */
20701 + cfi_dma_buff_t buf_in;
20702 + cfi_dma_buff_t buf_out;
20703 +
20704 + /* CFI specific Control request wrapper */
20705 + struct cfi_usb_ctrlrequest ctrl_req;
20706 +
20707 + /* The list of active EP's in the PCD of type cfi_ep_t */
20708 + dwc_list_link_t active_eps;
20709 +
20710 + /* This flag shall control the propagation of a specific request
20711 + * to the gadget's processing routines.
20712 + * 0 - no gadget handling
20713 + * 1 - the gadget needs to know about this request (w/o completing a status
20714 + * phase - just return a 0 to the _setup callback)
20715 + */
20716 + uint8_t need_gadget_att;
20717 +
20718 + /* Flag indicating whether the status IN phase needs to be
20719 + * completed by the PCD
20720 + */
20721 + uint8_t need_status_in_complete;
20722 +};
20723 +typedef struct cfiobject cfiobject_t;
20724 +
20725 +#define DUMP_MSG
20726 +
20727 +#if defined(DUMP_MSG)
20728 +static inline void dump_msg(const u8 * buf, unsigned int length)
20729 +{
20730 + unsigned int start, num, i;
20731 + char line[52], *p;
20732 +
20733 + if (length >= 512)
20734 + return;
20735 +
20736 + start = 0;
20737 + while (length > 0) {
20738 + num = min(length, 16u);
20739 + p = line;
20740 + for (i = 0; i < num; ++i) {
20741 + if (i == 8)
20742 + *p++ = ' ';
20743 + DWC_SPRINTF(p, " %02x", buf[i]);
20744 + p += 3;
20745 + }
20746 + *p = 0;
20747 + DWC_DEBUG("%6x: %s\n", start, line);
20748 + buf += num;
20749 + start += num;
20750 + length -= num;
20751 + }
20752 +}
20753 +#else
20754 +static inline void dump_msg(const u8 * buf, unsigned int length)
20755 +{
20756 +}
20757 +#endif
20758 +
20759 +/**
20760 + * This function returns a pointer to cfi_ep_t object with the addr address.
20761 + */
20762 +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
20763 + uint8_t addr)
20764 +{
20765 + struct cfi_ep *pcfiep;
20766 + dwc_list_link_t *tmp;
20767 +
20768 + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20769 + pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20770 +
20771 + if (pcfiep->ep->desc->bEndpointAddress == addr) {
20772 + return pcfiep;
20773 + }
20774 + }
20775 +
20776 + return NULL;
20777 +}
20778 +
20779 +/**
20780 + * This function returns a pointer to cfi_ep_t object that matches
20781 + * the dwc_otg_pcd_ep object.
20782 + */
20783 +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
20784 + struct dwc_otg_pcd_ep *ep)
20785 +{
20786 + struct cfi_ep *pcfiep = NULL;
20787 + dwc_list_link_t *tmp;
20788 +
20789 + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20790 + pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20791 + if (pcfiep->ep == ep) {
20792 + return pcfiep;
20793 + }
20794 + }
20795 + return NULL;
20796 +}
20797 +
20798 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
20799 +
20800 +#endif /* (__DWC_OTG_CFI_H__) */
20801 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cil.c
20802 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100
20803 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2013-07-06 15:25:50.000000000 +0100
20804 @@ -0,0 +1,7151 @@
20805 +/* ==========================================================================
20806 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
20807 + * $Revision: #191 $
20808 + * $Date: 2012/08/10 $
20809 + * $Change: 2047372 $
20810 + *
20811 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20812 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20813 + * otherwise expressly agreed to in writing between Synopsys and you.
20814 + *
20815 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20816 + * any End User Software License Agreement or Agreement for Licensed Product
20817 + * with Synopsys or any supplement thereto. You are permitted to use and
20818 + * redistribute this Software in source and binary forms, with or without
20819 + * modification, provided that redistributions of source code must retain this
20820 + * notice. You may not view, use, disclose, copy or distribute this file or
20821 + * any information contained herein except pursuant to this license grant from
20822 + * Synopsys. If you do not agree with this notice, including the disclaimer
20823 + * below, then you are not authorized to use the Software.
20824 + *
20825 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20826 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20827 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20828 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20829 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20830 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20831 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20832 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20833 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20834 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20835 + * DAMAGE.
20836 + * ========================================================================== */
20837 +
20838 +/** @file
20839 + *
20840 + * The Core Interface Layer provides basic services for accessing and
20841 + * managing the DWC_otg hardware. These services are used by both the
20842 + * Host Controller Driver and the Peripheral Controller Driver.
20843 + *
20844 + * The CIL manages the memory map for the core so that the HCD and PCD
20845 + * don't have to do this separately. It also handles basic tasks like
20846 + * reading/writing the registers and data FIFOs in the controller.
20847 + * Some of the data access functions provide encapsulation of several
20848 + * operations required to perform a task, such as writing multiple
20849 + * registers to start a transfer. Finally, the CIL performs basic
20850 + * services that are not specific to either the host or device modes
20851 + * of operation. These services include management of the OTG Host
20852 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
20853 + * Diagnostic API is also provided to allow testing of the controller
20854 + * hardware.
20855 + *
20856 + * The Core Interface Layer has the following requirements:
20857 + * - Provides basic controller operations.
20858 + * - Minimal use of OS services.
20859 + * - The OS services used will be abstracted by using inline functions
20860 + * or macros.
20861 + *
20862 + */
20863 +
20864 +#include "dwc_os.h"
20865 +#include "dwc_otg_regs.h"
20866 +#include "dwc_otg_cil.h"
20867 +
20868 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
20869 +
20870 +/**
20871 + * This function is called to initialize the DWC_otg CSR data
20872 + * structures. The register addresses in the device and host
20873 + * structures are initialized from the base address supplied by the
20874 + * caller. The calling function must make the OS calls to get the
20875 + * base address of the DWC_otg controller registers. The core_params
20876 + * argument holds the parameters that specify how the core should be
20877 + * configured.
20878 + *
20879 + * @param reg_base_addr Base address of DWC_otg core registers
20880 + *
20881 + */
20882 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
20883 +{
20884 + dwc_otg_core_if_t *core_if = 0;
20885 + dwc_otg_dev_if_t *dev_if = 0;
20886 + dwc_otg_host_if_t *host_if = 0;
20887 + uint8_t *reg_base = (uint8_t *) reg_base_addr;
20888 + int i = 0;
20889 +
20890 + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
20891 +
20892 + core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));
20893 +
20894 + if (core_if == NULL) {
20895 + DWC_DEBUGPL(DBG_CIL,
20896 + "Allocation of dwc_otg_core_if_t failed\n");
20897 + return 0;
20898 + }
20899 + core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
20900 +
20901 + /*
20902 + * Allocate the Device Mode structures.
20903 + */
20904 + dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));
20905 +
20906 + if (dev_if == NULL) {
20907 + DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
20908 + DWC_FREE(core_if);
20909 + return 0;
20910 + }
20911 +
20912 + dev_if->dev_global_regs =
20913 + (dwc_otg_device_global_regs_t *) (reg_base +
20914 + DWC_DEV_GLOBAL_REG_OFFSET);
20915 +
20916 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
20917 + dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
20918 + (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
20919 + (i * DWC_EP_REG_OFFSET));
20920 +
20921 + dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
20922 + (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
20923 + (i * DWC_EP_REG_OFFSET));
20924 + DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
20925 + i, &dev_if->in_ep_regs[i]->diepctl);
20926 + DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
20927 + i, &dev_if->out_ep_regs[i]->doepctl);
20928 + }
20929 +
20930 + dev_if->speed = 0; // unknown
20931 +
20932 + core_if->dev_if = dev_if;
20933 +
20934 + /*
20935 + * Allocate the Host Mode structures.
20936 + */
20937 + host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));
20938 +
20939 + if (host_if == NULL) {
20940 + DWC_DEBUGPL(DBG_CIL,
20941 + "Allocation of dwc_otg_host_if_t failed\n");
20942 + DWC_FREE(dev_if);
20943 + DWC_FREE(core_if);
20944 + return 0;
20945 + }
20946 +
20947 + host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
20948 + (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
20949 +
20950 + host_if->hprt0 =
20951 + (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
20952 +
20953 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
20954 + host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
20955 + (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
20956 + (i * DWC_OTG_CHAN_REGS_OFFSET));
20957 + DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
20958 + i, &host_if->hc_regs[i]->hcchar);
20959 + }
20960 +
20961 + host_if->num_host_channels = MAX_EPS_CHANNELS;
20962 + core_if->host_if = host_if;
20963 +
20964 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
20965 + core_if->data_fifo[i] =
20966 + (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
20967 + (i * DWC_OTG_DATA_FIFO_SIZE));
20968 + DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",
20969 + i, (unsigned long)core_if->data_fifo[i]);
20970 + }
20971 +
20972 + core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
20973 +
20974 + /* Initiate lx_state to L3 disconnected state */
20975 + core_if->lx_state = DWC_OTG_L3;
20976 + /*
20977 + * Store the contents of the hardware configuration registers here for
20978 + * easy access later.
20979 + */
20980 + core_if->hwcfg1.d32 =
20981 + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
20982 + core_if->hwcfg2.d32 =
20983 + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
20984 + core_if->hwcfg3.d32 =
20985 + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
20986 + core_if->hwcfg4.d32 =
20987 + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
20988 +
20989 + /* Force host mode to get HPTXFSIZ exact power on value */
20990 + {
20991 + gusbcfg_data_t gusbcfg = {.d32 = 0 };
20992 + gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
20993 + gusbcfg.b.force_host_mode = 1;
20994 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
20995 + dwc_mdelay(100);
20996 + core_if->hptxfsiz.d32 =
20997 + DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
20998 + gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
20999 + gusbcfg.b.force_host_mode = 0;
21000 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21001 + dwc_mdelay(100);
21002 + }
21003 +
21004 + DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
21005 + DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
21006 + DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
21007 + DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
21008 +
21009 + core_if->hcfg.d32 =
21010 + DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21011 + core_if->dcfg.d32 =
21012 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21013 +
21014 + DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
21015 + DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
21016 +
21017 + DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
21018 + DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
21019 + DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
21020 + DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
21021 + core_if->hwcfg2.b.num_host_chan);
21022 + DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
21023 + core_if->hwcfg2.b.nonperio_tx_q_depth);
21024 + DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
21025 + core_if->hwcfg2.b.host_perio_tx_q_depth);
21026 + DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
21027 + core_if->hwcfg2.b.dev_token_q_depth);
21028 +
21029 + DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
21030 + core_if->hwcfg3.b.dfifo_depth);
21031 + DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
21032 + core_if->hwcfg3.b.xfer_size_cntr_width);
21033 +
21034 + /*
21035 + * Set the SRP sucess bit for FS-I2c
21036 + */
21037 + core_if->srp_success = 0;
21038 + core_if->srp_timer_started = 0;
21039 +
21040 + /*
21041 + * Create new workqueue and init works
21042 + */
21043 + core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
21044 + if (core_if->wq_otg == 0) {
21045 + DWC_WARN("DWC_WORKQ_ALLOC failed\n");
21046 + DWC_FREE(host_if);
21047 + DWC_FREE(dev_if);
21048 + DWC_FREE(core_if);
21049 + return 0;
21050 + }
21051 +
21052 + core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
21053 +
21054 + DWC_PRINTF("Core Release: %x.%x%x%x\n",
21055 + (core_if->snpsid >> 12 & 0xF),
21056 + (core_if->snpsid >> 8 & 0xF),
21057 + (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
21058 +
21059 + core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
21060 + w_wakeup_detected, core_if);
21061 + if (core_if->wkp_timer == 0) {
21062 + DWC_WARN("DWC_TIMER_ALLOC failed\n");
21063 + DWC_FREE(host_if);
21064 + DWC_FREE(dev_if);
21065 + DWC_WORKQ_FREE(core_if->wq_otg);
21066 + DWC_FREE(core_if);
21067 + return 0;
21068 + }
21069 +
21070 + if (dwc_otg_setup_params(core_if)) {
21071 + DWC_WARN("Error while setting core params\n");
21072 + }
21073 +
21074 + core_if->hibernation_suspend = 0;
21075 +
21076 + /** ADP initialization */
21077 + dwc_otg_adp_init(core_if);
21078 +
21079 + return core_if;
21080 +}
21081 +
21082 +/**
21083 + * This function frees the structures allocated by dwc_otg_cil_init().
21084 + *
21085 + * @param core_if The core interface pointer returned from
21086 + * dwc_otg_cil_init().
21087 + *
21088 + */
21089 +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
21090 +{
21091 + dctl_data_t dctl = {.d32 = 0 };
21092 + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
21093 +
21094 + /* Disable all interrupts */
21095 + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);
21096 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
21097 +
21098 + dctl.b.sftdiscon = 1;
21099 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
21100 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,
21101 + dctl.d32);
21102 + }
21103 +
21104 + if (core_if->wq_otg) {
21105 + DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
21106 + DWC_WORKQ_FREE(core_if->wq_otg);
21107 + }
21108 + if (core_if->dev_if) {
21109 + DWC_FREE(core_if->dev_if);
21110 + }
21111 + if (core_if->host_if) {
21112 + DWC_FREE(core_if->host_if);
21113 + }
21114 +
21115 + /** Remove ADP Stuff */
21116 + dwc_otg_adp_remove(core_if);
21117 + if (core_if->core_params) {
21118 + DWC_FREE(core_if->core_params);
21119 + }
21120 + if (core_if->wkp_timer) {
21121 + DWC_TIMER_FREE(core_if->wkp_timer);
21122 + }
21123 + if (core_if->srp_timer) {
21124 + DWC_TIMER_FREE(core_if->srp_timer);
21125 + }
21126 + DWC_FREE(core_if);
21127 +}
21128 +
21129 +/**
21130 + * This function enables the controller's Global Interrupt in the AHB Config
21131 + * register.
21132 + *
21133 + * @param core_if Programming view of DWC_otg controller.
21134 + */
21135 +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
21136 +{
21137 + gahbcfg_data_t ahbcfg = {.d32 = 0 };
21138 + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
21139 + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
21140 +}
21141 +
21142 +/**
21143 + * This function disables the controller's Global Interrupt in the AHB Config
21144 + * register.
21145 + *
21146 + * @param core_if Programming view of DWC_otg controller.
21147 + */
21148 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
21149 +{
21150 + gahbcfg_data_t ahbcfg = {.d32 = 0 };
21151 + ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */
21152 + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
21153 +}
21154 +
21155 +/**
21156 + * This function initializes the commmon interrupts, used in both
21157 + * device and host modes.
21158 + *
21159 + * @param core_if Programming view of the DWC_otg controller
21160 + *
21161 + */
21162 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
21163 +{
21164 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
21165 + gintmsk_data_t intr_mask = {.d32 = 0 };
21166 +
21167 + /* Clear any pending OTG Interrupts */
21168 + DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);
21169 +
21170 + /* Clear any pending interrupts */
21171 + DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
21172 +
21173 + /*
21174 + * Enable the interrupts in the GINTMSK.
21175 + */
21176 + intr_mask.b.modemismatch = 1;
21177 + intr_mask.b.otgintr = 1;
21178 +
21179 + if (!core_if->dma_enable) {
21180 + intr_mask.b.rxstsqlvl = 1;
21181 + }
21182 +
21183 + intr_mask.b.conidstschng = 1;
21184 + intr_mask.b.wkupintr = 1;
21185 + intr_mask.b.disconnect = 0;
21186 + intr_mask.b.usbsuspend = 1;
21187 + intr_mask.b.sessreqintr = 1;
21188 +#ifdef CONFIG_USB_DWC_OTG_LPM
21189 + if (core_if->core_params->lpm_enable) {
21190 + intr_mask.b.lpmtranrcvd = 1;
21191 + }
21192 +#endif
21193 + DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
21194 +}
21195 +
21196 +/*
21197 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21198 + * Hibernation. This function is for exiting from Device mode hibernation by
21199 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21200 + * @param core_if Programming view of DWC_otg controller.
21201 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21202 + * @param reset - indicates whether resume is initiated by Reset.
21203 + */
21204 +int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
21205 + int rem_wakeup, int reset)
21206 +{
21207 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
21208 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
21209 + dctl_data_t dctl = {.d32 = 0 };
21210 +
21211 + int timeout = 2000;
21212 +
21213 + if (!core_if->hibernation_suspend) {
21214 + DWC_PRINTF("Already exited from Hibernation\n");
21215 + return 1;
21216 + }
21217 +
21218 + DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);
21219 + /* Switch-on voltage to the core */
21220 + gpwrdn.b.pwrdnswtch = 1;
21221 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21222 + dwc_udelay(10);
21223 +
21224 + /* Reset core */
21225 + gpwrdn.d32 = 0;
21226 + gpwrdn.b.pwrdnrstn = 1;
21227 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21228 + dwc_udelay(10);
21229 +
21230 + /* Assert Restore signal */
21231 + gpwrdn.d32 = 0;
21232 + gpwrdn.b.restore = 1;
21233 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21234 + dwc_udelay(10);
21235 +
21236 + /* Disable power clamps */
21237 + gpwrdn.d32 = 0;
21238 + gpwrdn.b.pwrdnclmp = 1;
21239 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21240 +
21241 + if (rem_wakeup) {
21242 + dwc_udelay(70);
21243 + }
21244 +
21245 + /* Deassert Reset core */
21246 + gpwrdn.d32 = 0;
21247 + gpwrdn.b.pwrdnrstn = 1;
21248 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21249 + dwc_udelay(10);
21250 +
21251 + /* Disable PMU interrupt */
21252 + gpwrdn.d32 = 0;
21253 + gpwrdn.b.pmuintsel = 1;
21254 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21255 +
21256 + /* Mask interrupts from gpwrdn */
21257 + gpwrdn.d32 = 0;
21258 + gpwrdn.b.connect_det_msk = 1;
21259 + gpwrdn.b.srp_det_msk = 1;
21260 + gpwrdn.b.disconn_det_msk = 1;
21261 + gpwrdn.b.rst_det_msk = 1;
21262 + gpwrdn.b.lnstchng_msk = 1;
21263 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21264 +
21265 + /* Indicates that we are going out from hibernation */
21266 + core_if->hibernation_suspend = 0;
21267 +
21268 + /*
21269 + * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1
21270 + * indicates restore from remote_wakeup
21271 + */
21272 + restore_essential_regs(core_if, rem_wakeup, 0);
21273 +
21274 + /*
21275 + * Wait a little for seeing new value of variable hibernation_suspend if
21276 + * Restore done interrupt received before polling
21277 + */
21278 + dwc_udelay(10);
21279 +
21280 + if (core_if->hibernation_suspend == 0) {
21281 + /*
21282 + * Wait For Restore_done Interrupt. This mechanism of polling the
21283 + * interrupt is introduced to avoid any possible race conditions
21284 + */
21285 + do {
21286 + gintsts_data_t gintsts;
21287 + gintsts.d32 =
21288 + DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21289 + if (gintsts.b.restoredone) {
21290 + gintsts.d32 = 0;
21291 + gintsts.b.restoredone = 1;
21292 + DWC_WRITE_REG32(&core_if->core_global_regs->
21293 + gintsts, gintsts.d32);
21294 + DWC_PRINTF("Restore Done Interrupt seen\n");
21295 + break;
21296 + }
21297 + dwc_udelay(10);
21298 + } while (--timeout);
21299 + if (!timeout) {
21300 + DWC_PRINTF("Restore Done interrupt wasn't generated here\n");
21301 + }
21302 + }
21303 + /* Clear all pending interupts */
21304 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21305 +
21306 + /* De-assert Restore */
21307 + gpwrdn.d32 = 0;
21308 + gpwrdn.b.restore = 1;
21309 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21310 + dwc_udelay(10);
21311 +
21312 + if (!rem_wakeup) {
21313 + pcgcctl.d32 = 0;
21314 + pcgcctl.b.rstpdwnmodule = 1;
21315 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
21316 + }
21317 +
21318 + /* Restore GUSBCFG and DCFG */
21319 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21320 + core_if->gr_backup->gusbcfg_local);
21321 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
21322 + core_if->dr_backup->dcfg);
21323 +
21324 + /* De-assert Wakeup Logic */
21325 + gpwrdn.d32 = 0;
21326 + gpwrdn.b.pmuactv = 1;
21327 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21328 + dwc_udelay(10);
21329 +
21330 + if (!rem_wakeup) {
21331 + /* Set Device programming done bit */
21332 + dctl.b.pwronprgdone = 1;
21333 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
21334 + } else {
21335 + /* Start Remote Wakeup Signaling */
21336 + dctl.d32 = core_if->dr_backup->dctl;
21337 + dctl.b.rmtwkupsig = 1;
21338 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
21339 + }
21340 +
21341 + dwc_mdelay(2);
21342 + /* Clear all pending interupts */
21343 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21344 +
21345 + /* Restore global registers */
21346 + dwc_otg_restore_global_regs(core_if);
21347 + /* Restore device global registers */
21348 + dwc_otg_restore_dev_regs(core_if, rem_wakeup);
21349 +
21350 + if (rem_wakeup) {
21351 + dwc_mdelay(7);
21352 + dctl.d32 = 0;
21353 + dctl.b.rmtwkupsig = 1;
21354 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
21355 + }
21356 +
21357 + core_if->hibernation_suspend = 0;
21358 + /* The core will be in ON STATE */
21359 + core_if->lx_state = DWC_OTG_L0;
21360 + DWC_PRINTF("Hibernation recovery completes here\n");
21361 +
21362 + return 1;
21363 +}
21364 +
21365 +/*
21366 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21367 + * Hibernation. This function is for exiting from Host mode hibernation by
21368 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21369 + * @param core_if Programming view of DWC_otg controller.
21370 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21371 + * @param reset - indicates whether resume is initiated by Reset.
21372 + */
21373 +int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
21374 + int rem_wakeup, int reset)
21375 +{
21376 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
21377 + hprt0_data_t hprt0 = {.d32 = 0 };
21378 +
21379 + int timeout = 2000;
21380 +
21381 + DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);
21382 + /* Switch-on voltage to the core */
21383 + gpwrdn.b.pwrdnswtch = 1;
21384 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21385 + dwc_udelay(10);
21386 +
21387 + /* Reset core */
21388 + gpwrdn.d32 = 0;
21389 + gpwrdn.b.pwrdnrstn = 1;
21390 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21391 + dwc_udelay(10);
21392 +
21393 + /* Assert Restore signal */
21394 + gpwrdn.d32 = 0;
21395 + gpwrdn.b.restore = 1;
21396 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21397 + dwc_udelay(10);
21398 +
21399 + /* Disable power clamps */
21400 + gpwrdn.d32 = 0;
21401 + gpwrdn.b.pwrdnclmp = 1;
21402 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21403 +
21404 + if (!rem_wakeup) {
21405 + dwc_udelay(50);
21406 + }
21407 +
21408 + /* Deassert Reset core */
21409 + gpwrdn.d32 = 0;
21410 + gpwrdn.b.pwrdnrstn = 1;
21411 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21412 + dwc_udelay(10);
21413 +
21414 + /* Disable PMU interrupt */
21415 + gpwrdn.d32 = 0;
21416 + gpwrdn.b.pmuintsel = 1;
21417 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21418 +
21419 + gpwrdn.d32 = 0;
21420 + gpwrdn.b.connect_det_msk = 1;
21421 + gpwrdn.b.srp_det_msk = 1;
21422 + gpwrdn.b.disconn_det_msk = 1;
21423 + gpwrdn.b.rst_det_msk = 1;
21424 + gpwrdn.b.lnstchng_msk = 1;
21425 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21426 +
21427 + /* Indicates that we are going out from hibernation */
21428 + core_if->hibernation_suspend = 0;
21429 +
21430 + /* Set Restore Essential Regs bit in PCGCCTL register */
21431 + restore_essential_regs(core_if, rem_wakeup, 1);
21432 +
21433 + /* Wait a little for seeing new value of variable hibernation_suspend if
21434 + * Restore done interrupt received before polling */
21435 + dwc_udelay(10);
21436 +
21437 + if (core_if->hibernation_suspend == 0) {
21438 + /* Wait For Restore_done Interrupt. This mechanism of polling the
21439 + * interrupt is introduced to avoid any possible race conditions
21440 + */
21441 + do {
21442 + gintsts_data_t gintsts;
21443 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21444 + if (gintsts.b.restoredone) {
21445 + gintsts.d32 = 0;
21446 + gintsts.b.restoredone = 1;
21447 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
21448 + DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");
21449 + break;
21450 + }
21451 + dwc_udelay(10);
21452 + } while (--timeout);
21453 + if (!timeout) {
21454 + DWC_WARN("Restore Done interrupt wasn't generated\n");
21455 + }
21456 + }
21457 +
21458 + /* Set the flag's value to 0 again after receiving restore done interrupt */
21459 + core_if->hibernation_suspend = 0;
21460 +
21461 + /* This step is not described in functional spec but if not wait for this
21462 + * delay, mismatch interrupts occurred because just after restore core is
21463 + * in Device mode(gintsts.curmode == 0) */
21464 + dwc_mdelay(100);
21465 +
21466 + /* Clear all pending interrupts */
21467 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21468 +
21469 + /* De-assert Restore */
21470 + gpwrdn.d32 = 0;
21471 + gpwrdn.b.restore = 1;
21472 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21473 + dwc_udelay(10);
21474 +
21475 + /* Restore GUSBCFG and HCFG */
21476 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21477 + core_if->gr_backup->gusbcfg_local);
21478 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
21479 + core_if->hr_backup->hcfg_local);
21480 +
21481 + /* De-assert Wakeup Logic */
21482 + gpwrdn.d32 = 0;
21483 + gpwrdn.b.pmuactv = 1;
21484 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21485 + dwc_udelay(10);
21486 +
21487 + /* Start the Resume operation by programming HPRT0 */
21488 + hprt0.d32 = core_if->hr_backup->hprt0_local;
21489 + hprt0.b.prtpwr = 1;
21490 + hprt0.b.prtena = 0;
21491 + hprt0.b.prtsusp = 0;
21492 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21493 +
21494 + DWC_PRINTF("Resume Starts Now\n");
21495 + if (!reset) { // Indicates it is Resume Operation
21496 + hprt0.d32 = core_if->hr_backup->hprt0_local;
21497 + hprt0.b.prtres = 1;
21498 + hprt0.b.prtpwr = 1;
21499 + hprt0.b.prtena = 0;
21500 + hprt0.b.prtsusp = 0;
21501 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21502 +
21503 + if (!rem_wakeup)
21504 + hprt0.b.prtres = 0;
21505 + /* Wait for Resume time and then program HPRT again */
21506 + dwc_mdelay(100);
21507 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21508 +
21509 + } else { // Indicates it is Reset Operation
21510 + hprt0.d32 = core_if->hr_backup->hprt0_local;
21511 + hprt0.b.prtrst = 1;
21512 + hprt0.b.prtpwr = 1;
21513 + hprt0.b.prtena = 0;
21514 + hprt0.b.prtsusp = 0;
21515 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21516 + /* Wait for Reset time and then program HPRT again */
21517 + dwc_mdelay(60);
21518 + hprt0.b.prtrst = 0;
21519 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21520 + }
21521 + /* Clear all interrupt status */
21522 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
21523 + hprt0.b.prtconndet = 1;
21524 + hprt0.b.prtenchng = 1;
21525 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21526 +
21527 + /* Clear all pending interupts */
21528 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21529 +
21530 + /* Restore global registers */
21531 + dwc_otg_restore_global_regs(core_if);
21532 + /* Restore host global registers */
21533 + dwc_otg_restore_host_regs(core_if, reset);
21534 +
21535 + /* The core will be in ON STATE */
21536 + core_if->lx_state = DWC_OTG_L0;
21537 + DWC_PRINTF("Hibernation recovery is complete here\n");
21538 + return 0;
21539 +}
21540 +
21541 +/** Saves some register values into system memory. */
21542 +int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)
21543 +{
21544 + struct dwc_otg_global_regs_backup *gr;
21545 + int i;
21546 +
21547 + gr = core_if->gr_backup;
21548 + if (!gr) {
21549 + gr = DWC_ALLOC(sizeof(*gr));
21550 + if (!gr) {
21551 + return -DWC_E_NO_MEMORY;
21552 + }
21553 + core_if->gr_backup = gr;
21554 + }
21555 +
21556 + gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
21557 + gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21558 + gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
21559 + gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21560 + gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
21561 + gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
21562 + gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21563 +#ifdef CONFIG_USB_DWC_OTG_LPM
21564 + gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
21565 +#endif
21566 + gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);
21567 + gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);
21568 + gr->gdfifocfg_local =
21569 + DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);
21570 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21571 + gr->dtxfsiz_local[i] =
21572 + DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));
21573 + }
21574 +
21575 + DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");
21576 + DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local);
21577 + DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local);
21578 + DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local);
21579 + DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local);
21580 + DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local);
21581 + DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",
21582 + gr->gnptxfsiz_local);
21583 + DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n",
21584 + gr->hptxfsiz_local);
21585 +#ifdef CONFIG_USB_DWC_OTG_LPM
21586 + DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local);
21587 +#endif
21588 + DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local);
21589 + DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local);
21590 + DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local);
21591 +
21592 + return 0;
21593 +}
21594 +
21595 +/** Saves GINTMSK register before setting the msk bits. */
21596 +int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)
21597 +{
21598 + struct dwc_otg_global_regs_backup *gr;
21599 +
21600 + gr = core_if->gr_backup;
21601 + if (!gr) {
21602 + gr = DWC_ALLOC(sizeof(*gr));
21603 + if (!gr) {
21604 + return -DWC_E_NO_MEMORY;
21605 + }
21606 + core_if->gr_backup = gr;
21607 + }
21608 +
21609 + gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21610 +
21611 + DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");
21612 + DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local);
21613 +
21614 + return 0;
21615 +}
21616 +
21617 +int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)
21618 +{
21619 + struct dwc_otg_dev_regs_backup *dr;
21620 + int i;
21621 +
21622 + dr = core_if->dr_backup;
21623 + if (!dr) {
21624 + dr = DWC_ALLOC(sizeof(*dr));
21625 + if (!dr) {
21626 + return -DWC_E_NO_MEMORY;
21627 + }
21628 + core_if->dr_backup = dr;
21629 + }
21630 +
21631 + dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21632 + dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
21633 + dr->daintmsk =
21634 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
21635 + dr->diepmsk =
21636 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);
21637 + dr->doepmsk =
21638 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);
21639 +
21640 + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21641 + dr->diepctl[i] =
21642 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
21643 + dr->dieptsiz[i] =
21644 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);
21645 + dr->diepdma[i] =
21646 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
21647 + }
21648 +
21649 + DWC_DEBUGPL(DBG_ANY,
21650 + "=============Backing Host registers==============\n");
21651 + DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg);
21652 + DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl);
21653 + DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n",
21654 + dr->daintmsk);
21655 + DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk);
21656 + DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk);
21657 + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21658 + DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i,
21659 + dr->diepctl[i]);
21660 + DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n",
21661 + i, dr->dieptsiz[i]);
21662 + DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i,
21663 + dr->diepdma[i]);
21664 + }
21665 +
21666 + return 0;
21667 +}
21668 +
21669 +int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)
21670 +{
21671 + struct dwc_otg_host_regs_backup *hr;
21672 + int i;
21673 +
21674 + hr = core_if->hr_backup;
21675 + if (!hr) {
21676 + hr = DWC_ALLOC(sizeof(*hr));
21677 + if (!hr) {
21678 + return -DWC_E_NO_MEMORY;
21679 + }
21680 + core_if->hr_backup = hr;
21681 + }
21682 +
21683 + hr->hcfg_local =
21684 + DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21685 + hr->haintmsk_local =
21686 + DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
21687 + for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21688 + hr->hcintmsk_local[i] =
21689 + DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);
21690 + }
21691 + hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);
21692 + hr->hfir_local =
21693 + DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
21694 +
21695 + DWC_DEBUGPL(DBG_ANY,
21696 + "=============Backing Host registers===============\n");
21697 + DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n",
21698 + hr->hcfg_local);
21699 + DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);
21700 + for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21701 + DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,
21702 + hr->hcintmsk_local[i]);
21703 + }
21704 + DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n",
21705 + hr->hprt0_local);
21706 + DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n",
21707 + hr->hfir_local);
21708 +
21709 + return 0;
21710 +}
21711 +
21712 +int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)
21713 +{
21714 + struct dwc_otg_global_regs_backup *gr;
21715 + int i;
21716 +
21717 + gr = core_if->gr_backup;
21718 + if (!gr) {
21719 + return -DWC_E_INVALID;
21720 + }
21721 +
21722 + DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
21723 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
21724 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
21725 + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);
21726 + DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);
21727 + DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,
21728 + gr->gnptxfsiz_local);
21729 + DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,
21730 + gr->hptxfsiz_local);
21731 + DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,
21732 + gr->gdfifocfg_local);
21733 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21734 + DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],
21735 + gr->dtxfsiz_local[i]);
21736 + }
21737 +
21738 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21739 + DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);
21740 + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,
21741 + (gr->gahbcfg_local));
21742 + return 0;
21743 +}
21744 +
21745 +int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)
21746 +{
21747 + struct dwc_otg_dev_regs_backup *dr;
21748 + int i;
21749 +
21750 + dr = core_if->dr_backup;
21751 +
21752 + if (!dr) {
21753 + return -DWC_E_INVALID;
21754 + }
21755 +
21756 + if (!rem_wakeup) {
21757 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
21758 + dr->dctl);
21759 + }
21760 +
21761 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
21762 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
21763 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
21764 +
21765 + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21766 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
21767 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
21768 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);
21769 + }
21770 +
21771 + return 0;
21772 +}
21773 +
21774 +int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)
21775 +{
21776 + struct dwc_otg_host_regs_backup *hr;
21777 + int i;
21778 + hr = core_if->hr_backup;
21779 +
21780 + if (!hr) {
21781 + return -DWC_E_INVALID;
21782 + }
21783 +
21784 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);
21785 + //if (!reset)
21786 + //{
21787 + // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);
21788 + //}
21789 +
21790 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,
21791 + hr->haintmsk_local);
21792 + for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21793 + DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,
21794 + hr->hcintmsk_local[i]);
21795 + }
21796 +
21797 + return 0;
21798 +}
21799 +
21800 +int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)
21801 +{
21802 + struct dwc_otg_global_regs_backup *gr;
21803 +
21804 + gr = core_if->gr_backup;
21805 +
21806 + /* Restore values for LPM and I2C */
21807 +#ifdef CONFIG_USB_DWC_OTG_LPM
21808 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);
21809 +#endif
21810 + DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);
21811 +
21812 + return 0;
21813 +}
21814 +
21815 +int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)
21816 +{
21817 + struct dwc_otg_global_regs_backup *gr;
21818 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
21819 + gahbcfg_data_t gahbcfg = {.d32 = 0 };
21820 + gusbcfg_data_t gusbcfg = {.d32 = 0 };
21821 + gintmsk_data_t gintmsk = {.d32 = 0 };
21822 +
21823 + /* Restore LPM and I2C registers */
21824 + restore_lpm_i2c_regs(core_if);
21825 +
21826 + /* Set PCGCCTL to 0 */
21827 + DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);
21828 +
21829 + gr = core_if->gr_backup;
21830 + /* Load restore values for [31:14] bits */
21831 + DWC_WRITE_REG32(core_if->pcgcctl,
21832 + ((gr->pcgcctl_local & 0xffffc000) | 0x00020000));
21833 +
21834 + /* Umnask global Interrupt in GAHBCFG and restore it */
21835 + gahbcfg.d32 = gr->gahbcfg_local;
21836 + gahbcfg.b.glblintrmsk = 1;
21837 + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
21838 +
21839 + /* Clear all pending interupts */
21840 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21841 +
21842 + /* Unmask restore done interrupt */
21843 + gintmsk.b.restoredone = 1;
21844 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
21845 +
21846 + /* Restore GUSBCFG and HCFG/DCFG */
21847 + gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;
21848 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21849 +
21850 + if (is_host) {
21851 + hcfg_data_t hcfg = {.d32 = 0 };
21852 + hcfg.d32 = core_if->hr_backup->hcfg_local;
21853 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
21854 + hcfg.d32);
21855 +
21856 + /* Load restore values for [31:14] bits */
21857 + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
21858 + pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
21859 +
21860 + if (rmode)
21861 + pcgcctl.b.restoremode = 1;
21862 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
21863 + dwc_udelay(10);
21864 +
21865 + /* Load restore values for [31:14] bits and set EssRegRestored bit */
21866 + pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;
21867 + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
21868 + pcgcctl.b.ess_reg_restored = 1;
21869 + if (rmode)
21870 + pcgcctl.b.restoremode = 1;
21871 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
21872 + } else {
21873 + dcfg_data_t dcfg = {.d32 = 0 };
21874 + dcfg.d32 = core_if->dr_backup->dcfg;
21875 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
21876 +
21877 + /* Load restore values for [31:14] bits */
21878 + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
21879 + pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
21880 + if (!rmode) {
21881 + pcgcctl.d32 |= 0x208;
21882 + }
21883 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
21884 + dwc_udelay(10);
21885 +
21886 + /* Load restore values for [31:14] bits */
21887 + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
21888 + pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
21889 + pcgcctl.b.ess_reg_restored = 1;
21890 + if (!rmode)
21891 + pcgcctl.d32 |= 0x208;
21892 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
21893 + }
21894 +
21895 + return 0;
21896 +}
21897 +
21898 +/**
21899 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
21900 + * type.
21901 + */
21902 +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
21903 +{
21904 + uint32_t val;
21905 + hcfg_data_t hcfg;
21906 +
21907 + if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
21908 + (core_if->hwcfg2.b.fs_phy_type == 1) &&
21909 + (core_if->core_params->ulpi_fs_ls)) ||
21910 + (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
21911 + /* Full speed PHY */
21912 + val = DWC_HCFG_48_MHZ;
21913 + } else {
21914 + /* High speed PHY running at full speed or high speed */
21915 + val = DWC_HCFG_30_60_MHZ;
21916 + }
21917 +
21918 + DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
21919 + hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21920 + hcfg.b.fslspclksel = val;
21921 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
21922 +}
21923 +
21924 +/**
21925 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
21926 + * and the enumeration speed of the device.
21927 + */
21928 +static void init_devspd(dwc_otg_core_if_t * core_if)
21929 +{
21930 + uint32_t val;
21931 + dcfg_data_t dcfg;
21932 +
21933 + if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
21934 + (core_if->hwcfg2.b.fs_phy_type == 1) &&
21935 + (core_if->core_params->ulpi_fs_ls)) ||
21936 + (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
21937 + /* Full speed PHY */
21938 + val = 0x3;
21939 + } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
21940 + /* High speed PHY running at full speed */
21941 + val = 0x1;
21942 + } else {
21943 + /* High speed PHY running at high speed */
21944 + val = 0x0;
21945 + }
21946 +
21947 + DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
21948 +
21949 + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21950 + dcfg.b.devspd = val;
21951 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
21952 +}
21953 +
21954 +/**
21955 + * This function calculates the number of IN EPS
21956 + * using GHWCFG1 and GHWCFG2 registers values
21957 + *
21958 + * @param core_if Programming view of the DWC_otg controller
21959 + */
21960 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
21961 +{
21962 + uint32_t num_in_eps = 0;
21963 + uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
21964 + uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
21965 + uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
21966 + int i;
21967 +
21968 + for (i = 0; i < num_eps; ++i) {
21969 + if (!(hwcfg1 & 0x1))
21970 + num_in_eps++;
21971 +
21972 + hwcfg1 >>= 2;
21973 + }
21974 +
21975 + if (core_if->hwcfg4.b.ded_fifo_en) {
21976 + num_in_eps =
21977 + (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
21978 + }
21979 +
21980 + return num_in_eps;
21981 +}
21982 +
21983 +/**
21984 + * This function calculates the number of OUT EPS
21985 + * using GHWCFG1 and GHWCFG2 registers values
21986 + *
21987 + * @param core_if Programming view of the DWC_otg controller
21988 + */
21989 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
21990 +{
21991 + uint32_t num_out_eps = 0;
21992 + uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
21993 + uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
21994 + int i;
21995 +
21996 + for (i = 0; i < num_eps; ++i) {
21997 + if (!(hwcfg1 & 0x1))
21998 + num_out_eps++;
21999 +
22000 + hwcfg1 >>= 2;
22001 + }
22002 + return num_out_eps;
22003 +}
22004 +
22005 +/**
22006 + * This function initializes the DWC_otg controller registers and
22007 + * prepares the core for device mode or host mode operation.
22008 + *
22009 + * @param core_if Programming view of the DWC_otg controller
22010 + *
22011 + */
22012 +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
22013 +{
22014 + int i = 0;
22015 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22016 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22017 + gahbcfg_data_t ahbcfg = {.d32 = 0 };
22018 + gusbcfg_data_t usbcfg = {.d32 = 0 };
22019 + gi2cctl_data_t i2cctl = {.d32 = 0 };
22020 +
22021 + DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
22022 + core_if, global_regs);
22023 +
22024 + /* Common Initialization */
22025 + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22026 +
22027 + /* Program the ULPI External VBUS bit if needed */
22028 + usbcfg.b.ulpi_ext_vbus_drv =
22029 + (core_if->core_params->phy_ulpi_ext_vbus ==
22030 + DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
22031 +
22032 + /* Set external TS Dline pulsing */
22033 + usbcfg.b.term_sel_dl_pulse =
22034 + (core_if->core_params->ts_dline == 1) ? 1 : 0;
22035 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22036 +
22037 + /* Reset the Controller */
22038 + dwc_otg_core_reset(core_if);
22039 +
22040 + core_if->adp_enable = core_if->core_params->adp_supp_enable;
22041 + core_if->power_down = core_if->core_params->power_down;
22042 + core_if->otg_sts = 0;
22043 +
22044 + /* Initialize parameters from Hardware configuration registers. */
22045 + dev_if->num_in_eps = calc_num_in_eps(core_if);
22046 + dev_if->num_out_eps = calc_num_out_eps(core_if);
22047 +
22048 + DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
22049 + core_if->hwcfg4.b.num_dev_perio_in_ep);
22050 +
22051 + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22052 + dev_if->perio_tx_fifo_size[i] =
22053 + DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22054 + DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
22055 + i, dev_if->perio_tx_fifo_size[i]);
22056 + }
22057 +
22058 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22059 + dev_if->tx_fifo_size[i] =
22060 + DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22061 + DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
22062 + i, dev_if->tx_fifo_size[i]);
22063 + }
22064 +
22065 + core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
22066 + core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
22067 + core_if->nperio_tx_fifo_size =
22068 + DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
22069 +
22070 + DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
22071 + DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
22072 + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
22073 + core_if->nperio_tx_fifo_size);
22074 +
22075 + /* This programming sequence needs to happen in FS mode before any other
22076 + * programming occurs */
22077 + if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
22078 + (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22079 + /* If FS mode with FS PHY */
22080 +
22081 + /* core_init() is now called on every switch so only call the
22082 + * following for the first time through. */
22083 + if (!core_if->phy_init_done) {
22084 + core_if->phy_init_done = 1;
22085 + DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
22086 + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22087 + usbcfg.b.physel = 1;
22088 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22089 +
22090 + /* Reset after a PHY select */
22091 + dwc_otg_core_reset(core_if);
22092 + }
22093 +
22094 + /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
22095 + * do this on HNP Dev/Host mode switches (done in dev_init and
22096 + * host_init). */
22097 + if (dwc_otg_is_host_mode(core_if)) {
22098 + init_fslspclksel(core_if);
22099 + } else {
22100 + init_devspd(core_if);
22101 + }
22102 +
22103 + if (core_if->core_params->i2c_enable) {
22104 + DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
22105 + /* Program GUSBCFG.OtgUtmifsSel to I2C */
22106 + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22107 + usbcfg.b.otgutmifssel = 1;
22108 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22109 +
22110 + /* Program GI2CCTL.I2CEn */
22111 + i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);
22112 + i2cctl.b.i2cdevaddr = 1;
22113 + i2cctl.b.i2cen = 0;
22114 + DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22115 + i2cctl.b.i2cen = 1;
22116 + DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22117 + }
22118 +
22119 + } /* endif speed == DWC_SPEED_PARAM_FULL */
22120 + else {
22121 + /* High speed PHY. */
22122 + if (!core_if->phy_init_done) {
22123 + core_if->phy_init_done = 1;
22124 + /* HS PHY parameters. These parameters are preserved
22125 + * during soft reset so only program the first time. Do
22126 + * a soft reset immediately after setting phyif. */
22127 +
22128 + if (core_if->core_params->phy_type == 2) {
22129 + /* ULPI interface */
22130 + usbcfg.b.ulpi_utmi_sel = 1;
22131 + usbcfg.b.phyif = 0;
22132 + usbcfg.b.ddrsel =
22133 + core_if->core_params->phy_ulpi_ddr;
22134 + } else if (core_if->core_params->phy_type == 1) {
22135 + /* UTMI+ interface */
22136 + usbcfg.b.ulpi_utmi_sel = 0;
22137 + if (core_if->core_params->phy_utmi_width == 16) {
22138 + usbcfg.b.phyif = 1;
22139 +
22140 + } else {
22141 + usbcfg.b.phyif = 0;
22142 + }
22143 + } else {
22144 + DWC_ERROR("FS PHY TYPE\n");
22145 + }
22146 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22147 + /* Reset after setting the PHY parameters */
22148 + dwc_otg_core_reset(core_if);
22149 + }
22150 + }
22151 +
22152 + if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
22153 + (core_if->hwcfg2.b.fs_phy_type == 1) &&
22154 + (core_if->core_params->ulpi_fs_ls)) {
22155 + DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
22156 + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22157 + usbcfg.b.ulpi_fsls = 1;
22158 + usbcfg.b.ulpi_clk_sus_m = 1;
22159 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22160 + } else {
22161 + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22162 + usbcfg.b.ulpi_fsls = 0;
22163 + usbcfg.b.ulpi_clk_sus_m = 0;
22164 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22165 + }
22166 +
22167 + /* Program the GAHBCFG Register. */
22168 + switch (core_if->hwcfg2.b.architecture) {
22169 +
22170 + case DWC_SLAVE_ONLY_ARCH:
22171 + DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
22172 + ahbcfg.b.nptxfemplvl_txfemplvl =
22173 + DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22174 + ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22175 + core_if->dma_enable = 0;
22176 + core_if->dma_desc_enable = 0;
22177 + break;
22178 +
22179 + case DWC_EXT_DMA_ARCH:
22180 + DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
22181 + {
22182 + uint8_t brst_sz = core_if->core_params->dma_burst_size;
22183 + ahbcfg.b.hburstlen = 0;
22184 + while (brst_sz > 1) {
22185 + ahbcfg.b.hburstlen++;
22186 + brst_sz >>= 1;
22187 + }
22188 + }
22189 + core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22190 + core_if->dma_desc_enable =
22191 + (core_if->core_params->dma_desc_enable != 0);
22192 + break;
22193 +
22194 + case DWC_INT_DMA_ARCH:
22195 + DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
22196 + /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
22197 + Host mode ISOC in issue fix - vahrama */
22198 + /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */
22199 + ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;
22200 + core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22201 + core_if->dma_desc_enable =
22202 + (core_if->core_params->dma_desc_enable != 0);
22203 + break;
22204 +
22205 + }
22206 + if (core_if->dma_enable) {
22207 + if (core_if->dma_desc_enable) {
22208 + DWC_PRINTF("Using Descriptor DMA mode\n");
22209 + } else {
22210 + DWC_PRINTF("Using Buffer DMA mode\n");
22211 +
22212 + }
22213 + } else {
22214 + DWC_PRINTF("Using Slave mode\n");
22215 + core_if->dma_desc_enable = 0;
22216 + }
22217 +
22218 + if (core_if->core_params->ahb_single) {
22219 + ahbcfg.b.ahbsingle = 1;
22220 + }
22221 +
22222 + ahbcfg.b.dmaenable = core_if->dma_enable;
22223 + DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
22224 +
22225 + core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
22226 +
22227 + core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
22228 + core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
22229 + DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
22230 + ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
22231 + DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
22232 + ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
22233 +
22234 + /*
22235 + * Program the GUSBCFG register.
22236 + */
22237 + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22238 +
22239 + switch (core_if->hwcfg2.b.op_mode) {
22240 + case DWC_MODE_HNP_SRP_CAPABLE:
22241 + usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
22242 + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
22243 + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22244 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22245 + break;
22246 +
22247 + case DWC_MODE_SRP_ONLY_CAPABLE:
22248 + usbcfg.b.hnpcap = 0;
22249 + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22250 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22251 + break;
22252 +
22253 + case DWC_MODE_NO_HNP_SRP_CAPABLE:
22254 + usbcfg.b.hnpcap = 0;
22255 + usbcfg.b.srpcap = 0;
22256 + break;
22257 +
22258 + case DWC_MODE_SRP_CAPABLE_DEVICE:
22259 + usbcfg.b.hnpcap = 0;
22260 + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22261 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22262 + break;
22263 +
22264 + case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
22265 + usbcfg.b.hnpcap = 0;
22266 + usbcfg.b.srpcap = 0;
22267 + break;
22268 +
22269 + case DWC_MODE_SRP_CAPABLE_HOST:
22270 + usbcfg.b.hnpcap = 0;
22271 + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22272 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22273 + break;
22274 +
22275 + case DWC_MODE_NO_SRP_CAPABLE_HOST:
22276 + usbcfg.b.hnpcap = 0;
22277 + usbcfg.b.srpcap = 0;
22278 + break;
22279 + }
22280 +
22281 + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22282 +
22283 +#ifdef CONFIG_USB_DWC_OTG_LPM
22284 + if (core_if->core_params->lpm_enable) {
22285 + glpmcfg_data_t lpmcfg = {.d32 = 0 };
22286 +
22287 + /* To enable LPM support set lpm_cap_en bit */
22288 + lpmcfg.b.lpm_cap_en = 1;
22289 +
22290 + /* Make AppL1Res ACK */
22291 + lpmcfg.b.appl_resp = 1;
22292 +
22293 + /* Retry 3 times */
22294 + lpmcfg.b.retry_count = 3;
22295 +
22296 + DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,
22297 + 0, lpmcfg.d32);
22298 +
22299 + }
22300 +#endif
22301 + if (core_if->core_params->ic_usb_cap) {
22302 + gusbcfg_data_t gusbcfg = {.d32 = 0 };
22303 + gusbcfg.b.ic_usb_cap = 1;
22304 + DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,
22305 + 0, gusbcfg.d32);
22306 + }
22307 + {
22308 + gotgctl_data_t gotgctl = {.d32 = 0 };
22309 + gotgctl.b.otgver = core_if->core_params->otg_ver;
22310 + DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,
22311 + gotgctl.d32);
22312 + /* Set OTG version supported */
22313 + core_if->otg_ver = core_if->core_params->otg_ver;
22314 + DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
22315 + core_if->core_params->otg_ver, core_if->otg_ver);
22316 + }
22317 +
22318 +
22319 + /* Enable common interrupts */
22320 + dwc_otg_enable_common_interrupts(core_if);
22321 +
22322 + /* Do device or host intialization based on mode during PCD
22323 + * and HCD initialization */
22324 + if (dwc_otg_is_host_mode(core_if)) {
22325 + DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
22326 + core_if->op_state = A_HOST;
22327 + } else {
22328 + DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
22329 + core_if->op_state = B_PERIPHERAL;
22330 +#ifdef DWC_DEVICE_ONLY
22331 + dwc_otg_core_dev_init(core_if);
22332 +#endif
22333 + }
22334 +}
22335 +
22336 +/**
22337 + * This function enables the Device mode interrupts.
22338 + *
22339 + * @param core_if Programming view of DWC_otg controller
22340 + */
22341 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
22342 +{
22343 + gintmsk_data_t intr_mask = {.d32 = 0 };
22344 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22345 +
22346 + DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
22347 +
22348 + /* Disable all interrupts. */
22349 + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22350 +
22351 + /* Clear any pending interrupts */
22352 + DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22353 +
22354 + /* Enable the common interrupts */
22355 + dwc_otg_enable_common_interrupts(core_if);
22356 +
22357 + /* Enable interrupts */
22358 + intr_mask.b.usbreset = 1;
22359 + intr_mask.b.enumdone = 1;
22360 + /* Disable Disconnect interrupt in Device mode */
22361 + intr_mask.b.disconnect = 0;
22362 +
22363 + if (!core_if->multiproc_int_enable) {
22364 + intr_mask.b.inepintr = 1;
22365 + intr_mask.b.outepintr = 1;
22366 + }
22367 +
22368 + intr_mask.b.erlysuspend = 1;
22369 +
22370 + if (core_if->en_multiple_tx_fifo == 0) {
22371 + intr_mask.b.epmismatch = 1;
22372 + }
22373 +
22374 + //intr_mask.b.incomplisoout = 1;
22375 + intr_mask.b.incomplisoin = 1;
22376 +
22377 +/* Enable the ignore frame number for ISOC xfers - MAS */
22378 +/* Disable to support high bandwith ISOC transfers - manukz */
22379 +#if 0
22380 +#ifdef DWC_UTE_PER_IO
22381 + if (core_if->dma_enable) {
22382 + if (core_if->dma_desc_enable) {
22383 + dctl_data_t dctl1 = {.d32 = 0 };
22384 + dctl1.b.ifrmnum = 1;
22385 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
22386 + dctl, 0, dctl1.d32);
22387 + DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",
22388 + DWC_READ_REG32(&core_if->dev_if->
22389 + dev_global_regs->dctl));
22390 + }
22391 + }
22392 +#endif
22393 +#endif
22394 +#ifdef DWC_EN_ISOC
22395 + if (core_if->dma_enable) {
22396 + if (core_if->dma_desc_enable == 0) {
22397 + if (core_if->pti_enh_enable) {
22398 + dctl_data_t dctl = {.d32 = 0 };
22399 + dctl.b.ifrmnum = 1;
22400 + DWC_MODIFY_REG32(&core_if->
22401 + dev_if->dev_global_regs->dctl,
22402 + 0, dctl.d32);
22403 + } else {
22404 + intr_mask.b.incomplisoin = 1;
22405 + intr_mask.b.incomplisoout = 1;
22406 + }
22407 + }
22408 + } else {
22409 + intr_mask.b.incomplisoin = 1;
22410 + intr_mask.b.incomplisoout = 1;
22411 + }
22412 +#endif /* DWC_EN_ISOC */
22413 +
22414 + /** @todo NGS: Should this be a module parameter? */
22415 +#ifdef USE_PERIODIC_EP
22416 + intr_mask.b.isooutdrop = 1;
22417 + intr_mask.b.eopframe = 1;
22418 + intr_mask.b.incomplisoin = 1;
22419 + intr_mask.b.incomplisoout = 1;
22420 +#endif
22421 +
22422 + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
22423 +
22424 + DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
22425 + DWC_READ_REG32(&global_regs->gintmsk));
22426 +}
22427 +
22428 +/**
22429 + * This function initializes the DWC_otg controller registers for
22430 + * device mode.
22431 + *
22432 + * @param core_if Programming view of DWC_otg controller
22433 + *
22434 + */
22435 +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
22436 +{
22437 + int i;
22438 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22439 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22440 + dwc_otg_core_params_t *params = core_if->core_params;
22441 + dcfg_data_t dcfg = {.d32 = 0 };
22442 + depctl_data_t diepctl = {.d32 = 0 };
22443 + grstctl_t resetctl = {.d32 = 0 };
22444 + uint32_t rx_fifo_size;
22445 + fifosize_data_t nptxfifosize;
22446 + fifosize_data_t txfifosize;
22447 + dthrctl_data_t dthrctl;
22448 + fifosize_data_t ptxfifosize;
22449 + uint16_t rxfsiz, nptxfsiz;
22450 + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
22451 + hwcfg3_data_t hwcfg3 = {.d32 = 0 };
22452 +
22453 + /* Restart the Phy Clock */
22454 + DWC_WRITE_REG32(core_if->pcgcctl, 0);
22455 +
22456 + /* Device configuration register */
22457 + init_devspd(core_if);
22458 + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22459 + dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
22460 + dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
22461 + /* Enable Device OUT NAK in case of DDMA mode*/
22462 + if (core_if->core_params->dev_out_nak) {
22463 + dcfg.b.endevoutnak = 1;
22464 + }
22465 +
22466 + if (core_if->core_params->cont_on_bna) {
22467 + dctl_data_t dctl = {.d32 = 0 };
22468 + dctl.b.encontonbna = 1;
22469 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22470 + }
22471 +
22472 +
22473 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22474 +
22475 + /* Configure data FIFO sizes */
22476 + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
22477 + DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
22478 + core_if->total_fifo_size);
22479 + DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
22480 + params->dev_rx_fifo_size);
22481 + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
22482 + params->dev_nperio_tx_fifo_size);
22483 +
22484 + /* Rx FIFO */
22485 + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
22486 + DWC_READ_REG32(&global_regs->grxfsiz));
22487 +
22488 +#ifdef DWC_UTE_CFI
22489 + core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);
22490 + core_if->init_rxfsiz = params->dev_rx_fifo_size;
22491 +#endif
22492 + rx_fifo_size = params->dev_rx_fifo_size;
22493 + DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
22494 +
22495 + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
22496 + DWC_READ_REG32(&global_regs->grxfsiz));
22497 +
22498 + /** Set Periodic Tx FIFO Mask all bits 0 */
22499 + core_if->p_tx_msk = 0;
22500 +
22501 + /** Set Tx FIFO Mask all bits 0 */
22502 + core_if->tx_msk = 0;
22503 +
22504 + if (core_if->en_multiple_tx_fifo == 0) {
22505 + /* Non-periodic Tx FIFO */
22506 + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22507 + DWC_READ_REG32(&global_regs->gnptxfsiz));
22508 +
22509 + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22510 + nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22511 +
22512 + DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22513 + nptxfifosize.d32);
22514 +
22515 + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22516 + DWC_READ_REG32(&global_regs->gnptxfsiz));
22517 +
22518 + /**@todo NGS: Fix Periodic FIFO Sizing! */
22519 + /*
22520 + * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
22521 + * Indexes of the FIFO size module parameters in the
22522 + * dev_perio_tx_fifo_size array and the FIFO size registers in
22523 + * the dptxfsiz array run from 0 to 14.
22524 + */
22525 + /** @todo Finish debug of this */
22526 + ptxfifosize.b.startaddr =
22527 + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22528 + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22529 + ptxfifosize.b.depth =
22530 + params->dev_perio_tx_fifo_size[i];
22531 + DWC_DEBUGPL(DBG_CIL,
22532 + "initial dtxfsiz[%d]=%08x\n", i,
22533 + DWC_READ_REG32(&global_regs->dtxfsiz
22534 + [i]));
22535 + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22536 + ptxfifosize.d32);
22537 + DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",
22538 + i,
22539 + DWC_READ_REG32(&global_regs->dtxfsiz
22540 + [i]));
22541 + ptxfifosize.b.startaddr += ptxfifosize.b.depth;
22542 + }
22543 + } else {
22544 + /*
22545 + * Tx FIFOs These FIFOs are numbered from 1 to 15.
22546 + * Indexes of the FIFO size module parameters in the
22547 + * dev_tx_fifo_size array and the FIFO size registers in
22548 + * the dtxfsiz array run from 0 to 14.
22549 + */
22550 +
22551 + /* Non-periodic Tx FIFO */
22552 + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22553 + DWC_READ_REG32(&global_regs->gnptxfsiz));
22554 +
22555 +#ifdef DWC_UTE_CFI
22556 + core_if->pwron_gnptxfsiz =
22557 + (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22558 + core_if->init_gnptxfsiz =
22559 + params->dev_nperio_tx_fifo_size;
22560 +#endif
22561 + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22562 + nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22563 +
22564 + DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22565 + nptxfifosize.d32);
22566 +
22567 + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22568 + DWC_READ_REG32(&global_regs->gnptxfsiz));
22569 +
22570 + txfifosize.b.startaddr =
22571 + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22572 +
22573 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22574 +
22575 + txfifosize.b.depth =
22576 + params->dev_tx_fifo_size[i];
22577 +
22578 + DWC_DEBUGPL(DBG_CIL,
22579 + "initial dtxfsiz[%d]=%08x\n",
22580 + i,
22581 + DWC_READ_REG32(&global_regs->dtxfsiz
22582 + [i]));
22583 +
22584 +#ifdef DWC_UTE_CFI
22585 + core_if->pwron_txfsiz[i] =
22586 + (DWC_READ_REG32
22587 + (&global_regs->dtxfsiz[i]) >> 16);
22588 + core_if->init_txfsiz[i] =
22589 + params->dev_tx_fifo_size[i];
22590 +#endif
22591 + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22592 + txfifosize.d32);
22593 +
22594 + DWC_DEBUGPL(DBG_CIL,
22595 + "new dtxfsiz[%d]=%08x\n",
22596 + i,
22597 + DWC_READ_REG32(&global_regs->dtxfsiz
22598 + [i]));
22599 +
22600 + txfifosize.b.startaddr += txfifosize.b.depth;
22601 + }
22602 + if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
22603 + /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */
22604 + gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
22605 + hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);
22606 + gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);
22607 + DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22608 + rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
22609 + nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22610 + gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;
22611 + DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22612 + }
22613 + }
22614 +
22615 + /* Flush the FIFOs */
22616 + dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
22617 + dwc_otg_flush_rx_fifo(core_if);
22618 +
22619 + /* Flush the Learning Queue. */
22620 + resetctl.b.intknqflsh = 1;
22621 + DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
22622 +
22623 + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
22624 + core_if->start_predict = 0;
22625 + for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
22626 + core_if->nextep_seq[i] = 0xff; // 0xff - EP not active
22627 + }
22628 + core_if->nextep_seq[0] = 0;
22629 + core_if->first_in_nextep_seq = 0;
22630 + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
22631 + diepctl.b.nextep = 0;
22632 + DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
22633 +
22634 + /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
22635 + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22636 + dcfg.b.epmscnt = 2;
22637 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22638 +
22639 + DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
22640 + __func__, core_if->first_in_nextep_seq);
22641 + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
22642 + DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
22643 + }
22644 + DWC_DEBUGPL(DBG_CILV,"\n");
22645 + }
22646 +
22647 + /* Clear all pending Device Interrupts */
22648 + /** @todo - if the condition needed to be checked
22649 + * or in any case all pending interrutps should be cleared?
22650 + */
22651 + if (core_if->multiproc_int_enable) {
22652 + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22653 + DWC_WRITE_REG32(&dev_if->
22654 + dev_global_regs->diepeachintmsk[i], 0);
22655 + }
22656 + }
22657 +
22658 + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
22659 + DWC_WRITE_REG32(&dev_if->
22660 + dev_global_regs->doepeachintmsk[i], 0);
22661 + }
22662 +
22663 + DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
22664 + DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);
22665 + } else {
22666 + DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
22667 + DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
22668 + DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
22669 + DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
22670 + }
22671 +
22672 + for (i = 0; i <= dev_if->num_in_eps; i++) {
22673 + depctl_data_t depctl;
22674 + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
22675 + if (depctl.b.epena) {
22676 + depctl.d32 = 0;
22677 + depctl.b.epdis = 1;
22678 + depctl.b.snak = 1;
22679 + } else {
22680 + depctl.d32 = 0;
22681 + }
22682 +
22683 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
22684 +
22685 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
22686 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
22687 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
22688 + }
22689 +
22690 + for (i = 0; i <= dev_if->num_out_eps; i++) {
22691 + depctl_data_t depctl;
22692 + depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
22693 + if (depctl.b.epena) {
22694 + dctl_data_t dctl = {.d32 = 0 };
22695 + gintmsk_data_t gintsts = {.d32 = 0 };
22696 + doepint_data_t doepint = {.d32 = 0 };
22697 + dctl.b.sgoutnak = 1;
22698 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22699 + do {
22700 + dwc_udelay(10);
22701 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
22702 + } while (!gintsts.b.goutnakeff);
22703 + gintsts.d32 = 0;
22704 + gintsts.b.goutnakeff = 1;
22705 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
22706 +
22707 + depctl.d32 = 0;
22708 + depctl.b.epdis = 1;
22709 + depctl.b.snak = 1;
22710 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);
22711 + do {
22712 + dwc_udelay(10);
22713 + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
22714 + out_ep_regs[i]->doepint);
22715 + } while (!doepint.b.epdisabled);
22716 +
22717 + doepint.b.epdisabled = 1;
22718 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);
22719 +
22720 + dctl.d32 = 0;
22721 + dctl.b.cgoutnak = 1;
22722 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22723 + } else {
22724 + depctl.d32 = 0;
22725 + }
22726 +
22727 + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
22728 +
22729 + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
22730 + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
22731 + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
22732 + }
22733 +
22734 + if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
22735 + dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
22736 + dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
22737 + dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
22738 +
22739 + dev_if->rx_thr_length = params->rx_thr_length;
22740 + dev_if->tx_thr_length = params->tx_thr_length;
22741 +
22742 + dev_if->setup_desc_index = 0;
22743 +
22744 + dthrctl.d32 = 0;
22745 + dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
22746 + dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
22747 + dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
22748 + dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
22749 + dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
22750 + dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
22751 +
22752 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
22753 + dthrctl.d32);
22754 +
22755 + DWC_DEBUGPL(DBG_CIL,
22756 + "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
22757 + dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
22758 + dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
22759 + dthrctl.b.rx_thr_len);
22760 +
22761 + }
22762 +
22763 + dwc_otg_enable_device_interrupts(core_if);
22764 +
22765 + {
22766 + diepmsk_data_t msk = {.d32 = 0 };
22767 + msk.b.txfifoundrn = 1;
22768 + if (core_if->multiproc_int_enable) {
22769 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->
22770 + diepeachintmsk[0], msk.d32, msk.d32);
22771 + } else {
22772 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,
22773 + msk.d32, msk.d32);
22774 + }
22775 + }
22776 +
22777 + if (core_if->multiproc_int_enable) {
22778 + /* Set NAK on Babble */
22779 + dctl_data_t dctl = {.d32 = 0 };
22780 + dctl.b.nakonbble = 1;
22781 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22782 + }
22783 +
22784 + if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
22785 + dctl_data_t dctl = {.d32 = 0 };
22786 + dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
22787 + dctl.b.sftdiscon = 0;
22788 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
22789 + }
22790 +}
22791 +
22792 +/**
22793 + * This function enables the Host mode interrupts.
22794 + *
22795 + * @param core_if Programming view of DWC_otg controller
22796 + */
22797 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
22798 +{
22799 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22800 + gintmsk_data_t intr_mask = {.d32 = 0 };
22801 +
22802 + DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
22803 +
22804 + /* Disable all interrupts. */
22805 + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22806 +
22807 + /* Clear any pending interrupts. */
22808 + DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22809 +
22810 + /* Enable the common interrupts */
22811 + dwc_otg_enable_common_interrupts(core_if);
22812 +
22813 + /*
22814 + * Enable host mode interrupts without disturbing common
22815 + * interrupts.
22816 + */
22817 +
22818 + intr_mask.b.disconnect = 1;
22819 + intr_mask.b.portintr = 1;
22820 + intr_mask.b.hcintr = 1;
22821 +
22822 + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
22823 +}
22824 +
22825 +/**
22826 + * This function disables the Host Mode interrupts.
22827 + *
22828 + * @param core_if Programming view of DWC_otg controller
22829 + */
22830 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
22831 +{
22832 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22833 + gintmsk_data_t intr_mask = {.d32 = 0 };
22834 +
22835 + DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
22836 +
22837 + /*
22838 + * Disable host mode interrupts without disturbing common
22839 + * interrupts.
22840 + */
22841 + intr_mask.b.sofintr = 1;
22842 + intr_mask.b.portintr = 1;
22843 + intr_mask.b.hcintr = 1;
22844 + intr_mask.b.ptxfempty = 1;
22845 + intr_mask.b.nptxfempty = 1;
22846 +
22847 + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);
22848 +}
22849 +
22850 +/**
22851 + * This function initializes the DWC_otg controller registers for
22852 + * host mode.
22853 + *
22854 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
22855 + * request queues. Host channels are reset to ensure that they are ready for
22856 + * performing transfers.
22857 + *
22858 + * @param core_if Programming view of DWC_otg controller
22859 + *
22860 + */
22861 +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
22862 +{
22863 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22864 + dwc_otg_host_if_t *host_if = core_if->host_if;
22865 + dwc_otg_core_params_t *params = core_if->core_params;
22866 + hprt0_data_t hprt0 = {.d32 = 0 };
22867 + fifosize_data_t nptxfifosize;
22868 + fifosize_data_t ptxfifosize;
22869 + uint16_t rxfsiz, nptxfsiz, hptxfsiz;
22870 + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
22871 + int i;
22872 + hcchar_data_t hcchar;
22873 + hcfg_data_t hcfg;
22874 + hfir_data_t hfir;
22875 + dwc_otg_hc_regs_t *hc_regs;
22876 + int num_channels;
22877 + gotgctl_data_t gotgctl = {.d32 = 0 };
22878 +
22879 + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
22880 +
22881 + /* Restart the Phy Clock */
22882 + DWC_WRITE_REG32(core_if->pcgcctl, 0);
22883 +
22884 + /* Initialize Host Configuration Register */
22885 + init_fslspclksel(core_if);
22886 + if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
22887 + hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
22888 + hcfg.b.fslssupp = 1;
22889 + DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
22890 +
22891 + }
22892 +
22893 + /* This bit allows dynamic reloading of the HFIR register
22894 + * during runtime. This bit needs to be programmed during
22895 + * initial configuration and its value must not be changed
22896 + * during runtime.*/
22897 + if (core_if->core_params->reload_ctl == 1) {
22898 + hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
22899 + hfir.b.hfirrldctrl = 1;
22900 + DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
22901 + }
22902 +
22903 + if (core_if->core_params->dma_desc_enable) {
22904 + uint8_t op_mode = core_if->hwcfg2.b.op_mode;
22905 + if (!
22906 + (core_if->hwcfg4.b.desc_dma
22907 + && (core_if->snpsid >= OTG_CORE_REV_2_90a)
22908 + && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
22909 + || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
22910 + || (op_mode ==
22911 + DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)
22912 + || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
22913 + || (op_mode ==
22914 + DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
22915 +
22916 + DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
22917 + "Either core version is below 2.90a or "
22918 + "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
22919 + "To run the driver in Buffer DMA host mode set dma_desc_enable "
22920 + "module parameter to 0.\n");
22921 + return;
22922 + }
22923 + hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
22924 + hcfg.b.descdma = 1;
22925 + DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
22926 + }
22927 +
22928 + /* Configure data FIFO sizes */
22929 + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
22930 + DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
22931 + core_if->total_fifo_size);
22932 + DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
22933 + params->host_rx_fifo_size);
22934 + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
22935 + params->host_nperio_tx_fifo_size);
22936 + DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
22937 + params->host_perio_tx_fifo_size);
22938 +
22939 + /* Rx FIFO */
22940 + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
22941 + DWC_READ_REG32(&global_regs->grxfsiz));
22942 + DWC_WRITE_REG32(&global_regs->grxfsiz,
22943 + params->host_rx_fifo_size);
22944 + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
22945 + DWC_READ_REG32(&global_regs->grxfsiz));
22946 +
22947 + /* Non-periodic Tx FIFO */
22948 + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22949 + DWC_READ_REG32(&global_regs->gnptxfsiz));
22950 + nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
22951 + nptxfifosize.b.startaddr = params->host_rx_fifo_size;
22952 + DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
22953 + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22954 + DWC_READ_REG32(&global_regs->gnptxfsiz));
22955 +
22956 + /* Periodic Tx FIFO */
22957 + DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
22958 + DWC_READ_REG32(&global_regs->hptxfsiz));
22959 + ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
22960 + ptxfifosize.b.startaddr =
22961 + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22962 + DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
22963 + DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
22964 + DWC_READ_REG32(&global_regs->hptxfsiz));
22965 +
22966 + if (core_if->en_multiple_tx_fifo
22967 + && core_if->snpsid <= OTG_CORE_REV_2_94a) {
22968 + /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
22969 + gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
22970 + rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
22971 + nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22972 + hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);
22973 + gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;
22974 + DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22975 + }
22976 + }
22977 +
22978 + /* TODO - check this */
22979 + /* Clear Host Set HNP Enable in the OTG Control Register */
22980 + gotgctl.b.hstsethnpen = 1;
22981 + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
22982 + /* Make sure the FIFOs are flushed. */
22983 + dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );
22984 + dwc_otg_flush_rx_fifo(core_if);
22985 +
22986 + /* Clear Host Set HNP Enable in the OTG Control Register */
22987 + gotgctl.b.hstsethnpen = 1;
22988 + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
22989 +
22990 + if (!core_if->core_params->dma_desc_enable) {
22991 + /* Flush out any leftover queued requests. */
22992 + num_channels = core_if->core_params->host_channels;
22993 +
22994 + for (i = 0; i < num_channels; i++) {
22995 + hc_regs = core_if->host_if->hc_regs[i];
22996 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
22997 + hcchar.b.chen = 0;
22998 + hcchar.b.chdis = 1;
22999 + hcchar.b.epdir = 0;
23000 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23001 + }
23002 +
23003 + /* Halt all channels to put them into a known state. */
23004 + for (i = 0; i < num_channels; i++) {
23005 + int count = 0;
23006 + hc_regs = core_if->host_if->hc_regs[i];
23007 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23008 + hcchar.b.chen = 1;
23009 + hcchar.b.chdis = 1;
23010 + hcchar.b.epdir = 0;
23011 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23012 + DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
23013 + do {
23014 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23015 + if (++count > 1000) {
23016 + DWC_ERROR
23017 + ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
23018 + __func__, i, hcchar.d32, &hc_regs->hcchar);
23019 + break;
23020 + }
23021 + dwc_udelay(1);
23022 + } while (hcchar.b.chen);
23023 + }
23024 + }
23025 +
23026 + /* Turn on the vbus power. */
23027 + DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
23028 + if (core_if->op_state == A_HOST) {
23029 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
23030 + DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
23031 + if (hprt0.b.prtpwr == 0) {
23032 + hprt0.b.prtpwr = 1;
23033 + DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);
23034 + }
23035 + }
23036 +
23037 + dwc_otg_enable_host_interrupts(core_if);
23038 +}
23039 +
23040 +/**
23041 + * Prepares a host channel for transferring packets to/from a specific
23042 + * endpoint. The HCCHARn register is set up with the characteristics specified
23043 + * in _hc. Host channel interrupts that may need to be serviced while this
23044 + * transfer is in progress are enabled.
23045 + *
23046 + * @param core_if Programming view of DWC_otg controller
23047 + * @param hc Information needed to initialize the host channel
23048 + */
23049 +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23050 +{
23051 + uint32_t intr_enable;
23052 + hcintmsk_data_t hc_intr_mask;
23053 + gintmsk_data_t gintmsk = {.d32 = 0 };
23054 + hcchar_data_t hcchar;
23055 + hcsplt_data_t hcsplt;
23056 +
23057 + uint8_t hc_num = hc->hc_num;
23058 + dwc_otg_host_if_t *host_if = core_if->host_if;
23059 + dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
23060 +
23061 + /* Clear old interrupt conditions for this host channel. */
23062 + hc_intr_mask.d32 = 0xFFFFFFFF;
23063 + hc_intr_mask.b.reserved14_31 = 0;
23064 + DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);
23065 +
23066 + /* Enable channel interrupts required for this transfer. */
23067 + hc_intr_mask.d32 = 0;
23068 + hc_intr_mask.b.chhltd = 1;
23069 + if (core_if->dma_enable) {
23070 + /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
23071 + if (!core_if->dma_desc_enable)
23072 + hc_intr_mask.b.ahberr = 1;
23073 + else {
23074 + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23075 + hc_intr_mask.b.xfercompl = 1;
23076 + }
23077 +
23078 + if (hc->error_state && !hc->do_split &&
23079 + hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
23080 + hc_intr_mask.b.ack = 1;
23081 + if (hc->ep_is_in) {
23082 + hc_intr_mask.b.datatglerr = 1;
23083 + if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23084 + hc_intr_mask.b.nak = 1;
23085 + }
23086 + }
23087 + }
23088 + } else {
23089 + switch (hc->ep_type) {
23090 + case DWC_OTG_EP_TYPE_CONTROL:
23091 + case DWC_OTG_EP_TYPE_BULK:
23092 + hc_intr_mask.b.xfercompl = 1;
23093 + hc_intr_mask.b.stall = 1;
23094 + hc_intr_mask.b.xacterr = 1;
23095 + hc_intr_mask.b.datatglerr = 1;
23096 + if (hc->ep_is_in) {
23097 + hc_intr_mask.b.bblerr = 1;
23098 + } else {
23099 + hc_intr_mask.b.nak = 1;
23100 + hc_intr_mask.b.nyet = 1;
23101 + if (hc->do_ping) {
23102 + hc_intr_mask.b.ack = 1;
23103 + }
23104 + }
23105 +
23106 + if (hc->do_split) {
23107 + hc_intr_mask.b.nak = 1;
23108 + if (hc->complete_split) {
23109 + hc_intr_mask.b.nyet = 1;
23110 + } else {
23111 + hc_intr_mask.b.ack = 1;
23112 + }
23113 + }
23114 +
23115 + if (hc->error_state) {
23116 + hc_intr_mask.b.ack = 1;
23117 + }
23118 + break;
23119 + case DWC_OTG_EP_TYPE_INTR:
23120 + hc_intr_mask.b.xfercompl = 1;
23121 + hc_intr_mask.b.nak = 1;
23122 + hc_intr_mask.b.stall = 1;
23123 + hc_intr_mask.b.xacterr = 1;
23124 + hc_intr_mask.b.datatglerr = 1;
23125 + hc_intr_mask.b.frmovrun = 1;
23126 +
23127 + if (hc->ep_is_in) {
23128 + hc_intr_mask.b.bblerr = 1;
23129 + }
23130 + if (hc->error_state) {
23131 + hc_intr_mask.b.ack = 1;
23132 + }
23133 + if (hc->do_split) {
23134 + if (hc->complete_split) {
23135 + hc_intr_mask.b.nyet = 1;
23136 + } else {
23137 + hc_intr_mask.b.ack = 1;
23138 + }
23139 + }
23140 + break;
23141 + case DWC_OTG_EP_TYPE_ISOC:
23142 + hc_intr_mask.b.xfercompl = 1;
23143 + hc_intr_mask.b.frmovrun = 1;
23144 + hc_intr_mask.b.ack = 1;
23145 +
23146 + if (hc->ep_is_in) {
23147 + hc_intr_mask.b.xacterr = 1;
23148 + hc_intr_mask.b.bblerr = 1;
23149 + }
23150 + break;
23151 + }
23152 + }
23153 + DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
23154 +
23155 + /* Enable the top level host channel interrupt. */
23156 + intr_enable = (1 << hc_num);
23157 + DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
23158 +
23159 + /* Make sure host channel interrupts are enabled. */
23160 + gintmsk.b.hcintr = 1;
23161 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
23162 +
23163 + /*
23164 + * Program the HCCHARn register with the endpoint characteristics for
23165 + * the current transfer.
23166 + */
23167 + hcchar.d32 = 0;
23168 + hcchar.b.devaddr = hc->dev_addr;
23169 + hcchar.b.epnum = hc->ep_num;
23170 + hcchar.b.epdir = hc->ep_is_in;
23171 + hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
23172 + hcchar.b.eptype = hc->ep_type;
23173 + hcchar.b.mps = hc->max_packet;
23174 +
23175 + DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
23176 +
23177 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",
23178 + __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);
23179 + DWC_DEBUGPL(DBG_HCDV, " Is In %d, Is Low Speed %d, EP Type %d, "
23180 + "Max Pkt %d, Multi Cnt %d\n",
23181 + hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,
23182 + hcchar.b.mps, hcchar.b.multicnt);
23183 +
23184 + /*
23185 + * Program the HCSPLIT register for SPLITs
23186 + */
23187 + hcsplt.d32 = 0;
23188 + if (hc->do_split) {
23189 + DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
23190 + hc->hc_num,
23191 + hc->complete_split ? "CSPLIT" : "SSPLIT");
23192 + hcsplt.b.compsplt = hc->complete_split;
23193 + hcsplt.b.xactpos = hc->xact_pos;
23194 + hcsplt.b.hubaddr = hc->hub_addr;
23195 + hcsplt.b.prtaddr = hc->port_addr;
23196 + DWC_DEBUGPL(DBG_HCDV, "\t comp split %d\n", hc->complete_split);
23197 + DWC_DEBUGPL(DBG_HCDV, "\t xact pos %d\n", hc->xact_pos);
23198 + DWC_DEBUGPL(DBG_HCDV, "\t hub addr %d\n", hc->hub_addr);
23199 + DWC_DEBUGPL(DBG_HCDV, "\t port addr %d\n", hc->port_addr);
23200 + DWC_DEBUGPL(DBG_HCDV, "\t is_in %d\n", hc->ep_is_in);
23201 + DWC_DEBUGPL(DBG_HCDV, "\t Max Pkt: %d\n", hcchar.b.mps);
23202 + DWC_DEBUGPL(DBG_HCDV, "\t xferlen: %d\n", hc->xfer_len);
23203 + }
23204 + DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
23205 +
23206 +}
23207 +
23208 +/**
23209 + * Attempts to halt a host channel. This function should only be called in
23210 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
23211 + * normal circumstances in DMA mode, the controller halts the channel when the
23212 + * transfer is complete or a condition occurs that requires application
23213 + * intervention.
23214 + *
23215 + * In slave mode, checks for a free request queue entry, then sets the Channel
23216 + * Enable and Channel Disable bits of the Host Channel Characteristics
23217 + * register of the specified channel to intiate the halt. If there is no free
23218 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
23219 + * register to flush requests for this channel. In the latter case, sets a
23220 + * flag to indicate that the host channel needs to be halted when a request
23221 + * queue slot is open.
23222 + *
23223 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
23224 + * HCCHARn register. The controller ensures there is space in the request
23225 + * queue before submitting the halt request.
23226 + *
23227 + * Some time may elapse before the core flushes any posted requests for this
23228 + * host channel and halts. The Channel Halted interrupt handler completes the
23229 + * deactivation of the host channel.
23230 + *
23231 + * @param core_if Controller register interface.
23232 + * @param hc Host channel to halt.
23233 + * @param halt_status Reason for halting the channel.
23234 + */
23235 +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
23236 + dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
23237 +{
23238 + gnptxsts_data_t nptxsts;
23239 + hptxsts_data_t hptxsts;
23240 + hcchar_data_t hcchar;
23241 + dwc_otg_hc_regs_t *hc_regs;
23242 + dwc_otg_core_global_regs_t *global_regs;
23243 + dwc_otg_host_global_regs_t *host_global_regs;
23244 +
23245 + hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23246 + global_regs = core_if->core_global_regs;
23247 + host_global_regs = core_if->host_if->host_global_regs;
23248 +
23249 + DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
23250 + "halt_status = %d\n", halt_status);
23251 +
23252 + if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
23253 + halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
23254 + /*
23255 + * Disable all channel interrupts except Ch Halted. The QTD
23256 + * and QH state associated with this transfer has been cleared
23257 + * (in the case of URB_DEQUEUE), so the channel needs to be
23258 + * shut down carefully to prevent crashes.
23259 + */
23260 + hcintmsk_data_t hcintmsk;
23261 + hcintmsk.d32 = 0;
23262 + hcintmsk.b.chhltd = 1;
23263 + DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);
23264 +
23265 + /*
23266 + * Make sure no other interrupts besides halt are currently
23267 + * pending. Handling another interrupt could cause a crash due
23268 + * to the QTD and QH state.
23269 + */
23270 + DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);
23271 +
23272 + /*
23273 + * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
23274 + * even if the channel was already halted for some other
23275 + * reason.
23276 + */
23277 + hc->halt_status = halt_status;
23278 +
23279 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23280 + if (hcchar.b.chen == 0) {
23281 + /*
23282 + * The channel is either already halted or it hasn't
23283 + * started yet. In DMA mode, the transfer may halt if
23284 + * it finishes normally or a condition occurs that
23285 + * requires driver intervention. Don't want to halt
23286 + * the channel again. In either Slave or DMA mode,
23287 + * it's possible that the transfer has been assigned
23288 + * to a channel, but not started yet when an URB is
23289 + * dequeued. Don't want to halt a channel that hasn't
23290 + * started yet.
23291 + */
23292 + return;
23293 + }
23294 + }
23295 + if (hc->halt_pending) {
23296 + /*
23297 + * A halt has already been issued for this channel. This might
23298 + * happen when a transfer is aborted by a higher level in
23299 + * the stack.
23300 + */
23301 +#ifdef DEBUG
23302 + DWC_PRINTF
23303 + ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
23304 + __func__, hc->hc_num);
23305 +
23306 +#endif
23307 + return;
23308 + }
23309 +
23310 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23311 +
23312 + /* No need to set the bit in DDMA for disabling the channel */
23313 + //TODO check it everywhere channel is disabled
23314 + if (!core_if->core_params->dma_desc_enable)
23315 + hcchar.b.chen = 1;
23316 + hcchar.b.chdis = 1;
23317 +
23318 + if (!core_if->dma_enable) {
23319 + /* Check for space in the request queue to issue the halt. */
23320 + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
23321 + hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
23322 + nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
23323 + if (nptxsts.b.nptxqspcavail == 0) {
23324 + hcchar.b.chen = 0;
23325 + }
23326 + } else {
23327 + hptxsts.d32 =
23328 + DWC_READ_REG32(&host_global_regs->hptxsts);
23329 + if ((hptxsts.b.ptxqspcavail == 0)
23330 + || (core_if->queuing_high_bandwidth)) {
23331 + hcchar.b.chen = 0;
23332 + }
23333 + }
23334 + }
23335 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23336 +
23337 + hc->halt_status = halt_status;
23338 +
23339 + if (hcchar.b.chen) {
23340 + hc->halt_pending = 1;
23341 + hc->halt_on_queue = 0;
23342 + } else {
23343 + hc->halt_on_queue = 1;
23344 + }
23345 +
23346 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23347 + DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32);
23348 + DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending);
23349 + DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue);
23350 + DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status);
23351 +
23352 + return;
23353 +}
23354 +
23355 +/**
23356 + * Clears the transfer state for a host channel. This function is normally
23357 + * called after a transfer is done and the host channel is being released.
23358 + *
23359 + * @param core_if Programming view of DWC_otg controller.
23360 + * @param hc Identifies the host channel to clean up.
23361 + */
23362 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23363 +{
23364 + dwc_otg_hc_regs_t *hc_regs;
23365 +
23366 + hc->xfer_started = 0;
23367 +
23368 + /*
23369 + * Clear channel interrupt enables and any unhandled channel interrupt
23370 + * conditions.
23371 + */
23372 + hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23373 + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);
23374 + DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);
23375 +#ifdef DEBUG
23376 + DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
23377 +#endif
23378 +}
23379 +
23380 +/**
23381 + * Sets the channel property that indicates in which frame a periodic transfer
23382 + * should occur. This is always set to the _next_ frame. This function has no
23383 + * effect on non-periodic transfers.
23384 + *
23385 + * @param core_if Programming view of DWC_otg controller.
23386 + * @param hc Identifies the host channel to set up and its properties.
23387 + * @param hcchar Current value of the HCCHAR register for the specified host
23388 + * channel.
23389 + */
23390 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
23391 + dwc_hc_t * hc, hcchar_data_t * hcchar)
23392 +{
23393 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23394 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23395 + hfnum_data_t hfnum;
23396 + hfnum.d32 =
23397 + DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);
23398 +
23399 + /* 1 if _next_ frame is odd, 0 if it's even */
23400 + hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
23401 +#ifdef DEBUG
23402 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
23403 + && !hc->complete_split) {
23404 + switch (hfnum.b.frnum & 0x7) {
23405 + case 7:
23406 + core_if->hfnum_7_samples++;
23407 + core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
23408 + break;
23409 + case 0:
23410 + core_if->hfnum_0_samples++;
23411 + core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
23412 + break;
23413 + default:
23414 + core_if->hfnum_other_samples++;
23415 + core_if->hfnum_other_frrem_accum +=
23416 + hfnum.b.frrem;
23417 + break;
23418 + }
23419 + }
23420 +#endif
23421 + }
23422 +}
23423 +
23424 +#ifdef DEBUG
23425 +void hc_xfer_timeout(void *ptr)
23426 +{
23427 + hc_xfer_info_t *xfer_info = NULL;
23428 + int hc_num = 0;
23429 +
23430 + if (ptr)
23431 + xfer_info = (hc_xfer_info_t *) ptr;
23432 +
23433 + if (!xfer_info->hc) {
23434 + DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);
23435 + return;
23436 + }
23437 +
23438 + hc_num = xfer_info->hc->hc_num;
23439 + DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
23440 + DWC_WARN(" start_hcchar_val 0x%08x\n",
23441 + xfer_info->core_if->start_hcchar_val[hc_num]);
23442 +}
23443 +#endif
23444 +
23445 +void ep_xfer_timeout(void *ptr)
23446 +{
23447 + ep_xfer_info_t *xfer_info = NULL;
23448 + int ep_num = 0;
23449 + dctl_data_t dctl = {.d32 = 0 };
23450 + gintsts_data_t gintsts = {.d32 = 0 };
23451 + gintmsk_data_t gintmsk = {.d32 = 0 };
23452 +
23453 + if (ptr)
23454 + xfer_info = (ep_xfer_info_t *) ptr;
23455 +
23456 + if (!xfer_info->ep) {
23457 + DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);
23458 + return;
23459 + }
23460 +
23461 + ep_num = xfer_info->ep->num;
23462 + DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);
23463 + /* Put the sate to 2 as it was time outed */
23464 + xfer_info->state = 2;
23465 +
23466 + dctl.d32 =
23467 + DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);
23468 + gintsts.d32 =
23469 + DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);
23470 + gintmsk.d32 =
23471 + DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);
23472 +
23473 + if (!gintmsk.b.goutnakeff) {
23474 + /* Unmask it */
23475 + gintmsk.b.goutnakeff = 1;
23476 + DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,
23477 + gintmsk.d32);
23478 +
23479 + }
23480 +
23481 + if (!gintsts.b.goutnakeff) {
23482 + dctl.b.sgoutnak = 1;
23483 + }
23484 + DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,
23485 + dctl.d32);
23486 +
23487 +}
23488 +
23489 +void set_pid_isoc(dwc_hc_t * hc)
23490 +{
23491 + /* Set up the initial PID for the transfer. */
23492 + if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
23493 + if (hc->ep_is_in) {
23494 + if (hc->multi_count == 1) {
23495 + hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23496 + } else if (hc->multi_count == 2) {
23497 + hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
23498 + } else {
23499 + hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
23500 + }
23501 + } else {
23502 + if (hc->multi_count == 1) {
23503 + hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23504 + } else {
23505 + hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
23506 + }
23507 + }
23508 + } else {
23509 + hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23510 + }
23511 +}
23512 +
23513 +/**
23514 + * This function does the setup for a data transfer for a host channel and
23515 + * starts the transfer. May be called in either Slave mode or DMA mode. In
23516 + * Slave mode, the caller must ensure that there is sufficient space in the
23517 + * request queue and Tx Data FIFO.
23518 + *
23519 + * For an OUT transfer in Slave mode, it loads a data packet into the
23520 + * appropriate FIFO. If necessary, additional data packets will be loaded in
23521 + * the Host ISR.
23522 + *
23523 + * For an IN transfer in Slave mode, a data packet is requested. The data
23524 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
23525 + * additional data packets are requested in the Host ISR.
23526 + *
23527 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
23528 + * register along with a packet count of 1 and the channel is enabled. This
23529 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
23530 + * simply set to 0 since no data transfer occurs in this case.
23531 + *
23532 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
23533 + * all the information required to perform the subsequent data transfer. In
23534 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
23535 + * controller performs the entire PING protocol, then starts the data
23536 + * transfer.
23537 + *
23538 + * @param core_if Programming view of DWC_otg controller.
23539 + * @param hc Information needed to initialize the host channel. The xfer_len
23540 + * value may be reduced to accommodate the max widths of the XferSize and
23541 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
23542 + * to reflect the final xfer_len value.
23543 + */
23544 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23545 +{
23546 + hcchar_data_t hcchar;
23547 + hctsiz_data_t hctsiz;
23548 + uint16_t num_packets;
23549 + uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
23550 + uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
23551 + dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23552 +
23553 + hctsiz.d32 = 0;
23554 +
23555 + if (hc->do_ping) {
23556 + if (!core_if->dma_enable) {
23557 + dwc_otg_hc_do_ping(core_if, hc);
23558 + hc->xfer_started = 1;
23559 + return;
23560 + } else {
23561 + hctsiz.b.dopng = 1;
23562 + }
23563 + }
23564 +
23565 + if (hc->do_split) {
23566 + num_packets = 1;
23567 +
23568 + if (hc->complete_split && !hc->ep_is_in) {
23569 + /* For CSPLIT OUT Transfer, set the size to 0 so the
23570 + * core doesn't expect any data written to the FIFO */
23571 + hc->xfer_len = 0;
23572 + } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
23573 + hc->xfer_len = hc->max_packet;
23574 + } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
23575 + hc->xfer_len = 188;
23576 + }
23577 +
23578 + hctsiz.b.xfersize = hc->xfer_len;
23579 + } else {
23580 + /*
23581 + * Ensure that the transfer length and packet count will fit
23582 + * in the widths allocated for them in the HCTSIZn register.
23583 + */
23584 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23585 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23586 + /*
23587 + * Make sure the transfer size is no larger than one
23588 + * (micro)frame's worth of data. (A check was done
23589 + * when the periodic transfer was accepted to ensure
23590 + * that a (micro)frame's worth of data can be
23591 + * programmed into a channel.)
23592 + */
23593 + uint32_t max_periodic_len =
23594 + hc->multi_count * hc->max_packet;
23595 + if (hc->xfer_len > max_periodic_len) {
23596 + hc->xfer_len = max_periodic_len;
23597 + } else {
23598 + }
23599 + } else if (hc->xfer_len > max_hc_xfer_size) {
23600 + /* Make sure that xfer_len is a multiple of max packet size. */
23601 + hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
23602 + }
23603 +
23604 + if (hc->xfer_len > 0) {
23605 + num_packets =
23606 + (hc->xfer_len + hc->max_packet -
23607 + 1) / hc->max_packet;
23608 + if (num_packets > max_hc_pkt_count) {
23609 + num_packets = max_hc_pkt_count;
23610 + hc->xfer_len = num_packets * hc->max_packet;
23611 + }
23612 + } else {
23613 + /* Need 1 packet for transfer length of 0. */
23614 + num_packets = 1;
23615 + }
23616 +
23617 + if (hc->ep_is_in) {
23618 + /* Always program an integral # of max packets for IN transfers. */
23619 + hc->xfer_len = num_packets * hc->max_packet;
23620 + }
23621 +
23622 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23623 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23624 + /*
23625 + * Make sure that the multi_count field matches the
23626 + * actual transfer length.
23627 + */
23628 + hc->multi_count = num_packets;
23629 + }
23630 +
23631 + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23632 + set_pid_isoc(hc);
23633 +
23634 + hctsiz.b.xfersize = hc->xfer_len;
23635 + }
23636 +
23637 + hc->start_pkt_count = num_packets;
23638 + hctsiz.b.pktcnt = num_packets;
23639 + hctsiz.b.pid = hc->data_pid_start;
23640 + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23641 +
23642 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23643 + DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
23644 + DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt);
23645 + DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
23646 +
23647 + if (core_if->dma_enable) {
23648 + dwc_dma_t dma_addr;
23649 + if (hc->align_buff) {
23650 + dma_addr = hc->align_buff;
23651 + } else {
23652 + dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);
23653 + }
23654 + DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);
23655 + }
23656 +
23657 + /* Start the split */
23658 + if (hc->do_split) {
23659 + hcsplt_data_t hcsplt;
23660 + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
23661 + hcsplt.b.spltena = 1;
23662 + DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);
23663 + }
23664 +
23665 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23666 + hcchar.b.multicnt = hc->multi_count;
23667 + hc_set_even_odd_frame(core_if, hc, &hcchar);
23668 +#ifdef DEBUG
23669 + core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23670 + if (hcchar.b.chdis) {
23671 + DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23672 + __func__, hc->hc_num, hcchar.d32);
23673 + }
23674 +#endif
23675 +
23676 + /* Set host channel enable after all other setup is complete. */
23677 + hcchar.b.chen = 1;
23678 + hcchar.b.chdis = 0;
23679 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23680 +
23681 + hc->xfer_started = 1;
23682 + hc->requests++;
23683 +
23684 + if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
23685 + /* Load OUT packet into the appropriate Tx FIFO. */
23686 + dwc_otg_hc_write_packet(core_if, hc);
23687 + }
23688 +#ifdef DEBUG
23689 + if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23690 + DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
23691 + hc->hc_num, core_if);//GRAYG
23692 + core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23693 + core_if->hc_xfer_info[hc->hc_num].hc = hc;
23694 +
23695 + /* Start a timer for this transfer. */
23696 + DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23697 + }
23698 +#endif
23699 +}
23700 +
23701 +/**
23702 + * This function does the setup for a data transfer for a host channel
23703 + * and starts the transfer in Descriptor DMA mode.
23704 + *
23705 + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
23706 + * Sets PID and NTD values. For periodic transfers
23707 + * initializes SCHED_INFO field with micro-frame bitmap.
23708 + *
23709 + * Initializes HCDMA register with descriptor list address and CTD value
23710 + * then starts the transfer via enabling the channel.
23711 + *
23712 + * @param core_if Programming view of DWC_otg controller.
23713 + * @param hc Information needed to initialize the host channel.
23714 + */
23715 +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23716 +{
23717 + dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23718 + hcchar_data_t hcchar;
23719 + hctsiz_data_t hctsiz;
23720 + hcdma_data_t hcdma;
23721 +
23722 + hctsiz.d32 = 0;
23723 +
23724 + if (hc->do_ping)
23725 + hctsiz.b_ddma.dopng = 1;
23726 +
23727 + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23728 + set_pid_isoc(hc);
23729 +
23730 + /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
23731 + hctsiz.b_ddma.pid = hc->data_pid_start;
23732 + hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
23733 + hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */
23734 +
23735 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23736 + DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
23737 + DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd);
23738 +
23739 + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23740 +
23741 + hcdma.d32 = 0;
23742 + hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;
23743 +
23744 + /* Always start from first descriptor. */
23745 + hcdma.b.ctd = 0;
23746 + DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);
23747 +
23748 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23749 + hcchar.b.multicnt = hc->multi_count;
23750 +
23751 +#ifdef DEBUG
23752 + core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23753 + if (hcchar.b.chdis) {
23754 + DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23755 + __func__, hc->hc_num, hcchar.d32);
23756 + }
23757 +#endif
23758 +
23759 + /* Set host channel enable after all other setup is complete. */
23760 + hcchar.b.chen = 1;
23761 + hcchar.b.chdis = 0;
23762 +
23763 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23764 +
23765 + hc->xfer_started = 1;
23766 + hc->requests++;
23767 +
23768 +#ifdef DEBUG
23769 + if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)
23770 + && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
23771 + DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
23772 + hc->hc_num, core_if);//GRAYG
23773 + core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23774 + core_if->hc_xfer_info[hc->hc_num].hc = hc;
23775 + /* Start a timer for this transfer. */
23776 + DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23777 + }
23778 +#endif
23779 +
23780 +}
23781 +
23782 +/**
23783 + * This function continues a data transfer that was started by previous call
23784 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
23785 + * sufficient space in the request queue and Tx Data FIFO. This function
23786 + * should only be called in Slave mode. In DMA mode, the controller acts
23787 + * autonomously to complete transfers programmed to a host channel.
23788 + *
23789 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
23790 + * if there is any data remaining to be queued. For an IN transfer, another
23791 + * data packet is always requested. For the SETUP phase of a control transfer,
23792 + * this function does nothing.
23793 + *
23794 + * @return 1 if a new request is queued, 0 if no more requests are required
23795 + * for this transfer.
23796 + */
23797 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23798 +{
23799 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23800 +
23801 + if (hc->do_split) {
23802 + /* SPLITs always queue just once per channel */
23803 + return 0;
23804 + } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
23805 + /* SETUPs are queued only once since they can't be NAKed. */
23806 + return 0;
23807 + } else if (hc->ep_is_in) {
23808 + /*
23809 + * Always queue another request for other IN transfers. If
23810 + * back-to-back INs are issued and NAKs are received for both,
23811 + * the driver may still be processing the first NAK when the
23812 + * second NAK is received. When the interrupt handler clears
23813 + * the NAK interrupt for the first NAK, the second NAK will
23814 + * not be seen. So we can't depend on the NAK interrupt
23815 + * handler to requeue a NAKed request. Instead, IN requests
23816 + * are issued each time this function is called. When the
23817 + * transfer completes, the extra requests for the channel will
23818 + * be flushed.
23819 + */
23820 + hcchar_data_t hcchar;
23821 + dwc_otg_hc_regs_t *hc_regs =
23822 + core_if->host_if->hc_regs[hc->hc_num];
23823 +
23824 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23825 + hc_set_even_odd_frame(core_if, hc, &hcchar);
23826 + hcchar.b.chen = 1;
23827 + hcchar.b.chdis = 0;
23828 + DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n",
23829 + hcchar.d32);
23830 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23831 + hc->requests++;
23832 + return 1;
23833 + } else {
23834 + /* OUT transfers. */
23835 + if (hc->xfer_count < hc->xfer_len) {
23836 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23837 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23838 + hcchar_data_t hcchar;
23839 + dwc_otg_hc_regs_t *hc_regs;
23840 + hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23841 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23842 + hc_set_even_odd_frame(core_if, hc, &hcchar);
23843 + }
23844 +
23845 + /* Load OUT packet into the appropriate Tx FIFO. */
23846 + dwc_otg_hc_write_packet(core_if, hc);
23847 + hc->requests++;
23848 + return 1;
23849 + } else {
23850 + return 0;
23851 + }
23852 + }
23853 +}
23854 +
23855 +/**
23856 + * Starts a PING transfer. This function should only be called in Slave mode.
23857 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
23858 + */
23859 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23860 +{
23861 + hcchar_data_t hcchar;
23862 + hctsiz_data_t hctsiz;
23863 + dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23864 +
23865 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23866 +
23867 + hctsiz.d32 = 0;
23868 + hctsiz.b.dopng = 1;
23869 + hctsiz.b.pktcnt = 1;
23870 + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23871 +
23872 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23873 + hcchar.b.chen = 1;
23874 + hcchar.b.chdis = 0;
23875 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23876 +}
23877 +
23878 +/*
23879 + * This function writes a packet into the Tx FIFO associated with the Host
23880 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
23881 + * Tx FIFO is written. For a channel associated with a periodic EP, the
23882 + * periodic Tx FIFO is written. This function should only be called in Slave
23883 + * mode.
23884 + *
23885 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
23886 + * then number of bytes written to the Tx FIFO.
23887 + */
23888 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23889 +{
23890 + uint32_t i;
23891 + uint32_t remaining_count;
23892 + uint32_t byte_count;
23893 + uint32_t dword_count;
23894 +
23895 + uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
23896 + uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
23897 +
23898 + remaining_count = hc->xfer_len - hc->xfer_count;
23899 + if (remaining_count > hc->max_packet) {
23900 + byte_count = hc->max_packet;
23901 + } else {
23902 + byte_count = remaining_count;
23903 + }
23904 +
23905 + dword_count = (byte_count + 3) / 4;
23906 +
23907 + if ((((unsigned long)data_buff) & 0x3) == 0) {
23908 + /* xfer_buff is DWORD aligned. */
23909 + for (i = 0; i < dword_count; i++, data_buff++) {
23910 + DWC_WRITE_REG32(data_fifo, *data_buff);
23911 + }
23912 + } else {
23913 + /* xfer_buff is not DWORD aligned. */
23914 + for (i = 0; i < dword_count; i++, data_buff++) {
23915 + uint32_t data;
23916 + data =
23917 + (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
23918 + 16 | data_buff[3] << 24);
23919 + DWC_WRITE_REG32(data_fifo, data);
23920 + }
23921 + }
23922 +
23923 + hc->xfer_count += byte_count;
23924 + hc->xfer_buff += byte_count;
23925 +}
23926 +
23927 +/**
23928 + * Gets the current USB frame number. This is the frame number from the last
23929 + * SOF packet.
23930 + */
23931 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
23932 +{
23933 + dsts_data_t dsts;
23934 + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
23935 +
23936 + /* read current frame/microframe number from DSTS register */
23937 + return dsts.b.soffn;
23938 +}
23939 +
23940 +/**
23941 + * Calculates and gets the frame Interval value of HFIR register according PHY
23942 + * type and speed.The application can modify a value of HFIR register only after
23943 + * the Port Enable bit of the Host Port Control and Status register
23944 + * (HPRT.PrtEnaPort) has been set.
23945 +*/
23946 +
23947 +uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)
23948 +{
23949 + gusbcfg_data_t usbcfg;
23950 + hwcfg2_data_t hwcfg2;
23951 + hprt0_data_t hprt0;
23952 + int clock = 60; // default value
23953 + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
23954 + hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
23955 + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
23956 + if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
23957 + clock = 60;
23958 + if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)
23959 + clock = 48;
23960 + if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
23961 + !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
23962 + clock = 30;
23963 + if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
23964 + !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
23965 + clock = 60;
23966 + if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
23967 + !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
23968 + clock = 48;
23969 + if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)
23970 + clock = 48;
23971 + if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)
23972 + clock = 48;
23973 + if (hprt0.b.prtspd == 0)
23974 + /* High speed case */
23975 + return 125 * clock;
23976 + else
23977 + /* FS/LS case */
23978 + return 1000 * clock;
23979 +}
23980 +
23981 +/**
23982 + * This function reads a setup packet from the Rx FIFO into the destination
23983 + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
23984 + * Interrupt routine when a SETUP packet has been received in Slave mode.
23985 + *
23986 + * @param core_if Programming view of DWC_otg controller.
23987 + * @param dest Destination buffer for packet data.
23988 + */
23989 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
23990 +{
23991 + device_grxsts_data_t status;
23992 + /* Get the 8 bytes of a setup transaction data */
23993 +
23994 + /* Pop 2 DWORDS off the receive data FIFO into memory */
23995 + dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
23996 + dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
23997 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
23998 + status.d32 =
23999 + DWC_READ_REG32(&core_if->core_global_regs->grxstsp);
24000 + DWC_DEBUGPL(DBG_ANY,
24001 + "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",
24002 + status.b.epnum, status.b.bcnt, status.b.pktsts,
24003 + status.b.fn, status.b.fn);
24004 + }
24005 +}
24006 +
24007 +/**
24008 + * This function enables EP0 OUT to receive SETUP packets and configures EP0
24009 + * IN for transmitting packets. It is normally called when the
24010 + * "Enumeration Done" interrupt occurs.
24011 + *
24012 + * @param core_if Programming view of DWC_otg controller.
24013 + * @param ep The EP0 data.
24014 + */
24015 +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24016 +{
24017 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24018 + dsts_data_t dsts;
24019 + depctl_data_t diepctl;
24020 + depctl_data_t doepctl;
24021 + dctl_data_t dctl = {.d32 = 0 };
24022 +
24023 + ep->stp_rollover = 0;
24024 + /* Read the Device Status and Endpoint 0 Control registers */
24025 + dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
24026 + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
24027 + doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
24028 +
24029 + /* Set the MPS of the IN EP based on the enumeration speed */
24030 + switch (dsts.b.enumspd) {
24031 + case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
24032 + case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
24033 + case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
24034 + diepctl.b.mps = DWC_DEP0CTL_MPS_64;
24035 + break;
24036 + case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
24037 + diepctl.b.mps = DWC_DEP0CTL_MPS_8;
24038 + break;
24039 + }
24040 +
24041 + DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
24042 +
24043 + /* Enable OUT EP for receive */
24044 + if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
24045 + doepctl.b.epena = 1;
24046 + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
24047 + }
24048 +#ifdef VERBOSE
24049 + DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
24050 + DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
24051 + DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
24052 + DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
24053 +#endif
24054 + dctl.b.cgnpinnak = 1;
24055 +
24056 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
24057 + DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
24058 + DWC_READ_REG32(&dev_if->dev_global_regs->dctl));
24059 +
24060 +}
24061 +
24062 +/**
24063 + * This function activates an EP. The Device EP control register for
24064 + * the EP is configured as defined in the ep structure. Note: This
24065 + * function is not used for EP0.
24066 + *
24067 + * @param core_if Programming view of DWC_otg controller.
24068 + * @param ep The EP to activate.
24069 + */
24070 +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24071 +{
24072 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24073 + depctl_data_t depctl;
24074 + volatile uint32_t *addr;
24075 + daint_data_t daintmsk = {.d32 = 0 };
24076 + dcfg_data_t dcfg;
24077 + uint8_t i;
24078 +
24079 + DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
24080 + (ep->is_in ? "IN" : "OUT"));
24081 +
24082 +#ifdef DWC_UTE_PER_IO
24083 + ep->xiso_frame_num = 0xFFFFFFFF;
24084 + ep->xiso_active_xfers = 0;
24085 + ep->xiso_queued_xfers = 0;
24086 +#endif
24087 + /* Read DEPCTLn register */
24088 + if (ep->is_in == 1) {
24089 + addr = &dev_if->in_ep_regs[ep->num]->diepctl;
24090 + daintmsk.ep.in = 1 << ep->num;
24091 + } else {
24092 + addr = &dev_if->out_ep_regs[ep->num]->doepctl;
24093 + daintmsk.ep.out = 1 << ep->num;
24094 + }
24095 +
24096 + /* If the EP is already active don't change the EP Control
24097 + * register. */
24098 + depctl.d32 = DWC_READ_REG32(addr);
24099 + if (!depctl.b.usbactep) {
24100 + depctl.b.mps = ep->maxpacket;
24101 + depctl.b.eptype = ep->type;
24102 + depctl.b.txfnum = ep->tx_fifo_num;
24103 +
24104 + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24105 + depctl.b.setd0pid = 1; // ???
24106 + } else {
24107 + depctl.b.setd0pid = 1;
24108 + }
24109 + depctl.b.usbactep = 1;
24110 +
24111 + /* Update nextep_seq array and EPMSCNT in DCFG*/
24112 + if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP
24113 + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24114 + if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
24115 + break;
24116 + }
24117 + core_if->nextep_seq[i] = ep->num;
24118 + core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
24119 + depctl.b.nextep = core_if->nextep_seq[ep->num];
24120 + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
24121 + dcfg.b.epmscnt++;
24122 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
24123 +
24124 + DWC_DEBUGPL(DBG_PCDV,
24125 + "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24126 + __func__, core_if->first_in_nextep_seq);
24127 + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24128 + DWC_DEBUGPL(DBG_PCDV, "%2d\n",
24129 + core_if->nextep_seq[i]);
24130 + }
24131 +
24132 + }
24133 +
24134 +
24135 + DWC_WRITE_REG32(addr, depctl.d32);
24136 + DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));
24137 + }
24138 +
24139 + /* Enable the Interrupt for this EP */
24140 + if (core_if->multiproc_int_enable) {
24141 + if (ep->is_in == 1) {
24142 + diepmsk_data_t diepmsk = {.d32 = 0 };
24143 + diepmsk.b.xfercompl = 1;
24144 + diepmsk.b.timeout = 1;
24145 + diepmsk.b.epdisabled = 1;
24146 + diepmsk.b.ahberr = 1;
24147 + diepmsk.b.intknepmis = 1;
24148 + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
24149 + diepmsk.b.intknepmis = 0;
24150 + diepmsk.b.txfifoundrn = 1; //?????
24151 + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24152 + diepmsk.b.nak = 1;
24153 + }
24154 +
24155 +
24156 +
24157 +/*
24158 + if (core_if->dma_desc_enable) {
24159 + diepmsk.b.bna = 1;
24160 + }
24161 +*/
24162 +/*
24163 + if (core_if->dma_enable) {
24164 + doepmsk.b.nak = 1;
24165 + }
24166 +*/
24167 + DWC_WRITE_REG32(&dev_if->dev_global_regs->
24168 + diepeachintmsk[ep->num], diepmsk.d32);
24169 +
24170 + } else {
24171 + doepmsk_data_t doepmsk = {.d32 = 0 };
24172 + doepmsk.b.xfercompl = 1;
24173 + doepmsk.b.ahberr = 1;
24174 + doepmsk.b.epdisabled = 1;
24175 + if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24176 + doepmsk.b.outtknepdis = 1;
24177 +
24178 +/*
24179 +
24180 + if (core_if->dma_desc_enable) {
24181 + doepmsk.b.bna = 1;
24182 + }
24183 +*/
24184 +/*
24185 + doepmsk.b.babble = 1;
24186 + doepmsk.b.nyet = 1;
24187 + doepmsk.b.nak = 1;
24188 +*/
24189 + DWC_WRITE_REG32(&dev_if->dev_global_regs->
24190 + doepeachintmsk[ep->num], doepmsk.d32);
24191 + }
24192 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
24193 + 0, daintmsk.d32);
24194 + } else {
24195 + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24196 + if (ep->is_in) {
24197 + diepmsk_data_t diepmsk = {.d32 = 0 };
24198 + diepmsk.b.nak = 1;
24199 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
24200 + } else {
24201 + doepmsk_data_t doepmsk = {.d32 = 0 };
24202 + doepmsk.b.outtknepdis = 1;
24203 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
24204 + }
24205 + }
24206 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
24207 + 0, daintmsk.d32);
24208 + }
24209 +
24210 + DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
24211 + DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));
24212 +
24213 + ep->stall_clear_flag = 0;
24214 +
24215 + return;
24216 +}
24217 +
24218 +/**
24219 + * This function deactivates an EP. This is done by clearing the USB Active
24220 + * EP bit in the Device EP control register. Note: This function is not used
24221 + * for EP0. EP0 cannot be deactivated.
24222 + *
24223 + * @param core_if Programming view of DWC_otg controller.
24224 + * @param ep The EP to deactivate.
24225 + */
24226 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24227 +{
24228 + depctl_data_t depctl = {.d32 = 0 };
24229 + volatile uint32_t *addr;
24230 + daint_data_t daintmsk = {.d32 = 0 };
24231 + dcfg_data_t dcfg;
24232 + uint8_t i = 0;
24233 +
24234 +#ifdef DWC_UTE_PER_IO
24235 + ep->xiso_frame_num = 0xFFFFFFFF;
24236 + ep->xiso_active_xfers = 0;
24237 + ep->xiso_queued_xfers = 0;
24238 +#endif
24239 +
24240 + /* Read DEPCTLn register */
24241 + if (ep->is_in == 1) {
24242 + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
24243 + daintmsk.ep.in = 1 << ep->num;
24244 + } else {
24245 + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
24246 + daintmsk.ep.out = 1 << ep->num;
24247 + }
24248 +
24249 + depctl.d32 = DWC_READ_REG32(addr);
24250 +
24251 + depctl.b.usbactep = 0;
24252 +
24253 + /* Update nextep_seq array and EPMSCNT in DCFG*/
24254 + if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN
24255 + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24256 + if (core_if->nextep_seq[i] == ep->num)
24257 + break;
24258 + }
24259 + core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];
24260 + if (core_if->first_in_nextep_seq == ep->num)
24261 + core_if->first_in_nextep_seq = i;
24262 + core_if->nextep_seq[ep->num] = 0xff;
24263 + depctl.b.nextep = 0;
24264 + dcfg.d32 =
24265 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
24266 + dcfg.b.epmscnt--;
24267 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
24268 + dcfg.d32);
24269 +
24270 + DWC_DEBUGPL(DBG_PCDV,
24271 + "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24272 + __func__, core_if->first_in_nextep_seq);
24273 + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24274 + DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
24275 + }
24276 + }
24277 +
24278 + if (ep->is_in == 1)
24279 + depctl.b.txfnum = 0;
24280 +
24281 + if (core_if->dma_desc_enable)
24282 + depctl.b.epdis = 1;
24283 +
24284 + DWC_WRITE_REG32(addr, depctl.d32);
24285 + depctl.d32 = DWC_READ_REG32(addr);
24286 + if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC
24287 + && depctl.b.epena) {
24288 + depctl_data_t depctl = {.d32 = 0};
24289 + if (ep->is_in) {
24290 + diepint_data_t diepint = {.d32 = 0};
24291 +
24292 + depctl.b.snak = 1;
24293 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24294 + diepctl, depctl.d32);
24295 + do {
24296 + dwc_udelay(10);
24297 + diepint.d32 =
24298 + DWC_READ_REG32(&core_if->
24299 + dev_if->in_ep_regs[ep->num]->
24300 + diepint);
24301 + } while (!diepint.b.inepnakeff);
24302 + diepint.b.inepnakeff = 1;
24303 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24304 + diepint, diepint.d32);
24305 + depctl.d32 = 0;
24306 + depctl.b.epdis = 1;
24307 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24308 + diepctl, depctl.d32);
24309 + do {
24310 + dwc_udelay(10);
24311 + diepint.d32 =
24312 + DWC_READ_REG32(&core_if->
24313 + dev_if->in_ep_regs[ep->num]->
24314 + diepint);
24315 + } while (!diepint.b.epdisabled);
24316 + diepint.b.epdisabled = 1;
24317 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24318 + diepint, diepint.d32);
24319 + } else {
24320 + dctl_data_t dctl = {.d32 = 0};
24321 + gintmsk_data_t gintsts = {.d32 = 0};
24322 + doepint_data_t doepint = {.d32 = 0};
24323 + dctl.b.sgoutnak = 1;
24324 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
24325 + dctl, 0, dctl.d32);
24326 + do {
24327 + dwc_udelay(10);
24328 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
24329 + } while (!gintsts.b.goutnakeff);
24330 + gintsts.d32 = 0;
24331 + gintsts.b.goutnakeff = 1;
24332 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
24333 +
24334 + depctl.d32 = 0;
24335 + depctl.b.epdis = 1;
24336 + depctl.b.snak = 1;
24337 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
24338 + do
24339 + {
24340 + dwc_udelay(10);
24341 + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
24342 + out_ep_regs[ep->num]->doepint);
24343 + } while (!doepint.b.epdisabled);
24344 +
24345 + doepint.b.epdisabled = 1;
24346 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
24347 +
24348 + dctl.d32 = 0;
24349 + dctl.b.cgoutnak = 1;
24350 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
24351 + }
24352 + }
24353 +
24354 + /* Disable the Interrupt for this EP */
24355 + if (core_if->multiproc_int_enable) {
24356 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
24357 + daintmsk.d32, 0);
24358 +
24359 + if (ep->is_in == 1) {
24360 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24361 + diepeachintmsk[ep->num], 0);
24362 + } else {
24363 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24364 + doepeachintmsk[ep->num], 0);
24365 + }
24366 + } else {
24367 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,
24368 + daintmsk.d32, 0);
24369 + }
24370 +
24371 +}
24372 +
24373 +/**
24374 + * This function initializes dma descriptor chain.
24375 + *
24376 + * @param core_if Programming view of DWC_otg controller.
24377 + * @param ep The EP to start the transfer on.
24378 + */
24379 +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24380 +{
24381 + dwc_otg_dev_dma_desc_t *dma_desc;
24382 + uint32_t offset;
24383 + uint32_t xfer_est;
24384 + int i;
24385 + unsigned maxxfer_local, total_len;
24386 +
24387 + if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&
24388 + (ep->maxpacket%4)) {
24389 + maxxfer_local = ep->maxpacket;
24390 + total_len = ep->xfer_len;
24391 + } else {
24392 + maxxfer_local = ep->maxxfer;
24393 + total_len = ep->total_len;
24394 + }
24395 +
24396 + ep->desc_cnt = (total_len / maxxfer_local) +
24397 + ((total_len % maxxfer_local) ? 1 : 0);
24398 +
24399 + if (!ep->desc_cnt)
24400 + ep->desc_cnt = 1;
24401 +
24402 + if (ep->desc_cnt > MAX_DMA_DESC_CNT)
24403 + ep->desc_cnt = MAX_DMA_DESC_CNT;
24404 +
24405 + dma_desc = ep->desc_addr;
24406 + if (maxxfer_local == ep->maxpacket) {
24407 + if ((total_len % maxxfer_local) &&
24408 + (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
24409 + xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
24410 + (total_len % maxxfer_local);
24411 + } else
24412 + xfer_est = ep->desc_cnt * maxxfer_local;
24413 + } else
24414 + xfer_est = total_len;
24415 + offset = 0;
24416 + for (i = 0; i < ep->desc_cnt; ++i) {
24417 + /** DMA Descriptor Setup */
24418 + if (xfer_est > maxxfer_local) {
24419 + dma_desc->status.b.bs = BS_HOST_BUSY;
24420 + dma_desc->status.b.l = 0;
24421 + dma_desc->status.b.ioc = 0;
24422 + dma_desc->status.b.sp = 0;
24423 + dma_desc->status.b.bytes = maxxfer_local;
24424 + dma_desc->buf = ep->dma_addr + offset;
24425 + dma_desc->status.b.sts = 0;
24426 + dma_desc->status.b.bs = BS_HOST_READY;
24427 +
24428 + xfer_est -= maxxfer_local;
24429 + offset += maxxfer_local;
24430 + } else {
24431 + dma_desc->status.b.bs = BS_HOST_BUSY;
24432 + dma_desc->status.b.l = 1;
24433 + dma_desc->status.b.ioc = 1;
24434 + if (ep->is_in) {
24435 + dma_desc->status.b.sp =
24436 + (xfer_est %
24437 + ep->maxpacket) ? 1 : ((ep->
24438 + sent_zlp) ? 1 : 0);
24439 + dma_desc->status.b.bytes = xfer_est;
24440 + } else {
24441 + if (maxxfer_local == ep->maxpacket)
24442 + dma_desc->status.b.bytes = xfer_est;
24443 + else
24444 + dma_desc->status.b.bytes =
24445 + xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
24446 + }
24447 +
24448 + dma_desc->buf = ep->dma_addr + offset;
24449 + dma_desc->status.b.sts = 0;
24450 + dma_desc->status.b.bs = BS_HOST_READY;
24451 + }
24452 + dma_desc++;
24453 + }
24454 +}
24455 +/**
24456 + * This function is called when to write ISOC data into appropriate dedicated
24457 + * periodic FIFO.
24458 + */
24459 +static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
24460 +{
24461 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24462 + dwc_otg_dev_in_ep_regs_t *ep_regs;
24463 + dtxfsts_data_t txstatus = {.d32 = 0 };
24464 + uint32_t len = 0;
24465 + int epnum = dwc_ep->num;
24466 + int dwords;
24467 +
24468 + DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
24469 +
24470 + ep_regs = core_if->dev_if->in_ep_regs[epnum];
24471 +
24472 + len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24473 +
24474 + if (len > dwc_ep->maxpacket) {
24475 + len = dwc_ep->maxpacket;
24476 + }
24477 +
24478 + dwords = (len + 3) / 4;
24479 +
24480 + /* While there is space in the queue and space in the FIFO and
24481 + * More data to tranfer, Write packets to the Tx FIFO */
24482 + txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24483 + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
24484 +
24485 + while (txstatus.b.txfspcavail > dwords &&
24486 + dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {
24487 + /* Write the FIFO */
24488 + dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
24489 +
24490 + len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24491 + if (len > dwc_ep->maxpacket) {
24492 + len = dwc_ep->maxpacket;
24493 + }
24494 +
24495 + dwords = (len + 3) / 4;
24496 + txstatus.d32 =
24497 + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24498 + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
24499 + txstatus.d32);
24500 + }
24501 +
24502 + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
24503 + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
24504 +
24505 + return 1;
24506 +}
24507 +/**
24508 + * This function does the setup for a data transfer for an EP and
24509 + * starts the transfer. For an IN transfer, the packets will be
24510 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
24511 + * the packets are unloaded from the Rx FIFO in the ISR. the ISR.
24512 + *
24513 + * @param core_if Programming view of DWC_otg controller.
24514 + * @param ep The EP to start the transfer on.
24515 + */
24516 +
24517 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24518 +{
24519 + depctl_data_t depctl;
24520 + deptsiz_data_t deptsiz;
24521 + gintmsk_data_t intr_mask = {.d32 = 0 };
24522 +
24523 + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24524 + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
24525 + "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
24526 + ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
24527 + ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
24528 + ep->total_len);
24529 + /* IN endpoint */
24530 + if (ep->is_in == 1) {
24531 + dwc_otg_dev_in_ep_regs_t *in_regs =
24532 + core_if->dev_if->in_ep_regs[ep->num];
24533 +
24534 + gnptxsts_data_t gtxstatus;
24535 +
24536 + gtxstatus.d32 =
24537 + DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
24538 +
24539 + if (core_if->en_multiple_tx_fifo == 0
24540 + && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {
24541 +#ifdef DEBUG
24542 + DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
24543 +#endif
24544 + return;
24545 + }
24546 +
24547 + depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
24548 + deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
24549 +
24550 + if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24551 + ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24552 + ep->maxxfer : (ep->total_len - ep->xfer_len);
24553 + else
24554 + ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
24555 + MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24556 +
24557 +
24558 + /* Zero Length Packet? */
24559 + if ((ep->xfer_len - ep->xfer_count) == 0) {
24560 + deptsiz.b.xfersize = 0;
24561 + deptsiz.b.pktcnt = 1;
24562 + } else {
24563 + /* Program the transfer size and packet count
24564 + * as follows: xfersize = N * maxpacket +
24565 + * short_packet pktcnt = N + (short_packet
24566 + * exist ? 1 : 0)
24567 + */
24568 + deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24569 + deptsiz.b.pktcnt =
24570 + (ep->xfer_len - ep->xfer_count - 1 +
24571 + ep->maxpacket) / ep->maxpacket;
24572 + if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24573 + deptsiz.b.pktcnt = MAX_PKT_CNT;
24574 + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
24575 + }
24576 + if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24577 + deptsiz.b.mc = deptsiz.b.pktcnt;
24578 + }
24579 +
24580 + /* Write the DMA register */
24581 + if (core_if->dma_enable) {
24582 + if (core_if->dma_desc_enable == 0) {
24583 + if (ep->type != DWC_OTG_EP_TYPE_ISOC)
24584 + deptsiz.b.mc = 1;
24585 + DWC_WRITE_REG32(&in_regs->dieptsiz,
24586 + deptsiz.d32);
24587 + DWC_WRITE_REG32(&(in_regs->diepdma),
24588 + (uint32_t) ep->dma_addr);
24589 + } else {
24590 +#ifdef DWC_UTE_CFI
24591 + /* The descriptor chain should be already initialized by now */
24592 + if (ep->buff_mode != BM_STANDARD) {
24593 + DWC_WRITE_REG32(&in_regs->diepdma,
24594 + ep->descs_dma_addr);
24595 + } else {
24596 +#endif
24597 + init_dma_desc_chain(core_if, ep);
24598 + /** DIEPDMAn Register write */
24599 + DWC_WRITE_REG32(&in_regs->diepdma,
24600 + ep->dma_desc_addr);
24601 +#ifdef DWC_UTE_CFI
24602 + }
24603 +#endif
24604 + }
24605 + } else {
24606 + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
24607 + if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
24608 + /**
24609 + * Enable the Non-Periodic Tx FIFO empty interrupt,
24610 + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
24611 + * the data will be written into the fifo by the ISR.
24612 + */
24613 + if (core_if->en_multiple_tx_fifo == 0) {
24614 + intr_mask.b.nptxfempty = 1;
24615 + DWC_MODIFY_REG32
24616 + (&core_if->core_global_regs->gintmsk,
24617 + intr_mask.d32, intr_mask.d32);
24618 + } else {
24619 + /* Enable the Tx FIFO Empty Interrupt for this EP */
24620 + if (ep->xfer_len > 0) {
24621 + uint32_t fifoemptymsk = 0;
24622 + fifoemptymsk = 1 << ep->num;
24623 + DWC_MODIFY_REG32
24624 + (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
24625 + 0, fifoemptymsk);
24626 +
24627 + }
24628 + }
24629 + } else {
24630 + write_isoc_tx_fifo(core_if, ep);
24631 + }
24632 + }
24633 + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
24634 + depctl.b.nextep = core_if->nextep_seq[ep->num];
24635 +
24636 + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24637 + dsts_data_t dsts = {.d32 = 0};
24638 + if (ep->bInterval == 1) {
24639 + dsts.d32 =
24640 + DWC_READ_REG32(&core_if->dev_if->
24641 + dev_global_regs->dsts);
24642 + ep->frame_num = dsts.b.soffn + ep->bInterval;
24643 + if (ep->frame_num > 0x3FFF) {
24644 + ep->frm_overrun = 1;
24645 + ep->frame_num &= 0x3FFF;
24646 + } else
24647 + ep->frm_overrun = 0;
24648 + if (ep->frame_num & 0x1) {
24649 + depctl.b.setd1pid = 1;
24650 + } else {
24651 + depctl.b.setd0pid = 1;
24652 + }
24653 + }
24654 + }
24655 + /* EP enable, IN data in FIFO */
24656 + depctl.b.cnak = 1;
24657 + depctl.b.epena = 1;
24658 + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
24659 +
24660 + } else {
24661 + /* OUT endpoint */
24662 + dwc_otg_dev_out_ep_regs_t *out_regs =
24663 + core_if->dev_if->out_ep_regs[ep->num];
24664 +
24665 + depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
24666 + deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
24667 +
24668 + if (!core_if->dma_desc_enable) {
24669 + if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24670 + ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24671 + ep->maxxfer : (ep->total_len - ep->xfer_len);
24672 + else
24673 + ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len
24674 + - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24675 + }
24676 +
24677 + /* Program the transfer size and packet count as follows:
24678 + *
24679 + * pktcnt = N
24680 + * xfersize = N * maxpacket
24681 + */
24682 + if ((ep->xfer_len - ep->xfer_count) == 0) {
24683 + /* Zero Length Packet */
24684 + deptsiz.b.xfersize = ep->maxpacket;
24685 + deptsiz.b.pktcnt = 1;
24686 + } else {
24687 + deptsiz.b.pktcnt =
24688 + (ep->xfer_len - ep->xfer_count +
24689 + (ep->maxpacket - 1)) / ep->maxpacket;
24690 + if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24691 + deptsiz.b.pktcnt = MAX_PKT_CNT;
24692 + }
24693 + if (!core_if->dma_desc_enable) {
24694 + ep->xfer_len =
24695 + deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
24696 + }
24697 + deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24698 + }
24699 +
24700 + DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
24701 + ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
24702 +
24703 + if (core_if->dma_enable) {
24704 + if (!core_if->dma_desc_enable) {
24705 + DWC_WRITE_REG32(&out_regs->doeptsiz,
24706 + deptsiz.d32);
24707 +
24708 + DWC_WRITE_REG32(&(out_regs->doepdma),
24709 + (uint32_t) ep->dma_addr);
24710 + } else {
24711 +#ifdef DWC_UTE_CFI
24712 + /* The descriptor chain should be already initialized by now */
24713 + if (ep->buff_mode != BM_STANDARD) {
24714 + DWC_WRITE_REG32(&out_regs->doepdma,
24715 + ep->descs_dma_addr);
24716 + } else {
24717 +#endif
24718 + /** This is used for interrupt out transfers*/
24719 + if (!ep->xfer_len)
24720 + ep->xfer_len = ep->total_len;
24721 + init_dma_desc_chain(core_if, ep);
24722 +
24723 + if (core_if->core_params->dev_out_nak) {
24724 + if (ep->type == DWC_OTG_EP_TYPE_BULK) {
24725 + deptsiz.b.pktcnt = (ep->total_len +
24726 + (ep->maxpacket - 1)) / ep->maxpacket;
24727 + deptsiz.b.xfersize = ep->total_len;
24728 + /* Remember initial value of doeptsiz */
24729 + core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
24730 + DWC_WRITE_REG32(&out_regs->doeptsiz,
24731 + deptsiz.d32);
24732 + }
24733 + }
24734 + /** DOEPDMAn Register write */
24735 + DWC_WRITE_REG32(&out_regs->doepdma,
24736 + ep->dma_desc_addr);
24737 +#ifdef DWC_UTE_CFI
24738 + }
24739 +#endif
24740 + }
24741 + } else {
24742 + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
24743 + }
24744 +
24745 + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24746 + dsts_data_t dsts = {.d32 = 0};
24747 + if (ep->bInterval == 1) {
24748 + dsts.d32 =
24749 + DWC_READ_REG32(&core_if->dev_if->
24750 + dev_global_regs->dsts);
24751 + ep->frame_num = dsts.b.soffn + ep->bInterval;
24752 + if (ep->frame_num > 0x3FFF) {
24753 + ep->frm_overrun = 1;
24754 + ep->frame_num &= 0x3FFF;
24755 + } else
24756 + ep->frm_overrun = 0;
24757 +
24758 + if (ep->frame_num & 0x1) {
24759 + depctl.b.setd1pid = 1;
24760 + } else {
24761 + depctl.b.setd0pid = 1;
24762 + }
24763 + }
24764 + }
24765 +
24766 + /* EP enable */
24767 + depctl.b.cnak = 1;
24768 + depctl.b.epena = 1;
24769 +
24770 + DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
24771 +
24772 + DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
24773 + DWC_READ_REG32(&out_regs->doepctl),
24774 + DWC_READ_REG32(&out_regs->doeptsiz));
24775 + DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
24776 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
24777 + daintmsk),
24778 + DWC_READ_REG32(&core_if->core_global_regs->
24779 + gintmsk));
24780 +
24781 + /* Timer is scheduling only for out bulk transfers for
24782 + * "Device DDMA OUT NAK Enhancement" feature to inform user
24783 + * about received data payload in case of timeout
24784 + */
24785 + if (core_if->core_params->dev_out_nak) {
24786 + if (ep->type == DWC_OTG_EP_TYPE_BULK) {
24787 + core_if->ep_xfer_info[ep->num].core_if = core_if;
24788 + core_if->ep_xfer_info[ep->num].ep = ep;
24789 + core_if->ep_xfer_info[ep->num].state = 1;
24790 +
24791 + /* Start a timer for this transfer. */
24792 + DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);
24793 + }
24794 + }
24795 + }
24796 +}
24797 +
24798 +/**
24799 + * This function setup a zero length transfer in Buffer DMA and
24800 + * Slave modes for usb requests with zero field set
24801 + *
24802 + * @param core_if Programming view of DWC_otg controller.
24803 + * @param ep The EP to start the transfer on.
24804 + *
24805 + */
24806 +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24807 +{
24808 +
24809 + depctl_data_t depctl;
24810 + deptsiz_data_t deptsiz;
24811 + gintmsk_data_t intr_mask = {.d32 = 0 };
24812 +
24813 + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24814 + DWC_PRINTF("zero length transfer is called\n");
24815 +
24816 + /* IN endpoint */
24817 + if (ep->is_in == 1) {
24818 + dwc_otg_dev_in_ep_regs_t *in_regs =
24819 + core_if->dev_if->in_ep_regs[ep->num];
24820 +
24821 + depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
24822 + deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
24823 +
24824 + deptsiz.b.xfersize = 0;
24825 + deptsiz.b.pktcnt = 1;
24826 +
24827 + /* Write the DMA register */
24828 + if (core_if->dma_enable) {
24829 + if (core_if->dma_desc_enable == 0) {
24830 + deptsiz.b.mc = 1;
24831 + DWC_WRITE_REG32(&in_regs->dieptsiz,
24832 + deptsiz.d32);
24833 + DWC_WRITE_REG32(&(in_regs->diepdma),
24834 + (uint32_t) ep->dma_addr);
24835 + }
24836 + } else {
24837 + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
24838 + /**
24839 + * Enable the Non-Periodic Tx FIFO empty interrupt,
24840 + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
24841 + * the data will be written into the fifo by the ISR.
24842 + */
24843 + if (core_if->en_multiple_tx_fifo == 0) {
24844 + intr_mask.b.nptxfempty = 1;
24845 + DWC_MODIFY_REG32(&core_if->
24846 + core_global_regs->gintmsk,
24847 + intr_mask.d32, intr_mask.d32);
24848 + } else {
24849 + /* Enable the Tx FIFO Empty Interrupt for this EP */
24850 + if (ep->xfer_len > 0) {
24851 + uint32_t fifoemptymsk = 0;
24852 + fifoemptymsk = 1 << ep->num;
24853 + DWC_MODIFY_REG32(&core_if->
24854 + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
24855 + 0, fifoemptymsk);
24856 + }
24857 + }
24858 + }
24859 +
24860 + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
24861 + depctl.b.nextep = core_if->nextep_seq[ep->num];
24862 + /* EP enable, IN data in FIFO */
24863 + depctl.b.cnak = 1;
24864 + depctl.b.epena = 1;
24865 + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
24866 +
24867 + } else {
24868 + /* OUT endpoint */
24869 + dwc_otg_dev_out_ep_regs_t *out_regs =
24870 + core_if->dev_if->out_ep_regs[ep->num];
24871 +
24872 + depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
24873 + deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
24874 +
24875 + /* Zero Length Packet */
24876 + deptsiz.b.xfersize = ep->maxpacket;
24877 + deptsiz.b.pktcnt = 1;
24878 +
24879 + if (core_if->dma_enable) {
24880 + if (!core_if->dma_desc_enable) {
24881 + DWC_WRITE_REG32(&out_regs->doeptsiz,
24882 + deptsiz.d32);
24883 +
24884 + DWC_WRITE_REG32(&(out_regs->doepdma),
24885 + (uint32_t) ep->dma_addr);
24886 + }
24887 + } else {
24888 + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
24889 + }
24890 +
24891 + /* EP enable */
24892 + depctl.b.cnak = 1;
24893 + depctl.b.epena = 1;
24894 +
24895 + DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
24896 +
24897 + }
24898 +}
24899 +
24900 +/**
24901 + * This function does the setup for a data transfer for EP0 and starts
24902 + * the transfer. For an IN transfer, the packets will be loaded into
24903 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
24904 + * unloaded from the Rx FIFO in the ISR.
24905 + *
24906 + * @param core_if Programming view of DWC_otg controller.
24907 + * @param ep The EP0 data.
24908 + */
24909 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24910 +{
24911 + depctl_data_t depctl;
24912 + deptsiz0_data_t deptsiz;
24913 + gintmsk_data_t intr_mask = {.d32 = 0 };
24914 + dwc_otg_dev_dma_desc_t *dma_desc;
24915 +
24916 + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
24917 + "xfer_buff=%p start_xfer_buff=%p \n",
24918 + ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
24919 + ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
24920 +
24921 + ep->total_len = ep->xfer_len;
24922 +
24923 + /* IN endpoint */
24924 + if (ep->is_in == 1) {
24925 + dwc_otg_dev_in_ep_regs_t *in_regs =
24926 + core_if->dev_if->in_ep_regs[0];
24927 +
24928 + gnptxsts_data_t gtxstatus;
24929 +
24930 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
24931 + depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
24932 + if (depctl.b.epena)
24933 + return;
24934 + }
24935 +
24936 + gtxstatus.d32 =
24937 + DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
24938 +
24939 + /* If dedicated FIFO every time flush fifo before enable ep*/
24940 + if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)
24941 + dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
24942 +
24943 + if (core_if->en_multiple_tx_fifo == 0
24944 + && gtxstatus.b.nptxqspcavail == 0
24945 + && !core_if->dma_enable) {
24946 +#ifdef DEBUG
24947 + deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
24948 + DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
24949 + DWC_READ_REG32(&in_regs->diepctl));
24950 + DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
24951 + deptsiz.d32,
24952 + deptsiz.b.xfersize, deptsiz.b.pktcnt);
24953 + DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
24954 + gtxstatus.d32);
24955 +#endif
24956 + return;
24957 + }
24958 +
24959 + depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
24960 + deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
24961 +
24962 + /* Zero Length Packet? */
24963 + if (ep->xfer_len == 0) {
24964 + deptsiz.b.xfersize = 0;
24965 + deptsiz.b.pktcnt = 1;
24966 + } else {
24967 + /* Program the transfer size and packet count
24968 + * as follows: xfersize = N * maxpacket +
24969 + * short_packet pktcnt = N + (short_packet
24970 + * exist ? 1 : 0)
24971 + */
24972 + if (ep->xfer_len > ep->maxpacket) {
24973 + ep->xfer_len = ep->maxpacket;
24974 + deptsiz.b.xfersize = ep->maxpacket;
24975 + } else {
24976 + deptsiz.b.xfersize = ep->xfer_len;
24977 + }
24978 + deptsiz.b.pktcnt = 1;
24979 +
24980 + }
24981 + DWC_DEBUGPL(DBG_PCDV,
24982 + "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
24983 + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
24984 + deptsiz.d32);
24985 +
24986 + /* Write the DMA register */
24987 + if (core_if->dma_enable) {
24988 + if (core_if->dma_desc_enable == 0) {
24989 + DWC_WRITE_REG32(&in_regs->dieptsiz,
24990 + deptsiz.d32);
24991 +
24992 + DWC_WRITE_REG32(&(in_regs->diepdma),
24993 + (uint32_t) ep->dma_addr);
24994 + } else {
24995 + dma_desc = core_if->dev_if->in_desc_addr;
24996 +
24997 + /** DMA Descriptor Setup */
24998 + dma_desc->status.b.bs = BS_HOST_BUSY;
24999 + dma_desc->status.b.l = 1;
25000 + dma_desc->status.b.ioc = 1;
25001 + dma_desc->status.b.sp =
25002 + (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25003 + dma_desc->status.b.bytes = ep->xfer_len;
25004 + dma_desc->buf = ep->dma_addr;
25005 + dma_desc->status.b.sts = 0;
25006 + dma_desc->status.b.bs = BS_HOST_READY;
25007 +
25008 + /** DIEPDMA0 Register write */
25009 + DWC_WRITE_REG32(&in_regs->diepdma,
25010 + core_if->
25011 + dev_if->dma_in_desc_addr);
25012 + }
25013 + } else {
25014 + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25015 + }
25016 +
25017 + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25018 + depctl.b.nextep = core_if->nextep_seq[ep->num];
25019 + /* EP enable, IN data in FIFO */
25020 + depctl.b.cnak = 1;
25021 + depctl.b.epena = 1;
25022 + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25023 +
25024 + /**
25025 + * Enable the Non-Periodic Tx FIFO empty interrupt, the
25026 + * data will be written into the fifo by the ISR.
25027 + */
25028 + if (!core_if->dma_enable) {
25029 + if (core_if->en_multiple_tx_fifo == 0) {
25030 + intr_mask.b.nptxfempty = 1;
25031 + DWC_MODIFY_REG32(&core_if->
25032 + core_global_regs->gintmsk,
25033 + intr_mask.d32, intr_mask.d32);
25034 + } else {
25035 + /* Enable the Tx FIFO Empty Interrupt for this EP */
25036 + if (ep->xfer_len > 0) {
25037 + uint32_t fifoemptymsk = 0;
25038 + fifoemptymsk |= 1 << ep->num;
25039 + DWC_MODIFY_REG32(&core_if->
25040 + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25041 + 0, fifoemptymsk);
25042 + }
25043 + }
25044 + }
25045 + } else {
25046 + /* OUT endpoint */
25047 + dwc_otg_dev_out_ep_regs_t *out_regs =
25048 + core_if->dev_if->out_ep_regs[0];
25049 +
25050 + depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25051 + deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25052 +
25053 + /* Program the transfer size and packet count as follows:
25054 + * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
25055 + * pktcnt = N */
25056 + /* Zero Length Packet */
25057 + deptsiz.b.xfersize = ep->maxpacket;
25058 + deptsiz.b.pktcnt = 1;
25059 + if (core_if->snpsid >= OTG_CORE_REV_3_00a)
25060 + deptsiz.b.supcnt = 3;
25061 +
25062 + DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n",
25063 + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
25064 +
25065 + if (core_if->dma_enable) {
25066 + if (!core_if->dma_desc_enable) {
25067 + DWC_WRITE_REG32(&out_regs->doeptsiz,
25068 + deptsiz.d32);
25069 +
25070 + DWC_WRITE_REG32(&(out_regs->doepdma),
25071 + (uint32_t) ep->dma_addr);
25072 + } else {
25073 + dma_desc = core_if->dev_if->out_desc_addr;
25074 +
25075 + /** DMA Descriptor Setup */
25076 + dma_desc->status.b.bs = BS_HOST_BUSY;
25077 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25078 + dma_desc->status.b.mtrf = 0;
25079 + dma_desc->status.b.sr = 0;
25080 + }
25081 + dma_desc->status.b.l = 1;
25082 + dma_desc->status.b.ioc = 1;
25083 + dma_desc->status.b.bytes = ep->maxpacket;
25084 + dma_desc->buf = ep->dma_addr;
25085 + dma_desc->status.b.sts = 0;
25086 + dma_desc->status.b.bs = BS_HOST_READY;
25087 +
25088 + /** DOEPDMA0 Register write */
25089 + DWC_WRITE_REG32(&out_regs->doepdma,
25090 + core_if->dev_if->
25091 + dma_out_desc_addr);
25092 + }
25093 + } else {
25094 + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25095 + }
25096 +
25097 + /* EP enable */
25098 + depctl.b.cnak = 1;
25099 + depctl.b.epena = 1;
25100 + DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
25101 + }
25102 +}
25103 +
25104 +/**
25105 + * This function continues control IN transfers started by
25106 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
25107 + * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
25108 + * bit for the packet count.
25109 + *
25110 + * @param core_if Programming view of DWC_otg controller.
25111 + * @param ep The EP0 data.
25112 + */
25113 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25114 +{
25115 + depctl_data_t depctl;
25116 + deptsiz0_data_t deptsiz;
25117 + gintmsk_data_t intr_mask = {.d32 = 0 };
25118 + dwc_otg_dev_dma_desc_t *dma_desc;
25119 +
25120 + if (ep->is_in == 1) {
25121 + dwc_otg_dev_in_ep_regs_t *in_regs =
25122 + core_if->dev_if->in_ep_regs[0];
25123 + gnptxsts_data_t tx_status = {.d32 = 0 };
25124 +
25125 + tx_status.d32 =
25126 + DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25127 + /** @todo Should there be check for room in the Tx
25128 + * Status Queue. If not remove the code above this comment. */
25129 +
25130 + depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25131 + deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25132 +
25133 + /* Program the transfer size and packet count
25134 + * as follows: xfersize = N * maxpacket +
25135 + * short_packet pktcnt = N + (short_packet
25136 + * exist ? 1 : 0)
25137 + */
25138 +
25139 + if (core_if->dma_desc_enable == 0) {
25140 + deptsiz.b.xfersize =
25141 + (ep->total_len - ep->xfer_count) >
25142 + ep->maxpacket ? ep->maxpacket : (ep->total_len -
25143 + ep->xfer_count);
25144 + deptsiz.b.pktcnt = 1;
25145 + if (core_if->dma_enable == 0) {
25146 + ep->xfer_len += deptsiz.b.xfersize;
25147 + } else {
25148 + ep->xfer_len = deptsiz.b.xfersize;
25149 + }
25150 + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25151 + } else {
25152 + ep->xfer_len =
25153 + (ep->total_len - ep->xfer_count) >
25154 + ep->maxpacket ? ep->maxpacket : (ep->total_len -
25155 + ep->xfer_count);
25156 +
25157 + dma_desc = core_if->dev_if->in_desc_addr;
25158 +
25159 + /** DMA Descriptor Setup */
25160 + dma_desc->status.b.bs = BS_HOST_BUSY;
25161 + dma_desc->status.b.l = 1;
25162 + dma_desc->status.b.ioc = 1;
25163 + dma_desc->status.b.sp =
25164 + (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25165 + dma_desc->status.b.bytes = ep->xfer_len;
25166 + dma_desc->buf = ep->dma_addr;
25167 + dma_desc->status.b.sts = 0;
25168 + dma_desc->status.b.bs = BS_HOST_READY;
25169 +
25170 + /** DIEPDMA0 Register write */
25171 + DWC_WRITE_REG32(&in_regs->diepdma,
25172 + core_if->dev_if->dma_in_desc_addr);
25173 + }
25174 +
25175 + DWC_DEBUGPL(DBG_PCDV,
25176 + "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
25177 + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25178 + deptsiz.d32);
25179 +
25180 + /* Write the DMA register */
25181 + if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25182 + if (core_if->dma_desc_enable == 0)
25183 + DWC_WRITE_REG32(&(in_regs->diepdma),
25184 + (uint32_t) ep->dma_addr);
25185 + }
25186 + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25187 + depctl.b.nextep = core_if->nextep_seq[ep->num];
25188 + /* EP enable, IN data in FIFO */
25189 + depctl.b.cnak = 1;
25190 + depctl.b.epena = 1;
25191 + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25192 +
25193 + /**
25194 + * Enable the Non-Periodic Tx FIFO empty interrupt, the
25195 + * data will be written into the fifo by the ISR.
25196 + */
25197 + if (!core_if->dma_enable) {
25198 + if (core_if->en_multiple_tx_fifo == 0) {
25199 + /* First clear it from GINTSTS */
25200 + intr_mask.b.nptxfempty = 1;
25201 + DWC_MODIFY_REG32(&core_if->
25202 + core_global_regs->gintmsk,
25203 + intr_mask.d32, intr_mask.d32);
25204 +
25205 + } else {
25206 + /* Enable the Tx FIFO Empty Interrupt for this EP */
25207 + if (ep->xfer_len > 0) {
25208 + uint32_t fifoemptymsk = 0;
25209 + fifoemptymsk |= 1 << ep->num;
25210 + DWC_MODIFY_REG32(&core_if->
25211 + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25212 + 0, fifoemptymsk);
25213 + }
25214 + }
25215 + }
25216 + } else {
25217 + dwc_otg_dev_out_ep_regs_t *out_regs =
25218 + core_if->dev_if->out_ep_regs[0];
25219 +
25220 + depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25221 + deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25222 +
25223 + /* Program the transfer size and packet count
25224 + * as follows: xfersize = N * maxpacket +
25225 + * short_packet pktcnt = N + (short_packet
25226 + * exist ? 1 : 0)
25227 + */
25228 + deptsiz.b.xfersize = ep->maxpacket;
25229 + deptsiz.b.pktcnt = 1;
25230 +
25231 + if (core_if->dma_desc_enable == 0) {
25232 + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25233 + } else {
25234 + dma_desc = core_if->dev_if->out_desc_addr;
25235 +
25236 + /** DMA Descriptor Setup */
25237 + dma_desc->status.b.bs = BS_HOST_BUSY;
25238 + dma_desc->status.b.l = 1;
25239 + dma_desc->status.b.ioc = 1;
25240 + dma_desc->status.b.bytes = ep->maxpacket;
25241 + dma_desc->buf = ep->dma_addr;
25242 + dma_desc->status.b.sts = 0;
25243 + dma_desc->status.b.bs = BS_HOST_READY;
25244 +
25245 + /** DOEPDMA0 Register write */
25246 + DWC_WRITE_REG32(&out_regs->doepdma,
25247 + core_if->dev_if->dma_out_desc_addr);
25248 + }
25249 +
25250 + DWC_DEBUGPL(DBG_PCDV,
25251 + "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
25252 + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25253 + deptsiz.d32);
25254 +
25255 + /* Write the DMA register */
25256 + if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25257 + if (core_if->dma_desc_enable == 0)
25258 + DWC_WRITE_REG32(&(out_regs->doepdma),
25259 + (uint32_t) ep->dma_addr);
25260 +
25261 + }
25262 +
25263 + /* EP enable, IN data in FIFO */
25264 + depctl.b.cnak = 1;
25265 + depctl.b.epena = 1;
25266 + DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25267 +
25268 + }
25269 +}
25270 +
25271 +#ifdef DEBUG
25272 +void dump_msg(const u8 * buf, unsigned int length)
25273 +{
25274 + unsigned int start, num, i;
25275 + char line[52], *p;
25276 +
25277 + if (length >= 512)
25278 + return;
25279 + start = 0;
25280 + while (length > 0) {
25281 + num = length < 16u ? length : 16u;
25282 + p = line;
25283 + for (i = 0; i < num; ++i) {
25284 + if (i == 8)
25285 + *p++ = ' ';
25286 + DWC_SPRINTF(p, " %02x", buf[i]);
25287 + p += 3;
25288 + }
25289 + *p = 0;
25290 + DWC_PRINTF("%6x: %s\n", start, line);
25291 + buf += num;
25292 + start += num;
25293 + length -= num;
25294 + }
25295 +}
25296 +#else
25297 +static inline void dump_msg(const u8 * buf, unsigned int length)
25298 +{
25299 +}
25300 +#endif
25301 +
25302 +/**
25303 + * This function writes a packet into the Tx FIFO associated with the
25304 + * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For
25305 + * periodic EPs the periodic Tx FIFO associated with the EP is written
25306 + * with all packets for the next micro-frame.
25307 + *
25308 + * @param core_if Programming view of DWC_otg controller.
25309 + * @param ep The EP to write packet for.
25310 + * @param dma Indicates if DMA is being used.
25311 + */
25312 +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
25313 + int dma)
25314 +{
25315 + /**
25316 + * The buffer is padded to DWORD on a per packet basis in
25317 + * slave/dma mode if the MPS is not DWORD aligned. The last
25318 + * packet, if short, is also padded to a multiple of DWORD.
25319 + *
25320 + * ep->xfer_buff always starts DWORD aligned in memory and is a
25321 + * multiple of DWORD in length
25322 + *
25323 + * ep->xfer_len can be any number of bytes
25324 + *
25325 + * ep->xfer_count is a multiple of ep->maxpacket until the last
25326 + * packet
25327 + *
25328 + * FIFO access is DWORD */
25329 +
25330 + uint32_t i;
25331 + uint32_t byte_count;
25332 + uint32_t dword_count;
25333 + uint32_t *fifo;
25334 + uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
25335 +
25336 + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
25337 + ep);
25338 + if (ep->xfer_count >= ep->xfer_len) {
25339 + DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
25340 + return;
25341 + }
25342 +
25343 + /* Find the byte length of the packet either short packet or MPS */
25344 + if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
25345 + byte_count = ep->xfer_len - ep->xfer_count;
25346 + } else {
25347 + byte_count = ep->maxpacket;
25348 + }
25349 +
25350 + /* Find the DWORD length, padded by extra bytes as neccessary if MPS
25351 + * is not a multiple of DWORD */
25352 + dword_count = (byte_count + 3) / 4;
25353 +
25354 +#ifdef VERBOSE
25355 + dump_msg(ep->xfer_buff, byte_count);
25356 +#endif
25357 +
25358 + /**@todo NGS Where are the Periodic Tx FIFO addresses
25359 + * intialized? What should this be? */
25360 +
25361 + fifo = core_if->data_fifo[ep->num];
25362 +
25363 + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
25364 + fifo, data_buff, *data_buff, byte_count);
25365 +
25366 + if (!dma) {
25367 + for (i = 0; i < dword_count; i++, data_buff++) {
25368 + DWC_WRITE_REG32(fifo, *data_buff);
25369 + }
25370 + }
25371 +
25372 + ep->xfer_count += byte_count;
25373 + ep->xfer_buff += byte_count;
25374 + ep->dma_addr += byte_count;
25375 +}
25376 +
25377 +/**
25378 + * Set the EP STALL.
25379 + *
25380 + * @param core_if Programming view of DWC_otg controller.
25381 + * @param ep The EP to set the stall on.
25382 + */
25383 +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25384 +{
25385 + depctl_data_t depctl;
25386 + volatile uint32_t *depctl_addr;
25387 +
25388 + DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25389 + (ep->is_in ? "IN" : "OUT"));
25390 +
25391 + if (ep->is_in == 1) {
25392 + depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25393 + depctl.d32 = DWC_READ_REG32(depctl_addr);
25394 +
25395 + /* set the disable and stall bits */
25396 + if (depctl.b.epena) {
25397 + depctl.b.epdis = 1;
25398 + }
25399 + depctl.b.stall = 1;
25400 + DWC_WRITE_REG32(depctl_addr, depctl.d32);
25401 + } else {
25402 + depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25403 + depctl.d32 = DWC_READ_REG32(depctl_addr);
25404 +
25405 + /* set the stall bit */
25406 + depctl.b.stall = 1;
25407 + DWC_WRITE_REG32(depctl_addr, depctl.d32);
25408 + }
25409 +
25410 + DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25411 +
25412 + return;
25413 +}
25414 +
25415 +/**
25416 + * Clear the EP STALL.
25417 + *
25418 + * @param core_if Programming view of DWC_otg controller.
25419 + * @param ep The EP to clear stall from.
25420 + */
25421 +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25422 +{
25423 + depctl_data_t depctl;
25424 + volatile uint32_t *depctl_addr;
25425 +
25426 + DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25427 + (ep->is_in ? "IN" : "OUT"));
25428 +
25429 + if (ep->is_in == 1) {
25430 + depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25431 + } else {
25432 + depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25433 + }
25434 +
25435 + depctl.d32 = DWC_READ_REG32(depctl_addr);
25436 +
25437 + /* clear the stall bits */
25438 + depctl.b.stall = 0;
25439 +
25440 + /*
25441 + * USB Spec 9.4.5: For endpoints using data toggle, regardless
25442 + * of whether an endpoint has the Halt feature set, a
25443 + * ClearFeature(ENDPOINT_HALT) request always results in the
25444 + * data toggle being reinitialized to DATA0.
25445 + */
25446 + if (ep->type == DWC_OTG_EP_TYPE_INTR ||
25447 + ep->type == DWC_OTG_EP_TYPE_BULK) {
25448 + depctl.b.setd0pid = 1; /* DATA0 */
25449 + }
25450 +
25451 + DWC_WRITE_REG32(depctl_addr, depctl.d32);
25452 + DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25453 + return;
25454 +}
25455 +
25456 +/**
25457 + * This function reads a packet from the Rx FIFO into the destination
25458 + * buffer. To read SETUP data use dwc_otg_read_setup_packet.
25459 + *
25460 + * @param core_if Programming view of DWC_otg controller.
25461 + * @param dest Destination buffer for the packet.
25462 + * @param bytes Number of bytes to copy to the destination.
25463 + */
25464 +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
25465 + uint8_t * dest, uint16_t bytes)
25466 +{
25467 + int i;
25468 + int word_count = (bytes + 3) / 4;
25469 +
25470 + volatile uint32_t *fifo = core_if->data_fifo[0];
25471 + uint32_t *data_buff = (uint32_t *) dest;
25472 +
25473 + /**
25474 + * @todo Account for the case where _dest is not dword aligned. This
25475 + * requires reading data from the FIFO into a uint32_t temp buffer,
25476 + * then moving it into the data buffer.
25477 + */
25478 +
25479 + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
25480 + core_if, dest, bytes);
25481 +
25482 + for (i = 0; i < word_count; i++, data_buff++) {
25483 + *data_buff = DWC_READ_REG32(fifo);
25484 + }
25485 +
25486 + return;
25487 +}
25488 +
25489 +/**
25490 + * This functions reads the device registers and prints them
25491 + *
25492 + * @param core_if Programming view of DWC_otg controller.
25493 + */
25494 +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
25495 +{
25496 + int i;
25497 + volatile uint32_t *addr;
25498 +
25499 + DWC_PRINTF("Device Global Registers\n");
25500 + addr = &core_if->dev_if->dev_global_regs->dcfg;
25501 + DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n",
25502 + (unsigned long)addr, DWC_READ_REG32(addr));
25503 + addr = &core_if->dev_if->dev_global_regs->dctl;
25504 + DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n",
25505 + (unsigned long)addr, DWC_READ_REG32(addr));
25506 + addr = &core_if->dev_if->dev_global_regs->dsts;
25507 + DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n",
25508 + (unsigned long)addr, DWC_READ_REG32(addr));
25509 + addr = &core_if->dev_if->dev_global_regs->diepmsk;
25510 + DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
25511 + DWC_READ_REG32(addr));
25512 + addr = &core_if->dev_if->dev_global_regs->doepmsk;
25513 + DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
25514 + DWC_READ_REG32(addr));
25515 + addr = &core_if->dev_if->dev_global_regs->daint;
25516 + DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr,
25517 + DWC_READ_REG32(addr));
25518 + addr = &core_if->dev_if->dev_global_regs->daintmsk;
25519 + DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
25520 + DWC_READ_REG32(addr));
25521 + addr = &core_if->dev_if->dev_global_regs->dtknqr1;
25522 + DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr,
25523 + DWC_READ_REG32(addr));
25524 + if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
25525 + addr = &core_if->dev_if->dev_global_regs->dtknqr2;
25526 + DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n",
25527 + (unsigned long)addr, DWC_READ_REG32(addr));
25528 + }
25529 +
25530 + addr = &core_if->dev_if->dev_global_regs->dvbusdis;
25531 + DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr,
25532 + DWC_READ_REG32(addr));
25533 +
25534 + addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
25535 + DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n",
25536 + (unsigned long)addr, DWC_READ_REG32(addr));
25537 +
25538 + addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
25539 + DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n",
25540 + (unsigned long)addr, DWC_READ_REG32(addr));
25541 +
25542 + if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
25543 + addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25544 + DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n",
25545 + (unsigned long)addr, DWC_READ_REG32(addr));
25546 + }
25547 +
25548 + addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25549 + DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
25550 + DWC_READ_REG32(addr));
25551 +
25552 + if (core_if->hwcfg2.b.multi_proc_int) {
25553 +
25554 + addr = &core_if->dev_if->dev_global_regs->deachint;
25555 + DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n",
25556 + (unsigned long)addr, DWC_READ_REG32(addr));
25557 + addr = &core_if->dev_if->dev_global_regs->deachintmsk;
25558 + DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n",
25559 + (unsigned long)addr, DWC_READ_REG32(addr));
25560 +
25561 + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25562 + addr =
25563 + &core_if->dev_if->
25564 + dev_global_regs->diepeachintmsk[i];
25565 + DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n",
25566 + i, (unsigned long)addr,
25567 + DWC_READ_REG32(addr));
25568 + }
25569 +
25570 + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25571 + addr =
25572 + &core_if->dev_if->
25573 + dev_global_regs->doepeachintmsk[i];
25574 + DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n",
25575 + i, (unsigned long)addr,
25576 + DWC_READ_REG32(addr));
25577 + }
25578 + }
25579 +
25580 + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25581 + DWC_PRINTF("Device IN EP %d Registers\n", i);
25582 + addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
25583 + DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n",
25584 + (unsigned long)addr, DWC_READ_REG32(addr));
25585 + addr = &core_if->dev_if->in_ep_regs[i]->diepint;
25586 + DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n",
25587 + (unsigned long)addr, DWC_READ_REG32(addr));
25588 + addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
25589 + DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n",
25590 + (unsigned long)addr, DWC_READ_REG32(addr));
25591 + addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
25592 + DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n",
25593 + (unsigned long)addr, DWC_READ_REG32(addr));
25594 + addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
25595 + DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n",
25596 + (unsigned long)addr, DWC_READ_REG32(addr));
25597 + addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
25598 + DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n",
25599 + (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );
25600 + }
25601 +
25602 + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25603 + DWC_PRINTF("Device OUT EP %d Registers\n", i);
25604 + addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
25605 + DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n",
25606 + (unsigned long)addr, DWC_READ_REG32(addr));
25607 + addr = &core_if->dev_if->out_ep_regs[i]->doepint;
25608 + DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n",
25609 + (unsigned long)addr, DWC_READ_REG32(addr));
25610 + addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
25611 + DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n",
25612 + (unsigned long)addr, DWC_READ_REG32(addr));
25613 + addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
25614 + DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n",
25615 + (unsigned long)addr, DWC_READ_REG32(addr));
25616 + if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */
25617 + addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
25618 + DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n",
25619 + (unsigned long)addr, DWC_READ_REG32(addr));
25620 + }
25621 +
25622 + }
25623 +}
25624 +
25625 +/**
25626 + * This functions reads the SPRAM and prints its content
25627 + *
25628 + * @param core_if Programming view of DWC_otg controller.
25629 + */
25630 +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
25631 +{
25632 + volatile uint8_t *addr, *start_addr, *end_addr;
25633 +
25634 + DWC_PRINTF("SPRAM Data:\n");
25635 + start_addr = (void *)core_if->core_global_regs;
25636 + DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);
25637 + start_addr += 0x00028000;
25638 + end_addr = (void *)core_if->core_global_regs;
25639 + end_addr += 0x000280e0;
25640 +
25641 + for (addr = start_addr; addr < end_addr; addr += 16) {
25642 + DWC_PRINTF
25643 + ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
25644 + (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],
25645 + addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
25646 + addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
25647 + );
25648 + }
25649 +
25650 + return;
25651 +}
25652 +
25653 +/**
25654 + * This function reads the host registers and prints them
25655 + *
25656 + * @param core_if Programming view of DWC_otg controller.
25657 + */
25658 +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
25659 +{
25660 + int i;
25661 + volatile uint32_t *addr;
25662 +
25663 + DWC_PRINTF("Host Global Registers\n");
25664 + addr = &core_if->host_if->host_global_regs->hcfg;
25665 + DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n",
25666 + (unsigned long)addr, DWC_READ_REG32(addr));
25667 + addr = &core_if->host_if->host_global_regs->hfir;
25668 + DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n",
25669 + (unsigned long)addr, DWC_READ_REG32(addr));
25670 + addr = &core_if->host_if->host_global_regs->hfnum;
25671 + DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr,
25672 + DWC_READ_REG32(addr));
25673 + addr = &core_if->host_if->host_global_regs->hptxsts;
25674 + DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr,
25675 + DWC_READ_REG32(addr));
25676 + addr = &core_if->host_if->host_global_regs->haint;
25677 + DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr,
25678 + DWC_READ_REG32(addr));
25679 + addr = &core_if->host_if->host_global_regs->haintmsk;
25680 + DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
25681 + DWC_READ_REG32(addr));
25682 + if (core_if->dma_desc_enable) {
25683 + addr = &core_if->host_if->host_global_regs->hflbaddr;
25684 + DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n",
25685 + (unsigned long)addr, DWC_READ_REG32(addr));
25686 + }
25687 +
25688 + addr = core_if->host_if->hprt0;
25689 + DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr,
25690 + DWC_READ_REG32(addr));
25691 +
25692 + for (i = 0; i < core_if->core_params->host_channels; i++) {
25693 + DWC_PRINTF("Host Channel %d Specific Registers\n", i);
25694 + addr = &core_if->host_if->hc_regs[i]->hcchar;
25695 + DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n",
25696 + (unsigned long)addr, DWC_READ_REG32(addr));
25697 + addr = &core_if->host_if->hc_regs[i]->hcsplt;
25698 + DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n",
25699 + (unsigned long)addr, DWC_READ_REG32(addr));
25700 + addr = &core_if->host_if->hc_regs[i]->hcint;
25701 + DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n",
25702 + (unsigned long)addr, DWC_READ_REG32(addr));
25703 + addr = &core_if->host_if->hc_regs[i]->hcintmsk;
25704 + DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n",
25705 + (unsigned long)addr, DWC_READ_REG32(addr));
25706 + addr = &core_if->host_if->hc_regs[i]->hctsiz;
25707 + DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n",
25708 + (unsigned long)addr, DWC_READ_REG32(addr));
25709 + addr = &core_if->host_if->hc_regs[i]->hcdma;
25710 + DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n",
25711 + (unsigned long)addr, DWC_READ_REG32(addr));
25712 + if (core_if->dma_desc_enable) {
25713 + addr = &core_if->host_if->hc_regs[i]->hcdmab;
25714 + DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n",
25715 + (unsigned long)addr, DWC_READ_REG32(addr));
25716 + }
25717 +
25718 + }
25719 + return;
25720 +}
25721 +
25722 +/**
25723 + * This function reads the core global registers and prints them
25724 + *
25725 + * @param core_if Programming view of DWC_otg controller.
25726 + */
25727 +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
25728 +{
25729 + int i, ep_num;
25730 + volatile uint32_t *addr;
25731 + char *txfsiz;
25732 +
25733 + DWC_PRINTF("Core Global Registers\n");
25734 + addr = &core_if->core_global_regs->gotgctl;
25735 + DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
25736 + DWC_READ_REG32(addr));
25737 + addr = &core_if->core_global_regs->gotgint;
25738 + DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr,
25739 + DWC_READ_REG32(addr));
25740 + addr = &core_if->core_global_regs->gahbcfg;
25741 + DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
25742 + DWC_READ_REG32(addr));
25743 + addr = &core_if->core_global_regs->gusbcfg;
25744 + DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
25745 + DWC_READ_REG32(addr));
25746 + addr = &core_if->core_global_regs->grstctl;
25747 + DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
25748 + DWC_READ_REG32(addr));
25749 + addr = &core_if->core_global_regs->gintsts;
25750 + DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr,
25751 + DWC_READ_REG32(addr));
25752 + addr = &core_if->core_global_regs->gintmsk;
25753 + DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
25754 + DWC_READ_REG32(addr));
25755 + addr = &core_if->core_global_regs->grxstsr;
25756 + DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr,
25757 + DWC_READ_REG32(addr));
25758 + addr = &core_if->core_global_regs->grxfsiz;
25759 + DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
25760 + DWC_READ_REG32(addr));
25761 + addr = &core_if->core_global_regs->gnptxfsiz;
25762 + DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
25763 + DWC_READ_REG32(addr));
25764 + addr = &core_if->core_global_regs->gnptxsts;
25765 + DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr,
25766 + DWC_READ_REG32(addr));
25767 + addr = &core_if->core_global_regs->gi2cctl;
25768 + DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
25769 + DWC_READ_REG32(addr));
25770 + addr = &core_if->core_global_regs->gpvndctl;
25771 + DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
25772 + DWC_READ_REG32(addr));
25773 + addr = &core_if->core_global_regs->ggpio;
25774 + DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr,
25775 + DWC_READ_REG32(addr));
25776 + addr = &core_if->core_global_regs->guid;
25777 + DWC_PRINTF("GUID @0x%08lX : 0x%08X\n",
25778 + (unsigned long)addr, DWC_READ_REG32(addr));
25779 + addr = &core_if->core_global_regs->gsnpsid;
25780 + DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr,
25781 + DWC_READ_REG32(addr));
25782 + addr = &core_if->core_global_regs->ghwcfg1;
25783 + DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr,
25784 + DWC_READ_REG32(addr));
25785 + addr = &core_if->core_global_regs->ghwcfg2;
25786 + DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr,
25787 + DWC_READ_REG32(addr));
25788 + addr = &core_if->core_global_regs->ghwcfg3;
25789 + DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr,
25790 + DWC_READ_REG32(addr));
25791 + addr = &core_if->core_global_regs->ghwcfg4;
25792 + DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr,
25793 + DWC_READ_REG32(addr));
25794 + addr = &core_if->core_global_regs->glpmcfg;
25795 + DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
25796 + DWC_READ_REG32(addr));
25797 + addr = &core_if->core_global_regs->gpwrdn;
25798 + DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr,
25799 + DWC_READ_REG32(addr));
25800 + addr = &core_if->core_global_regs->gdfifocfg;
25801 + DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
25802 + DWC_READ_REG32(addr));
25803 + addr = &core_if->core_global_regs->adpctl;
25804 + DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
25805 + dwc_otg_adp_read_reg(core_if));
25806 + addr = &core_if->core_global_regs->hptxfsiz;
25807 + DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
25808 + DWC_READ_REG32(addr));
25809 +
25810 + if (core_if->en_multiple_tx_fifo == 0) {
25811 + ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;
25812 + txfsiz = "DPTXFSIZ";
25813 + } else {
25814 + ep_num = core_if->hwcfg4.b.num_in_eps;
25815 + txfsiz = "DIENPTXF";
25816 + }
25817 + for (i = 0; i < ep_num; i++) {
25818 + addr = &core_if->core_global_regs->dtxfsiz[i];
25819 + DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
25820 + (unsigned long)addr, DWC_READ_REG32(addr));
25821 + }
25822 + addr = core_if->pcgcctl;
25823 + DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
25824 + DWC_READ_REG32(addr));
25825 +}
25826 +
25827 +/**
25828 + * Flush a Tx FIFO.
25829 + *
25830 + * @param core_if Programming view of DWC_otg controller.
25831 + * @param num Tx FIFO to flush.
25832 + */
25833 +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
25834 +{
25835 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
25836 + volatile grstctl_t greset = {.d32 = 0 };
25837 + int count = 0;
25838 +
25839 + DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
25840 +
25841 + greset.b.txfflsh = 1;
25842 + greset.b.txfnum = num;
25843 + DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
25844 +
25845 + do {
25846 + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
25847 + if (++count > 10000) {
25848 + DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
25849 + __func__, greset.d32,
25850 + DWC_READ_REG32(&global_regs->gnptxsts));
25851 + break;
25852 + }
25853 + dwc_udelay(1);
25854 + } while (greset.b.txfflsh == 1);
25855 +
25856 + /* Wait for 3 PHY Clocks */
25857 + dwc_udelay(1);
25858 +}
25859 +
25860 +/**
25861 + * Flush Rx FIFO.
25862 + *
25863 + * @param core_if Programming view of DWC_otg controller.
25864 + */
25865 +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
25866 +{
25867 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
25868 + volatile grstctl_t greset = {.d32 = 0 };
25869 + int count = 0;
25870 +
25871 + DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
25872 + /*
25873 + *
25874 + */
25875 + greset.b.rxfflsh = 1;
25876 + DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
25877 +
25878 + do {
25879 + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
25880 + if (++count > 10000) {
25881 + DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
25882 + greset.d32);
25883 + break;
25884 + }
25885 + dwc_udelay(1);
25886 + } while (greset.b.rxfflsh == 1);
25887 +
25888 + /* Wait for 3 PHY Clocks */
25889 + dwc_udelay(1);
25890 +}
25891 +
25892 +/**
25893 + * Do core a soft reset of the core. Be careful with this because it
25894 + * resets all the internal state machines of the core.
25895 + */
25896 +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
25897 +{
25898 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
25899 + volatile grstctl_t greset = {.d32 = 0 };
25900 + int count = 0;
25901 +
25902 + DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
25903 + /* Wait for AHB master IDLE state. */
25904 + do {
25905 + dwc_udelay(10);
25906 + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
25907 + if (++count > 100000) {
25908 + DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
25909 + greset.d32);
25910 + return;
25911 + }
25912 + }
25913 + while (greset.b.ahbidle == 0);
25914 +
25915 + /* Core Soft Reset */
25916 + count = 0;
25917 + greset.b.csftrst = 1;
25918 + DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
25919 + do {
25920 + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
25921 + if (++count > 10000) {
25922 + DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
25923 + __func__, greset.d32);
25924 + break;
25925 + }
25926 + dwc_udelay(1);
25927 + }
25928 + while (greset.b.csftrst == 1);
25929 +
25930 + /* Wait for 3 PHY Clocks */
25931 + dwc_mdelay(100);
25932 +}
25933 +
25934 +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
25935 +{
25936 + return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
25937 +}
25938 +
25939 +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
25940 +{
25941 + return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
25942 +}
25943 +
25944 +/**
25945 + * Register HCD callbacks. The callbacks are used to start and stop
25946 + * the HCD for interrupt processing.
25947 + *
25948 + * @param core_if Programming view of DWC_otg controller.
25949 + * @param cb the HCD callback structure.
25950 + * @param p pointer to be passed to callback function (usb_hcd*).
25951 + */
25952 +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
25953 + dwc_otg_cil_callbacks_t * cb, void *p)
25954 +{
25955 + core_if->hcd_cb = cb;
25956 + cb->p = p;
25957 +}
25958 +
25959 +/**
25960 + * Register PCD callbacks. The callbacks are used to start and stop
25961 + * the PCD for interrupt processing.
25962 + *
25963 + * @param core_if Programming view of DWC_otg controller.
25964 + * @param cb the PCD callback structure.
25965 + * @param p pointer to be passed to callback function (pcd*).
25966 + */
25967 +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
25968 + dwc_otg_cil_callbacks_t * cb, void *p)
25969 +{
25970 + core_if->pcd_cb = cb;
25971 + cb->p = p;
25972 +}
25973 +
25974 +#ifdef DWC_EN_ISOC
25975 +
25976 +/**
25977 + * This function writes isoc data per 1 (micro)frame into tx fifo
25978 + *
25979 + * @param core_if Programming view of DWC_otg controller.
25980 + * @param ep The EP to start the transfer on.
25981 + *
25982 + */
25983 +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25984 +{
25985 + dwc_otg_dev_in_ep_regs_t *ep_regs;
25986 + dtxfsts_data_t txstatus = {.d32 = 0 };
25987 + uint32_t len = 0;
25988 + uint32_t dwords;
25989 +
25990 + ep->xfer_len = ep->data_per_frame;
25991 + ep->xfer_count = 0;
25992 +
25993 + ep_regs = core_if->dev_if->in_ep_regs[ep->num];
25994 +
25995 + len = ep->xfer_len - ep->xfer_count;
25996 +
25997 + if (len > ep->maxpacket) {
25998 + len = ep->maxpacket;
25999 + }
26000 +
26001 + dwords = (len + 3) / 4;
26002 +
26003 + /* While there is space in the queue and space in the FIFO and
26004 + * More data to tranfer, Write packets to the Tx FIFO */
26005 + txstatus.d32 =
26006 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
26007 + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
26008 +
26009 + while (txstatus.b.txfspcavail > dwords &&
26010 + ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
26011 + /* Write the FIFO */
26012 + dwc_otg_ep_write_packet(core_if, ep, 0);
26013 +
26014 + len = ep->xfer_len - ep->xfer_count;
26015 + if (len > ep->maxpacket) {
26016 + len = ep->maxpacket;
26017 + }
26018 +
26019 + dwords = (len + 3) / 4;
26020 + txstatus.d32 =
26021 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
26022 + dtxfsts);
26023 + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
26024 + txstatus.d32);
26025 + }
26026 +}
26027 +
26028 +/**
26029 + * This function initializes a descriptor chain for Isochronous transfer
26030 + *
26031 + * @param core_if Programming view of DWC_otg controller.
26032 + * @param ep The EP to start the transfer on.
26033 + *
26034 + */
26035 +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
26036 + dwc_ep_t * ep)
26037 +{
26038 + deptsiz_data_t deptsiz = {.d32 = 0 };
26039 + depctl_data_t depctl = {.d32 = 0 };
26040 + dsts_data_t dsts = {.d32 = 0 };
26041 + volatile uint32_t *addr;
26042 +
26043 + if (ep->is_in) {
26044 + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
26045 + } else {
26046 + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
26047 + }
26048 +
26049 + ep->xfer_len = ep->data_per_frame;
26050 + ep->xfer_count = 0;
26051 + ep->xfer_buff = ep->cur_pkt_addr;
26052 + ep->dma_addr = ep->cur_pkt_dma_addr;
26053 +
26054 + if (ep->is_in) {
26055 + /* Program the transfer size and packet count
26056 + * as follows: xfersize = N * maxpacket +
26057 + * short_packet pktcnt = N + (short_packet
26058 + * exist ? 1 : 0)
26059 + */
26060 + deptsiz.b.xfersize = ep->xfer_len;
26061 + deptsiz.b.pktcnt =
26062 + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
26063 + deptsiz.b.mc = deptsiz.b.pktcnt;
26064 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
26065 + deptsiz.d32);
26066 +
26067 + /* Write the DMA register */
26068 + if (core_if->dma_enable) {
26069 + DWC_WRITE_REG32(&
26070 + (core_if->dev_if->in_ep_regs[ep->num]->
26071 + diepdma), (uint32_t) ep->dma_addr);
26072 + }
26073 + } else {
26074 + deptsiz.b.pktcnt =
26075 + (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
26076 + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
26077 +
26078 + DWC_WRITE_REG32(&core_if->dev_if->
26079 + out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);
26080 +
26081 + if (core_if->dma_enable) {
26082 + DWC_WRITE_REG32(&
26083 + (core_if->dev_if->
26084 + out_ep_regs[ep->num]->doepdma),
26085 + (uint32_t) ep->dma_addr);
26086 + }
26087 + }
26088 +
26089 + /** Enable endpoint, clear nak */
26090 +
26091 + depctl.d32 = 0;
26092 + if (ep->bInterval == 1) {
26093 + dsts.d32 =
26094 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
26095 + ep->next_frame = dsts.b.soffn + ep->bInterval;
26096 +
26097 + if (ep->next_frame & 0x1) {
26098 + depctl.b.setd1pid = 1;
26099 + } else {
26100 + depctl.b.setd0pid = 1;
26101 + }
26102 + } else {
26103 + ep->next_frame += ep->bInterval;
26104 +
26105 + if (ep->next_frame & 0x1) {
26106 + depctl.b.setd1pid = 1;
26107 + } else {
26108 + depctl.b.setd0pid = 1;
26109 + }
26110 + }
26111 + depctl.b.epena = 1;
26112 + depctl.b.cnak = 1;
26113 +
26114 + DWC_MODIFY_REG32(addr, 0, depctl.d32);
26115 + depctl.d32 = DWC_READ_REG32(addr);
26116 +
26117 + if (ep->is_in && core_if->dma_enable == 0) {
26118 + write_isoc_frame_data(core_if, ep);
26119 + }
26120 +
26121 +}
26122 +#endif /* DWC_EN_ISOC */
26123 +
26124 +static void dwc_otg_set_uninitialized(int32_t * p, int size)
26125 +{
26126 + int i;
26127 + for (i = 0; i < size; i++) {
26128 + p[i] = -1;
26129 + }
26130 +}
26131 +
26132 +static int dwc_otg_param_initialized(int32_t val)
26133 +{
26134 + return val != -1;
26135 +}
26136 +
26137 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
26138 +{
26139 + int i;
26140 + core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
26141 + if (!core_if->core_params) {
26142 + return -DWC_E_NO_MEMORY;
26143 + }
26144 + dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
26145 + sizeof(*core_if->core_params) /
26146 + sizeof(int32_t));
26147 + DWC_PRINTF("Setting default values for core params\n");
26148 + dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
26149 + dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
26150 + dwc_otg_set_param_dma_desc_enable(core_if,
26151 + dwc_param_dma_desc_enable_default);
26152 + dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
26153 + dwc_otg_set_param_dma_burst_size(core_if,
26154 + dwc_param_dma_burst_size_default);
26155 + dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
26156 + dwc_param_host_support_fs_ls_low_power_default);
26157 + dwc_otg_set_param_enable_dynamic_fifo(core_if,
26158 + dwc_param_enable_dynamic_fifo_default);
26159 + dwc_otg_set_param_data_fifo_size(core_if,
26160 + dwc_param_data_fifo_size_default);
26161 + dwc_otg_set_param_dev_rx_fifo_size(core_if,
26162 + dwc_param_dev_rx_fifo_size_default);
26163 + dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
26164 + dwc_param_dev_nperio_tx_fifo_size_default);
26165 + dwc_otg_set_param_host_rx_fifo_size(core_if,
26166 + dwc_param_host_rx_fifo_size_default);
26167 + dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
26168 + dwc_param_host_nperio_tx_fifo_size_default);
26169 + dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
26170 + dwc_param_host_perio_tx_fifo_size_default);
26171 + dwc_otg_set_param_max_transfer_size(core_if,
26172 + dwc_param_max_transfer_size_default);
26173 + dwc_otg_set_param_max_packet_count(core_if,
26174 + dwc_param_max_packet_count_default);
26175 + dwc_otg_set_param_host_channels(core_if,
26176 + dwc_param_host_channels_default);
26177 + dwc_otg_set_param_dev_endpoints(core_if,
26178 + dwc_param_dev_endpoints_default);
26179 + dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
26180 + dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
26181 + dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
26182 + dwc_param_host_ls_low_power_phy_clk_default);
26183 + dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
26184 + dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
26185 + dwc_param_phy_ulpi_ext_vbus_default);
26186 + dwc_otg_set_param_phy_utmi_width(core_if,
26187 + dwc_param_phy_utmi_width_default);
26188 + dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
26189 + dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
26190 + dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
26191 + dwc_otg_set_param_en_multiple_tx_fifo(core_if,
26192 + dwc_param_en_multiple_tx_fifo_default);
26193 + for (i = 0; i < 15; i++) {
26194 + dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
26195 + dwc_param_dev_perio_tx_fifo_size_default,
26196 + i);
26197 + }
26198 +
26199 + for (i = 0; i < 15; i++) {
26200 + dwc_otg_set_param_dev_tx_fifo_size(core_if,
26201 + dwc_param_dev_tx_fifo_size_default,
26202 + i);
26203 + }
26204 + dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
26205 + dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
26206 + dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
26207 + dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
26208 + dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
26209 + dwc_otg_set_param_tx_thr_length(core_if,
26210 + dwc_param_tx_thr_length_default);
26211 + dwc_otg_set_param_rx_thr_length(core_if,
26212 + dwc_param_rx_thr_length_default);
26213 + dwc_otg_set_param_ahb_thr_ratio(core_if,
26214 + dwc_param_ahb_thr_ratio_default);
26215 + dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
26216 + dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
26217 + dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
26218 + dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
26219 + dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
26220 + dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
26221 + dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
26222 + DWC_PRINTF("Finished setting default values for core params\n");
26223 +
26224 + return 0;
26225 +}
26226 +
26227 +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
26228 +{
26229 + return core_if->dma_enable;
26230 +}
26231 +
26232 +/* Checks if the parameter is outside of its valid range of values */
26233 +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
26234 + (((_param_) < (_low_)) || \
26235 + ((_param_) > (_high_)))
26236 +
26237 +/* Parameter access functions */
26238 +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
26239 +{
26240 + int valid;
26241 + int retval = 0;
26242 + if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26243 + DWC_WARN("Wrong value for otg_cap parameter\n");
26244 + DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
26245 + retval = -DWC_E_INVALID;
26246 + goto out;
26247 + }
26248 +
26249 + valid = 1;
26250 + switch (val) {
26251 + case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
26252 + if (core_if->hwcfg2.b.op_mode !=
26253 + DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26254 + valid = 0;
26255 + break;
26256 + case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
26257 + if ((core_if->hwcfg2.b.op_mode !=
26258 + DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26259 + && (core_if->hwcfg2.b.op_mode !=
26260 + DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26261 + && (core_if->hwcfg2.b.op_mode !=
26262 + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26263 + && (core_if->hwcfg2.b.op_mode !=
26264 + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
26265 + valid = 0;
26266 + }
26267 + break;
26268 + case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
26269 + /* always valid */
26270 + break;
26271 + }
26272 + if (!valid) {
26273 + if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
26274 + DWC_ERROR
26275 + ("%d invalid for otg_cap paremter. Check HW configuration.\n",
26276 + val);
26277 + }
26278 + val =
26279 + (((core_if->hwcfg2.b.op_mode ==
26280 + DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26281 + || (core_if->hwcfg2.b.op_mode ==
26282 + DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26283 + || (core_if->hwcfg2.b.op_mode ==
26284 + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26285 + || (core_if->hwcfg2.b.op_mode ==
26286 + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
26287 + DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
26288 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
26289 + retval = -DWC_E_INVALID;
26290 + }
26291 +
26292 + core_if->core_params->otg_cap = val;
26293 +out:
26294 + return retval;
26295 +}
26296 +
26297 +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
26298 +{
26299 + return core_if->core_params->otg_cap;
26300 +}
26301 +
26302 +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
26303 +{
26304 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26305 + DWC_WARN("Wrong value for opt parameter\n");
26306 + return -DWC_E_INVALID;
26307 + }
26308 + core_if->core_params->opt = val;
26309 + return 0;
26310 +}
26311 +
26312 +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
26313 +{
26314 + return core_if->core_params->opt;
26315 +}
26316 +
26317 +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
26318 +{
26319 + int retval = 0;
26320 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26321 + DWC_WARN("Wrong value for dma enable\n");
26322 + return -DWC_E_INVALID;
26323 + }
26324 +
26325 + if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
26326 + if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
26327 + DWC_ERROR
26328 + ("%d invalid for dma_enable paremter. Check HW configuration.\n",
26329 + val);
26330 + }
26331 + val = 0;
26332 + retval = -DWC_E_INVALID;
26333 + }
26334 +
26335 + core_if->core_params->dma_enable = val;
26336 + if (val == 0) {
26337 + dwc_otg_set_param_dma_desc_enable(core_if, 0);
26338 + }
26339 + return retval;
26340 +}
26341 +
26342 +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
26343 +{
26344 + return core_if->core_params->dma_enable;
26345 +}
26346 +
26347 +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
26348 +{
26349 + int retval = 0;
26350 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26351 + DWC_WARN("Wrong value for dma_enable\n");
26352 + DWC_WARN("dma_desc_enable must be 0 or 1\n");
26353 + return -DWC_E_INVALID;
26354 + }
26355 +
26356 + if ((val == 1)
26357 + && ((dwc_otg_get_param_dma_enable(core_if) == 0)
26358 + || (core_if->hwcfg4.b.desc_dma == 0))) {
26359 + if (dwc_otg_param_initialized
26360 + (core_if->core_params->dma_desc_enable)) {
26361 + DWC_ERROR
26362 + ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
26363 + val);
26364 + }
26365 + val = 0;
26366 + retval = -DWC_E_INVALID;
26367 + }
26368 + core_if->core_params->dma_desc_enable = val;
26369 + return retval;
26370 +}
26371 +
26372 +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
26373 +{
26374 + return core_if->core_params->dma_desc_enable;
26375 +}
26376 +
26377 +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
26378 + int32_t val)
26379 +{
26380 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26381 + DWC_WARN("Wrong value for host_support_fs_low_power\n");
26382 + DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
26383 + return -DWC_E_INVALID;
26384 + }
26385 + core_if->core_params->host_support_fs_ls_low_power = val;
26386 + return 0;
26387 +}
26388 +
26389 +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
26390 + core_if)
26391 +{
26392 + return core_if->core_params->host_support_fs_ls_low_power;
26393 +}
26394 +
26395 +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
26396 + int32_t val)
26397 +{
26398 + int retval = 0;
26399 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26400 + DWC_WARN("Wrong value for enable_dynamic_fifo\n");
26401 + DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
26402 + return -DWC_E_INVALID;
26403 + }
26404 +
26405 + if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
26406 + if (dwc_otg_param_initialized
26407 + (core_if->core_params->enable_dynamic_fifo)) {
26408 + DWC_ERROR
26409 + ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
26410 + val);
26411 + }
26412 + val = 0;
26413 + retval = -DWC_E_INVALID;
26414 + }
26415 + core_if->core_params->enable_dynamic_fifo = val;
26416 + return retval;
26417 +}
26418 +
26419 +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
26420 +{
26421 + return core_if->core_params->enable_dynamic_fifo;
26422 +}
26423 +
26424 +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26425 +{
26426 + int retval = 0;
26427 + if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
26428 + DWC_WARN("Wrong value for data_fifo_size\n");
26429 + DWC_WARN("data_fifo_size must be 32-32768\n");
26430 + return -DWC_E_INVALID;
26431 + }
26432 +
26433 + if (val > core_if->hwcfg3.b.dfifo_depth) {
26434 + if (dwc_otg_param_initialized
26435 + (core_if->core_params->data_fifo_size)) {
26436 + DWC_ERROR
26437 + ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
26438 + val);
26439 + }
26440 + val = core_if->hwcfg3.b.dfifo_depth;
26441 + retval = -DWC_E_INVALID;
26442 + }
26443 +
26444 + core_if->core_params->data_fifo_size = val;
26445 + return retval;
26446 +}
26447 +
26448 +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
26449 +{
26450 + return core_if->core_params->data_fifo_size;
26451 +}
26452 +
26453 +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26454 +{
26455 + int retval = 0;
26456 + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26457 + DWC_WARN("Wrong value for dev_rx_fifo_size\n");
26458 + DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
26459 + return -DWC_E_INVALID;
26460 + }
26461 +
26462 + if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26463 + if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
26464 + DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
26465 + }
26466 + val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26467 + retval = -DWC_E_INVALID;
26468 + }
26469 +
26470 + core_if->core_params->dev_rx_fifo_size = val;
26471 + return retval;
26472 +}
26473 +
26474 +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
26475 +{
26476 + return core_if->core_params->dev_rx_fifo_size;
26477 +}
26478 +
26479 +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26480 + int32_t val)
26481 +{
26482 + int retval = 0;
26483 +
26484 + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26485 + DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
26486 + DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
26487 + return -DWC_E_INVALID;
26488 + }
26489 +
26490 + if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26491 + if (dwc_otg_param_initialized
26492 + (core_if->core_params->dev_nperio_tx_fifo_size)) {
26493 + DWC_ERROR
26494 + ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
26495 + val);
26496 + }
26497 + val =
26498 + (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26499 + 16);
26500 + retval = -DWC_E_INVALID;
26501 + }
26502 +
26503 + core_if->core_params->dev_nperio_tx_fifo_size = val;
26504 + return retval;
26505 +}
26506 +
26507 +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26508 +{
26509 + return core_if->core_params->dev_nperio_tx_fifo_size;
26510 +}
26511 +
26512 +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
26513 + int32_t val)
26514 +{
26515 + int retval = 0;
26516 +
26517 + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26518 + DWC_WARN("Wrong value for host_rx_fifo_size\n");
26519 + DWC_WARN("host_rx_fifo_size must be 16-32768\n");
26520 + return -DWC_E_INVALID;
26521 + }
26522 +
26523 + if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26524 + if (dwc_otg_param_initialized
26525 + (core_if->core_params->host_rx_fifo_size)) {
26526 + DWC_ERROR
26527 + ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
26528 + val);
26529 + }
26530 + val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26531 + retval = -DWC_E_INVALID;
26532 + }
26533 +
26534 + core_if->core_params->host_rx_fifo_size = val;
26535 + return retval;
26536 +
26537 +}
26538 +
26539 +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
26540 +{
26541 + return core_if->core_params->host_rx_fifo_size;
26542 +}
26543 +
26544 +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26545 + int32_t val)
26546 +{
26547 + int retval = 0;
26548 +
26549 + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26550 + DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
26551 + DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
26552 + return -DWC_E_INVALID;
26553 + }
26554 +
26555 + if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26556 + if (dwc_otg_param_initialized
26557 + (core_if->core_params->host_nperio_tx_fifo_size)) {
26558 + DWC_ERROR
26559 + ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
26560 + val);
26561 + }
26562 + val =
26563 + (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26564 + 16);
26565 + retval = -DWC_E_INVALID;
26566 + }
26567 +
26568 + core_if->core_params->host_nperio_tx_fifo_size = val;
26569 + return retval;
26570 +}
26571 +
26572 +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26573 +{
26574 + return core_if->core_params->host_nperio_tx_fifo_size;
26575 +}
26576 +
26577 +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26578 + int32_t val)
26579 +{
26580 + int retval = 0;
26581 + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26582 + DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
26583 + DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
26584 + return -DWC_E_INVALID;
26585 + }
26586 +
26587 + if (val > ((core_if->hptxfsiz.d32) >> 16)) {
26588 + if (dwc_otg_param_initialized
26589 + (core_if->core_params->host_perio_tx_fifo_size)) {
26590 + DWC_ERROR
26591 + ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
26592 + val);
26593 + }
26594 + val = (core_if->hptxfsiz.d32) >> 16;
26595 + retval = -DWC_E_INVALID;
26596 + }
26597 +
26598 + core_if->core_params->host_perio_tx_fifo_size = val;
26599 + return retval;
26600 +}
26601 +
26602 +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26603 +{
26604 + return core_if->core_params->host_perio_tx_fifo_size;
26605 +}
26606 +
26607 +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
26608 + int32_t val)
26609 +{
26610 + int retval = 0;
26611 +
26612 + if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
26613 + DWC_WARN("Wrong value for max_transfer_size\n");
26614 + DWC_WARN("max_transfer_size must be 2047-524288\n");
26615 + return -DWC_E_INVALID;
26616 + }
26617 +
26618 + if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
26619 + if (dwc_otg_param_initialized
26620 + (core_if->core_params->max_transfer_size)) {
26621 + DWC_ERROR
26622 + ("%d invalid for max_transfer_size. Check HW configuration.\n",
26623 + val);
26624 + }
26625 + val =
26626 + ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
26627 + 1);
26628 + retval = -DWC_E_INVALID;
26629 + }
26630 +
26631 + core_if->core_params->max_transfer_size = val;
26632 + return retval;
26633 +}
26634 +
26635 +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
26636 +{
26637 + return core_if->core_params->max_transfer_size;
26638 +}
26639 +
26640 +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
26641 +{
26642 + int retval = 0;
26643 +
26644 + if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
26645 + DWC_WARN("Wrong value for max_packet_count\n");
26646 + DWC_WARN("max_packet_count must be 15-511\n");
26647 + return -DWC_E_INVALID;
26648 + }
26649 +
26650 + if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
26651 + if (dwc_otg_param_initialized
26652 + (core_if->core_params->max_packet_count)) {
26653 + DWC_ERROR
26654 + ("%d invalid for max_packet_count. Check HW configuration.\n",
26655 + val);
26656 + }
26657 + val =
26658 + ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
26659 + retval = -DWC_E_INVALID;
26660 + }
26661 +
26662 + core_if->core_params->max_packet_count = val;
26663 + return retval;
26664 +}
26665 +
26666 +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
26667 +{
26668 + return core_if->core_params->max_packet_count;
26669 +}
26670 +
26671 +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
26672 +{
26673 + int retval = 0;
26674 +
26675 + if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
26676 + DWC_WARN("Wrong value for host_channels\n");
26677 + DWC_WARN("host_channels must be 1-16\n");
26678 + return -DWC_E_INVALID;
26679 + }
26680 +
26681 + if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
26682 + if (dwc_otg_param_initialized
26683 + (core_if->core_params->host_channels)) {
26684 + DWC_ERROR
26685 + ("%d invalid for host_channels. Check HW configurations.\n",
26686 + val);
26687 + }
26688 + val = (core_if->hwcfg2.b.num_host_chan + 1);
26689 + retval = -DWC_E_INVALID;
26690 + }
26691 +
26692 + core_if->core_params->host_channels = val;
26693 + return retval;
26694 +}
26695 +
26696 +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
26697 +{
26698 + return core_if->core_params->host_channels;
26699 +}
26700 +
26701 +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
26702 +{
26703 + int retval = 0;
26704 +
26705 + if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
26706 + DWC_WARN("Wrong value for dev_endpoints\n");
26707 + DWC_WARN("dev_endpoints must be 1-15\n");
26708 + return -DWC_E_INVALID;
26709 + }
26710 +
26711 + if (val > (core_if->hwcfg2.b.num_dev_ep)) {
26712 + if (dwc_otg_param_initialized
26713 + (core_if->core_params->dev_endpoints)) {
26714 + DWC_ERROR
26715 + ("%d invalid for dev_endpoints. Check HW configurations.\n",
26716 + val);
26717 + }
26718 + val = core_if->hwcfg2.b.num_dev_ep;
26719 + retval = -DWC_E_INVALID;
26720 + }
26721 +
26722 + core_if->core_params->dev_endpoints = val;
26723 + return retval;
26724 +}
26725 +
26726 +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
26727 +{
26728 + return core_if->core_params->dev_endpoints;
26729 +}
26730 +
26731 +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
26732 +{
26733 + int retval = 0;
26734 + int valid = 0;
26735 +
26736 + if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26737 + DWC_WARN("Wrong value for phy_type\n");
26738 + DWC_WARN("phy_type must be 0,1 or 2\n");
26739 + return -DWC_E_INVALID;
26740 + }
26741 +#ifndef NO_FS_PHY_HW_CHECKS
26742 + if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
26743 + ((core_if->hwcfg2.b.hs_phy_type == 1) ||
26744 + (core_if->hwcfg2.b.hs_phy_type == 3))) {
26745 + valid = 1;
26746 + } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
26747 + ((core_if->hwcfg2.b.hs_phy_type == 2) ||
26748 + (core_if->hwcfg2.b.hs_phy_type == 3))) {
26749 + valid = 1;
26750 + } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
26751 + (core_if->hwcfg2.b.fs_phy_type == 1)) {
26752 + valid = 1;
26753 + }
26754 + if (!valid) {
26755 + if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
26756 + DWC_ERROR
26757 + ("%d invalid for phy_type. Check HW configurations.\n",
26758 + val);
26759 + }
26760 + if (core_if->hwcfg2.b.hs_phy_type) {
26761 + if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
26762 + (core_if->hwcfg2.b.hs_phy_type == 1)) {
26763 + val = DWC_PHY_TYPE_PARAM_UTMI;
26764 + } else {
26765 + val = DWC_PHY_TYPE_PARAM_ULPI;
26766 + }
26767 + }
26768 + retval = -DWC_E_INVALID;
26769 + }
26770 +#endif
26771 + core_if->core_params->phy_type = val;
26772 + return retval;
26773 +}
26774 +
26775 +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
26776 +{
26777 + return core_if->core_params->phy_type;
26778 +}
26779 +
26780 +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
26781 +{
26782 + int retval = 0;
26783 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26784 + DWC_WARN("Wrong value for speed parameter\n");
26785 + DWC_WARN("max_speed parameter must be 0 or 1\n");
26786 + return -DWC_E_INVALID;
26787 + }
26788 + if ((val == 0)
26789 + && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
26790 + if (dwc_otg_param_initialized(core_if->core_params->speed)) {
26791 + DWC_ERROR
26792 + ("%d invalid for speed paremter. Check HW configuration.\n",
26793 + val);
26794 + }
26795 + val =
26796 + (dwc_otg_get_param_phy_type(core_if) ==
26797 + DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
26798 + retval = -DWC_E_INVALID;
26799 + }
26800 + core_if->core_params->speed = val;
26801 + return retval;
26802 +}
26803 +
26804 +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
26805 +{
26806 + return core_if->core_params->speed;
26807 +}
26808 +
26809 +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
26810 + int32_t val)
26811 +{
26812 + int retval = 0;
26813 +
26814 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26815 + DWC_WARN
26816 + ("Wrong value for host_ls_low_power_phy_clk parameter\n");
26817 + DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
26818 + return -DWC_E_INVALID;
26819 + }
26820 +
26821 + if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
26822 + && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
26823 + if (dwc_otg_param_initialized
26824 + (core_if->core_params->host_ls_low_power_phy_clk)) {
26825 + DWC_ERROR
26826 + ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
26827 + val);
26828 + }
26829 + val =
26830 + (dwc_otg_get_param_phy_type(core_if) ==
26831 + DWC_PHY_TYPE_PARAM_FS) ?
26832 + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
26833 + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
26834 + retval = -DWC_E_INVALID;
26835 + }
26836 +
26837 + core_if->core_params->host_ls_low_power_phy_clk = val;
26838 + return retval;
26839 +}
26840 +
26841 +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
26842 +{
26843 + return core_if->core_params->host_ls_low_power_phy_clk;
26844 +}
26845 +
26846 +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
26847 +{
26848 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26849 + DWC_WARN("Wrong value for phy_ulpi_ddr\n");
26850 + DWC_WARN("phy_upli_ddr must be 0 or 1\n");
26851 + return -DWC_E_INVALID;
26852 + }
26853 +
26854 + core_if->core_params->phy_ulpi_ddr = val;
26855 + return 0;
26856 +}
26857 +
26858 +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
26859 +{
26860 + return core_if->core_params->phy_ulpi_ddr;
26861 +}
26862 +
26863 +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
26864 + int32_t val)
26865 +{
26866 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26867 + DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
26868 + DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
26869 + return -DWC_E_INVALID;
26870 + }
26871 +
26872 + core_if->core_params->phy_ulpi_ext_vbus = val;
26873 + return 0;
26874 +}
26875 +
26876 +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
26877 +{
26878 + return core_if->core_params->phy_ulpi_ext_vbus;
26879 +}
26880 +
26881 +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
26882 +{
26883 + if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
26884 + DWC_WARN("Wrong valaue for phy_utmi_width\n");
26885 + DWC_WARN("phy_utmi_width must be 8 or 16\n");
26886 + return -DWC_E_INVALID;
26887 + }
26888 +
26889 + core_if->core_params->phy_utmi_width = val;
26890 + return 0;
26891 +}
26892 +
26893 +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
26894 +{
26895 + return core_if->core_params->phy_utmi_width;
26896 +}
26897 +
26898 +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
26899 +{
26900 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26901 + DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
26902 + DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
26903 + return -DWC_E_INVALID;
26904 + }
26905 +
26906 + core_if->core_params->ulpi_fs_ls = val;
26907 + return 0;
26908 +}
26909 +
26910 +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
26911 +{
26912 + return core_if->core_params->ulpi_fs_ls;
26913 +}
26914 +
26915 +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
26916 +{
26917 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26918 + DWC_WARN("Wrong valaue for ts_dline\n");
26919 + DWC_WARN("ts_dline must be 0 or 1\n");
26920 + return -DWC_E_INVALID;
26921 + }
26922 +
26923 + core_if->core_params->ts_dline = val;
26924 + return 0;
26925 +}
26926 +
26927 +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
26928 +{
26929 + return core_if->core_params->ts_dline;
26930 +}
26931 +
26932 +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
26933 +{
26934 + int retval = 0;
26935 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26936 + DWC_WARN("Wrong valaue for i2c_enable\n");
26937 + DWC_WARN("i2c_enable must be 0 or 1\n");
26938 + return -DWC_E_INVALID;
26939 + }
26940 +#ifndef NO_FS_PHY_HW_CHECK
26941 + if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
26942 + if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
26943 + DWC_ERROR
26944 + ("%d invalid for i2c_enable. Check HW configuration.\n",
26945 + val);
26946 + }
26947 + val = 0;
26948 + retval = -DWC_E_INVALID;
26949 + }
26950 +#endif
26951 +
26952 + core_if->core_params->i2c_enable = val;
26953 + return retval;
26954 +}
26955 +
26956 +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
26957 +{
26958 + return core_if->core_params->i2c_enable;
26959 +}
26960 +
26961 +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26962 + int32_t val, int fifo_num)
26963 +{
26964 + int retval = 0;
26965 +
26966 + if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
26967 + DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
26968 + DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
26969 + return -DWC_E_INVALID;
26970 + }
26971 +
26972 + if (val >
26973 + (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
26974 + if (dwc_otg_param_initialized
26975 + (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
26976 + DWC_ERROR
26977 + ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
26978 + val, fifo_num);
26979 + }
26980 + val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
26981 + retval = -DWC_E_INVALID;
26982 + }
26983 +
26984 + core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
26985 + return retval;
26986 +}
26987 +
26988 +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26989 + int fifo_num)
26990 +{
26991 + return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
26992 +}
26993 +
26994 +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
26995 + int32_t val)
26996 +{
26997 + int retval = 0;
26998 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26999 + DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
27000 + DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
27001 + return -DWC_E_INVALID;
27002 + }
27003 +
27004 + if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
27005 + if (dwc_otg_param_initialized
27006 + (core_if->core_params->en_multiple_tx_fifo)) {
27007 + DWC_ERROR
27008 + ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
27009 + val);
27010 + }
27011 + val = 0;
27012 + retval = -DWC_E_INVALID;
27013 + }
27014 +
27015 + core_if->core_params->en_multiple_tx_fifo = val;
27016 + return retval;
27017 +}
27018 +
27019 +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
27020 +{
27021 + return core_if->core_params->en_multiple_tx_fifo;
27022 +}
27023 +
27024 +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
27025 + int fifo_num)
27026 +{
27027 + int retval = 0;
27028 +
27029 + if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27030 + DWC_WARN("Wrong value for dev_tx_fifo_size\n");
27031 + DWC_WARN("dev_tx_fifo_size must be 4-768\n");
27032 + return -DWC_E_INVALID;
27033 + }
27034 +
27035 + if (val >
27036 + (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27037 + if (dwc_otg_param_initialized
27038 + (core_if->core_params->dev_tx_fifo_size[fifo_num])) {
27039 + DWC_ERROR
27040 + ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
27041 + val, fifo_num);
27042 + }
27043 + val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27044 + retval = -DWC_E_INVALID;
27045 + }
27046 +
27047 + core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
27048 + return retval;
27049 +}
27050 +
27051 +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
27052 + int fifo_num)
27053 +{
27054 + return core_if->core_params->dev_tx_fifo_size[fifo_num];
27055 +}
27056 +
27057 +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27058 +{
27059 + int retval = 0;
27060 +
27061 + if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
27062 + DWC_WARN("Wrong value for thr_ctl\n");
27063 + DWC_WARN("thr_ctl must be 0-7\n");
27064 + return -DWC_E_INVALID;
27065 + }
27066 +
27067 + if ((val != 0) &&
27068 + (!dwc_otg_get_param_dma_enable(core_if) ||
27069 + !core_if->hwcfg4.b.ded_fifo_en)) {
27070 + if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
27071 + DWC_ERROR
27072 + ("%d invalid for parameter thr_ctl. Check HW configuration.\n",
27073 + val);
27074 + }
27075 + val = 0;
27076 + retval = -DWC_E_INVALID;
27077 + }
27078 +
27079 + core_if->core_params->thr_ctl = val;
27080 + return retval;
27081 +}
27082 +
27083 +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
27084 +{
27085 + return core_if->core_params->thr_ctl;
27086 +}
27087 +
27088 +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
27089 +{
27090 + int retval = 0;
27091 +
27092 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27093 + DWC_WARN("Wrong value for lpm_enable\n");
27094 + DWC_WARN("lpm_enable must be 0 or 1\n");
27095 + return -DWC_E_INVALID;
27096 + }
27097 +
27098 + if (val && !core_if->hwcfg3.b.otg_lpm_en) {
27099 + if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
27100 + DWC_ERROR
27101 + ("%d invalid for parameter lpm_enable. Check HW configuration.\n",
27102 + val);
27103 + }
27104 + val = 0;
27105 + retval = -DWC_E_INVALID;
27106 + }
27107 +
27108 + core_if->core_params->lpm_enable = val;
27109 + return retval;
27110 +}
27111 +
27112 +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
27113 +{
27114 + return core_if->core_params->lpm_enable;
27115 +}
27116 +
27117 +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27118 +{
27119 + if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27120 + DWC_WARN("Wrong valaue for tx_thr_length\n");
27121 + DWC_WARN("tx_thr_length must be 8 - 128\n");
27122 + return -DWC_E_INVALID;
27123 + }
27124 +
27125 + core_if->core_params->tx_thr_length = val;
27126 + return 0;
27127 +}
27128 +
27129 +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
27130 +{
27131 + return core_if->core_params->tx_thr_length;
27132 +}
27133 +
27134 +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27135 +{
27136 + if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27137 + DWC_WARN("Wrong valaue for rx_thr_length\n");
27138 + DWC_WARN("rx_thr_length must be 8 - 128\n");
27139 + return -DWC_E_INVALID;
27140 + }
27141 +
27142 + core_if->core_params->rx_thr_length = val;
27143 + return 0;
27144 +}
27145 +
27146 +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
27147 +{
27148 + return core_if->core_params->rx_thr_length;
27149 +}
27150 +
27151 +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
27152 +{
27153 + if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
27154 + DWC_OTG_PARAM_TEST(val, 4, 4) &&
27155 + DWC_OTG_PARAM_TEST(val, 8, 8) &&
27156 + DWC_OTG_PARAM_TEST(val, 16, 16) &&
27157 + DWC_OTG_PARAM_TEST(val, 32, 32) &&
27158 + DWC_OTG_PARAM_TEST(val, 64, 64) &&
27159 + DWC_OTG_PARAM_TEST(val, 128, 128) &&
27160 + DWC_OTG_PARAM_TEST(val, 256, 256)) {
27161 + DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
27162 + return -DWC_E_INVALID;
27163 + }
27164 + core_if->core_params->dma_burst_size = val;
27165 + return 0;
27166 +}
27167 +
27168 +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
27169 +{
27170 + return core_if->core_params->dma_burst_size;
27171 +}
27172 +
27173 +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
27174 +{
27175 + int retval = 0;
27176 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27177 + DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
27178 + return -DWC_E_INVALID;
27179 + }
27180 + if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
27181 + if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
27182 + DWC_ERROR
27183 + ("%d invalid for parameter pti_enable. Check HW configuration.\n",
27184 + val);
27185 + }
27186 + retval = -DWC_E_INVALID;
27187 + val = 0;
27188 + }
27189 + core_if->core_params->pti_enable = val;
27190 + return retval;
27191 +}
27192 +
27193 +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
27194 +{
27195 + return core_if->core_params->pti_enable;
27196 +}
27197 +
27198 +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
27199 +{
27200 + int retval = 0;
27201 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27202 + DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
27203 + return -DWC_E_INVALID;
27204 + }
27205 + if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
27206 + if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
27207 + DWC_ERROR
27208 + ("%d invalid for parameter mpi_enable. Check HW configuration.\n",
27209 + val);
27210 + }
27211 + retval = -DWC_E_INVALID;
27212 + val = 0;
27213 + }
27214 + core_if->core_params->mpi_enable = val;
27215 + return retval;
27216 +}
27217 +
27218 +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
27219 +{
27220 + return core_if->core_params->mpi_enable;
27221 +}
27222 +
27223 +int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)
27224 +{
27225 + int retval = 0;
27226 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27227 + DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);
27228 + return -DWC_E_INVALID;
27229 + }
27230 + if (val && (core_if->hwcfg3.b.adp_supp == 0)) {
27231 + if (dwc_otg_param_initialized
27232 + (core_if->core_params->adp_supp_enable)) {
27233 + DWC_ERROR
27234 + ("%d invalid for parameter adp_enable. Check HW configuration.\n",
27235 + val);
27236 + }
27237 + retval = -DWC_E_INVALID;
27238 + val = 0;
27239 + }
27240 + core_if->core_params->adp_supp_enable = val;
27241 + /*Set OTG version 2.0 in case of enabling ADP*/
27242 + if (val)
27243 + dwc_otg_set_param_otg_ver(core_if, 1);
27244 +
27245 + return retval;
27246 +}
27247 +
27248 +int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)
27249 +{
27250 + return core_if->core_params->adp_supp_enable;
27251 +}
27252 +
27253 +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)
27254 +{
27255 + int retval = 0;
27256 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27257 + DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
27258 + DWC_WARN("ic_usb_cap must be 0 or 1\n");
27259 + return -DWC_E_INVALID;
27260 + }
27261 +
27262 + if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {
27263 + if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
27264 + DWC_ERROR
27265 + ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
27266 + val);
27267 + }
27268 + retval = -DWC_E_INVALID;
27269 + val = 0;
27270 + }
27271 + core_if->core_params->ic_usb_cap = val;
27272 + return retval;
27273 +}
27274 +
27275 +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
27276 +{
27277 + return core_if->core_params->ic_usb_cap;
27278 +}
27279 +
27280 +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
27281 +{
27282 + int retval = 0;
27283 + int valid = 1;
27284 +
27285 + if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27286 + DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
27287 + DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
27288 + return -DWC_E_INVALID;
27289 + }
27290 +
27291 + if (val
27292 + && (core_if->snpsid < OTG_CORE_REV_2_81a
27293 + || !dwc_otg_get_param_thr_ctl(core_if))) {
27294 + valid = 0;
27295 + } else if (val
27296 + && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <
27297 + 4)) {
27298 + valid = 0;
27299 + }
27300 + if (valid == 0) {
27301 + if (dwc_otg_param_initialized
27302 + (core_if->core_params->ahb_thr_ratio)) {
27303 + DWC_ERROR
27304 + ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",
27305 + val);
27306 + }
27307 + retval = -DWC_E_INVALID;
27308 + val = 0;
27309 + }
27310 +
27311 + core_if->core_params->ahb_thr_ratio = val;
27312 + return retval;
27313 +}
27314 +
27315 +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
27316 +{
27317 + return core_if->core_params->ahb_thr_ratio;
27318 +}
27319 +
27320 +int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)
27321 +{
27322 + int retval = 0;
27323 + int valid = 1;
27324 + hwcfg4_data_t hwcfg4 = {.d32 = 0 };
27325 + hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
27326 +
27327 + if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27328 + DWC_WARN("`%d' invalid for parameter `power_down'\n", val);
27329 + DWC_WARN("power_down must be 0 - 2\n");
27330 + return -DWC_E_INVALID;
27331 + }
27332 +
27333 + if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {
27334 + valid = 0;
27335 + }
27336 + if ((val == 3)
27337 + && ((core_if->snpsid < OTG_CORE_REV_3_00a)
27338 + || (hwcfg4.b.xhiber == 0))) {
27339 + valid = 0;
27340 + }
27341 + if (valid == 0) {
27342 + if (dwc_otg_param_initialized(core_if->core_params->power_down)) {
27343 + DWC_ERROR
27344 + ("%d invalid for parameter power_down. Check HW configuration.\n",
27345 + val);
27346 + }
27347 + retval = -DWC_E_INVALID;
27348 + val = 0;
27349 + }
27350 + core_if->core_params->power_down = val;
27351 + return retval;
27352 +}
27353 +
27354 +int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)
27355 +{
27356 + return core_if->core_params->power_down;
27357 +}
27358 +
27359 +int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27360 +{
27361 + int retval = 0;
27362 + int valid = 1;
27363 +
27364 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27365 + DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);
27366 + DWC_WARN("reload_ctl must be 0 or 1\n");
27367 + return -DWC_E_INVALID;
27368 + }
27369 +
27370 + if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {
27371 + valid = 0;
27372 + }
27373 + if (valid == 0) {
27374 + if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {
27375 + DWC_ERROR("%d invalid for parameter reload_ctl."
27376 + "Check HW configuration.\n", val);
27377 + }
27378 + retval = -DWC_E_INVALID;
27379 + val = 0;
27380 + }
27381 + core_if->core_params->reload_ctl = val;
27382 + return retval;
27383 +}
27384 +
27385 +int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)
27386 +{
27387 + return core_if->core_params->reload_ctl;
27388 +}
27389 +
27390 +int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)
27391 +{
27392 + int retval = 0;
27393 + int valid = 1;
27394 +
27395 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27396 + DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);
27397 + DWC_WARN("dev_out_nak must be 0 or 1\n");
27398 + return -DWC_E_INVALID;
27399 + }
27400 +
27401 + if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||
27402 + !(core_if->core_params->dma_desc_enable))) {
27403 + valid = 0;
27404 + }
27405 + if (valid == 0) {
27406 + if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {
27407 + DWC_ERROR("%d invalid for parameter dev_out_nak."
27408 + "Check HW configuration.\n", val);
27409 + }
27410 + retval = -DWC_E_INVALID;
27411 + val = 0;
27412 + }
27413 + core_if->core_params->dev_out_nak = val;
27414 + return retval;
27415 +}
27416 +
27417 +int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)
27418 +{
27419 + return core_if->core_params->dev_out_nak;
27420 +}
27421 +
27422 +int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
27423 +{
27424 + int retval = 0;
27425 + int valid = 1;
27426 +
27427 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27428 + DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
27429 + DWC_WARN("cont_on_bna must be 0 or 1\n");
27430 + return -DWC_E_INVALID;
27431 + }
27432 +
27433 + if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
27434 + !(core_if->core_params->dma_desc_enable))) {
27435 + valid = 0;
27436 + }
27437 + if (valid == 0) {
27438 + if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
27439 + DWC_ERROR("%d invalid for parameter cont_on_bna."
27440 + "Check HW configuration.\n", val);
27441 + }
27442 + retval = -DWC_E_INVALID;
27443 + val = 0;
27444 + }
27445 + core_if->core_params->cont_on_bna = val;
27446 + return retval;
27447 +}
27448 +
27449 +int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
27450 +{
27451 + return core_if->core_params->cont_on_bna;
27452 +}
27453 +
27454 +int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
27455 +{
27456 + int retval = 0;
27457 + int valid = 1;
27458 +
27459 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27460 + DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
27461 + DWC_WARN("ahb_single must be 0 or 1\n");
27462 + return -DWC_E_INVALID;
27463 + }
27464 +
27465 + if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
27466 + valid = 0;
27467 + }
27468 + if (valid == 0) {
27469 + if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
27470 + DWC_ERROR("%d invalid for parameter ahb_single."
27471 + "Check HW configuration.\n", val);
27472 + }
27473 + retval = -DWC_E_INVALID;
27474 + val = 0;
27475 + }
27476 + core_if->core_params->ahb_single = val;
27477 + return retval;
27478 +}
27479 +
27480 +int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
27481 +{
27482 + return core_if->core_params->ahb_single;
27483 +}
27484 +
27485 +int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
27486 +{
27487 + int retval = 0;
27488 +
27489 + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27490 + DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);
27491 + DWC_WARN
27492 + ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");
27493 + return -DWC_E_INVALID;
27494 + }
27495 +
27496 + core_if->core_params->otg_ver = val;
27497 + return retval;
27498 +}
27499 +
27500 +int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)
27501 +{
27502 + return core_if->core_params->otg_ver;
27503 +}
27504 +
27505 +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
27506 +{
27507 + gotgctl_data_t otgctl;
27508 + otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27509 + return otgctl.b.hstnegscs;
27510 +}
27511 +
27512 +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
27513 +{
27514 + gotgctl_data_t otgctl;
27515 + otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27516 + return otgctl.b.sesreqscs;
27517 +}
27518 +
27519 +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
27520 +{
27521 + if(core_if->otg_ver == 0) {
27522 + gotgctl_data_t otgctl;
27523 + otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27524 + otgctl.b.hnpreq = val;
27525 + DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);
27526 + } else {
27527 + core_if->otg_sts = val;
27528 + }
27529 +}
27530 +
27531 +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
27532 +{
27533 + return core_if->snpsid;
27534 +}
27535 +
27536 +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
27537 +{
27538 + gintsts_data_t gintsts;
27539 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
27540 + return gintsts.b.curmode;
27541 +}
27542 +
27543 +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
27544 +{
27545 + gusbcfg_data_t usbcfg;
27546 + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27547 + return usbcfg.b.hnpcap;
27548 +}
27549 +
27550 +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27551 +{
27552 + gusbcfg_data_t usbcfg;
27553 + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27554 + usbcfg.b.hnpcap = val;
27555 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27556 +}
27557 +
27558 +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
27559 +{
27560 + gusbcfg_data_t usbcfg;
27561 + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27562 + return usbcfg.b.srpcap;
27563 +}
27564 +
27565 +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27566 +{
27567 + gusbcfg_data_t usbcfg;
27568 + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27569 + usbcfg.b.srpcap = val;
27570 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27571 +}
27572 +
27573 +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
27574 +{
27575 + dcfg_data_t dcfg;
27576 + /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */
27577 +
27578 + dcfg.d32 = -1; //GRAYG
27579 + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
27580 + if (NULL == core_if)
27581 + DWC_ERROR("reg request with NULL core_if\n");
27582 + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
27583 + core_if, core_if->dev_if);
27584 + if (NULL == core_if->dev_if)
27585 + DWC_ERROR("reg request with NULL dev_if\n");
27586 + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
27587 + "dev_global_regs(%p)\n", __func__,
27588 + core_if, core_if->dev_if,
27589 + core_if->dev_if->dev_global_regs);
27590 + if (NULL == core_if->dev_if->dev_global_regs)
27591 + DWC_ERROR("reg request with NULL dev_global_regs\n");
27592 + else {
27593 + DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
27594 + "dev_global_regs(%p)->dcfg = %p\n", __func__,
27595 + core_if, core_if->dev_if,
27596 + core_if->dev_if->dev_global_regs,
27597 + &core_if->dev_if->dev_global_regs->dcfg);
27598 + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27599 + }
27600 + return dcfg.b.devspd;
27601 +}
27602 +
27603 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
27604 +{
27605 + dcfg_data_t dcfg;
27606 + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27607 + dcfg.b.devspd = val;
27608 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
27609 +}
27610 +
27611 +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
27612 +{
27613 + hprt0_data_t hprt0;
27614 + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27615 + return hprt0.b.prtconnsts;
27616 +}
27617 +
27618 +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
27619 +{
27620 + dsts_data_t dsts;
27621 + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
27622 + return dsts.b.enumspd;
27623 +}
27624 +
27625 +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
27626 +{
27627 + hprt0_data_t hprt0;
27628 + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27629 + return hprt0.b.prtpwr;
27630 +
27631 +}
27632 +
27633 +uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)
27634 +{
27635 + return core_if->hibernation_suspend;
27636 +}
27637 +
27638 +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
27639 +{
27640 + hprt0_data_t hprt0;
27641 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
27642 + hprt0.b.prtpwr = val;
27643 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27644 +}
27645 +
27646 +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
27647 +{
27648 + hprt0_data_t hprt0;
27649 + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27650 + return hprt0.b.prtsusp;
27651 +
27652 +}
27653 +
27654 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
27655 +{
27656 + hprt0_data_t hprt0;
27657 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
27658 + hprt0.b.prtsusp = val;
27659 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27660 +}
27661 +
27662 +uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)
27663 +{
27664 + hfir_data_t hfir;
27665 + hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27666 + return hfir.b.frint;
27667 +
27668 +}
27669 +
27670 +void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)
27671 +{
27672 + hfir_data_t hfir;
27673 + uint32_t fram_int;
27674 + fram_int = calc_frame_interval(core_if);
27675 + hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27676 + if (!core_if->core_params->reload_ctl) {
27677 + DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"
27678 + "not set to 1.\nShould load driver with reload_ctl=1"
27679 + " module parameter\n");
27680 + return;
27681 + }
27682 + switch (fram_int) {
27683 + case 3750:
27684 + if ((val < 3350) || (val > 4150)) {
27685 + DWC_WARN("HFIR interval for HS core and 30 MHz"
27686 + "clock freq should be from 3350 to 4150\n");
27687 + return;
27688 + }
27689 + break;
27690 + case 30000:
27691 + if ((val < 26820) || (val > 33180)) {
27692 + DWC_WARN("HFIR interval for FS/LS core and 30 MHz"
27693 + "clock freq should be from 26820 to 33180\n");
27694 + return;
27695 + }
27696 + break;
27697 + case 6000:
27698 + if ((val < 5360) || (val > 6640)) {
27699 + DWC_WARN("HFIR interval for HS core and 48 MHz"
27700 + "clock freq should be from 5360 to 6640\n");
27701 + return;
27702 + }
27703 + break;
27704 + case 48000:
27705 + if ((val < 42912) || (val > 53088)) {
27706 + DWC_WARN("HFIR interval for FS/LS core and 48 MHz"
27707 + "clock freq should be from 42912 to 53088\n");
27708 + return;
27709 + }
27710 + break;
27711 + case 7500:
27712 + if ((val < 6700) || (val > 8300)) {
27713 + DWC_WARN("HFIR interval for HS core and 60 MHz"
27714 + "clock freq should be from 6700 to 8300\n");
27715 + return;
27716 + }
27717 + break;
27718 + case 60000:
27719 + if ((val < 53640) || (val > 65536)) {
27720 + DWC_WARN("HFIR interval for FS/LS core and 60 MHz"
27721 + "clock freq should be from 53640 to 65536\n");
27722 + return;
27723 + }
27724 + break;
27725 + default:
27726 + DWC_WARN("Unknown frame interval\n");
27727 + return;
27728 + break;
27729 +
27730 + }
27731 + hfir.b.frint = val;
27732 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);
27733 +}
27734 +
27735 +uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)
27736 +{
27737 + hcfg_data_t hcfg;
27738 + hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
27739 + return hcfg.b.modechtimen;
27740 +
27741 +}
27742 +
27743 +void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)
27744 +{
27745 + hcfg_data_t hcfg;
27746 + hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
27747 + hcfg.b.modechtimen = val;
27748 + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
27749 +}
27750 +
27751 +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
27752 +{
27753 + hprt0_data_t hprt0;
27754 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
27755 + hprt0.b.prtres = val;
27756 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27757 +}
27758 +
27759 +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
27760 +{
27761 + dctl_data_t dctl;
27762 + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
27763 + return dctl.b.rmtwkupsig;
27764 +}
27765 +
27766 +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
27767 +{
27768 + glpmcfg_data_t lpmcfg;
27769 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27770 +
27771 + DWC_ASSERT(!
27772 + ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
27773 + "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
27774 + core_if->lx_state, lpmcfg.b.prt_sleep_sts);
27775 +
27776 + return lpmcfg.b.prt_sleep_sts;
27777 +}
27778 +
27779 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
27780 +{
27781 + glpmcfg_data_t lpmcfg;
27782 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27783 + return lpmcfg.b.rem_wkup_en;
27784 +}
27785 +
27786 +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
27787 +{
27788 + glpmcfg_data_t lpmcfg;
27789 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27790 + return lpmcfg.b.appl_resp;
27791 +}
27792 +
27793 +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
27794 +{
27795 + glpmcfg_data_t lpmcfg;
27796 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27797 + lpmcfg.b.appl_resp = val;
27798 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
27799 +}
27800 +
27801 +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
27802 +{
27803 + glpmcfg_data_t lpmcfg;
27804 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27805 + return lpmcfg.b.hsic_connect;
27806 +}
27807 +
27808 +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
27809 +{
27810 + glpmcfg_data_t lpmcfg;
27811 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27812 + lpmcfg.b.hsic_connect = val;
27813 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
27814 +}
27815 +
27816 +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
27817 +{
27818 + glpmcfg_data_t lpmcfg;
27819 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27820 + return lpmcfg.b.inv_sel_hsic;
27821 +
27822 +}
27823 +
27824 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
27825 +{
27826 + glpmcfg_data_t lpmcfg;
27827 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27828 + lpmcfg.b.inv_sel_hsic = val;
27829 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
27830 +}
27831 +
27832 +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
27833 +{
27834 + return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27835 +}
27836 +
27837 +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
27838 +{
27839 + DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);
27840 +}
27841 +
27842 +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
27843 +{
27844 + return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27845 +}
27846 +
27847 +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
27848 +{
27849 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);
27850 +}
27851 +
27852 +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
27853 +{
27854 + return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
27855 +}
27856 +
27857 +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
27858 +{
27859 + DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);
27860 +}
27861 +
27862 +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
27863 +{
27864 + return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
27865 +}
27866 +
27867 +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
27868 +{
27869 + DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);
27870 +}
27871 +
27872 +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
27873 +{
27874 + return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);
27875 +}
27876 +
27877 +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
27878 +{
27879 + DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);
27880 +}
27881 +
27882 +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
27883 +{
27884 + return DWC_READ_REG32(&core_if->core_global_regs->ggpio);
27885 +}
27886 +
27887 +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
27888 +{
27889 + DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);
27890 +}
27891 +
27892 +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
27893 +{
27894 + return DWC_READ_REG32(core_if->host_if->hprt0);
27895 +
27896 +}
27897 +
27898 +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
27899 +{
27900 + DWC_WRITE_REG32(core_if->host_if->hprt0, val);
27901 +}
27902 +
27903 +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
27904 +{
27905 + return DWC_READ_REG32(&core_if->core_global_regs->guid);
27906 +}
27907 +
27908 +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
27909 +{
27910 + DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);
27911 +}
27912 +
27913 +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
27914 +{
27915 + return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
27916 +}
27917 +
27918 +uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)
27919 +{
27920 + return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);
27921 +}
27922 +
27923 +/**
27924 + * Start the SRP timer to detect when the SRP does not complete within
27925 + * 6 seconds.
27926 + *
27927 + * @param core_if the pointer to core_if strucure.
27928 + */
27929 +void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)
27930 +{
27931 + core_if->srp_timer_started = 1;
27932 + DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );
27933 +}
27934 +
27935 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)
27936 +{
27937 + uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);
27938 + gotgctl_data_t mem;
27939 + gotgctl_data_t val;
27940 +
27941 + val.d32 = DWC_READ_REG32(addr);
27942 + if (val.b.sesreq) {
27943 + DWC_ERROR("Session Request Already active!\n");
27944 + return;
27945 + }
27946 +
27947 + DWC_INFO("Session Request Initated\n"); //NOTICE
27948 + mem.d32 = DWC_READ_REG32(addr);
27949 + mem.b.sesreq = 1;
27950 + DWC_WRITE_REG32(addr, mem.d32);
27951 +
27952 + /* Start the SRP timer */
27953 + dwc_otg_pcd_start_srp_timer(core_if);
27954 + return;
27955 +}
27956 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cil.h
27957 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100
27958 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2013-07-06 15:25:50.000000000 +0100
27959 @@ -0,0 +1,1464 @@
27960 +/* ==========================================================================
27961 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
27962 + * $Revision: #123 $
27963 + * $Date: 2012/08/10 $
27964 + * $Change: 2047372 $
27965 + *
27966 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
27967 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
27968 + * otherwise expressly agreed to in writing between Synopsys and you.
27969 + *
27970 + * The Software IS NOT an item of Licensed Software or Licensed Product under
27971 + * any End User Software License Agreement or Agreement for Licensed Product
27972 + * with Synopsys or any supplement thereto. You are permitted to use and
27973 + * redistribute this Software in source and binary forms, with or without
27974 + * modification, provided that redistributions of source code must retain this
27975 + * notice. You may not view, use, disclose, copy or distribute this file or
27976 + * any information contained herein except pursuant to this license grant from
27977 + * Synopsys. If you do not agree with this notice, including the disclaimer
27978 + * below, then you are not authorized to use the Software.
27979 + *
27980 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
27981 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27982 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27983 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
27984 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27985 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27986 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27987 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27988 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27989 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27990 + * DAMAGE.
27991 + * ========================================================================== */
27992 +
27993 +#if !defined(__DWC_CIL_H__)
27994 +#define __DWC_CIL_H__
27995 +
27996 +#include "dwc_list.h"
27997 +#include "dwc_otg_dbg.h"
27998 +#include "dwc_otg_regs.h"
27999 +
28000 +#include "dwc_otg_core_if.h"
28001 +#include "dwc_otg_adp.h"
28002 +
28003 +/**
28004 + * @file
28005 + * This file contains the interface to the Core Interface Layer.
28006 + */
28007 +
28008 +#ifdef DWC_UTE_CFI
28009 +
28010 +#define MAX_DMA_DESCS_PER_EP 256
28011 +
28012 +/**
28013 + * Enumeration for the data buffer mode
28014 + */
28015 +typedef enum _data_buffer_mode {
28016 + BM_STANDARD = 0, /* data buffer is in normal mode */
28017 + BM_SG = 1, /* data buffer uses the scatter/gather mode */
28018 + BM_CONCAT = 2, /* data buffer uses the concatenation mode */
28019 + BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */
28020 + BM_ALIGN = 4 /* data buffer is in buffer alignment mode */
28021 +} data_buffer_mode_e;
28022 +#endif //DWC_UTE_CFI
28023 +
28024 +/** Macros defined for DWC OTG HW Release version */
28025 +
28026 +#define OTG_CORE_REV_2_60a 0x4F54260A
28027 +#define OTG_CORE_REV_2_71a 0x4F54271A
28028 +#define OTG_CORE_REV_2_72a 0x4F54272A
28029 +#define OTG_CORE_REV_2_80a 0x4F54280A
28030 +#define OTG_CORE_REV_2_81a 0x4F54281A
28031 +#define OTG_CORE_REV_2_90a 0x4F54290A
28032 +#define OTG_CORE_REV_2_91a 0x4F54291A
28033 +#define OTG_CORE_REV_2_92a 0x4F54292A
28034 +#define OTG_CORE_REV_2_93a 0x4F54293A
28035 +#define OTG_CORE_REV_2_94a 0x4F54294A
28036 +#define OTG_CORE_REV_3_00a 0x4F54300A
28037 +
28038 +/**
28039 + * Information for each ISOC packet.
28040 + */
28041 +typedef struct iso_pkt_info {
28042 + uint32_t offset;
28043 + uint32_t length;
28044 + int32_t status;
28045 +} iso_pkt_info_t;
28046 +
28047 +/**
28048 + * The <code>dwc_ep</code> structure represents the state of a single
28049 + * endpoint when acting in device mode. It contains the data items
28050 + * needed for an endpoint to be activated and transfer packets.
28051 + */
28052 +typedef struct dwc_ep {
28053 + /** EP number used for register address lookup */
28054 + uint8_t num;
28055 + /** EP direction 0 = OUT */
28056 + unsigned is_in:1;
28057 + /** EP active. */
28058 + unsigned active:1;
28059 +
28060 + /**
28061 + * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
28062 + * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
28063 + unsigned tx_fifo_num:4;
28064 + /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */
28065 + unsigned type:2;
28066 +#define DWC_OTG_EP_TYPE_CONTROL 0
28067 +#define DWC_OTG_EP_TYPE_ISOC 1
28068 +#define DWC_OTG_EP_TYPE_BULK 2
28069 +#define DWC_OTG_EP_TYPE_INTR 3
28070 +
28071 + /** DATA start PID for INTR and BULK EP */
28072 + unsigned data_pid_start:1;
28073 + /** Frame (even/odd) for ISOC EP */
28074 + unsigned even_odd_frame:1;
28075 + /** Max Packet bytes */
28076 + unsigned maxpacket:11;
28077 +
28078 + /** Max Transfer size */
28079 + uint32_t maxxfer;
28080 +
28081 + /** @name Transfer state */
28082 + /** @{ */
28083 +
28084 + /**
28085 + * Pointer to the beginning of the transfer buffer -- do not modify
28086 + * during transfer.
28087 + */
28088 +
28089 + dwc_dma_t dma_addr;
28090 +
28091 + dwc_dma_t dma_desc_addr;
28092 + dwc_otg_dev_dma_desc_t *desc_addr;
28093 +
28094 + uint8_t *start_xfer_buff;
28095 + /** pointer to the transfer buffer */
28096 + uint8_t *xfer_buff;
28097 + /** Number of bytes to transfer */
28098 + unsigned xfer_len:19;
28099 + /** Number of bytes transferred. */
28100 + unsigned xfer_count:19;
28101 + /** Sent ZLP */
28102 + unsigned sent_zlp:1;
28103 + /** Total len for control transfer */
28104 + unsigned total_len:19;
28105 +
28106 + /** stall clear flag */
28107 + unsigned stall_clear_flag:1;
28108 +
28109 + /** SETUP pkt cnt rollover flag for EP0 out*/
28110 + unsigned stp_rollover;
28111 +
28112 +#ifdef DWC_UTE_CFI
28113 + /* The buffer mode */
28114 + data_buffer_mode_e buff_mode;
28115 +
28116 + /* The chain of DMA descriptors.
28117 + * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
28118 + */
28119 + dwc_otg_dma_desc_t *descs;
28120 +
28121 + /* The DMA address of the descriptors chain start */
28122 + dma_addr_t descs_dma_addr;
28123 + /** This variable stores the length of the last enqueued request */
28124 + uint32_t cfi_req_len;
28125 +#endif //DWC_UTE_CFI
28126 +
28127 +/** Max DMA Descriptor count for any EP */
28128 +#define MAX_DMA_DESC_CNT 256
28129 + /** Allocated DMA Desc count */
28130 + uint32_t desc_cnt;
28131 +
28132 + /** bInterval */
28133 + uint32_t bInterval;
28134 + /** Next frame num to setup next ISOC transfer */
28135 + uint32_t frame_num;
28136 + /** Indicates SOF number overrun in DSTS */
28137 + uint8_t frm_overrun;
28138 +
28139 +#ifdef DWC_UTE_PER_IO
28140 + /** Next frame num for which will be setup DMA Desc */
28141 + uint32_t xiso_frame_num;
28142 + /** bInterval */
28143 + uint32_t xiso_bInterval;
28144 + /** Count of currently active transfers - shall be either 0 or 1 */
28145 + int xiso_active_xfers;
28146 + int xiso_queued_xfers;
28147 +#endif
28148 +#ifdef DWC_EN_ISOC
28149 + /**
28150 + * Variables specific for ISOC EPs
28151 + *
28152 + */
28153 + /** DMA addresses of ISOC buffers */
28154 + dwc_dma_t dma_addr0;
28155 + dwc_dma_t dma_addr1;
28156 +
28157 + dwc_dma_t iso_dma_desc_addr;
28158 + dwc_otg_dev_dma_desc_t *iso_desc_addr;
28159 +
28160 + /** pointer to the transfer buffers */
28161 + uint8_t *xfer_buff0;
28162 + uint8_t *xfer_buff1;
28163 +
28164 + /** number of ISOC Buffer is processing */
28165 + uint32_t proc_buf_num;
28166 + /** Interval of ISOC Buffer processing */
28167 + uint32_t buf_proc_intrvl;
28168 + /** Data size for regular frame */
28169 + uint32_t data_per_frame;
28170 +
28171 + /* todo - pattern data support is to be implemented in the future */
28172 + /** Data size for pattern frame */
28173 + uint32_t data_pattern_frame;
28174 + /** Frame number of pattern data */
28175 + uint32_t sync_frame;
28176 +
28177 + /** bInterval */
28178 + uint32_t bInterval;
28179 + /** ISO Packet number per frame */
28180 + uint32_t pkt_per_frm;
28181 + /** Next frame num for which will be setup DMA Desc */
28182 + uint32_t next_frame;
28183 + /** Number of packets per buffer processing */
28184 + uint32_t pkt_cnt;
28185 + /** Info for all isoc packets */
28186 + iso_pkt_info_t *pkt_info;
28187 + /** current pkt number */
28188 + uint32_t cur_pkt;
28189 + /** current pkt number */
28190 + uint8_t *cur_pkt_addr;
28191 + /** current pkt number */
28192 + uint32_t cur_pkt_dma_addr;
28193 +#endif /* DWC_EN_ISOC */
28194 +
28195 +/** @} */
28196 +} dwc_ep_t;
28197 +
28198 +/*
28199 + * Reasons for halting a host channel.
28200 + */
28201 +typedef enum dwc_otg_halt_status {
28202 + DWC_OTG_HC_XFER_NO_HALT_STATUS,
28203 + DWC_OTG_HC_XFER_COMPLETE,
28204 + DWC_OTG_HC_XFER_URB_COMPLETE,
28205 + DWC_OTG_HC_XFER_ACK,
28206 + DWC_OTG_HC_XFER_NAK,
28207 + DWC_OTG_HC_XFER_NYET,
28208 + DWC_OTG_HC_XFER_STALL,
28209 + DWC_OTG_HC_XFER_XACT_ERR,
28210 + DWC_OTG_HC_XFER_FRAME_OVERRUN,
28211 + DWC_OTG_HC_XFER_BABBLE_ERR,
28212 + DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
28213 + DWC_OTG_HC_XFER_AHB_ERR,
28214 + DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
28215 + DWC_OTG_HC_XFER_URB_DEQUEUE
28216 +} dwc_otg_halt_status_e;
28217 +
28218 +/**
28219 + * Host channel descriptor. This structure represents the state of a single
28220 + * host channel when acting in host mode. It contains the data items needed to
28221 + * transfer packets to an endpoint via a host channel.
28222 + */
28223 +typedef struct dwc_hc {
28224 + /** Host channel number used for register address lookup */
28225 + uint8_t hc_num;
28226 +
28227 + /** Device to access */
28228 + unsigned dev_addr:7;
28229 +
28230 + /** EP to access */
28231 + unsigned ep_num:4;
28232 +
28233 + /** EP direction. 0: OUT, 1: IN */
28234 + unsigned ep_is_in:1;
28235 +
28236 + /**
28237 + * EP speed.
28238 + * One of the following values:
28239 + * - DWC_OTG_EP_SPEED_LOW
28240 + * - DWC_OTG_EP_SPEED_FULL
28241 + * - DWC_OTG_EP_SPEED_HIGH
28242 + */
28243 + unsigned speed:2;
28244 +#define DWC_OTG_EP_SPEED_LOW 0
28245 +#define DWC_OTG_EP_SPEED_FULL 1
28246 +#define DWC_OTG_EP_SPEED_HIGH 2
28247 +
28248 + /**
28249 + * Endpoint type.
28250 + * One of the following values:
28251 + * - DWC_OTG_EP_TYPE_CONTROL: 0
28252 + * - DWC_OTG_EP_TYPE_ISOC: 1
28253 + * - DWC_OTG_EP_TYPE_BULK: 2
28254 + * - DWC_OTG_EP_TYPE_INTR: 3
28255 + */
28256 + unsigned ep_type:2;
28257 +
28258 + /** Max packet size in bytes */
28259 + unsigned max_packet:11;
28260 +
28261 + /**
28262 + * PID for initial transaction.
28263 + * 0: DATA0,<br>
28264 + * 1: DATA2,<br>
28265 + * 2: DATA1,<br>
28266 + * 3: MDATA (non-Control EP),
28267 + * SETUP (Control EP)
28268 + */
28269 + unsigned data_pid_start:2;
28270 +#define DWC_OTG_HC_PID_DATA0 0
28271 +#define DWC_OTG_HC_PID_DATA2 1
28272 +#define DWC_OTG_HC_PID_DATA1 2
28273 +#define DWC_OTG_HC_PID_MDATA 3
28274 +#define DWC_OTG_HC_PID_SETUP 3
28275 +
28276 + /** Number of periodic transactions per (micro)frame */
28277 + unsigned multi_count:2;
28278 +
28279 + /** @name Transfer State */
28280 + /** @{ */
28281 +
28282 + /** Pointer to the current transfer buffer position. */
28283 + uint8_t *xfer_buff;
28284 + /**
28285 + * In Buffer DMA mode this buffer will be used
28286 + * if xfer_buff is not DWORD aligned.
28287 + */
28288 + dwc_dma_t align_buff;
28289 + /** Total number of bytes to transfer. */
28290 + uint32_t xfer_len;
28291 + /** Number of bytes transferred so far. */
28292 + uint32_t xfer_count;
28293 + /** Packet count at start of transfer.*/
28294 + uint16_t start_pkt_count;
28295 +
28296 + /**
28297 + * Flag to indicate whether the transfer has been started. Set to 1 if
28298 + * it has been started, 0 otherwise.
28299 + */
28300 + uint8_t xfer_started;
28301 +
28302 + /**
28303 + * Set to 1 to indicate that a PING request should be issued on this
28304 + * channel. If 0, process normally.
28305 + */
28306 + uint8_t do_ping;
28307 +
28308 + /**
28309 + * Set to 1 to indicate that the error count for this transaction is
28310 + * non-zero. Set to 0 if the error count is 0.
28311 + */
28312 + uint8_t error_state;
28313 +
28314 + /**
28315 + * Set to 1 to indicate that this channel should be halted the next
28316 + * time a request is queued for the channel. This is necessary in
28317 + * slave mode if no request queue space is available when an attempt
28318 + * is made to halt the channel.
28319 + */
28320 + uint8_t halt_on_queue;
28321 +
28322 + /**
28323 + * Set to 1 if the host channel has been halted, but the core is not
28324 + * finished flushing queued requests. Otherwise 0.
28325 + */
28326 + uint8_t halt_pending;
28327 +
28328 + /**
28329 + * Reason for halting the host channel.
28330 + */
28331 + dwc_otg_halt_status_e halt_status;
28332 +
28333 + /*
28334 + * Split settings for the host channel
28335 + */
28336 + uint8_t do_split; /**< Enable split for the channel */
28337 + uint8_t complete_split; /**< Enable complete split */
28338 + uint8_t hub_addr; /**< Address of high speed hub */
28339 +
28340 + uint8_t port_addr; /**< Port of the low/full speed device */
28341 + /** Split transaction position
28342 + * One of the following values:
28343 + * - DWC_HCSPLIT_XACTPOS_MID
28344 + * - DWC_HCSPLIT_XACTPOS_BEGIN
28345 + * - DWC_HCSPLIT_XACTPOS_END
28346 + * - DWC_HCSPLIT_XACTPOS_ALL */
28347 + uint8_t xact_pos;
28348 +
28349 + /** Set when the host channel does a short read. */
28350 + uint8_t short_read;
28351 +
28352 + /**
28353 + * Number of requests issued for this channel since it was assigned to
28354 + * the current transfer (not counting PINGs).
28355 + */
28356 + uint8_t requests;
28357 +
28358 + /**
28359 + * Queue Head for the transfer being processed by this channel.
28360 + */
28361 + struct dwc_otg_qh *qh;
28362 +
28363 + /** @} */
28364 +
28365 + /** Entry in list of host channels. */
28366 + DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
28367 +
28368 + /** @name Descriptor DMA support */
28369 + /** @{ */
28370 +
28371 + /** Number of Transfer Descriptors */
28372 + uint16_t ntd;
28373 +
28374 + /** Descriptor List DMA address */
28375 + dwc_dma_t desc_list_addr;
28376 +
28377 + /** Scheduling micro-frame bitmap. */
28378 + uint8_t schinfo;
28379 +
28380 + /** @} */
28381 +} dwc_hc_t;
28382 +
28383 +/**
28384 + * The following parameters may be specified when starting the module. These
28385 + * parameters define how the DWC_otg controller should be configured.
28386 + */
28387 +typedef struct dwc_otg_core_params {
28388 + int32_t opt;
28389 +
28390 + /**
28391 + * Specifies the OTG capabilities. The driver will automatically
28392 + * detect the value for this parameter if none is specified.
28393 + * 0 - HNP and SRP capable (default)
28394 + * 1 - SRP Only capable
28395 + * 2 - No HNP/SRP capable
28396 + */
28397 + int32_t otg_cap;
28398 +
28399 + /**
28400 + * Specifies whether to use slave or DMA mode for accessing the data
28401 + * FIFOs. The driver will automatically detect the value for this
28402 + * parameter if none is specified.
28403 + * 0 - Slave
28404 + * 1 - DMA (default, if available)
28405 + */
28406 + int32_t dma_enable;
28407 +
28408 + /**
28409 + * When DMA mode is enabled specifies whether to use address DMA or DMA
28410 + * Descriptor mode for accessing the data FIFOs in device mode. The driver
28411 + * will automatically detect the value for this if none is specified.
28412 + * 0 - address DMA
28413 + * 1 - DMA Descriptor(default, if available)
28414 + */
28415 + int32_t dma_desc_enable;
28416 + /** The DMA Burst size (applicable only for External DMA
28417 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
28418 + */
28419 + int32_t dma_burst_size; /* Translate this to GAHBCFG values */
28420 +
28421 + /**
28422 + * Specifies the maximum speed of operation in host and device mode.
28423 + * The actual speed depends on the speed of the attached device and
28424 + * the value of phy_type. The actual speed depends on the speed of the
28425 + * attached device.
28426 + * 0 - High Speed (default)
28427 + * 1 - Full Speed
28428 + */
28429 + int32_t speed;
28430 + /** Specifies whether low power mode is supported when attached
28431 + * to a Full Speed or Low Speed device in host mode.
28432 + * 0 - Don't support low power mode (default)
28433 + * 1 - Support low power mode
28434 + */
28435 + int32_t host_support_fs_ls_low_power;
28436 +
28437 + /** Specifies the PHY clock rate in low power mode when connected to a
28438 + * Low Speed device in host mode. This parameter is applicable only if
28439 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
28440 + * then defaults to 6 MHZ otherwise 48 MHZ.
28441 + *
28442 + * 0 - 48 MHz
28443 + * 1 - 6 MHz
28444 + */
28445 + int32_t host_ls_low_power_phy_clk;
28446 +
28447 + /**
28448 + * 0 - Use cC FIFO size parameters
28449 + * 1 - Allow dynamic FIFO sizing (default)
28450 + */
28451 + int32_t enable_dynamic_fifo;
28452 +
28453 + /** Total number of 4-byte words in the data FIFO memory. This
28454 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
28455 + * Tx FIFOs.
28456 + * 32 to 32768 (default 8192)
28457 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
28458 + */
28459 + int32_t data_fifo_size;
28460 +
28461 + /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
28462 + * FIFO sizing is enabled.
28463 + * 16 to 32768 (default 1064)
28464 + */
28465 + int32_t dev_rx_fifo_size;
28466 +
28467 + /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
28468 + * when dynamic FIFO sizing is enabled.
28469 + * 16 to 32768 (default 1024)
28470 + */
28471 + int32_t dev_nperio_tx_fifo_size;
28472 +
28473 + /** Number of 4-byte words in each of the periodic Tx FIFOs in device
28474 + * mode when dynamic FIFO sizing is enabled.
28475 + * 4 to 768 (default 256)
28476 + */
28477 + uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
28478 +
28479 + /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
28480 + * FIFO sizing is enabled.
28481 + * 16 to 32768 (default 1024)
28482 + */
28483 + int32_t host_rx_fifo_size;
28484 +
28485 + /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
28486 + * when Dynamic FIFO sizing is enabled in the core.
28487 + * 16 to 32768 (default 1024)
28488 + */
28489 + int32_t host_nperio_tx_fifo_size;
28490 +
28491 + /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
28492 + * FIFO sizing is enabled.
28493 + * 16 to 32768 (default 1024)
28494 + */
28495 + int32_t host_perio_tx_fifo_size;
28496 +
28497 + /** The maximum transfer size supported in bytes.
28498 + * 2047 to 65,535 (default 65,535)
28499 + */
28500 + int32_t max_transfer_size;
28501 +
28502 + /** The maximum number of packets in a transfer.
28503 + * 15 to 511 (default 511)
28504 + */
28505 + int32_t max_packet_count;
28506 +
28507 + /** The number of host channel registers to use.
28508 + * 1 to 16 (default 12)
28509 + * Note: The FPGA configuration supports a maximum of 12 host channels.
28510 + */
28511 + int32_t host_channels;
28512 +
28513 + /** The number of endpoints in addition to EP0 available for device
28514 + * mode operations.
28515 + * 1 to 15 (default 6 IN and OUT)
28516 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
28517 + * endpoints in addition to EP0.
28518 + */
28519 + int32_t dev_endpoints;
28520 +
28521 + /**
28522 + * Specifies the type of PHY interface to use. By default, the driver
28523 + * will automatically detect the phy_type.
28524 + *
28525 + * 0 - Full Speed PHY
28526 + * 1 - UTMI+ (default)
28527 + * 2 - ULPI
28528 + */
28529 + int32_t phy_type;
28530 +
28531 + /**
28532 + * Specifies the UTMI+ Data Width. This parameter is
28533 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
28534 + * PHY_TYPE, this parameter indicates the data width between
28535 + * the MAC and the ULPI Wrapper.) Also, this parameter is
28536 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
28537 + * to "8 and 16 bits", meaning that the core has been
28538 + * configured to work at either data path width.
28539 + *
28540 + * 8 or 16 bits (default 16)
28541 + */
28542 + int32_t phy_utmi_width;
28543 +
28544 + /**
28545 + * Specifies whether the ULPI operates at double or single
28546 + * data rate. This parameter is only applicable if PHY_TYPE is
28547 + * ULPI.
28548 + *
28549 + * 0 - single data rate ULPI interface with 8 bit wide data
28550 + * bus (default)
28551 + * 1 - double data rate ULPI interface with 4 bit wide data
28552 + * bus
28553 + */
28554 + int32_t phy_ulpi_ddr;
28555 +
28556 + /**
28557 + * Specifies whether to use the internal or external supply to
28558 + * drive the vbus with a ULPI phy.
28559 + */
28560 + int32_t phy_ulpi_ext_vbus;
28561 +
28562 + /**
28563 + * Specifies whether to use the I2Cinterface for full speed PHY. This
28564 + * parameter is only applicable if PHY_TYPE is FS.
28565 + * 0 - No (default)
28566 + * 1 - Yes
28567 + */
28568 + int32_t i2c_enable;
28569 +
28570 + int32_t ulpi_fs_ls;
28571 +
28572 + int32_t ts_dline;
28573 +
28574 + /**
28575 + * Specifies whether dedicated transmit FIFOs are
28576 + * enabled for non periodic IN endpoints in device mode
28577 + * 0 - No
28578 + * 1 - Yes
28579 + */
28580 + int32_t en_multiple_tx_fifo;
28581 +
28582 + /** Number of 4-byte words in each of the Tx FIFOs in device
28583 + * mode when dynamic FIFO sizing is enabled.
28584 + * 4 to 768 (default 256)
28585 + */
28586 + uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
28587 +
28588 + /** Thresholding enable flag-
28589 + * bit 0 - enable non-ISO Tx thresholding
28590 + * bit 1 - enable ISO Tx thresholding
28591 + * bit 2 - enable Rx thresholding
28592 + */
28593 + uint32_t thr_ctl;
28594 +
28595 + /** Thresholding length for Tx
28596 + * FIFOs in 32 bit DWORDs
28597 + */
28598 + uint32_t tx_thr_length;
28599 +
28600 + /** Thresholding length for Rx
28601 + * FIFOs in 32 bit DWORDs
28602 + */
28603 + uint32_t rx_thr_length;
28604 +
28605 + /**
28606 + * Specifies whether LPM (Link Power Management) support is enabled
28607 + */
28608 + int32_t lpm_enable;
28609 +
28610 + /** Per Transfer Interrupt
28611 + * mode enable flag
28612 + * 1 - Enabled
28613 + * 0 - Disabled
28614 + */
28615 + int32_t pti_enable;
28616 +
28617 + /** Multi Processor Interrupt
28618 + * mode enable flag
28619 + * 1 - Enabled
28620 + * 0 - Disabled
28621 + */
28622 + int32_t mpi_enable;
28623 +
28624 + /** IS_USB Capability
28625 + * 1 - Enabled
28626 + * 0 - Disabled
28627 + */
28628 + int32_t ic_usb_cap;
28629 +
28630 + /** AHB Threshold Ratio
28631 + * 2'b00 AHB Threshold = MAC Threshold
28632 + * 2'b01 AHB Threshold = 1/2 MAC Threshold
28633 + * 2'b10 AHB Threshold = 1/4 MAC Threshold
28634 + * 2'b11 AHB Threshold = 1/8 MAC Threshold
28635 + */
28636 + int32_t ahb_thr_ratio;
28637 +
28638 + /** ADP Support
28639 + * 1 - Enabled
28640 + * 0 - Disabled
28641 + */
28642 + int32_t adp_supp_enable;
28643 +
28644 + /** HFIR Reload Control
28645 + * 0 - The HFIR cannot be reloaded dynamically.
28646 + * 1 - Allow dynamic reloading of the HFIR register during runtime.
28647 + */
28648 + int32_t reload_ctl;
28649 +
28650 + /** DCFG: Enable device Out NAK
28651 + * 0 - The core does not set NAK after Bulk Out transfer complete.
28652 + * 1 - The core sets NAK after Bulk OUT transfer complete.
28653 + */
28654 + int32_t dev_out_nak;
28655 +
28656 + /** DCFG: Enable Continue on BNA
28657 + * After receiving BNA interrupt the core disables the endpoint,when the
28658 + * endpoint is re-enabled by the application the core starts processing
28659 + * 0 - from the DOEPDMA descriptor
28660 + * 1 - from the descriptor which received the BNA.
28661 + */
28662 + int32_t cont_on_bna;
28663 +
28664 + /** GAHBCFG: AHB Single Support
28665 + * This bit when programmed supports SINGLE transfers for remainder
28666 + * data in a transfer for DMA mode of operation.
28667 + * 0 - in this case the remainder data will be sent using INCR burst size.
28668 + * 1 - in this case the remainder data will be sent using SINGLE burst size.
28669 + */
28670 + int32_t ahb_single;
28671 +
28672 + /** Core Power down mode
28673 + * 0 - No Power Down is enabled
28674 + * 1 - Reserved
28675 + * 2 - Complete Power Down (Hibernation)
28676 + */
28677 + int32_t power_down;
28678 +
28679 + /** OTG revision supported
28680 + * 0 - OTG 1.3 revision
28681 + * 1 - OTG 2.0 revision
28682 + */
28683 + int32_t otg_ver;
28684 +
28685 +} dwc_otg_core_params_t;
28686 +
28687 +#ifdef DEBUG
28688 +struct dwc_otg_core_if;
28689 +typedef struct hc_xfer_info {
28690 + struct dwc_otg_core_if *core_if;
28691 + dwc_hc_t *hc;
28692 +} hc_xfer_info_t;
28693 +#endif
28694 +
28695 +typedef struct ep_xfer_info {
28696 + struct dwc_otg_core_if *core_if;
28697 + dwc_ep_t *ep;
28698 + uint8_t state;
28699 +} ep_xfer_info_t;
28700 +/*
28701 + * Device States
28702 + */
28703 +typedef enum dwc_otg_lx_state {
28704 + /** On state */
28705 + DWC_OTG_L0,
28706 + /** LPM sleep state*/
28707 + DWC_OTG_L1,
28708 + /** USB suspend state*/
28709 + DWC_OTG_L2,
28710 + /** Off state*/
28711 + DWC_OTG_L3
28712 +} dwc_otg_lx_state_e;
28713 +
28714 +struct dwc_otg_global_regs_backup {
28715 + uint32_t gotgctl_local;
28716 + uint32_t gintmsk_local;
28717 + uint32_t gahbcfg_local;
28718 + uint32_t gusbcfg_local;
28719 + uint32_t grxfsiz_local;
28720 + uint32_t gnptxfsiz_local;
28721 +#ifdef CONFIG_USB_DWC_OTG_LPM
28722 + uint32_t glpmcfg_local;
28723 +#endif
28724 + uint32_t gi2cctl_local;
28725 + uint32_t hptxfsiz_local;
28726 + uint32_t pcgcctl_local;
28727 + uint32_t gdfifocfg_local;
28728 + uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];
28729 + uint32_t gpwrdn_local;
28730 + uint32_t xhib_pcgcctl;
28731 + uint32_t xhib_gpwrdn;
28732 +};
28733 +
28734 +struct dwc_otg_host_regs_backup {
28735 + uint32_t hcfg_local;
28736 + uint32_t haintmsk_local;
28737 + uint32_t hcintmsk_local[MAX_EPS_CHANNELS];
28738 + uint32_t hprt0_local;
28739 + uint32_t hfir_local;
28740 +};
28741 +
28742 +struct dwc_otg_dev_regs_backup {
28743 + uint32_t dcfg;
28744 + uint32_t dctl;
28745 + uint32_t daintmsk;
28746 + uint32_t diepmsk;
28747 + uint32_t doepmsk;
28748 + uint32_t diepctl[MAX_EPS_CHANNELS];
28749 + uint32_t dieptsiz[MAX_EPS_CHANNELS];
28750 + uint32_t diepdma[MAX_EPS_CHANNELS];
28751 +};
28752 +/**
28753 + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
28754 + * the DWC_otg controller acting in either host or device mode. It
28755 + * represents the programming view of the controller as a whole.
28756 + */
28757 +struct dwc_otg_core_if {
28758 + /** Parameters that define how the core should be configured.*/
28759 + dwc_otg_core_params_t *core_params;
28760 +
28761 + /** Core Global registers starting at offset 000h. */
28762 + dwc_otg_core_global_regs_t *core_global_regs;
28763 +
28764 + /** Device-specific information */
28765 + dwc_otg_dev_if_t *dev_if;
28766 + /** Host-specific information */
28767 + dwc_otg_host_if_t *host_if;
28768 +
28769 + /** Value from SNPSID register */
28770 + uint32_t snpsid;
28771 +
28772 + /*
28773 + * Set to 1 if the core PHY interface bits in USBCFG have been
28774 + * initialized.
28775 + */
28776 + uint8_t phy_init_done;
28777 +
28778 + /*
28779 + * SRP Success flag, set by srp success interrupt in FS I2C mode
28780 + */
28781 + uint8_t srp_success;
28782 + uint8_t srp_timer_started;
28783 + /** Timer for SRP. If it expires before SRP is successful
28784 + * clear the SRP. */
28785 + dwc_timer_t *srp_timer;
28786 +
28787 +#ifdef DWC_DEV_SRPCAP
28788 + /* This timer is needed to power on the hibernated host core if SRP is not
28789 + * initiated on connected SRP capable device for limited period of time
28790 + */
28791 + uint8_t pwron_timer_started;
28792 + dwc_timer_t *pwron_timer;
28793 +#endif
28794 + /* Common configuration information */
28795 + /** Power and Clock Gating Control Register */
28796 + volatile uint32_t *pcgcctl;
28797 +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
28798 +
28799 + /** Push/pop addresses for endpoints or host channels.*/
28800 + uint32_t *data_fifo[MAX_EPS_CHANNELS];
28801 +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
28802 +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
28803 +
28804 + /** Total RAM for FIFOs (Bytes) */
28805 + uint16_t total_fifo_size;
28806 + /** Size of Rx FIFO (Bytes) */
28807 + uint16_t rx_fifo_size;
28808 + /** Size of Non-periodic Tx FIFO (Bytes) */
28809 + uint16_t nperio_tx_fifo_size;
28810 +
28811 + /** 1 if DMA is enabled, 0 otherwise. */
28812 + uint8_t dma_enable;
28813 +
28814 + /** 1 if DMA descriptor is enabled, 0 otherwise. */
28815 + uint8_t dma_desc_enable;
28816 +
28817 + /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
28818 + uint8_t pti_enh_enable;
28819 +
28820 + /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
28821 + uint8_t multiproc_int_enable;
28822 +
28823 + /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
28824 + uint8_t en_multiple_tx_fifo;
28825 +
28826 + /** Set to 1 if multiple packets of a high-bandwidth transfer is in
28827 + * process of being queued */
28828 + uint8_t queuing_high_bandwidth;
28829 +
28830 + /** Hardware Configuration -- stored here for convenience.*/
28831 + hwcfg1_data_t hwcfg1;
28832 + hwcfg2_data_t hwcfg2;
28833 + hwcfg3_data_t hwcfg3;
28834 + hwcfg4_data_t hwcfg4;
28835 + fifosize_data_t hptxfsiz;
28836 +
28837 + /** Host and Device Configuration -- stored here for convenience.*/
28838 + hcfg_data_t hcfg;
28839 + dcfg_data_t dcfg;
28840 +
28841 + /** The operational State, during transations
28842 + * (a_host>>a_peripherial and b_device=>b_host) this may not
28843 + * match the core but allows the software to determine
28844 + * transitions.
28845 + */
28846 + uint8_t op_state;
28847 +
28848 + /**
28849 + * Set to 1 if the HCD needs to be restarted on a session request
28850 + * interrupt. This is required if no connector ID status change has
28851 + * occurred since the HCD was last disconnected.
28852 + */
28853 + uint8_t restart_hcd_on_session_req;
28854 +
28855 + /** HCD callbacks */
28856 + /** A-Device is a_host */
28857 +#define A_HOST (1)
28858 + /** A-Device is a_suspend */
28859 +#define A_SUSPEND (2)
28860 + /** A-Device is a_peripherial */
28861 +#define A_PERIPHERAL (3)
28862 + /** B-Device is operating as a Peripheral. */
28863 +#define B_PERIPHERAL (4)
28864 + /** B-Device is operating as a Host. */
28865 +#define B_HOST (5)
28866 +
28867 + /** HCD callbacks */
28868 + struct dwc_otg_cil_callbacks *hcd_cb;
28869 + /** PCD callbacks */
28870 + struct dwc_otg_cil_callbacks *pcd_cb;
28871 +
28872 + /** Device mode Periodic Tx FIFO Mask */
28873 + uint32_t p_tx_msk;
28874 + /** Device mode Periodic Tx FIFO Mask */
28875 + uint32_t tx_msk;
28876 +
28877 + /** Workqueue object used for handling several interrupts */
28878 + dwc_workq_t *wq_otg;
28879 +
28880 + /** Timer object used for handling "Wakeup Detected" Interrupt */
28881 + dwc_timer_t *wkp_timer;
28882 + /** This arrays used for debug purposes for DEV OUT NAK enhancement */
28883 + uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];
28884 + ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];
28885 + dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];
28886 +#ifdef DEBUG
28887 + uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
28888 +
28889 + hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
28890 + dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
28891 +
28892 + uint32_t hfnum_7_samples;
28893 + uint64_t hfnum_7_frrem_accum;
28894 + uint32_t hfnum_0_samples;
28895 + uint64_t hfnum_0_frrem_accum;
28896 + uint32_t hfnum_other_samples;
28897 + uint64_t hfnum_other_frrem_accum;
28898 +#endif
28899 +
28900 +#ifdef DWC_UTE_CFI
28901 + uint16_t pwron_rxfsiz;
28902 + uint16_t pwron_gnptxfsiz;
28903 + uint16_t pwron_txfsiz[15];
28904 +
28905 + uint16_t init_rxfsiz;
28906 + uint16_t init_gnptxfsiz;
28907 + uint16_t init_txfsiz[15];
28908 +#endif
28909 +
28910 + /** Lx state of device */
28911 + dwc_otg_lx_state_e lx_state;
28912 +
28913 + /** Saved Core Global registers */
28914 + struct dwc_otg_global_regs_backup *gr_backup;
28915 + /** Saved Host registers */
28916 + struct dwc_otg_host_regs_backup *hr_backup;
28917 + /** Saved Device registers */
28918 + struct dwc_otg_dev_regs_backup *dr_backup;
28919 +
28920 + /** Power Down Enable */
28921 + uint32_t power_down;
28922 +
28923 + /** ADP support Enable */
28924 + uint32_t adp_enable;
28925 +
28926 + /** ADP structure object */
28927 + dwc_otg_adp_t adp;
28928 +
28929 + /** hibernation/suspend flag */
28930 + int hibernation_suspend;
28931 +
28932 + /** Device mode extended hibernation flag */
28933 + int xhib;
28934 +
28935 + /** OTG revision supported */
28936 + uint32_t otg_ver;
28937 +
28938 + /** OTG status flag used for HNP polling */
28939 + uint8_t otg_sts;
28940 +
28941 + /** Pointer to either hcd->lock or pcd->lock */
28942 + dwc_spinlock_t *lock;
28943 +
28944 + /** Start predict NextEP based on Learning Queue if equal 1,
28945 + * also used as counter of disabled NP IN EP's */
28946 + uint8_t start_predict;
28947 +
28948 + /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and
28949 + * active, 0xff otherwise */
28950 + uint8_t nextep_seq[MAX_EPS_CHANNELS];
28951 +
28952 + /** Index of fisrt EP in nextep_seq array which should be re-enabled **/
28953 + uint8_t first_in_nextep_seq;
28954 +
28955 + /** Frame number while entering to ISR - needed for ISOCs **/
28956 + uint32_t frame_num;
28957 +
28958 +};
28959 +
28960 +#ifdef DEBUG
28961 +/*
28962 + * This function is called when transfer is timed out.
28963 + */
28964 +extern void hc_xfer_timeout(void *ptr);
28965 +#endif
28966 +
28967 +/*
28968 + * This function is called when transfer is timed out on endpoint.
28969 + */
28970 +extern void ep_xfer_timeout(void *ptr);
28971 +
28972 +/*
28973 + * The following functions are functions for works
28974 + * using during handling some interrupts
28975 + */
28976 +extern void w_conn_id_status_change(void *p);
28977 +
28978 +extern void w_wakeup_detected(void *p);
28979 +
28980 +/** Saves global register values into system memory. */
28981 +extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);
28982 +/** Saves device register values into system memory. */
28983 +extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);
28984 +/** Saves host register values into system memory. */
28985 +extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);
28986 +/** Restore global register values. */
28987 +extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);
28988 +/** Restore host register values. */
28989 +extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);
28990 +/** Restore device register values. */
28991 +extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,
28992 + int rem_wakeup);
28993 +extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);
28994 +extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,
28995 + int is_host);
28996 +
28997 +extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
28998 + int restore_mode, int reset);
28999 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
29000 + int rem_wakeup, int reset);
29001 +
29002 +/*
29003 + * The following functions support initialization of the CIL driver component
29004 + * and the DWC_otg controller.
29005 + */
29006 +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
29007 +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
29008 +
29009 +/** @name Device CIL Functions
29010 + * The following functions support managing the DWC_otg controller in device
29011 + * mode.
29012 + */
29013 +/**@{*/
29014 +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
29015 +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
29016 + uint32_t * _dest);
29017 +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
29018 +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29019 +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29020 +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29021 +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
29022 + dwc_ep_t * _ep);
29023 +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
29024 + dwc_ep_t * _ep);
29025 +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
29026 + dwc_ep_t * _ep);
29027 +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
29028 + dwc_ep_t * _ep);
29029 +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
29030 + dwc_ep_t * _ep, int _dma);
29031 +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29032 +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
29033 + dwc_ep_t * _ep);
29034 +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
29035 +
29036 +#ifdef DWC_EN_ISOC
29037 +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
29038 + dwc_ep_t * ep);
29039 +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
29040 + dwc_ep_t * ep);
29041 +#endif /* DWC_EN_ISOC */
29042 +/**@}*/
29043 +
29044 +/** @name Host CIL Functions
29045 + * The following functions support managing the DWC_otg controller in host
29046 + * mode.
29047 + */
29048 +/**@{*/
29049 +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29050 +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
29051 + dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
29052 +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29053 +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
29054 + dwc_hc_t * _hc);
29055 +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
29056 + dwc_hc_t * _hc);
29057 +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29058 +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
29059 + dwc_hc_t * _hc);
29060 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
29061 +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
29062 +
29063 +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,
29064 + dwc_hc_t * hc);
29065 +
29066 +extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);
29067 +
29068 +/* Macro used to clear one channel interrupt */
29069 +#define clear_hc_int(_hc_regs_, _intr_) \
29070 +do { \
29071 + hcint_data_t hcint_clear = {.d32 = 0}; \
29072 + hcint_clear.b._intr_ = 1; \
29073 + DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \
29074 +} while (0)
29075 +
29076 +/*
29077 + * Macro used to disable one channel interrupt. Channel interrupts are
29078 + * disabled when the channel is halted or released by the interrupt handler.
29079 + * There is no need to handle further interrupts of that type until the
29080 + * channel is re-assigned. In fact, subsequent handling may cause crashes
29081 + * because the channel structures are cleaned up when the channel is released.
29082 + */
29083 +#define disable_hc_int(_hc_regs_, _intr_) \
29084 +do { \
29085 + hcintmsk_data_t hcintmsk = {.d32 = 0}; \
29086 + hcintmsk.b._intr_ = 1; \
29087 + DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
29088 +} while (0)
29089 +
29090 +/**
29091 + * This function Reads HPRT0 in preparation to modify. It keeps the
29092 + * WC bits 0 so that if they are read as 1, they won't clear when you
29093 + * write it back
29094 + */
29095 +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
29096 +{
29097 + hprt0_data_t hprt0;
29098 + hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);
29099 + hprt0.b.prtena = 0;
29100 + hprt0.b.prtconndet = 0;
29101 + hprt0.b.prtenchng = 0;
29102 + hprt0.b.prtovrcurrchng = 0;
29103 + return hprt0.d32;
29104 +}
29105 +
29106 +/**@}*/
29107 +
29108 +/** @name Common CIL Functions
29109 + * The following functions support managing the DWC_otg controller in either
29110 + * device or host mode.
29111 + */
29112 +/**@{*/
29113 +
29114 +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
29115 + uint8_t * dest, uint16_t bytes);
29116 +
29117 +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
29118 +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
29119 +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
29120 +
29121 +/**
29122 + * This function returns the Core Interrupt register.
29123 + */
29124 +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
29125 +{
29126 + return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
29127 + DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
29128 +}
29129 +
29130 +/**
29131 + * This function returns the OTG Interrupt register.
29132 + */
29133 +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
29134 +{
29135 + return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));
29136 +}
29137 +
29138 +/**
29139 + * This function reads the Device All Endpoints Interrupt register and
29140 + * returns the IN endpoint interrupt bits.
29141 + */
29142 +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
29143 + core_if)
29144 +{
29145 +
29146 + uint32_t v;
29147 +
29148 + if (core_if->multiproc_int_enable) {
29149 + v = DWC_READ_REG32(&core_if->dev_if->
29150 + dev_global_regs->deachint) &
29151 + DWC_READ_REG32(&core_if->
29152 + dev_if->dev_global_regs->deachintmsk);
29153 + } else {
29154 + v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29155 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29156 + }
29157 + return (v & 0xffff);
29158 +}
29159 +
29160 +/**
29161 + * This function reads the Device All Endpoints Interrupt register and
29162 + * returns the OUT endpoint interrupt bits.
29163 + */
29164 +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
29165 + core_if)
29166 +{
29167 + uint32_t v;
29168 +
29169 + if (core_if->multiproc_int_enable) {
29170 + v = DWC_READ_REG32(&core_if->dev_if->
29171 + dev_global_regs->deachint) &
29172 + DWC_READ_REG32(&core_if->
29173 + dev_if->dev_global_regs->deachintmsk);
29174 + } else {
29175 + v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29176 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29177 + }
29178 +
29179 + return ((v & 0xffff0000) >> 16);
29180 +}
29181 +
29182 +/**
29183 + * This function returns the Device IN EP Interrupt register
29184 + */
29185 +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
29186 + dwc_ep_t * ep)
29187 +{
29188 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
29189 + uint32_t v, msk, emp;
29190 +
29191 + if (core_if->multiproc_int_enable) {
29192 + msk =
29193 + DWC_READ_REG32(&dev_if->
29194 + dev_global_regs->diepeachintmsk[ep->num]);
29195 + emp =
29196 + DWC_READ_REG32(&dev_if->
29197 + dev_global_regs->dtknqr4_fifoemptymsk);
29198 + msk |= ((emp >> ep->num) & 0x1) << 7;
29199 + v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29200 + } else {
29201 + msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
29202 + emp =
29203 + DWC_READ_REG32(&dev_if->
29204 + dev_global_regs->dtknqr4_fifoemptymsk);
29205 + msk |= ((emp >> ep->num) & 0x1) << 7;
29206 + v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29207 + }
29208 +
29209 + return v;
29210 +}
29211 +
29212 +/**
29213 + * This function returns the Device OUT EP Interrupt register
29214 + */
29215 +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
29216 + _core_if, dwc_ep_t * _ep)
29217 +{
29218 + dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
29219 + uint32_t v;
29220 + doepmsk_data_t msk = {.d32 = 0 };
29221 +
29222 + if (_core_if->multiproc_int_enable) {
29223 + msk.d32 =
29224 + DWC_READ_REG32(&dev_if->
29225 + dev_global_regs->doepeachintmsk[_ep->num]);
29226 + if (_core_if->pti_enh_enable) {
29227 + msk.b.pktdrpsts = 1;
29228 + }
29229 + v = DWC_READ_REG32(&dev_if->
29230 + out_ep_regs[_ep->num]->doepint) & msk.d32;
29231 + } else {
29232 + msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
29233 + if (_core_if->pti_enh_enable) {
29234 + msk.b.pktdrpsts = 1;
29235 + }
29236 + v = DWC_READ_REG32(&dev_if->
29237 + out_ep_regs[_ep->num]->doepint) & msk.d32;
29238 + }
29239 + return v;
29240 +}
29241 +
29242 +/**
29243 + * This function returns the Host All Channel Interrupt register
29244 + */
29245 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
29246 + _core_if)
29247 +{
29248 + return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));
29249 +}
29250 +
29251 +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
29252 + _core_if, dwc_hc_t * _hc)
29253 +{
29254 + return (DWC_READ_REG32
29255 + (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
29256 +}
29257 +
29258 +/**
29259 + * This function returns the mode of the operation, host or device.
29260 + *
29261 + * @return 0 - Device Mode, 1 - Host Mode
29262 + */
29263 +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
29264 +{
29265 + return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
29266 +}
29267 +
29268 +/**@}*/
29269 +
29270 +/**
29271 + * DWC_otg CIL callback structure. This structure allows the HCD and
29272 + * PCD to register functions used for starting and stopping the PCD
29273 + * and HCD for role change on for a DRD.
29274 + */
29275 +typedef struct dwc_otg_cil_callbacks {
29276 + /** Start function for role change */
29277 + int (*start) (void *_p);
29278 + /** Stop Function for role change */
29279 + int (*stop) (void *_p);
29280 + /** Disconnect Function for role change */
29281 + int (*disconnect) (void *_p);
29282 + /** Resume/Remote wakeup Function */
29283 + int (*resume_wakeup) (void *_p);
29284 + /** Suspend function */
29285 + int (*suspend) (void *_p);
29286 + /** Session Start (SRP) */
29287 + int (*session_start) (void *_p);
29288 +#ifdef CONFIG_USB_DWC_OTG_LPM
29289 + /** Sleep (switch to L0 state) */
29290 + int (*sleep) (void *_p);
29291 +#endif
29292 + /** Pointer passed to start() and stop() */
29293 + void *p;
29294 +} dwc_otg_cil_callbacks_t;
29295 +
29296 +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
29297 + dwc_otg_cil_callbacks_t * _cb,
29298 + void *_p);
29299 +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
29300 + dwc_otg_cil_callbacks_t * _cb,
29301 + void *_p);
29302 +
29303 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);
29304 +
29305 +//////////////////////////////////////////////////////////////////////
29306 +/** Start the HCD. Helper function for using the HCD callbacks.
29307 + *
29308 + * @param core_if Programming view of DWC_otg controller.
29309 + */
29310 +static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)
29311 +{
29312 + if (core_if->hcd_cb && core_if->hcd_cb->start) {
29313 + core_if->hcd_cb->start(core_if->hcd_cb->p);
29314 + }
29315 +}
29316 +
29317 +/** Stop the HCD. Helper function for using the HCD callbacks.
29318 + *
29319 + * @param core_if Programming view of DWC_otg controller.
29320 + */
29321 +static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)
29322 +{
29323 + if (core_if->hcd_cb && core_if->hcd_cb->stop) {
29324 + core_if->hcd_cb->stop(core_if->hcd_cb->p);
29325 + }
29326 +}
29327 +
29328 +/** Disconnect the HCD. Helper function for using the HCD callbacks.
29329 + *
29330 + * @param core_if Programming view of DWC_otg controller.
29331 + */
29332 +static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)
29333 +{
29334 + if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
29335 + core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
29336 + }
29337 +}
29338 +
29339 +/** Inform the HCD the a New Session has begun. Helper function for
29340 + * using the HCD callbacks.
29341 + *
29342 + * @param core_if Programming view of DWC_otg controller.
29343 + */
29344 +static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)
29345 +{
29346 + if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
29347 + core_if->hcd_cb->session_start(core_if->hcd_cb->p);
29348 + }
29349 +}
29350 +
29351 +#ifdef CONFIG_USB_DWC_OTG_LPM
29352 +/**
29353 + * Inform the HCD about LPM sleep.
29354 + * Helper function for using the HCD callbacks.
29355 + *
29356 + * @param core_if Programming view of DWC_otg controller.
29357 + */
29358 +static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)
29359 +{
29360 + if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
29361 + core_if->hcd_cb->sleep(core_if->hcd_cb->p);
29362 + }
29363 +}
29364 +#endif
29365 +
29366 +/** Resume the HCD. Helper function for using the HCD callbacks.
29367 + *
29368 + * @param core_if Programming view of DWC_otg controller.
29369 + */
29370 +static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)
29371 +{
29372 + if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
29373 + core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
29374 + }
29375 +}
29376 +
29377 +/** Start the PCD. Helper function for using the PCD callbacks.
29378 + *
29379 + * @param core_if Programming view of DWC_otg controller.
29380 + */
29381 +static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)
29382 +{
29383 + if (core_if->pcd_cb && core_if->pcd_cb->start) {
29384 + core_if->pcd_cb->start(core_if->pcd_cb->p);
29385 + }
29386 +}
29387 +
29388 +/** Stop the PCD. Helper function for using the PCD callbacks.
29389 + *
29390 + * @param core_if Programming view of DWC_otg controller.
29391 + */
29392 +static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)
29393 +{
29394 + if (core_if->pcd_cb && core_if->pcd_cb->stop) {
29395 + core_if->pcd_cb->stop(core_if->pcd_cb->p);
29396 + }
29397 +}
29398 +
29399 +/** Suspend the PCD. Helper function for using the PCD callbacks.
29400 + *
29401 + * @param core_if Programming view of DWC_otg controller.
29402 + */
29403 +static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)
29404 +{
29405 + if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
29406 + core_if->pcd_cb->suspend(core_if->pcd_cb->p);
29407 + }
29408 +}
29409 +
29410 +/** Resume the PCD. Helper function for using the PCD callbacks.
29411 + *
29412 + * @param core_if Programming view of DWC_otg controller.
29413 + */
29414 +static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)
29415 +{
29416 + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
29417 + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
29418 + }
29419 +}
29420 +
29421 +//////////////////////////////////////////////////////////////////////
29422 +
29423 +#endif
29424 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29425 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100
29426 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2013-07-06 15:25:50.000000000 +0100
29427 @@ -0,0 +1,1571 @@
29428 +/* ==========================================================================
29429 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
29430 + * $Revision: #32 $
29431 + * $Date: 2012/08/10 $
29432 + * $Change: 2047372 $
29433 + *
29434 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
29435 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
29436 + * otherwise expressly agreed to in writing between Synopsys and you.
29437 + *
29438 + * The Software IS NOT an item of Licensed Software or Licensed Product under
29439 + * any End User Software License Agreement or Agreement for Licensed Product
29440 + * with Synopsys or any supplement thereto. You are permitted to use and
29441 + * redistribute this Software in source and binary forms, with or without
29442 + * modification, provided that redistributions of source code must retain this
29443 + * notice. You may not view, use, disclose, copy or distribute this file or
29444 + * any information contained herein except pursuant to this license grant from
29445 + * Synopsys. If you do not agree with this notice, including the disclaimer
29446 + * below, then you are not authorized to use the Software.
29447 + *
29448 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
29449 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29450 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29451 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
29452 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29453 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29454 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29455 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29456 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29457 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29458 + * DAMAGE.
29459 + * ========================================================================== */
29460 +
29461 +/** @file
29462 + *
29463 + * The Core Interface Layer provides basic services for accessing and
29464 + * managing the DWC_otg hardware. These services are used by both the
29465 + * Host Controller Driver and the Peripheral Controller Driver.
29466 + *
29467 + * This file contains the Common Interrupt handlers.
29468 + */
29469 +#include "dwc_os.h"
29470 +#include "dwc_otg_regs.h"
29471 +#include "dwc_otg_cil.h"
29472 +#include "dwc_otg_driver.h"
29473 +#include "dwc_otg_pcd.h"
29474 +#include "dwc_otg_hcd.h"
29475 +#include "dwc_otg_mphi_fix.h"
29476 +
29477 +extern bool fiq_fix_enable;
29478 +
29479 +#ifdef DEBUG
29480 +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
29481 +{
29482 + return (core_if->op_state == A_HOST ? "a_host" :
29483 + (core_if->op_state == A_SUSPEND ? "a_suspend" :
29484 + (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
29485 + (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
29486 + (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
29487 +}
29488 +#endif
29489 +
29490 +/** This function will log a debug message
29491 + *
29492 + * @param core_if Programming view of DWC_otg controller.
29493 + */
29494 +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
29495 +{
29496 + gintsts_data_t gintsts;
29497 + DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
29498 + dwc_otg_mode(core_if) ? "Host" : "Device");
29499 +
29500 + /* Clear interrupt */
29501 + gintsts.d32 = 0;
29502 + gintsts.b.modemismatch = 1;
29503 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29504 + return 1;
29505 +}
29506 +
29507 +/**
29508 + * This function handles the OTG Interrupts. It reads the OTG
29509 + * Interrupt Register (GOTGINT) to determine what interrupt has
29510 + * occurred.
29511 + *
29512 + * @param core_if Programming view of DWC_otg controller.
29513 + */
29514 +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
29515 +{
29516 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
29517 + gotgint_data_t gotgint;
29518 + gotgctl_data_t gotgctl;
29519 + gintmsk_data_t gintmsk;
29520 + gpwrdn_data_t gpwrdn;
29521 +
29522 + gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
29523 + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29524 + DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
29525 + op_state_str(core_if));
29526 +
29527 + if (gotgint.b.sesenddet) {
29528 + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29529 + "Session End Detected++ (%s)\n",
29530 + op_state_str(core_if));
29531 + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29532 +
29533 + if (core_if->op_state == B_HOST) {
29534 + cil_pcd_start(core_if);
29535 + core_if->op_state = B_PERIPHERAL;
29536 + } else {
29537 + /* If not B_HOST and Device HNP still set. HNP
29538 + * Did not succeed!*/
29539 + if (gotgctl.b.devhnpen) {
29540 + DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
29541 + __DWC_ERROR("Device Not Connected/Responding!\n");
29542 + }
29543 +
29544 + /* If Session End Detected the B-Cable has
29545 + * been disconnected. */
29546 + /* Reset PCD and Gadget driver to a
29547 + * clean state. */
29548 + core_if->lx_state = DWC_OTG_L0;
29549 + DWC_SPINUNLOCK(core_if->lock);
29550 + cil_pcd_stop(core_if);
29551 + DWC_SPINLOCK(core_if->lock);
29552 +
29553 + if (core_if->adp_enable) {
29554 + if (core_if->power_down == 2) {
29555 + gpwrdn.d32 = 0;
29556 + gpwrdn.b.pwrdnswtch = 1;
29557 + DWC_MODIFY_REG32(&core_if->
29558 + core_global_regs->
29559 + gpwrdn, gpwrdn.d32, 0);
29560 + }
29561 +
29562 + gpwrdn.d32 = 0;
29563 + gpwrdn.b.pmuintsel = 1;
29564 + gpwrdn.b.pmuactv = 1;
29565 + DWC_MODIFY_REG32(&core_if->core_global_regs->
29566 + gpwrdn, 0, gpwrdn.d32);
29567 +
29568 + dwc_otg_adp_sense_start(core_if);
29569 + }
29570 + }
29571 +
29572 + gotgctl.d32 = 0;
29573 + gotgctl.b.devhnpen = 1;
29574 + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29575 + }
29576 + if (gotgint.b.sesreqsucstschng) {
29577 + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29578 + "Session Reqeust Success Status Change++\n");
29579 + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29580 + if (gotgctl.b.sesreqscs) {
29581 +
29582 + if ((core_if->core_params->phy_type ==
29583 + DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
29584 + core_if->srp_success = 1;
29585 + } else {
29586 + DWC_SPINUNLOCK(core_if->lock);
29587 + cil_pcd_resume(core_if);
29588 + DWC_SPINLOCK(core_if->lock);
29589 + /* Clear Session Request */
29590 + gotgctl.d32 = 0;
29591 + gotgctl.b.sesreq = 1;
29592 + DWC_MODIFY_REG32(&global_regs->gotgctl,
29593 + gotgctl.d32, 0);
29594 + }
29595 + }
29596 + }
29597 + if (gotgint.b.hstnegsucstschng) {
29598 + /* Print statements during the HNP interrupt handling
29599 + * can cause it to fail.*/
29600 + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29601 + /* WA for 3.00a- HW is not setting cur_mode, even sometimes
29602 + * this does not help*/
29603 + if (core_if->snpsid >= OTG_CORE_REV_3_00a)
29604 + dwc_udelay(100);
29605 + if (gotgctl.b.hstnegscs) {
29606 + if (dwc_otg_is_host_mode(core_if)) {
29607 + core_if->op_state = B_HOST;
29608 + /*
29609 + * Need to disable SOF interrupt immediately.
29610 + * When switching from device to host, the PCD
29611 + * interrupt handler won't handle the
29612 + * interrupt if host mode is already set. The
29613 + * HCD interrupt handler won't get called if
29614 + * the HCD state is HALT. This means that the
29615 + * interrupt does not get handled and Linux
29616 + * complains loudly.
29617 + */
29618 + gintmsk.d32 = 0;
29619 + gintmsk.b.sofintr = 1;
29620 + DWC_MODIFY_REG32(&global_regs->gintmsk,
29621 + gintmsk.d32, 0);
29622 + /* Call callback function with spin lock released */
29623 + DWC_SPINUNLOCK(core_if->lock);
29624 + cil_pcd_stop(core_if);
29625 + /*
29626 + * Initialize the Core for Host mode.
29627 + */
29628 + cil_hcd_start(core_if);
29629 + DWC_SPINLOCK(core_if->lock);
29630 + core_if->op_state = B_HOST;
29631 + }
29632 + } else {
29633 + gotgctl.d32 = 0;
29634 + gotgctl.b.hnpreq = 1;
29635 + gotgctl.b.devhnpen = 1;
29636 + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29637 + DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
29638 + __DWC_ERROR("Device Not Connected/Responding\n");
29639 + }
29640 + }
29641 + if (gotgint.b.hstnegdet) {
29642 + /* The disconnect interrupt is set at the same time as
29643 + * Host Negotiation Detected. During the mode
29644 + * switch all interrupts are cleared so the disconnect
29645 + * interrupt handler will not get executed.
29646 + */
29647 + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29648 + "Host Negotiation Detected++ (%s)\n",
29649 + (dwc_otg_is_host_mode(core_if) ? "Host" :
29650 + "Device"));
29651 + if (dwc_otg_is_device_mode(core_if)) {
29652 + DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
29653 + core_if->op_state);
29654 + DWC_SPINUNLOCK(core_if->lock);
29655 + cil_hcd_disconnect(core_if);
29656 + cil_pcd_start(core_if);
29657 + DWC_SPINLOCK(core_if->lock);
29658 + core_if->op_state = A_PERIPHERAL;
29659 + } else {
29660 + /*
29661 + * Need to disable SOF interrupt immediately. When
29662 + * switching from device to host, the PCD interrupt
29663 + * handler won't handle the interrupt if host mode is
29664 + * already set. The HCD interrupt handler won't get
29665 + * called if the HCD state is HALT. This means that
29666 + * the interrupt does not get handled and Linux
29667 + * complains loudly.
29668 + */
29669 + gintmsk.d32 = 0;
29670 + gintmsk.b.sofintr = 1;
29671 + DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
29672 + DWC_SPINUNLOCK(core_if->lock);
29673 + cil_pcd_stop(core_if);
29674 + cil_hcd_start(core_if);
29675 + DWC_SPINLOCK(core_if->lock);
29676 + core_if->op_state = A_HOST;
29677 + }
29678 + }
29679 + if (gotgint.b.adevtoutchng) {
29680 + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29681 + "A-Device Timeout Change++\n");
29682 + }
29683 + if (gotgint.b.debdone) {
29684 + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
29685 + }
29686 +
29687 + /* Clear GOTGINT */
29688 + DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
29689 +
29690 + return 1;
29691 +}
29692 +
29693 +void w_conn_id_status_change(void *p)
29694 +{
29695 + dwc_otg_core_if_t *core_if = p;
29696 + uint32_t count = 0;
29697 + gotgctl_data_t gotgctl = {.d32 = 0 };
29698 +
29699 + gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
29700 + DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
29701 + DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
29702 +
29703 + /* B-Device connector (Device Mode) */
29704 + if (gotgctl.b.conidsts) {
29705 + /* Wait for switch to device mode. */
29706 + while (!dwc_otg_is_device_mode(core_if)) {
29707 + DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
29708 + (dwc_otg_is_host_mode(core_if) ? "Host" :
29709 + "Peripheral"));
29710 + dwc_mdelay(100);
29711 + if (++count > 10000)
29712 + break;
29713 + }
29714 + DWC_ASSERT(++count < 10000,
29715 + "Connection id status change timed out");
29716 + core_if->op_state = B_PERIPHERAL;
29717 + dwc_otg_core_init(core_if);
29718 + dwc_otg_enable_global_interrupts(core_if);
29719 + cil_pcd_start(core_if);
29720 + } else {
29721 + /* A-Device connector (Host Mode) */
29722 + while (!dwc_otg_is_host_mode(core_if)) {
29723 + DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
29724 + (dwc_otg_is_host_mode(core_if) ? "Host" :
29725 + "Peripheral"));
29726 + dwc_mdelay(100);
29727 + if (++count > 10000)
29728 + break;
29729 + }
29730 + DWC_ASSERT(++count < 10000,
29731 + "Connection id status change timed out");
29732 + core_if->op_state = A_HOST;
29733 + /*
29734 + * Initialize the Core for Host mode.
29735 + */
29736 + dwc_otg_core_init(core_if);
29737 + dwc_otg_enable_global_interrupts(core_if);
29738 + cil_hcd_start(core_if);
29739 + }
29740 +}
29741 +
29742 +/**
29743 + * This function handles the Connector ID Status Change Interrupt. It
29744 + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
29745 + * is a Device to Host Mode transition or a Host Mode to Device
29746 + * Transition.
29747 + *
29748 + * This only occurs when the cable is connected/removed from the PHY
29749 + * connector.
29750 + *
29751 + * @param core_if Programming view of DWC_otg controller.
29752 + */
29753 +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
29754 +{
29755 +
29756 + /*
29757 + * Need to disable SOF interrupt immediately. If switching from device
29758 + * to host, the PCD interrupt handler won't handle the interrupt if
29759 + * host mode is already set. The HCD interrupt handler won't get
29760 + * called if the HCD state is HALT. This means that the interrupt does
29761 + * not get handled and Linux complains loudly.
29762 + */
29763 + gintmsk_data_t gintmsk = {.d32 = 0 };
29764 + gintsts_data_t gintsts = {.d32 = 0 };
29765 +
29766 + gintmsk.b.sofintr = 1;
29767 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
29768 +
29769 + DWC_DEBUGPL(DBG_CIL,
29770 + " ++Connector ID Status Change Interrupt++ (%s)\n",
29771 + (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
29772 +
29773 + DWC_SPINUNLOCK(core_if->lock);
29774 +
29775 + /*
29776 + * Need to schedule a work, as there are possible DELAY function calls
29777 + * Release lock before scheduling workq as it holds spinlock during scheduling
29778 + */
29779 +
29780 + DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
29781 + core_if, "connection id status change");
29782 + DWC_SPINLOCK(core_if->lock);
29783 +
29784 + /* Set flag and clear interrupt */
29785 + gintsts.b.conidstschng = 1;
29786 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29787 +
29788 + return 1;
29789 +}
29790 +
29791 +/**
29792 + * This interrupt indicates that a device is initiating the Session
29793 + * Request Protocol to request the host to turn on bus power so a new
29794 + * session can begin. The handler responds by turning on bus power. If
29795 + * the DWC_otg controller is in low power mode, the handler brings the
29796 + * controller out of low power mode before turning on bus power.
29797 + *
29798 + * @param core_if Programming view of DWC_otg controller.
29799 + */
29800 +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
29801 +{
29802 + gintsts_data_t gintsts;
29803 +
29804 +#ifndef DWC_HOST_ONLY
29805 + DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
29806 +
29807 + if (dwc_otg_is_device_mode(core_if)) {
29808 + DWC_PRINTF("SRP: Device mode\n");
29809 + } else {
29810 + hprt0_data_t hprt0;
29811 + DWC_PRINTF("SRP: Host mode\n");
29812 +
29813 + /* Turn on the port power bit. */
29814 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
29815 + hprt0.b.prtpwr = 1;
29816 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
29817 +
29818 + /* Start the Connection timer. So a message can be displayed
29819 + * if connect does not occur within 10 seconds. */
29820 + cil_hcd_session_start(core_if);
29821 + }
29822 +#endif
29823 +
29824 + /* Clear interrupt */
29825 + gintsts.d32 = 0;
29826 + gintsts.b.sessreqintr = 1;
29827 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29828 +
29829 + return 1;
29830 +}
29831 +
29832 +void w_wakeup_detected(void *p)
29833 +{
29834 + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
29835 + /*
29836 + * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
29837 + * so that OPT tests pass with all PHYs).
29838 + */
29839 + hprt0_data_t hprt0 = {.d32 = 0 };
29840 +#if 0
29841 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
29842 + /* Restart the Phy Clock */
29843 + pcgcctl.b.stoppclk = 1;
29844 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
29845 + dwc_udelay(10);
29846 +#endif //0
29847 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
29848 + DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
29849 +// dwc_mdelay(70);
29850 + hprt0.b.prtres = 0; /* Resume */
29851 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
29852 + DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
29853 + DWC_READ_REG32(core_if->host_if->hprt0));
29854 +
29855 + cil_hcd_resume(core_if);
29856 +
29857 + /** Change to L0 state*/
29858 + core_if->lx_state = DWC_OTG_L0;
29859 +}
29860 +
29861 +/**
29862 + * This interrupt indicates that the DWC_otg controller has detected a
29863 + * resume or remote wakeup sequence. If the DWC_otg controller is in
29864 + * low power mode, the handler must brings the controller out of low
29865 + * power mode. The controller automatically begins resume
29866 + * signaling. The handler schedules a time to stop resume signaling.
29867 + */
29868 +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
29869 +{
29870 + gintsts_data_t gintsts;
29871 +
29872 + DWC_DEBUGPL(DBG_ANY,
29873 + "++Resume and Remote Wakeup Detected Interrupt++\n");
29874 +
29875 + DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
29876 +
29877 + if (dwc_otg_is_device_mode(core_if)) {
29878 + dctl_data_t dctl = {.d32 = 0 };
29879 + DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
29880 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
29881 + dsts));
29882 + if (core_if->lx_state == DWC_OTG_L2) {
29883 +#ifdef PARTIAL_POWER_DOWN
29884 + if (core_if->hwcfg4.b.power_optimiz) {
29885 + pcgcctl_data_t power = {.d32 = 0 };
29886 +
29887 + power.d32 = DWC_READ_REG32(core_if->pcgcctl);
29888 + DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
29889 + power.d32);
29890 +
29891 + power.b.stoppclk = 0;
29892 + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
29893 +
29894 + power.b.pwrclmp = 0;
29895 + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
29896 +
29897 + power.b.rstpdwnmodule = 0;
29898 + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
29899 + }
29900 +#endif
29901 + /* Clear the Remote Wakeup Signaling */
29902 + dctl.b.rmtwkupsig = 1;
29903 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
29904 + dctl, dctl.d32, 0);
29905 +
29906 + DWC_SPINUNLOCK(core_if->lock);
29907 + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
29908 + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
29909 + }
29910 + DWC_SPINLOCK(core_if->lock);
29911 + } else {
29912 + glpmcfg_data_t lpmcfg;
29913 + lpmcfg.d32 =
29914 + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
29915 + lpmcfg.b.hird_thres &= (~(1 << 4));
29916 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
29917 + lpmcfg.d32);
29918 + }
29919 + /** Change to L0 state*/
29920 + core_if->lx_state = DWC_OTG_L0;
29921 + } else {
29922 + if (core_if->lx_state != DWC_OTG_L1) {
29923 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
29924 +
29925 + /* Restart the Phy Clock */
29926 + pcgcctl.b.stoppclk = 1;
29927 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
29928 + DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
29929 + } else {
29930 + /** Change to L0 state*/
29931 + core_if->lx_state = DWC_OTG_L0;
29932 + }
29933 + }
29934 +
29935 + /* Clear interrupt */
29936 + gintsts.d32 = 0;
29937 + gintsts.b.wkupintr = 1;
29938 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29939 +
29940 + return 1;
29941 +}
29942 +
29943 +/**
29944 + * This interrupt indicates that the Wakeup Logic has detected a
29945 + * Device disconnect.
29946 + */
29947 +static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
29948 +{
29949 + gpwrdn_data_t gpwrdn = { .d32 = 0 };
29950 + gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
29951 + gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
29952 +
29953 + DWC_PRINTF("%s called\n", __FUNCTION__);
29954 +
29955 + if (!core_if->hibernation_suspend) {
29956 + DWC_PRINTF("Already exited from Hibernation\n");
29957 + return 1;
29958 + }
29959 +
29960 + /* Switch on the voltage to the core */
29961 + gpwrdn.b.pwrdnswtch = 1;
29962 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
29963 + dwc_udelay(10);
29964 +
29965 + /* Reset the core */
29966 + gpwrdn.d32 = 0;
29967 + gpwrdn.b.pwrdnrstn = 1;
29968 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
29969 + dwc_udelay(10);
29970 +
29971 + /* Disable power clamps*/
29972 + gpwrdn.d32 = 0;
29973 + gpwrdn.b.pwrdnclmp = 1;
29974 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
29975 +
29976 + /* Remove reset the core signal */
29977 + gpwrdn.d32 = 0;
29978 + gpwrdn.b.pwrdnrstn = 1;
29979 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
29980 + dwc_udelay(10);
29981 +
29982 + /* Disable PMU interrupt */
29983 + gpwrdn.d32 = 0;
29984 + gpwrdn.b.pmuintsel = 1;
29985 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
29986 +
29987 + core_if->hibernation_suspend = 0;
29988 +
29989 + /* Disable PMU */
29990 + gpwrdn.d32 = 0;
29991 + gpwrdn.b.pmuactv = 1;
29992 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
29993 + dwc_udelay(10);
29994 +
29995 + if (gpwrdn_temp.b.idsts) {
29996 + core_if->op_state = B_PERIPHERAL;
29997 + dwc_otg_core_init(core_if);
29998 + dwc_otg_enable_global_interrupts(core_if);
29999 + cil_pcd_start(core_if);
30000 + } else {
30001 + core_if->op_state = A_HOST;
30002 + dwc_otg_core_init(core_if);
30003 + dwc_otg_enable_global_interrupts(core_if);
30004 + cil_hcd_start(core_if);
30005 + }
30006 +
30007 + return 1;
30008 +}
30009 +
30010 +/**
30011 + * This interrupt indicates that the Wakeup Logic has detected a
30012 + * remote wakeup sequence.
30013 + */
30014 +static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30015 +{
30016 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30017 + DWC_DEBUGPL(DBG_ANY,
30018 + "++Powerdown Remote Wakeup Detected Interrupt++\n");
30019 +
30020 + if (!core_if->hibernation_suspend) {
30021 + DWC_PRINTF("Already exited from Hibernation\n");
30022 + return 1;
30023 + }
30024 +
30025 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30026 + if (gpwrdn.b.idsts) { // Device Mode
30027 + if ((core_if->power_down == 2)
30028 + && (core_if->hibernation_suspend == 1)) {
30029 + dwc_otg_device_hibernation_restore(core_if, 0, 0);
30030 + }
30031 + } else {
30032 + if ((core_if->power_down == 2)
30033 + && (core_if->hibernation_suspend == 1)) {
30034 + dwc_otg_host_hibernation_restore(core_if, 1, 0);
30035 + }
30036 + }
30037 + return 1;
30038 +}
30039 +
30040 +static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
30041 +{
30042 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30043 + gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30044 + dwc_otg_core_if_t *core_if = otg_dev->core_if;
30045 +
30046 + DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30047 + gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30048 + if (core_if->power_down == 2) {
30049 + if (!core_if->hibernation_suspend) {
30050 + DWC_PRINTF("Already exited from Hibernation\n");
30051 + return 1;
30052 + }
30053 + DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
30054 + /* Switch on the voltage to the core */
30055 + gpwrdn.b.pwrdnswtch = 1;
30056 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30057 + dwc_udelay(10);
30058 +
30059 + /* Reset the core */
30060 + gpwrdn.d32 = 0;
30061 + gpwrdn.b.pwrdnrstn = 1;
30062 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30063 + dwc_udelay(10);
30064 +
30065 + /* Disable power clamps */
30066 + gpwrdn.d32 = 0;
30067 + gpwrdn.b.pwrdnclmp = 1;
30068 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30069 +
30070 + /* Remove reset the core signal */
30071 + gpwrdn.d32 = 0;
30072 + gpwrdn.b.pwrdnrstn = 1;
30073 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30074 + dwc_udelay(10);
30075 +
30076 + /* Disable PMU interrupt */
30077 + gpwrdn.d32 = 0;
30078 + gpwrdn.b.pmuintsel = 1;
30079 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30080 +
30081 + /*Indicates that we are exiting from hibernation */
30082 + core_if->hibernation_suspend = 0;
30083 +
30084 + /* Disable PMU */
30085 + gpwrdn.d32 = 0;
30086 + gpwrdn.b.pmuactv = 1;
30087 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30088 + dwc_udelay(10);
30089 +
30090 + gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
30091 + if (gpwrdn.b.dis_vbus == 1) {
30092 + gpwrdn.d32 = 0;
30093 + gpwrdn.b.dis_vbus = 1;
30094 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30095 + }
30096 +
30097 + if (gpwrdn_temp.b.idsts) {
30098 + core_if->op_state = B_PERIPHERAL;
30099 + dwc_otg_core_init(core_if);
30100 + dwc_otg_enable_global_interrupts(core_if);
30101 + cil_pcd_start(core_if);
30102 + } else {
30103 + core_if->op_state = A_HOST;
30104 + dwc_otg_core_init(core_if);
30105 + dwc_otg_enable_global_interrupts(core_if);
30106 + cil_hcd_start(core_if);
30107 + }
30108 + }
30109 +
30110 + if (core_if->adp_enable) {
30111 + uint8_t is_host = 0;
30112 + DWC_SPINUNLOCK(core_if->lock);
30113 + /* Change the core_if's lock to hcd/pcd lock depend on mode? */
30114 +#ifndef DWC_HOST_ONLY
30115 + if (gpwrdn_temp.b.idsts)
30116 + core_if->lock = otg_dev->pcd->lock;
30117 +#endif
30118 +#ifndef DWC_DEVICE_ONLY
30119 + if (!gpwrdn_temp.b.idsts) {
30120 + core_if->lock = otg_dev->hcd->lock;
30121 + is_host = 1;
30122 + }
30123 +#endif
30124 + DWC_PRINTF("RESTART ADP\n");
30125 + if (core_if->adp.probe_enabled)
30126 + dwc_otg_adp_probe_stop(core_if);
30127 + if (core_if->adp.sense_enabled)
30128 + dwc_otg_adp_sense_stop(core_if);
30129 + if (core_if->adp.sense_timer_started)
30130 + DWC_TIMER_CANCEL(core_if->adp.sense_timer);
30131 + if (core_if->adp.vbuson_timer_started)
30132 + DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
30133 + core_if->adp.probe_timer_values[0] = -1;
30134 + core_if->adp.probe_timer_values[1] = -1;
30135 + core_if->adp.sense_timer_started = 0;
30136 + core_if->adp.vbuson_timer_started = 0;
30137 + core_if->adp.probe_counter = 0;
30138 + core_if->adp.gpwrdn = 0;
30139 +
30140 + /* Disable PMU and restart ADP */
30141 + gpwrdn_temp.d32 = 0;
30142 + gpwrdn_temp.b.pmuactv = 1;
30143 + gpwrdn_temp.b.pmuintsel = 1;
30144 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30145 + DWC_PRINTF("Check point 1\n");
30146 + dwc_mdelay(110);
30147 + dwc_otg_adp_start(core_if, is_host);
30148 + DWC_SPINLOCK(core_if->lock);
30149 + }
30150 +
30151 +
30152 + return 1;
30153 +}
30154 +
30155 +static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
30156 +{
30157 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30158 + int32_t otg_cap_param = core_if->core_params->otg_cap;
30159 + DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30160 +
30161 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30162 + if (core_if->power_down == 2) {
30163 + if (!core_if->hibernation_suspend) {
30164 + DWC_PRINTF("Already exited from Hibernation\n");
30165 + return 1;
30166 + }
30167 +
30168 + if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30169 + otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
30170 + gpwrdn.b.bsessvld == 0) {
30171 + /* Save gpwrdn register for further usage if stschng interrupt */
30172 + core_if->gr_backup->gpwrdn_local =
30173 + DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30174 + /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
30175 + return 1;
30176 + }
30177 +
30178 + /* Switch on the voltage to the core */
30179 + gpwrdn.d32 = 0;
30180 + gpwrdn.b.pwrdnswtch = 1;
30181 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30182 + dwc_udelay(10);
30183 +
30184 + /* Reset the core */
30185 + gpwrdn.d32 = 0;
30186 + gpwrdn.b.pwrdnrstn = 1;
30187 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30188 + dwc_udelay(10);
30189 +
30190 + /* Disable power clamps */
30191 + gpwrdn.d32 = 0;
30192 + gpwrdn.b.pwrdnclmp = 1;
30193 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30194 +
30195 + /* Remove reset the core signal */
30196 + gpwrdn.d32 = 0;
30197 + gpwrdn.b.pwrdnrstn = 1;
30198 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30199 + dwc_udelay(10);
30200 +
30201 + /* Disable PMU interrupt */
30202 + gpwrdn.d32 = 0;
30203 + gpwrdn.b.pmuintsel = 1;
30204 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30205 + dwc_udelay(10);
30206 +
30207 + /*Indicates that we are exiting from hibernation */
30208 + core_if->hibernation_suspend = 0;
30209 +
30210 + /* Disable PMU */
30211 + gpwrdn.d32 = 0;
30212 + gpwrdn.b.pmuactv = 1;
30213 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30214 + dwc_udelay(10);
30215 +
30216 + core_if->op_state = B_PERIPHERAL;
30217 + dwc_otg_core_init(core_if);
30218 + dwc_otg_enable_global_interrupts(core_if);
30219 + cil_pcd_start(core_if);
30220 +
30221 + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30222 + otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
30223 + /*
30224 + * Initiate SRP after initial ADP probe.
30225 + */
30226 + dwc_otg_initiate_srp(core_if);
30227 + }
30228 + }
30229 +
30230 + return 1;
30231 +}
30232 +/**
30233 + * This interrupt indicates that the Wakeup Logic has detected a
30234 + * status change either on IDDIG or BSessVld.
30235 + */
30236 +static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
30237 +{
30238 + int retval;
30239 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30240 + gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30241 + dwc_otg_core_if_t *core_if = otg_dev->core_if;
30242 +
30243 + DWC_PRINTF("%s called\n", __FUNCTION__);
30244 +
30245 + if (core_if->power_down == 2) {
30246 + if (core_if->hibernation_suspend <= 0) {
30247 + DWC_PRINTF("Already exited from Hibernation\n");
30248 + return 1;
30249 + } else
30250 + gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
30251 +
30252 + } else {
30253 + gpwrdn_temp.d32 = core_if->adp.gpwrdn;
30254 + }
30255 +
30256 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30257 +
30258 + if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
30259 + retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
30260 + } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
30261 + retval = dwc_otg_handle_pwrdn_session_change(core_if);
30262 + }
30263 +
30264 + return retval;
30265 +}
30266 +
30267 +/**
30268 + * This interrupt indicates that the Wakeup Logic has detected a
30269 + * SRP.
30270 + */
30271 +static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
30272 +{
30273 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30274 +
30275 + DWC_PRINTF("%s called\n", __FUNCTION__);
30276 +
30277 + if (!core_if->hibernation_suspend) {
30278 + DWC_PRINTF("Already exited from Hibernation\n");
30279 + return 1;
30280 + }
30281 +#ifdef DWC_DEV_SRPCAP
30282 + if (core_if->pwron_timer_started) {
30283 + core_if->pwron_timer_started = 0;
30284 + DWC_TIMER_CANCEL(core_if->pwron_timer);
30285 + }
30286 +#endif
30287 +
30288 + /* Switch on the voltage to the core */
30289 + gpwrdn.b.pwrdnswtch = 1;
30290 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30291 + dwc_udelay(10);
30292 +
30293 + /* Reset the core */
30294 + gpwrdn.d32 = 0;
30295 + gpwrdn.b.pwrdnrstn = 1;
30296 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30297 + dwc_udelay(10);
30298 +
30299 + /* Disable power clamps */
30300 + gpwrdn.d32 = 0;
30301 + gpwrdn.b.pwrdnclmp = 1;
30302 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30303 +
30304 + /* Remove reset the core signal */
30305 + gpwrdn.d32 = 0;
30306 + gpwrdn.b.pwrdnrstn = 1;
30307 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30308 + dwc_udelay(10);
30309 +
30310 + /* Disable PMU interrupt */
30311 + gpwrdn.d32 = 0;
30312 + gpwrdn.b.pmuintsel = 1;
30313 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30314 +
30315 + /* Indicates that we are exiting from hibernation */
30316 + core_if->hibernation_suspend = 0;
30317 +
30318 + /* Disable PMU */
30319 + gpwrdn.d32 = 0;
30320 + gpwrdn.b.pmuactv = 1;
30321 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30322 + dwc_udelay(10);
30323 +
30324 + /* Programm Disable VBUS to 0 */
30325 + gpwrdn.d32 = 0;
30326 + gpwrdn.b.dis_vbus = 1;
30327 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30328 +
30329 + /*Initialize the core as Host */
30330 + core_if->op_state = A_HOST;
30331 + dwc_otg_core_init(core_if);
30332 + dwc_otg_enable_global_interrupts(core_if);
30333 + cil_hcd_start(core_if);
30334 +
30335 + return 1;
30336 +}
30337 +
30338 +/** This interrupt indicates that restore command after Hibernation
30339 + * was completed by the core. */
30340 +int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
30341 +{
30342 + pcgcctl_data_t pcgcctl;
30343 + DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
30344 +
30345 + //TODO De-assert restore signal. 8.a
30346 + pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
30347 + if (pcgcctl.b.restoremode == 1) {
30348 + gintmsk_data_t gintmsk = {.d32 = 0 };
30349 + /*
30350 + * If restore mode is Remote Wakeup,
30351 + * unmask Remote Wakeup interrupt.
30352 + */
30353 + gintmsk.b.wkupintr = 1;
30354 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
30355 + 0, gintmsk.d32);
30356 + }
30357 +
30358 + return 1;
30359 +}
30360 +
30361 +/**
30362 + * This interrupt indicates that a device has been disconnected from
30363 + * the root port.
30364 + */
30365 +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
30366 +{
30367 + gintsts_data_t gintsts;
30368 +
30369 + DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
30370 + (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
30371 + op_state_str(core_if));
30372 +
30373 +/** @todo Consolidate this if statement. */
30374 +#ifndef DWC_HOST_ONLY
30375 + if (core_if->op_state == B_HOST) {
30376 + /* If in device mode Disconnect and stop the HCD, then
30377 + * start the PCD. */
30378 + DWC_SPINUNLOCK(core_if->lock);
30379 + cil_hcd_disconnect(core_if);
30380 + cil_pcd_start(core_if);
30381 + DWC_SPINLOCK(core_if->lock);
30382 + core_if->op_state = B_PERIPHERAL;
30383 + } else if (dwc_otg_is_device_mode(core_if)) {
30384 + gotgctl_data_t gotgctl = {.d32 = 0 };
30385 + gotgctl.d32 =
30386 + DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
30387 + if (gotgctl.b.hstsethnpen == 1) {
30388 + /* Do nothing, if HNP in process the OTG
30389 + * interrupt "Host Negotiation Detected"
30390 + * interrupt will do the mode switch.
30391 + */
30392 + } else if (gotgctl.b.devhnpen == 0) {
30393 + /* If in device mode Disconnect and stop the HCD, then
30394 + * start the PCD. */
30395 + DWC_SPINUNLOCK(core_if->lock);
30396 + cil_hcd_disconnect(core_if);
30397 + cil_pcd_start(core_if);
30398 + DWC_SPINLOCK(core_if->lock);
30399 + core_if->op_state = B_PERIPHERAL;
30400 + } else {
30401 + DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
30402 + }
30403 + } else {
30404 + if (core_if->op_state == A_HOST) {
30405 + /* A-Cable still connected but device disconnected. */
30406 + cil_hcd_disconnect(core_if);
30407 + if (core_if->adp_enable) {
30408 + gpwrdn_data_t gpwrdn = { .d32 = 0 };
30409 + cil_hcd_stop(core_if);
30410 + /* Enable Power Down Logic */
30411 + gpwrdn.b.pmuintsel = 1;
30412 + gpwrdn.b.pmuactv = 1;
30413 + DWC_MODIFY_REG32(&core_if->core_global_regs->
30414 + gpwrdn, 0, gpwrdn.d32);
30415 + dwc_otg_adp_probe_start(core_if);
30416 +
30417 + /* Power off the core */
30418 + if (core_if->power_down == 2) {
30419 + gpwrdn.d32 = 0;
30420 + gpwrdn.b.pwrdnswtch = 1;
30421 + DWC_MODIFY_REG32
30422 + (&core_if->core_global_regs->gpwrdn,
30423 + gpwrdn.d32, 0);
30424 + }
30425 + }
30426 + }
30427 + }
30428 +#endif
30429 + /* Change to L3(OFF) state */
30430 + core_if->lx_state = DWC_OTG_L3;
30431 +
30432 + gintsts.d32 = 0;
30433 + gintsts.b.disconnect = 1;
30434 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30435 + return 1;
30436 +}
30437 +
30438 +/**
30439 + * This interrupt indicates that SUSPEND state has been detected on
30440 + * the USB.
30441 + *
30442 + * For HNP the USB Suspend interrupt signals the change from
30443 + * "a_peripheral" to "a_host".
30444 + *
30445 + * When power management is enabled the core will be put in low power
30446 + * mode.
30447 + */
30448 +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
30449 +{
30450 + dsts_data_t dsts;
30451 + gintsts_data_t gintsts;
30452 + dcfg_data_t dcfg;
30453 +
30454 + DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
30455 +
30456 + if (dwc_otg_is_device_mode(core_if)) {
30457 + /* Check the Device status register to determine if the Suspend
30458 + * state is active. */
30459 + dsts.d32 =
30460 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
30461 + DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
30462 + DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
30463 + "HWCFG4.power Optimize=%d\n",
30464 + dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
30465 +
30466 +#ifdef PARTIAL_POWER_DOWN
30467 +/** @todo Add a module parameter for power management. */
30468 +
30469 + if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
30470 + pcgcctl_data_t power = {.d32 = 0 };
30471 + DWC_DEBUGPL(DBG_CIL, "suspend\n");
30472 +
30473 + power.b.pwrclmp = 1;
30474 + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30475 +
30476 + power.b.rstpdwnmodule = 1;
30477 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30478 +
30479 + power.b.stoppclk = 1;
30480 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30481 +
30482 + } else {
30483 + DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
30484 + }
30485 +#endif
30486 + /* PCD callback for suspend. Release the lock inside of callback function */
30487 + cil_pcd_suspend(core_if);
30488 + if (core_if->power_down == 2)
30489 + {
30490 + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30491 + DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
30492 + DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
30493 +
30494 + if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30495 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
30496 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30497 + gusbcfg_data_t gusbcfg = {.d32 = 0 };
30498 +
30499 + /* Change to L2(suspend) state */
30500 + core_if->lx_state = DWC_OTG_L2;
30501 +
30502 + /* Clear interrupt in gintsts */
30503 + gintsts.d32 = 0;
30504 + gintsts.b.usbsuspend = 1;
30505 + DWC_WRITE_REG32(&core_if->core_global_regs->
30506 + gintsts, gintsts.d32);
30507 + DWC_PRINTF("Start of hibernation completed\n");
30508 + dwc_otg_save_global_regs(core_if);
30509 + dwc_otg_save_dev_regs(core_if);
30510 +
30511 + gusbcfg.d32 =
30512 + DWC_READ_REG32(&core_if->core_global_regs->
30513 + gusbcfg);
30514 + if (gusbcfg.b.ulpi_utmi_sel == 1) {
30515 + /* ULPI interface */
30516 + /* Suspend the Phy Clock */
30517 + pcgcctl.d32 = 0;
30518 + pcgcctl.b.stoppclk = 1;
30519 + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30520 + pcgcctl.d32);
30521 + dwc_udelay(10);
30522 + gpwrdn.b.pmuactv = 1;
30523 + DWC_MODIFY_REG32(&core_if->
30524 + core_global_regs->
30525 + gpwrdn, 0, gpwrdn.d32);
30526 + } else {
30527 + /* UTMI+ Interface */
30528 + gpwrdn.b.pmuactv = 1;
30529 + DWC_MODIFY_REG32(&core_if->
30530 + core_global_regs->
30531 + gpwrdn, 0, gpwrdn.d32);
30532 + dwc_udelay(10);
30533 + pcgcctl.b.stoppclk = 1;
30534 + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30535 + pcgcctl.d32);
30536 + dwc_udelay(10);
30537 + }
30538 +
30539 + /* Set flag to indicate that we are in hibernation */
30540 + core_if->hibernation_suspend = 1;
30541 + /* Enable interrupts from wake up logic */
30542 + gpwrdn.d32 = 0;
30543 + gpwrdn.b.pmuintsel = 1;
30544 + DWC_MODIFY_REG32(&core_if->core_global_regs->
30545 + gpwrdn, 0, gpwrdn.d32);
30546 + dwc_udelay(10);
30547 +
30548 + /* Unmask device mode interrupts in GPWRDN */
30549 + gpwrdn.d32 = 0;
30550 + gpwrdn.b.rst_det_msk = 1;
30551 + gpwrdn.b.lnstchng_msk = 1;
30552 + gpwrdn.b.sts_chngint_msk = 1;
30553 + DWC_MODIFY_REG32(&core_if->core_global_regs->
30554 + gpwrdn, 0, gpwrdn.d32);
30555 + dwc_udelay(10);
30556 +
30557 + /* Enable Power Down Clamp */
30558 + gpwrdn.d32 = 0;
30559 + gpwrdn.b.pwrdnclmp = 1;
30560 + DWC_MODIFY_REG32(&core_if->core_global_regs->
30561 + gpwrdn, 0, gpwrdn.d32);
30562 + dwc_udelay(10);
30563 +
30564 + /* Switch off VDD */
30565 + gpwrdn.d32 = 0;
30566 + gpwrdn.b.pwrdnswtch = 1;
30567 + DWC_MODIFY_REG32(&core_if->core_global_regs->
30568 + gpwrdn, 0, gpwrdn.d32);
30569 +
30570 + /* Save gpwrdn register for further usage if stschng interrupt */
30571 + core_if->gr_backup->gpwrdn_local =
30572 + DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30573 + DWC_PRINTF("Hibernation completed\n");
30574 +
30575 + return 1;
30576 + }
30577 + } else if (core_if->power_down == 3) {
30578 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
30579 + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30580 + DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);
30581 + DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);
30582 +
30583 + if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30584 + DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");
30585 + core_if->xhib = 1;
30586 +
30587 + /* Clear interrupt in gintsts */
30588 + gintsts.d32 = 0;
30589 + gintsts.b.usbsuspend = 1;
30590 + DWC_WRITE_REG32(&core_if->core_global_regs->
30591 + gintsts, gintsts.d32);
30592 +
30593 + dwc_otg_save_global_regs(core_if);
30594 + dwc_otg_save_dev_regs(core_if);
30595 +
30596 + /* Wait for 10 PHY clocks */
30597 + dwc_udelay(10);
30598 +
30599 + /* Program GPIO register while entering to xHib */
30600 + DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);
30601 +
30602 + pcgcctl.b.enbl_extnd_hiber = 1;
30603 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30604 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30605 +
30606 + pcgcctl.d32 = 0;
30607 + pcgcctl.b.extnd_hiber_pwrclmp = 1;
30608 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30609 +
30610 + pcgcctl.d32 = 0;
30611 + pcgcctl.b.extnd_hiber_switch = 1;
30612 + core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30613 + core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;
30614 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30615 +
30616 + DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");
30617 +
30618 + return 1;
30619 + }
30620 + }
30621 + } else {
30622 + if (core_if->op_state == A_PERIPHERAL) {
30623 + DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
30624 + /* Clear the a_peripheral flag, back to a_host. */
30625 + DWC_SPINUNLOCK(core_if->lock);
30626 + cil_pcd_stop(core_if);
30627 + cil_hcd_start(core_if);
30628 + DWC_SPINLOCK(core_if->lock);
30629 + core_if->op_state = A_HOST;
30630 + }
30631 + }
30632 +
30633 + /* Change to L2(suspend) state */
30634 + core_if->lx_state = DWC_OTG_L2;
30635 +
30636 + /* Clear interrupt */
30637 + gintsts.d32 = 0;
30638 + gintsts.b.usbsuspend = 1;
30639 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30640 +
30641 + return 1;
30642 +}
30643 +
30644 +static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)
30645 +{
30646 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30647 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
30648 + gahbcfg_data_t gahbcfg = {.d32 = 0 };
30649 +
30650 + dwc_udelay(10);
30651 +
30652 + /* Program GPIO register while entering to xHib */
30653 + DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
30654 +
30655 + pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
30656 + pcgcctl.b.extnd_hiber_pwrclmp = 0;
30657 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30658 + dwc_udelay(10);
30659 +
30660 + gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
30661 + gpwrdn.b.restore = 1;
30662 + DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
30663 + dwc_udelay(10);
30664 +
30665 + restore_lpm_i2c_regs(core_if);
30666 +
30667 + pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30668 + pcgcctl.b.max_xcvrselect = 1;
30669 + pcgcctl.b.ess_reg_restored = 0;
30670 + pcgcctl.b.extnd_hiber_switch = 0;
30671 + pcgcctl.b.extnd_hiber_pwrclmp = 0;
30672 + pcgcctl.b.enbl_extnd_hiber = 1;
30673 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30674 +
30675 + gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
30676 + gahbcfg.b.glblintrmsk = 1;
30677 + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
30678 +
30679 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
30680 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
30681 +
30682 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
30683 + core_if->gr_backup->gusbcfg_local);
30684 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
30685 + core_if->dr_backup->dcfg);
30686 +
30687 + pcgcctl.d32 = 0;
30688 + pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30689 + pcgcctl.b.max_xcvrselect = 1;
30690 + pcgcctl.d32 |= 0x608;
30691 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30692 + dwc_udelay(10);
30693 +
30694 + pcgcctl.d32 = 0;
30695 + pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30696 + pcgcctl.b.max_xcvrselect = 1;
30697 + pcgcctl.b.ess_reg_restored = 1;
30698 + pcgcctl.b.enbl_extnd_hiber = 1;
30699 + pcgcctl.b.rstpdwnmodule = 1;
30700 + pcgcctl.b.restoremode = 1;
30701 + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30702 +
30703 + DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30704 +
30705 + return 1;
30706 +}
30707 +
30708 +#ifdef CONFIG_USB_DWC_OTG_LPM
30709 +/**
30710 + * This function hadles LPM transaction received interrupt.
30711 + */
30712 +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
30713 +{
30714 + glpmcfg_data_t lpmcfg;
30715 + gintsts_data_t gintsts;
30716 +
30717 + if (!core_if->core_params->lpm_enable) {
30718 + DWC_PRINTF("Unexpected LPM interrupt\n");
30719 + }
30720 +
30721 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30722 + DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
30723 +
30724 + if (dwc_otg_is_host_mode(core_if)) {
30725 + cil_hcd_sleep(core_if);
30726 + } else {
30727 + lpmcfg.b.hird_thres |= (1 << 4);
30728 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30729 + lpmcfg.d32);
30730 + }
30731 +
30732 + /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
30733 + dwc_udelay(10);
30734 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30735 + if (lpmcfg.b.prt_sleep_sts) {
30736 + /* Save the current state */
30737 + core_if->lx_state = DWC_OTG_L1;
30738 + }
30739 +
30740 + /* Clear interrupt */
30741 + gintsts.d32 = 0;
30742 + gintsts.b.lpmtranrcvd = 1;
30743 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30744 + return 1;
30745 +}
30746 +#endif /* CONFIG_USB_DWC_OTG_LPM */
30747 +
30748 +/**
30749 + * This function returns the Core Interrupt register.
30750 + */
30751 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
30752 +{
30753 + gahbcfg_data_t gahbcfg = {.d32 = 0 };
30754 + gintsts_data_t gintsts;
30755 + gintmsk_data_t gintmsk;
30756 + gintmsk_data_t gintmsk_common = {.d32 = 0 };
30757 + gintmsk_common.b.wkupintr = 1;
30758 + gintmsk_common.b.sessreqintr = 1;
30759 + gintmsk_common.b.conidstschng = 1;
30760 + gintmsk_common.b.otgintr = 1;
30761 + gintmsk_common.b.modemismatch = 1;
30762 + gintmsk_common.b.disconnect = 1;
30763 + gintmsk_common.b.usbsuspend = 1;
30764 +#ifdef CONFIG_USB_DWC_OTG_LPM
30765 + gintmsk_common.b.lpmtranrcvd = 1;
30766 +#endif
30767 + gintmsk_common.b.restoredone = 1;
30768 + /** @todo: The port interrupt occurs while in device
30769 + * mode. Added code to CIL to clear the interrupt for now!
30770 + */
30771 + gintmsk_common.b.portintr = 1;
30772 +
30773 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
30774 + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
30775 + gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
30776 +
30777 +#ifdef DEBUG
30778 + /* if any common interrupts set */
30779 + if (gintsts.d32 & gintmsk_common.d32) {
30780 + DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n",
30781 + gintsts.d32, gintmsk.d32);
30782 + }
30783 +#endif
30784 + if (!fiq_fix_enable){
30785 + if (gahbcfg.b.glblintrmsk)
30786 + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
30787 + else
30788 + return 0;
30789 + }
30790 + else {
30791 + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
30792 + }
30793 +
30794 +}
30795 +
30796 +/* MACRO for clearing interupt bits in GPWRDN register */
30797 +#define CLEAR_GPWRDN_INTR(__core_if,__intr) \
30798 +do { \
30799 + gpwrdn_data_t gpwrdn = {.d32=0}; \
30800 + gpwrdn.b.__intr = 1; \
30801 + DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
30802 + 0, gpwrdn.d32); \
30803 +} while (0)
30804 +
30805 +/**
30806 + * Common interrupt handler.
30807 + *
30808 + * The common interrupts are those that occur in both Host and Device mode.
30809 + * This handler handles the following interrupts:
30810 + * - Mode Mismatch Interrupt
30811 + * - Disconnect Interrupt
30812 + * - OTG Interrupt
30813 + * - Connector ID Status Change Interrupt
30814 + * - Session Request Interrupt.
30815 + * - Resume / Remote Wakeup Detected Interrupt.
30816 + * - LPM Transaction Received Interrupt
30817 + * - ADP Transaction Received Interrupt
30818 + *
30819 + */
30820 +int32_t dwc_otg_handle_common_intr(void *dev)
30821 +{
30822 + int retval = 0;
30823 + gintsts_data_t gintsts;
30824 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30825 + dwc_otg_device_t *otg_dev = dev;
30826 + dwc_otg_core_if_t *core_if = otg_dev->core_if;
30827 + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30828 + if (dwc_otg_is_device_mode(core_if))
30829 + core_if->frame_num = dwc_otg_get_frame_number(core_if);
30830 +
30831 + if (core_if->lock)
30832 + DWC_SPINLOCK(core_if->lock);
30833 +
30834 + if (core_if->power_down == 3 && core_if->xhib == 1) {
30835 + DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
30836 + retval |= dwc_otg_handle_xhib_exit_intr(core_if);
30837 + core_if->xhib = 2;
30838 + if (core_if->lock)
30839 + DWC_SPINUNLOCK(core_if->lock);
30840 +
30841 + return retval;
30842 + }
30843 +
30844 + if (core_if->hibernation_suspend <= 0) {
30845 + gintsts.d32 = dwc_otg_read_common_intr(core_if);
30846 +
30847 + if (gintsts.b.modemismatch) {
30848 + retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
30849 + }
30850 + if (gintsts.b.otgintr) {
30851 + retval |= dwc_otg_handle_otg_intr(core_if);
30852 + }
30853 + if (gintsts.b.conidstschng) {
30854 + retval |=
30855 + dwc_otg_handle_conn_id_status_change_intr(core_if);
30856 + }
30857 + if (gintsts.b.disconnect) {
30858 + retval |= dwc_otg_handle_disconnect_intr(core_if);
30859 + }
30860 + if (gintsts.b.sessreqintr) {
30861 + retval |= dwc_otg_handle_session_req_intr(core_if);
30862 + }
30863 + if (gintsts.b.wkupintr) {
30864 + retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
30865 + }
30866 + if (gintsts.b.usbsuspend) {
30867 + retval |= dwc_otg_handle_usb_suspend_intr(core_if);
30868 + }
30869 +#ifdef CONFIG_USB_DWC_OTG_LPM
30870 + if (gintsts.b.lpmtranrcvd) {
30871 + retval |= dwc_otg_handle_lpm_intr(core_if);
30872 + }
30873 +#endif
30874 + if (gintsts.b.restoredone) {
30875 + gintsts.d32 = 0;
30876 + if (core_if->power_down == 2)
30877 + core_if->hibernation_suspend = -1;
30878 + else if (core_if->power_down == 3 && core_if->xhib == 2) {
30879 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
30880 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
30881 + dctl_data_t dctl = {.d32 = 0 };
30882 +
30883 + DWC_WRITE_REG32(&core_if->core_global_regs->
30884 + gintsts, 0xFFFFFFFF);
30885 +
30886 + DWC_DEBUGPL(DBG_ANY,
30887 + "RESTORE DONE generated\n");
30888 +
30889 + gpwrdn.b.restore = 1;
30890 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30891 + dwc_udelay(10);
30892 +
30893 + pcgcctl.b.rstpdwnmodule = 1;
30894 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30895 +
30896 + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);
30897 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);
30898 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);
30899 + dwc_udelay(50);
30900 +
30901 + dctl.b.pwronprgdone = 1;
30902 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
30903 + dwc_udelay(10);
30904 +
30905 + dwc_otg_restore_global_regs(core_if);
30906 + dwc_otg_restore_dev_regs(core_if, 0);
30907 +
30908 + dctl.d32 = 0;
30909 + dctl.b.pwronprgdone = 1;
30910 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
30911 + dwc_udelay(10);
30912 +
30913 + pcgcctl.d32 = 0;
30914 + pcgcctl.b.enbl_extnd_hiber = 1;
30915 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30916 +
30917 + /* The core will be in ON STATE */
30918 + core_if->lx_state = DWC_OTG_L0;
30919 + core_if->xhib = 0;
30920 +
30921 + DWC_SPINUNLOCK(core_if->lock);
30922 + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
30923 + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
30924 + }
30925 + DWC_SPINLOCK(core_if->lock);
30926 +
30927 + }
30928 +
30929 + gintsts.b.restoredone = 1;
30930 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
30931 + DWC_PRINTF(" --Restore done interrupt received-- \n");
30932 + retval |= 1;
30933 + }
30934 + if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
30935 + /* The port interrupt occurs while in device mode with HPRT0
30936 + * Port Enable/Disable.
30937 + */
30938 + gintsts.d32 = 0;
30939 + gintsts.b.portintr = 1;
30940 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
30941 + retval |= 1;
30942 +
30943 + }
30944 + } else {
30945 + DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
30946 +
30947 + if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
30948 + CLEAR_GPWRDN_INTR(core_if, disconn_det);
30949 + if (gpwrdn.b.linestate == 0) {
30950 + dwc_otg_handle_pwrdn_disconnect_intr(core_if);
30951 + } else {
30952 + DWC_PRINTF("Disconnect detected while linestate is not 0\n");
30953 + }
30954 +
30955 + retval |= 1;
30956 + }
30957 + if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
30958 + CLEAR_GPWRDN_INTR(core_if, lnstschng);
30959 + /* remote wakeup from hibernation */
30960 + if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
30961 + dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
30962 + } else {
30963 + DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
30964 + }
30965 + retval |= 1;
30966 + }
30967 + if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
30968 + CLEAR_GPWRDN_INTR(core_if, rst_det);
30969 + if (gpwrdn.b.linestate == 0) {
30970 + DWC_PRINTF("Reset detected\n");
30971 + retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
30972 + }
30973 + }
30974 + if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
30975 + CLEAR_GPWRDN_INTR(core_if, srp_det);
30976 + dwc_otg_handle_pwrdn_srp_intr(core_if);
30977 + retval |= 1;
30978 + }
30979 + }
30980 + /* Handle ADP interrupt here */
30981 + if (gpwrdn.b.adp_int) {
30982 + DWC_PRINTF("ADP interrupt\n");
30983 + CLEAR_GPWRDN_INTR(core_if, adp_int);
30984 + dwc_otg_adp_handle_intr(core_if);
30985 + retval |= 1;
30986 + }
30987 + if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
30988 + DWC_PRINTF("STS CHNG interrupt asserted\n");
30989 + CLEAR_GPWRDN_INTR(core_if, sts_chngint);
30990 + dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
30991 +
30992 + retval |= 1;
30993 + }
30994 + if (core_if->lock)
30995 + DWC_SPINUNLOCK(core_if->lock);
30996 +
30997 + return retval;
30998 +}
30999 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31000 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100
31001 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2013-07-06 15:25:50.000000000 +0100
31002 @@ -0,0 +1,705 @@
31003 +/* ==========================================================================
31004 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
31005 + * $Revision: #13 $
31006 + * $Date: 2012/08/10 $
31007 + * $Change: 2047372 $
31008 + *
31009 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31010 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31011 + * otherwise expressly agreed to in writing between Synopsys and you.
31012 + *
31013 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31014 + * any End User Software License Agreement or Agreement for Licensed Product
31015 + * with Synopsys or any supplement thereto. You are permitted to use and
31016 + * redistribute this Software in source and binary forms, with or without
31017 + * modification, provided that redistributions of source code must retain this
31018 + * notice. You may not view, use, disclose, copy or distribute this file or
31019 + * any information contained herein except pursuant to this license grant from
31020 + * Synopsys. If you do not agree with this notice, including the disclaimer
31021 + * below, then you are not authorized to use the Software.
31022 + *
31023 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31024 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31025 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31026 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31027 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31028 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31029 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31030 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31031 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31032 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31033 + * DAMAGE.
31034 + * ========================================================================== */
31035 +#if !defined(__DWC_CORE_IF_H__)
31036 +#define __DWC_CORE_IF_H__
31037 +
31038 +#include "dwc_os.h"
31039 +
31040 +/** @file
31041 + * This file defines DWC_OTG Core API
31042 + */
31043 +
31044 +struct dwc_otg_core_if;
31045 +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
31046 +
31047 +/** Maximum number of Periodic FIFOs */
31048 +#define MAX_PERIO_FIFOS 15
31049 +/** Maximum number of Periodic FIFOs */
31050 +#define MAX_TX_FIFOS 15
31051 +
31052 +/** Maximum number of Endpoints/HostChannels */
31053 +#define MAX_EPS_CHANNELS 16
31054 +
31055 +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
31056 +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
31057 +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
31058 +
31059 +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
31060 +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
31061 +
31062 +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
31063 +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
31064 +
31065 +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
31066 +
31067 +/** This function should be called on every hardware interrupt. */
31068 +extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
31069 +
31070 +/** @name OTG Core Parameters */
31071 +/** @{ */
31072 +
31073 +/**
31074 + * Specifies the OTG capabilities. The driver will automatically
31075 + * detect the value for this parameter if none is specified.
31076 + * 0 - HNP and SRP capable (default)
31077 + * 1 - SRP Only capable
31078 + * 2 - No HNP/SRP capable
31079 + */
31080 +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
31081 +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
31082 +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
31083 +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
31084 +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
31085 +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
31086 +
31087 +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
31088 +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
31089 +#define dwc_param_opt_default 1
31090 +
31091 +/**
31092 + * Specifies whether to use slave or DMA mode for accessing the data
31093 + * FIFOs. The driver will automatically detect the value for this
31094 + * parameter if none is specified.
31095 + * 0 - Slave
31096 + * 1 - DMA (default, if available)
31097 + */
31098 +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
31099 + int32_t val);
31100 +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
31101 +#define dwc_param_dma_enable_default 1
31102 +
31103 +/**
31104 + * When DMA mode is enabled specifies whether to use
31105 + * address DMA or DMA Descritor mode for accessing the data
31106 + * FIFOs in device mode. The driver will automatically detect
31107 + * the value for this parameter if none is specified.
31108 + * 0 - address DMA
31109 + * 1 - DMA Descriptor(default, if available)
31110 + */
31111 +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
31112 + int32_t val);
31113 +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
31114 +//#define dwc_param_dma_desc_enable_default 1
31115 +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
31116 +
31117 +/** The DMA Burst size (applicable only for External DMA
31118 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
31119 + */
31120 +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
31121 + int32_t val);
31122 +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
31123 +#define dwc_param_dma_burst_size_default 32
31124 +
31125 +/**
31126 + * Specifies the maximum speed of operation in host and device mode.
31127 + * The actual speed depends on the speed of the attached device and
31128 + * the value of phy_type. The actual speed depends on the speed of the
31129 + * attached device.
31130 + * 0 - High Speed (default)
31131 + * 1 - Full Speed
31132 + */
31133 +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
31134 +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
31135 +#define dwc_param_speed_default 0
31136 +#define DWC_SPEED_PARAM_HIGH 0
31137 +#define DWC_SPEED_PARAM_FULL 1
31138 +
31139 +/** Specifies whether low power mode is supported when attached
31140 + * to a Full Speed or Low Speed device in host mode.
31141 + * 0 - Don't support low power mode (default)
31142 + * 1 - Support low power mode
31143 + */
31144 +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
31145 + core_if, int32_t val);
31146 +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
31147 + * core_if);
31148 +#define dwc_param_host_support_fs_ls_low_power_default 0
31149 +
31150 +/** Specifies the PHY clock rate in low power mode when connected to a
31151 + * Low Speed device in host mode. This parameter is applicable only if
31152 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
31153 + * then defaults to 6 MHZ otherwise 48 MHZ.
31154 + *
31155 + * 0 - 48 MHz
31156 + * 1 - 6 MHz
31157 + */
31158 +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31159 + core_if, int32_t val);
31160 +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31161 + core_if);
31162 +#define dwc_param_host_ls_low_power_phy_clk_default 0
31163 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
31164 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
31165 +
31166 +/**
31167 + * 0 - Use cC FIFO size parameters
31168 + * 1 - Allow dynamic FIFO sizing (default)
31169 + */
31170 +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
31171 + int32_t val);
31172 +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
31173 + core_if);
31174 +#define dwc_param_enable_dynamic_fifo_default 1
31175 +
31176 +/** Total number of 4-byte words in the data FIFO memory. This
31177 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
31178 + * Tx FIFOs.
31179 + * 32 to 32768 (default 8192)
31180 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
31181 + */
31182 +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
31183 + int32_t val);
31184 +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
31185 +//#define dwc_param_data_fifo_size_default 8192
31186 +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
31187 +
31188 +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
31189 + * FIFO sizing is enabled.
31190 + * 16 to 32768 (default 1064)
31191 + */
31192 +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
31193 + int32_t val);
31194 +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
31195 +#define dwc_param_dev_rx_fifo_size_default 1064
31196 +
31197 +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
31198 + * when dynamic FIFO sizing is enabled.
31199 + * 16 to 32768 (default 1024)
31200 + */
31201 +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31202 + core_if, int32_t val);
31203 +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31204 + core_if);
31205 +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
31206 +
31207 +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
31208 + * mode when dynamic FIFO sizing is enabled.
31209 + * 4 to 768 (default 256)
31210 + */
31211 +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
31212 + int32_t val, int fifo_num);
31213 +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
31214 + core_if, int fifo_num);
31215 +#define dwc_param_dev_perio_tx_fifo_size_default 256
31216 +
31217 +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
31218 + * FIFO sizing is enabled.
31219 + * 16 to 32768 (default 1024)
31220 + */
31221 +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
31222 + int32_t val);
31223 +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
31224 +//#define dwc_param_host_rx_fifo_size_default 1024
31225 +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
31226 +
31227 +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
31228 + * when Dynamic FIFO sizing is enabled in the core.
31229 + * 16 to 32768 (default 1024)
31230 + */
31231 +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31232 + core_if, int32_t val);
31233 +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31234 + core_if);
31235 +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
31236 +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
31237 +
31238 +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
31239 + * FIFO sizing is enabled.
31240 + * 16 to 32768 (default 1024)
31241 + */
31242 +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31243 + core_if, int32_t val);
31244 +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31245 + core_if);
31246 +//#define dwc_param_host_perio_tx_fifo_size_default 1024
31247 +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
31248 +
31249 +/** The maximum transfer size supported in bytes.
31250 + * 2047 to 65,535 (default 65,535)
31251 + */
31252 +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
31253 + int32_t val);
31254 +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
31255 +#define dwc_param_max_transfer_size_default 65535
31256 +
31257 +/** The maximum number of packets in a transfer.
31258 + * 15 to 511 (default 511)
31259 + */
31260 +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
31261 + int32_t val);
31262 +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
31263 +#define dwc_param_max_packet_count_default 511
31264 +
31265 +/** The number of host channel registers to use.
31266 + * 1 to 16 (default 12)
31267 + * Note: The FPGA configuration supports a maximum of 12 host channels.
31268 + */
31269 +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
31270 + int32_t val);
31271 +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
31272 +//#define dwc_param_host_channels_default 12
31273 +#define dwc_param_host_channels_default 8 // Broadcom BCM2708
31274 +
31275 +/** The number of endpoints in addition to EP0 available for device
31276 + * mode operations.
31277 + * 1 to 15 (default 6 IN and OUT)
31278 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
31279 + * endpoints in addition to EP0.
31280 + */
31281 +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
31282 + int32_t val);
31283 +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
31284 +#define dwc_param_dev_endpoints_default 6
31285 +
31286 +/**
31287 + * Specifies the type of PHY interface to use. By default, the driver
31288 + * will automatically detect the phy_type.
31289 + *
31290 + * 0 - Full Speed PHY
31291 + * 1 - UTMI+ (default)
31292 + * 2 - ULPI
31293 + */
31294 +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
31295 +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
31296 +#define DWC_PHY_TYPE_PARAM_FS 0
31297 +#define DWC_PHY_TYPE_PARAM_UTMI 1
31298 +#define DWC_PHY_TYPE_PARAM_ULPI 2
31299 +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
31300 +
31301 +/**
31302 + * Specifies the UTMI+ Data Width. This parameter is
31303 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
31304 + * PHY_TYPE, this parameter indicates the data width between
31305 + * the MAC and the ULPI Wrapper.) Also, this parameter is
31306 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
31307 + * to "8 and 16 bits", meaning that the core has been
31308 + * configured to work at either data path width.
31309 + *
31310 + * 8 or 16 bits (default 16)
31311 + */
31312 +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
31313 + int32_t val);
31314 +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
31315 +//#define dwc_param_phy_utmi_width_default 16
31316 +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708
31317 +
31318 +/**
31319 + * Specifies whether the ULPI operates at double or single
31320 + * data rate. This parameter is only applicable if PHY_TYPE is
31321 + * ULPI.
31322 + *
31323 + * 0 - single data rate ULPI interface with 8 bit wide data
31324 + * bus (default)
31325 + * 1 - double data rate ULPI interface with 4 bit wide data
31326 + * bus
31327 + */
31328 +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
31329 + int32_t val);
31330 +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
31331 +#define dwc_param_phy_ulpi_ddr_default 0
31332 +
31333 +/**
31334 + * Specifies whether to use the internal or external supply to
31335 + * drive the vbus with a ULPI phy.
31336 + */
31337 +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
31338 + int32_t val);
31339 +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
31340 +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
31341 +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
31342 +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
31343 +
31344 +/**
31345 + * Specifies whether to use the I2Cinterface for full speed PHY. This
31346 + * parameter is only applicable if PHY_TYPE is FS.
31347 + * 0 - No (default)
31348 + * 1 - Yes
31349 + */
31350 +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
31351 + int32_t val);
31352 +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
31353 +#define dwc_param_i2c_enable_default 0
31354 +
31355 +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
31356 + int32_t val);
31357 +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
31358 +#define dwc_param_ulpi_fs_ls_default 0
31359 +
31360 +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
31361 +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
31362 +#define dwc_param_ts_dline_default 0
31363 +
31364 +/**
31365 + * Specifies whether dedicated transmit FIFOs are
31366 + * enabled for non periodic IN endpoints in device mode
31367 + * 0 - No
31368 + * 1 - Yes
31369 + */
31370 +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
31371 + int32_t val);
31372 +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
31373 + core_if);
31374 +#define dwc_param_en_multiple_tx_fifo_default 1
31375 +
31376 +/** Number of 4-byte words in each of the Tx FIFOs in device
31377 + * mode when dynamic FIFO sizing is enabled.
31378 + * 4 to 768 (default 256)
31379 + */
31380 +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31381 + int fifo_num, int32_t val);
31382 +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31383 + int fifo_num);
31384 +#define dwc_param_dev_tx_fifo_size_default 768
31385 +
31386 +/** Thresholding enable flag-
31387 + * bit 0 - enable non-ISO Tx thresholding
31388 + * bit 1 - enable ISO Tx thresholding
31389 + * bit 2 - enable Rx thresholding
31390 + */
31391 +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
31392 +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
31393 +#define dwc_param_thr_ctl_default 0
31394 +
31395 +/** Thresholding length for Tx
31396 + * FIFOs in 32 bit DWORDs
31397 + */
31398 +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
31399 + int32_t val);
31400 +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
31401 +#define dwc_param_tx_thr_length_default 64
31402 +
31403 +/** Thresholding length for Rx
31404 + * FIFOs in 32 bit DWORDs
31405 + */
31406 +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
31407 + int32_t val);
31408 +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
31409 +#define dwc_param_rx_thr_length_default 64
31410 +
31411 +/**
31412 + * Specifies whether LPM (Link Power Management) support is enabled
31413 + */
31414 +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
31415 + int32_t val);
31416 +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
31417 +#define dwc_param_lpm_enable_default 1
31418 +
31419 +/**
31420 + * Specifies whether PTI enhancement is enabled
31421 + */
31422 +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
31423 + int32_t val);
31424 +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
31425 +#define dwc_param_pti_enable_default 0
31426 +
31427 +/**
31428 + * Specifies whether MPI enhancement is enabled
31429 + */
31430 +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
31431 + int32_t val);
31432 +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
31433 +#define dwc_param_mpi_enable_default 0
31434 +
31435 +/**
31436 + * Specifies whether ADP capability is enabled
31437 + */
31438 +extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,
31439 + int32_t val);
31440 +extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);
31441 +#define dwc_param_adp_enable_default 0
31442 +
31443 +/**
31444 + * Specifies whether IC_USB capability is enabled
31445 + */
31446 +
31447 +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
31448 + int32_t val);
31449 +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
31450 +#define dwc_param_ic_usb_cap_default 0
31451 +
31452 +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,
31453 + int32_t val);
31454 +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
31455 +#define dwc_param_ahb_thr_ratio_default 0
31456 +
31457 +extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,
31458 + int32_t val);
31459 +extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);
31460 +#define dwc_param_power_down_default 0
31461 +
31462 +extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,
31463 + int32_t val);
31464 +extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);
31465 +#define dwc_param_reload_ctl_default 0
31466 +
31467 +extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,
31468 + int32_t val);
31469 +extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
31470 +#define dwc_param_dev_out_nak_default 0
31471 +
31472 +extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
31473 + int32_t val);
31474 +extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
31475 +#define dwc_param_cont_on_bna_default 0
31476 +
31477 +extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
31478 + int32_t val);
31479 +extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
31480 +#define dwc_param_ahb_single_default 0
31481 +
31482 +extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
31483 +extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
31484 +#define dwc_param_otg_ver_default 0
31485 +
31486 +/** @} */
31487 +
31488 +/** @name Access to registers and bit-fields */
31489 +
31490 +/**
31491 + * Dump core registers and SPRAM
31492 + */
31493 +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
31494 +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
31495 +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
31496 +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
31497 +
31498 +/**
31499 + * Get host negotiation status.
31500 + */
31501 +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
31502 +
31503 +/**
31504 + * Get srp status
31505 + */
31506 +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
31507 +
31508 +/**
31509 + * Set hnpreq bit in the GOTGCTL register.
31510 + */
31511 +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
31512 +
31513 +/**
31514 + * Get Content of SNPSID register.
31515 + */
31516 +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
31517 +
31518 +/**
31519 + * Get current mode.
31520 + * Returns 0 if in device mode, and 1 if in host mode.
31521 + */
31522 +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
31523 +
31524 +/**
31525 + * Get value of hnpcapable field in the GUSBCFG register
31526 + */
31527 +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
31528 +/**
31529 + * Set value of hnpcapable field in the GUSBCFG register
31530 + */
31531 +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31532 +
31533 +/**
31534 + * Get value of srpcapable field in the GUSBCFG register
31535 + */
31536 +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
31537 +/**
31538 + * Set value of srpcapable field in the GUSBCFG register
31539 + */
31540 +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31541 +
31542 +/**
31543 + * Get value of devspeed field in the DCFG register
31544 + */
31545 +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
31546 +/**
31547 + * Set value of devspeed field in the DCFG register
31548 + */
31549 +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
31550 +
31551 +/**
31552 + * Get the value of busconnected field from the HPRT0 register
31553 + */
31554 +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
31555 +
31556 +/**
31557 + * Gets the device enumeration Speed.
31558 + */
31559 +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
31560 +
31561 +/**
31562 + * Get value of prtpwr field from the HPRT0 register
31563 + */
31564 +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
31565 +
31566 +/**
31567 + * Get value of flag indicating core state - hibernated or not
31568 + */
31569 +extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);
31570 +
31571 +/**
31572 + * Set value of prtpwr field from the HPRT0 register
31573 + */
31574 +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
31575 +
31576 +/**
31577 + * Get value of prtsusp field from the HPRT0 regsiter
31578 + */
31579 +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
31580 +/**
31581 + * Set value of prtpwr field from the HPRT0 register
31582 + */
31583 +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
31584 +
31585 +/**
31586 + * Get value of ModeChTimEn field from the HCFG regsiter
31587 + */
31588 +extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);
31589 +/**
31590 + * Set value of ModeChTimEn field from the HCFG regsiter
31591 + */
31592 +extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);
31593 +
31594 +/**
31595 + * Get value of Fram Interval field from the HFIR regsiter
31596 + */
31597 +extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);
31598 +/**
31599 + * Set value of Frame Interval field from the HFIR regsiter
31600 + */
31601 +extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);
31602 +
31603 +/**
31604 + * Set value of prtres field from the HPRT0 register
31605 + *FIXME Remove?
31606 + */
31607 +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
31608 +
31609 +/**
31610 + * Get value of rmtwkupsig bit in DCTL register
31611 + */
31612 +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
31613 +
31614 +/**
31615 + * Get value of prt_sleep_sts field from the GLPMCFG register
31616 + */
31617 +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
31618 +
31619 +/**
31620 + * Get value of rem_wkup_en field from the GLPMCFG register
31621 + */
31622 +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
31623 +
31624 +/**
31625 + * Get value of appl_resp field from the GLPMCFG register
31626 + */
31627 +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
31628 +/**
31629 + * Set value of appl_resp field from the GLPMCFG register
31630 + */
31631 +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
31632 +
31633 +/**
31634 + * Get value of hsic_connect field from the GLPMCFG register
31635 + */
31636 +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
31637 +/**
31638 + * Set value of hsic_connect field from the GLPMCFG register
31639 + */
31640 +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
31641 +
31642 +/**
31643 + * Get value of inv_sel_hsic field from the GLPMCFG register.
31644 + */
31645 +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
31646 +/**
31647 + * Set value of inv_sel_hsic field from the GLPMFG register.
31648 + */
31649 +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
31650 +
31651 +/*
31652 + * Some functions for accessing registers
31653 + */
31654 +
31655 +/**
31656 + * GOTGCTL register
31657 + */
31658 +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
31659 +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
31660 +
31661 +/**
31662 + * GUSBCFG register
31663 + */
31664 +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
31665 +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
31666 +
31667 +/**
31668 + * GRXFSIZ register
31669 + */
31670 +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
31671 +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31672 +
31673 +/**
31674 + * GNPTXFSIZ register
31675 + */
31676 +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
31677 +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31678 +
31679 +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
31680 +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
31681 +
31682 +/**
31683 + * GGPIO register
31684 + */
31685 +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
31686 +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
31687 +
31688 +/**
31689 + * GUID register
31690 + */
31691 +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
31692 +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
31693 +
31694 +/**
31695 + * HPRT0 register
31696 + */
31697 +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
31698 +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
31699 +
31700 +/**
31701 + * GHPTXFSIZE
31702 + */
31703 +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
31704 +
31705 +/** @} */
31706 +
31707 +#endif /* __DWC_CORE_IF_H__ */
31708 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
31709 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100
31710 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2013-07-06 15:25:50.000000000 +0100
31711 @@ -0,0 +1,117 @@
31712 +/* ==========================================================================
31713 + *
31714 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31715 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31716 + * otherwise expressly agreed to in writing between Synopsys and you.
31717 + *
31718 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31719 + * any End User Software License Agreement or Agreement for Licensed Product
31720 + * with Synopsys or any supplement thereto. You are permitted to use and
31721 + * redistribute this Software in source and binary forms, with or without
31722 + * modification, provided that redistributions of source code must retain this
31723 + * notice. You may not view, use, disclose, copy or distribute this file or
31724 + * any information contained herein except pursuant to this license grant from
31725 + * Synopsys. If you do not agree with this notice, including the disclaimer
31726 + * below, then you are not authorized to use the Software.
31727 + *
31728 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31729 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31730 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31731 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31732 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31733 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31734 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31735 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31736 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31737 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31738 + * DAMAGE.
31739 + * ========================================================================== */
31740 +
31741 +#ifndef __DWC_OTG_DBG_H__
31742 +#define __DWC_OTG_DBG_H__
31743 +
31744 +/** @file
31745 + * This file defines debug levels.
31746 + * Debugging support vanishes in non-debug builds.
31747 + */
31748 +
31749 +/**
31750 + * The Debug Level bit-mask variable.
31751 + */
31752 +extern uint32_t g_dbg_lvl;
31753 +/**
31754 + * Set the Debug Level variable.
31755 + */
31756 +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
31757 +{
31758 + uint32_t old = g_dbg_lvl;
31759 + g_dbg_lvl = new;
31760 + return old;
31761 +}
31762 +
31763 +#define DBG_USER (0x1)
31764 +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
31765 +#define DBG_CIL (0x2)
31766 +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
31767 + * messages */
31768 +#define DBG_CILV (0x20)
31769 +/** When debug level has the DBG_PCD bit set, display PCD (Device) debug
31770 + * messages */
31771 +#define DBG_PCD (0x4)
31772 +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
31773 + * messages */
31774 +#define DBG_PCDV (0x40)
31775 +/** When debug level has the DBG_HCD bit set, display Host debug messages */
31776 +#define DBG_HCD (0x8)
31777 +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
31778 + * messages */
31779 +#define DBG_HCDV (0x80)
31780 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
31781 + * mode. */
31782 +#define DBG_HCD_URB (0x800)
31783 +/** When debug level has the DBG_HCDI bit set, display host interrupt
31784 + * messages. */
31785 +#define DBG_HCDI (0x1000)
31786 +
31787 +/** When debug level has any bit set, display debug messages */
31788 +#define DBG_ANY (0xFF)
31789 +
31790 +/** All debug messages off */
31791 +#define DBG_OFF 0
31792 +
31793 +/** Prefix string for DWC_DEBUG print macros. */
31794 +#define USB_DWC "DWC_otg: "
31795 +
31796 +/**
31797 + * Print a debug message when the Global debug level variable contains
31798 + * the bit defined in <code>lvl</code>.
31799 + *
31800 + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
31801 + * @param[in] x - like printf
31802 + *
31803 + * Example:<p>
31804 + * <code>
31805 + * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
31806 + * </code>
31807 + * <br>
31808 + * results in:<br>
31809 + * <code>
31810 + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
31811 + * </code>
31812 + */
31813 +#ifdef DEBUG
31814 +
31815 +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
31816 +# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x )
31817 +
31818 +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
31819 +
31820 +#else
31821 +
31822 +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
31823 +# define DWC_DEBUGP(x...)
31824 +
31825 +# define CHK_DEBUG_LEVEL(level) (0)
31826 +
31827 +#endif /*DEBUG*/
31828 +#endif
31829 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_driver.c
31830 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100
31831 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2013-07-06 15:25:50.000000000 +0100
31832 @@ -0,0 +1,1732 @@
31833 +/* ==========================================================================
31834 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
31835 + * $Revision: #92 $
31836 + * $Date: 2012/08/10 $
31837 + * $Change: 2047372 $
31838 + *
31839 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31840 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31841 + * otherwise expressly agreed to in writing between Synopsys and you.
31842 + *
31843 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31844 + * any End User Software License Agreement or Agreement for Licensed Product
31845 + * with Synopsys or any supplement thereto. You are permitted to use and
31846 + * redistribute this Software in source and binary forms, with or without
31847 + * modification, provided that redistributions of source code must retain this
31848 + * notice. You may not view, use, disclose, copy or distribute this file or
31849 + * any information contained herein except pursuant to this license grant from
31850 + * Synopsys. If you do not agree with this notice, including the disclaimer
31851 + * below, then you are not authorized to use the Software.
31852 + *
31853 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31854 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31855 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31856 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31857 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31858 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31859 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31860 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31861 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31862 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31863 + * DAMAGE.
31864 + * ========================================================================== */
31865 +
31866 +/** @file
31867 + * The dwc_otg_driver module provides the initialization and cleanup entry
31868 + * points for the DWC_otg driver. This module will be dynamically installed
31869 + * after Linux is booted using the insmod command. When the module is
31870 + * installed, the dwc_otg_driver_init function is called. When the module is
31871 + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
31872 + *
31873 + * This module also defines a data structure for the dwc_otg_driver, which is
31874 + * used in conjunction with the standard ARM lm_device structure. These
31875 + * structures allow the OTG driver to comply with the standard Linux driver
31876 + * model in which devices and drivers are registered with a bus driver. This
31877 + * has the benefit that Linux can expose attributes of the driver and device
31878 + * in its special sysfs file system. Users can then read or write files in
31879 + * this file system to perform diagnostics on the driver components or the
31880 + * device.
31881 + */
31882 +
31883 +#include "dwc_otg_os_dep.h"
31884 +#include "dwc_os.h"
31885 +#include "dwc_otg_dbg.h"
31886 +#include "dwc_otg_driver.h"
31887 +#include "dwc_otg_attr.h"
31888 +#include "dwc_otg_core_if.h"
31889 +#include "dwc_otg_pcd_if.h"
31890 +#include "dwc_otg_hcd_if.h"
31891 +
31892 +#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012"
31893 +#define DWC_DRIVER_DESC "HS OTG USB Controller driver"
31894 +
31895 +bool microframe_schedule=true;
31896 +
31897 +static const char dwc_driver_name[] = "dwc_otg";
31898 +
31899 +extern void* dummy_send;
31900 +
31901 +extern int pcd_init(
31902 +#ifdef LM_INTERFACE
31903 + struct lm_device *_dev
31904 +#elif defined(PCI_INTERFACE)
31905 + struct pci_dev *_dev
31906 +#elif defined(PLATFORM_INTERFACE)
31907 + struct platform_device *dev
31908 +#endif
31909 + );
31910 +extern int hcd_init(
31911 +#ifdef LM_INTERFACE
31912 + struct lm_device *_dev
31913 +#elif defined(PCI_INTERFACE)
31914 + struct pci_dev *_dev
31915 +#elif defined(PLATFORM_INTERFACE)
31916 + struct platform_device *dev
31917 +#endif
31918 + );
31919 +
31920 +extern int pcd_remove(
31921 +#ifdef LM_INTERFACE
31922 + struct lm_device *_dev
31923 +#elif defined(PCI_INTERFACE)
31924 + struct pci_dev *_dev
31925 +#elif defined(PLATFORM_INTERFACE)
31926 + struct platform_device *_dev
31927 +#endif
31928 + );
31929 +
31930 +extern void hcd_remove(
31931 +#ifdef LM_INTERFACE
31932 + struct lm_device *_dev
31933 +#elif defined(PCI_INTERFACE)
31934 + struct pci_dev *_dev
31935 +#elif defined(PLATFORM_INTERFACE)
31936 + struct platform_device *_dev
31937 +#endif
31938 + );
31939 +
31940 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
31941 +
31942 +/*-------------------------------------------------------------------------*/
31943 +/* Encapsulate the module parameter settings */
31944 +
31945 +struct dwc_otg_driver_module_params {
31946 + int32_t opt;
31947 + int32_t otg_cap;
31948 + int32_t dma_enable;
31949 + int32_t dma_desc_enable;
31950 + int32_t dma_burst_size;
31951 + int32_t speed;
31952 + int32_t host_support_fs_ls_low_power;
31953 + int32_t host_ls_low_power_phy_clk;
31954 + int32_t enable_dynamic_fifo;
31955 + int32_t data_fifo_size;
31956 + int32_t dev_rx_fifo_size;
31957 + int32_t dev_nperio_tx_fifo_size;
31958 + uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
31959 + int32_t host_rx_fifo_size;
31960 + int32_t host_nperio_tx_fifo_size;
31961 + int32_t host_perio_tx_fifo_size;
31962 + int32_t max_transfer_size;
31963 + int32_t max_packet_count;
31964 + int32_t host_channels;
31965 + int32_t dev_endpoints;
31966 + int32_t phy_type;
31967 + int32_t phy_utmi_width;
31968 + int32_t phy_ulpi_ddr;
31969 + int32_t phy_ulpi_ext_vbus;
31970 + int32_t i2c_enable;
31971 + int32_t ulpi_fs_ls;
31972 + int32_t ts_dline;
31973 + int32_t en_multiple_tx_fifo;
31974 + uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
31975 + uint32_t thr_ctl;
31976 + uint32_t tx_thr_length;
31977 + uint32_t rx_thr_length;
31978 + int32_t pti_enable;
31979 + int32_t mpi_enable;
31980 + int32_t lpm_enable;
31981 + int32_t ic_usb_cap;
31982 + int32_t ahb_thr_ratio;
31983 + int32_t power_down;
31984 + int32_t reload_ctl;
31985 + int32_t dev_out_nak;
31986 + int32_t cont_on_bna;
31987 + int32_t ahb_single;
31988 + int32_t otg_ver;
31989 + int32_t adp_enable;
31990 +};
31991 +
31992 +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
31993 + .opt = -1,
31994 + .otg_cap = -1,
31995 + .dma_enable = -1,
31996 + .dma_desc_enable = -1,
31997 + .dma_burst_size = -1,
31998 + .speed = -1,
31999 + .host_support_fs_ls_low_power = -1,
32000 + .host_ls_low_power_phy_clk = -1,
32001 + .enable_dynamic_fifo = -1,
32002 + .data_fifo_size = -1,
32003 + .dev_rx_fifo_size = -1,
32004 + .dev_nperio_tx_fifo_size = -1,
32005 + .dev_perio_tx_fifo_size = {
32006 + /* dev_perio_tx_fifo_size_1 */
32007 + -1,
32008 + -1,
32009 + -1,
32010 + -1,
32011 + -1,
32012 + -1,
32013 + -1,
32014 + -1,
32015 + -1,
32016 + -1,
32017 + -1,
32018 + -1,
32019 + -1,
32020 + -1,
32021 + -1
32022 + /* 15 */
32023 + },
32024 + .host_rx_fifo_size = -1,
32025 + .host_nperio_tx_fifo_size = -1,
32026 + .host_perio_tx_fifo_size = -1,
32027 + .max_transfer_size = -1,
32028 + .max_packet_count = -1,
32029 + .host_channels = -1,
32030 + .dev_endpoints = -1,
32031 + .phy_type = -1,
32032 + .phy_utmi_width = -1,
32033 + .phy_ulpi_ddr = -1,
32034 + .phy_ulpi_ext_vbus = -1,
32035 + .i2c_enable = -1,
32036 + .ulpi_fs_ls = -1,
32037 + .ts_dline = -1,
32038 + .en_multiple_tx_fifo = -1,
32039 + .dev_tx_fifo_size = {
32040 + /* dev_tx_fifo_size */
32041 + -1,
32042 + -1,
32043 + -1,
32044 + -1,
32045 + -1,
32046 + -1,
32047 + -1,
32048 + -1,
32049 + -1,
32050 + -1,
32051 + -1,
32052 + -1,
32053 + -1,
32054 + -1,
32055 + -1
32056 + /* 15 */
32057 + },
32058 + .thr_ctl = -1,
32059 + .tx_thr_length = -1,
32060 + .rx_thr_length = -1,
32061 + .pti_enable = -1,
32062 + .mpi_enable = -1,
32063 + .lpm_enable = 0,
32064 + .ic_usb_cap = -1,
32065 + .ahb_thr_ratio = -1,
32066 + .power_down = -1,
32067 + .reload_ctl = -1,
32068 + .dev_out_nak = -1,
32069 + .cont_on_bna = -1,
32070 + .ahb_single = -1,
32071 + .otg_ver = -1,
32072 + .adp_enable = -1,
32073 +};
32074 +
32075 +//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
32076 +extern bool fiq_fix_enable;
32077 +
32078 +//Global variable to switch the nak holdoff on or off
32079 +bool nak_holdoff_enable = true;
32080 +
32081 +
32082 +/**
32083 + * This function shows the Driver Version.
32084 + */
32085 +static ssize_t version_show(struct device_driver *dev, char *buf)
32086 +{
32087 + return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
32088 + DWC_DRIVER_VERSION);
32089 +}
32090 +
32091 +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
32092 +
32093 +/**
32094 + * Global Debug Level Mask.
32095 + */
32096 +uint32_t g_dbg_lvl = 0; /* OFF */
32097 +
32098 +/**
32099 + * This function shows the driver Debug Level.
32100 + */
32101 +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
32102 +{
32103 + return sprintf(buf, "0x%0x\n", g_dbg_lvl);
32104 +}
32105 +
32106 +/**
32107 + * This function stores the driver Debug Level.
32108 + */
32109 +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
32110 + size_t count)
32111 +{
32112 + g_dbg_lvl = simple_strtoul(buf, NULL, 16);
32113 + return count;
32114 +}
32115 +
32116 +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
32117 + dbg_level_store);
32118 +
32119 +/**
32120 + * This function is called during module intialization
32121 + * to pass module parameters to the DWC_OTG CORE.
32122 + */
32123 +static int set_parameters(dwc_otg_core_if_t * core_if)
32124 +{
32125 + int retval = 0;
32126 + int i;
32127 +
32128 + if (dwc_otg_module_params.otg_cap != -1) {
32129 + retval +=
32130 + dwc_otg_set_param_otg_cap(core_if,
32131 + dwc_otg_module_params.otg_cap);
32132 + }
32133 + if (dwc_otg_module_params.dma_enable != -1) {
32134 + retval +=
32135 + dwc_otg_set_param_dma_enable(core_if,
32136 + dwc_otg_module_params.
32137 + dma_enable);
32138 + }
32139 + if (dwc_otg_module_params.dma_desc_enable != -1) {
32140 + retval +=
32141 + dwc_otg_set_param_dma_desc_enable(core_if,
32142 + dwc_otg_module_params.
32143 + dma_desc_enable);
32144 + }
32145 + if (dwc_otg_module_params.opt != -1) {
32146 + retval +=
32147 + dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
32148 + }
32149 + if (dwc_otg_module_params.dma_burst_size != -1) {
32150 + retval +=
32151 + dwc_otg_set_param_dma_burst_size(core_if,
32152 + dwc_otg_module_params.
32153 + dma_burst_size);
32154 + }
32155 + if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
32156 + retval +=
32157 + dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
32158 + dwc_otg_module_params.
32159 + host_support_fs_ls_low_power);
32160 + }
32161 + if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
32162 + retval +=
32163 + dwc_otg_set_param_enable_dynamic_fifo(core_if,
32164 + dwc_otg_module_params.
32165 + enable_dynamic_fifo);
32166 + }
32167 + if (dwc_otg_module_params.data_fifo_size != -1) {
32168 + retval +=
32169 + dwc_otg_set_param_data_fifo_size(core_if,
32170 + dwc_otg_module_params.
32171 + data_fifo_size);
32172 + }
32173 + if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
32174 + retval +=
32175 + dwc_otg_set_param_dev_rx_fifo_size(core_if,
32176 + dwc_otg_module_params.
32177 + dev_rx_fifo_size);
32178 + }
32179 + if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
32180 + retval +=
32181 + dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
32182 + dwc_otg_module_params.
32183 + dev_nperio_tx_fifo_size);
32184 + }
32185 + if (dwc_otg_module_params.host_rx_fifo_size != -1) {
32186 + retval +=
32187 + dwc_otg_set_param_host_rx_fifo_size(core_if,
32188 + dwc_otg_module_params.host_rx_fifo_size);
32189 + }
32190 + if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
32191 + retval +=
32192 + dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
32193 + dwc_otg_module_params.
32194 + host_nperio_tx_fifo_size);
32195 + }
32196 + if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
32197 + retval +=
32198 + dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
32199 + dwc_otg_module_params.
32200 + host_perio_tx_fifo_size);
32201 + }
32202 + if (dwc_otg_module_params.max_transfer_size != -1) {
32203 + retval +=
32204 + dwc_otg_set_param_max_transfer_size(core_if,
32205 + dwc_otg_module_params.
32206 + max_transfer_size);
32207 + }
32208 + if (dwc_otg_module_params.max_packet_count != -1) {
32209 + retval +=
32210 + dwc_otg_set_param_max_packet_count(core_if,
32211 + dwc_otg_module_params.
32212 + max_packet_count);
32213 + }
32214 + if (dwc_otg_module_params.host_channels != -1) {
32215 + retval +=
32216 + dwc_otg_set_param_host_channels(core_if,
32217 + dwc_otg_module_params.
32218 + host_channels);
32219 + }
32220 + if (dwc_otg_module_params.dev_endpoints != -1) {
32221 + retval +=
32222 + dwc_otg_set_param_dev_endpoints(core_if,
32223 + dwc_otg_module_params.
32224 + dev_endpoints);
32225 + }
32226 + if (dwc_otg_module_params.phy_type != -1) {
32227 + retval +=
32228 + dwc_otg_set_param_phy_type(core_if,
32229 + dwc_otg_module_params.phy_type);
32230 + }
32231 + if (dwc_otg_module_params.speed != -1) {
32232 + retval +=
32233 + dwc_otg_set_param_speed(core_if,
32234 + dwc_otg_module_params.speed);
32235 + }
32236 + if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
32237 + retval +=
32238 + dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
32239 + dwc_otg_module_params.
32240 + host_ls_low_power_phy_clk);
32241 + }
32242 + if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
32243 + retval +=
32244 + dwc_otg_set_param_phy_ulpi_ddr(core_if,
32245 + dwc_otg_module_params.
32246 + phy_ulpi_ddr);
32247 + }
32248 + if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
32249 + retval +=
32250 + dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
32251 + dwc_otg_module_params.
32252 + phy_ulpi_ext_vbus);
32253 + }
32254 + if (dwc_otg_module_params.phy_utmi_width != -1) {
32255 + retval +=
32256 + dwc_otg_set_param_phy_utmi_width(core_if,
32257 + dwc_otg_module_params.
32258 + phy_utmi_width);
32259 + }
32260 + if (dwc_otg_module_params.ulpi_fs_ls != -1) {
32261 + retval +=
32262 + dwc_otg_set_param_ulpi_fs_ls(core_if,
32263 + dwc_otg_module_params.ulpi_fs_ls);
32264 + }
32265 + if (dwc_otg_module_params.ts_dline != -1) {
32266 + retval +=
32267 + dwc_otg_set_param_ts_dline(core_if,
32268 + dwc_otg_module_params.ts_dline);
32269 + }
32270 + if (dwc_otg_module_params.i2c_enable != -1) {
32271 + retval +=
32272 + dwc_otg_set_param_i2c_enable(core_if,
32273 + dwc_otg_module_params.
32274 + i2c_enable);
32275 + }
32276 + if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
32277 + retval +=
32278 + dwc_otg_set_param_en_multiple_tx_fifo(core_if,
32279 + dwc_otg_module_params.
32280 + en_multiple_tx_fifo);
32281 + }
32282 + for (i = 0; i < 15; i++) {
32283 + if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
32284 + retval +=
32285 + dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
32286 + dwc_otg_module_params.
32287 + dev_perio_tx_fifo_size
32288 + [i], i);
32289 + }
32290 + }
32291 +
32292 + for (i = 0; i < 15; i++) {
32293 + if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
32294 + retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
32295 + dwc_otg_module_params.
32296 + dev_tx_fifo_size
32297 + [i], i);
32298 + }
32299 + }
32300 + if (dwc_otg_module_params.thr_ctl != -1) {
32301 + retval +=
32302 + dwc_otg_set_param_thr_ctl(core_if,
32303 + dwc_otg_module_params.thr_ctl);
32304 + }
32305 + if (dwc_otg_module_params.mpi_enable != -1) {
32306 + retval +=
32307 + dwc_otg_set_param_mpi_enable(core_if,
32308 + dwc_otg_module_params.
32309 + mpi_enable);
32310 + }
32311 + if (dwc_otg_module_params.pti_enable != -1) {
32312 + retval +=
32313 + dwc_otg_set_param_pti_enable(core_if,
32314 + dwc_otg_module_params.
32315 + pti_enable);
32316 + }
32317 + if (dwc_otg_module_params.lpm_enable != -1) {
32318 + retval +=
32319 + dwc_otg_set_param_lpm_enable(core_if,
32320 + dwc_otg_module_params.
32321 + lpm_enable);
32322 + }
32323 + if (dwc_otg_module_params.ic_usb_cap != -1) {
32324 + retval +=
32325 + dwc_otg_set_param_ic_usb_cap(core_if,
32326 + dwc_otg_module_params.
32327 + ic_usb_cap);
32328 + }
32329 + if (dwc_otg_module_params.tx_thr_length != -1) {
32330 + retval +=
32331 + dwc_otg_set_param_tx_thr_length(core_if,
32332 + dwc_otg_module_params.tx_thr_length);
32333 + }
32334 + if (dwc_otg_module_params.rx_thr_length != -1) {
32335 + retval +=
32336 + dwc_otg_set_param_rx_thr_length(core_if,
32337 + dwc_otg_module_params.
32338 + rx_thr_length);
32339 + }
32340 + if (dwc_otg_module_params.ahb_thr_ratio != -1) {
32341 + retval +=
32342 + dwc_otg_set_param_ahb_thr_ratio(core_if,
32343 + dwc_otg_module_params.ahb_thr_ratio);
32344 + }
32345 + if (dwc_otg_module_params.power_down != -1) {
32346 + retval +=
32347 + dwc_otg_set_param_power_down(core_if,
32348 + dwc_otg_module_params.power_down);
32349 + }
32350 + if (dwc_otg_module_params.reload_ctl != -1) {
32351 + retval +=
32352 + dwc_otg_set_param_reload_ctl(core_if,
32353 + dwc_otg_module_params.reload_ctl);
32354 + }
32355 +
32356 + if (dwc_otg_module_params.dev_out_nak != -1) {
32357 + retval +=
32358 + dwc_otg_set_param_dev_out_nak(core_if,
32359 + dwc_otg_module_params.dev_out_nak);
32360 + }
32361 +
32362 + if (dwc_otg_module_params.cont_on_bna != -1) {
32363 + retval +=
32364 + dwc_otg_set_param_cont_on_bna(core_if,
32365 + dwc_otg_module_params.cont_on_bna);
32366 + }
32367 +
32368 + if (dwc_otg_module_params.ahb_single != -1) {
32369 + retval +=
32370 + dwc_otg_set_param_ahb_single(core_if,
32371 + dwc_otg_module_params.ahb_single);
32372 + }
32373 +
32374 + if (dwc_otg_module_params.otg_ver != -1) {
32375 + retval +=
32376 + dwc_otg_set_param_otg_ver(core_if,
32377 + dwc_otg_module_params.otg_ver);
32378 + }
32379 + if (dwc_otg_module_params.adp_enable != -1) {
32380 + retval +=
32381 + dwc_otg_set_param_adp_enable(core_if,
32382 + dwc_otg_module_params.
32383 + adp_enable);
32384 + }
32385 + return retval;
32386 +}
32387 +
32388 +/**
32389 + * This function is the top level interrupt handler for the Common
32390 + * (Device and host modes) interrupts.
32391 + */
32392 +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
32393 +{
32394 + int32_t retval = IRQ_NONE;
32395 +
32396 + retval = dwc_otg_handle_common_intr(dev);
32397 + if (retval != 0) {
32398 + S3C2410X_CLEAR_EINTPEND();
32399 + }
32400 + return IRQ_RETVAL(retval);
32401 +}
32402 +
32403 +/**
32404 + * This function is called when a lm_device is unregistered with the
32405 + * dwc_otg_driver. This happens, for example, when the rmmod command is
32406 + * executed. The device may or may not be electrically present. If it is
32407 + * present, the driver stops device processing. Any resources used on behalf
32408 + * of this device are freed.
32409 + *
32410 + * @param _dev
32411 + */
32412 +#ifdef LM_INTERFACE
32413 +#define REM_RETVAL(n)
32414 +static void dwc_otg_driver_remove( struct lm_device *_dev )
32415 +{ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
32416 +#elif defined(PCI_INTERFACE)
32417 +#define REM_RETVAL(n)
32418 +static void dwc_otg_driver_remove( struct pci_dev *_dev )
32419 +{ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
32420 +#elif defined(PLATFORM_INTERFACE)
32421 +#define REM_RETVAL(n) n
32422 +static int dwc_otg_driver_remove( struct platform_device *_dev )
32423 +{ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
32424 +#endif
32425 +
32426 + DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
32427 +
32428 + if (!otg_dev) {
32429 + /* Memory allocation for the dwc_otg_device failed. */
32430 + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
32431 + return REM_RETVAL(-ENOMEM);
32432 + }
32433 +#ifndef DWC_DEVICE_ONLY
32434 + if (otg_dev->hcd) {
32435 + hcd_remove(_dev);
32436 + } else {
32437 + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
32438 + return REM_RETVAL(-EINVAL);
32439 + }
32440 +#endif
32441 +
32442 +#ifndef DWC_HOST_ONLY
32443 + if (otg_dev->pcd) {
32444 + pcd_remove(_dev);
32445 + } else {
32446 + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);
32447 + return REM_RETVAL(-EINVAL);
32448 + }
32449 +#endif
32450 + /*
32451 + * Free the IRQ
32452 + */
32453 + if (otg_dev->common_irq_installed) {
32454 +#ifdef PLATFORM_INTERFACE
32455 + free_irq(platform_get_irq(_dev, 0), otg_dev);
32456 +#else
32457 + free_irq(_dev->irq, otg_dev);
32458 +#endif
32459 + } else {
32460 + DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
32461 + return REM_RETVAL(-ENXIO);
32462 + }
32463 +
32464 + if (otg_dev->core_if) {
32465 + dwc_otg_cil_remove(otg_dev->core_if);
32466 + } else {
32467 + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);
32468 + return REM_RETVAL(-ENXIO);
32469 + }
32470 +
32471 + /*
32472 + * Remove the device attributes
32473 + */
32474 + dwc_otg_attr_remove(_dev);
32475 +
32476 + /*
32477 + * Return the memory.
32478 + */
32479 + if (otg_dev->os_dep.base) {
32480 + iounmap(otg_dev->os_dep.base);
32481 + }
32482 + DWC_FREE(otg_dev);
32483 +
32484 + /*
32485 + * Clear the drvdata pointer.
32486 + */
32487 +#ifdef LM_INTERFACE
32488 + lm_set_drvdata(_dev, 0);
32489 +#elif defined(PCI_INTERFACE)
32490 + release_mem_region(otg_dev->os_dep.rsrc_start,
32491 + otg_dev->os_dep.rsrc_len);
32492 + pci_set_drvdata(_dev, 0);
32493 +#elif defined(PLATFORM_INTERFACE)
32494 + platform_set_drvdata(_dev, 0);
32495 +#endif
32496 + return REM_RETVAL(0);
32497 +}
32498 +
32499 +/**
32500 + * This function is called when an lm_device is bound to a
32501 + * dwc_otg_driver. It creates the driver components required to
32502 + * control the device (CIL, HCD, and PCD) and it initializes the
32503 + * device. The driver components are stored in a dwc_otg_device
32504 + * structure. A reference to the dwc_otg_device is saved in the
32505 + * lm_device. This allows the driver to access the dwc_otg_device
32506 + * structure on subsequent calls to driver methods for this device.
32507 + *
32508 + * @param _dev Bus device
32509 + */
32510 +static int dwc_otg_driver_probe(
32511 +#ifdef LM_INTERFACE
32512 + struct lm_device *_dev
32513 +#elif defined(PCI_INTERFACE)
32514 + struct pci_dev *_dev,
32515 + const struct pci_device_id *id
32516 +#elif defined(PLATFORM_INTERFACE)
32517 + struct platform_device *_dev
32518 +#endif
32519 + )
32520 +{
32521 + int retval = 0;
32522 + dwc_otg_device_t *dwc_otg_device;
32523 + int devirq;
32524 +
32525 + dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
32526 +#ifdef LM_INTERFACE
32527 + dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
32528 +#elif defined(PCI_INTERFACE)
32529 + if (!id) {
32530 + DWC_ERROR("Invalid pci_device_id %p", id);
32531 + return -EINVAL;
32532 + }
32533 +
32534 + if (!_dev || (pci_enable_device(_dev) < 0)) {
32535 + DWC_ERROR("Invalid pci_device %p", _dev);
32536 + return -ENODEV;
32537 + }
32538 + dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
32539 + /* other stuff needed as well? */
32540 +
32541 +#elif defined(PLATFORM_INTERFACE)
32542 + dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
32543 + (unsigned)_dev->resource->start,
32544 + (unsigned)(_dev->resource->end - _dev->resource->start));
32545 +#endif
32546 +
32547 + dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
32548 +
32549 + if (!dwc_otg_device) {
32550 + dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
32551 + return -ENOMEM;
32552 + }
32553 +
32554 + memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
32555 + dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
32556 +
32557 + /*
32558 + * Map the DWC_otg Core memory into virtual address space.
32559 + */
32560 +#ifdef LM_INTERFACE
32561 + dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);
32562 +
32563 + if (!dwc_otg_device->os_dep.base) {
32564 + dev_err(&_dev->dev, "ioremap() failed\n");
32565 + DWC_FREE(dwc_otg_device);
32566 + return -ENOMEM;
32567 + }
32568 + dev_dbg(&_dev->dev, "base=0x%08x\n",
32569 + (unsigned)dwc_otg_device->os_dep.base);
32570 +#elif defined(PCI_INTERFACE)
32571 + _dev->current_state = PCI_D0;
32572 + _dev->dev.power.power_state = PMSG_ON;
32573 +
32574 + if (!_dev->irq) {
32575 + DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",
32576 + pci_name(_dev));
32577 + iounmap(dwc_otg_device->os_dep.base);
32578 + DWC_FREE(dwc_otg_device);
32579 + return -ENODEV;
32580 + }
32581 +
32582 + dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);
32583 + dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);
32584 + DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",
32585 + (unsigned)dwc_otg_device->os_dep.rsrc_start,
32586 + (unsigned)dwc_otg_device->os_dep.rsrc_len);
32587 + if (!request_mem_region
32588 + (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,
32589 + "dwc_otg")) {
32590 + dev_dbg(&_dev->dev, "error requesting memory\n");
32591 + iounmap(dwc_otg_device->os_dep.base);
32592 + DWC_FREE(dwc_otg_device);
32593 + return -EFAULT;
32594 + }
32595 +
32596 + dwc_otg_device->os_dep.base =
32597 + ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,
32598 + dwc_otg_device->os_dep.rsrc_len);
32599 + if (dwc_otg_device->os_dep.base == NULL) {
32600 + dev_dbg(&_dev->dev, "error mapping memory\n");
32601 + release_mem_region(dwc_otg_device->os_dep.rsrc_start,
32602 + dwc_otg_device->os_dep.rsrc_len);
32603 + iounmap(dwc_otg_device->os_dep.base);
32604 + DWC_FREE(dwc_otg_device);
32605 + return -EFAULT;
32606 + }
32607 + dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",
32608 + dwc_otg_device->os_dep.base);
32609 + dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;
32610 + dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",
32611 + dwc_otg_device->os_dep.base);
32612 + dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
32613 + (unsigned)dwc_otg_device->os_dep.rsrc_start,
32614 + dwc_otg_device->os_dep.base);
32615 +
32616 + pci_set_master(_dev);
32617 + pci_set_drvdata(_dev, dwc_otg_device);
32618 +#elif defined(PLATFORM_INTERFACE)
32619 + DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
32620 + _dev->resource->start,
32621 + _dev->resource->end - _dev->resource->start + 1);
32622 +#if 1
32623 + if (!request_mem_region(_dev->resource[0].start,
32624 + _dev->resource[0].end - _dev->resource[0].start + 1,
32625 + "dwc_otg")) {
32626 + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
32627 + retval = -EFAULT;
32628 + goto fail;
32629 + }
32630 +
32631 + dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
32632 + _dev->resource[0].end -
32633 + _dev->resource[0].start+1);
32634 + if (fiq_fix_enable)
32635 + {
32636 + if (!request_mem_region(_dev->resource[1].start,
32637 + _dev->resource[1].end - _dev->resource[1].start + 1,
32638 + "dwc_otg")) {
32639 + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
32640 + retval = -EFAULT;
32641 + goto fail;
32642 + }
32643 +
32644 + dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
32645 + _dev->resource[1].end -
32646 + _dev->resource[1].start + 1);
32647 + dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
32648 + }
32649 +
32650 +#else
32651 + {
32652 + struct map_desc desc = {
32653 + .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
32654 + .pfn = __phys_to_pfn((unsigned)_dev->resource->start),
32655 + .length = SZ_128K,
32656 + .type = MT_DEVICE
32657 + };
32658 + iotable_init(&desc, 1);
32659 + dwc_otg_device->os_dep.base = (void *)desc.virtual;
32660 + }
32661 +#endif
32662 + if (!dwc_otg_device->os_dep.base) {
32663 + dev_err(&_dev->dev, "ioremap() failed\n");
32664 + retval = -ENOMEM;
32665 + goto fail;
32666 + }
32667 + dev_dbg(&_dev->dev, "base=0x%08x\n",
32668 + (unsigned)dwc_otg_device->os_dep.base);
32669 +#endif
32670 +
32671 + /*
32672 + * Initialize driver data to point to the global DWC_otg
32673 + * Device structure.
32674 + */
32675 +#ifdef LM_INTERFACE
32676 + lm_set_drvdata(_dev, dwc_otg_device);
32677 +#elif defined(PLATFORM_INTERFACE)
32678 + platform_set_drvdata(_dev, dwc_otg_device);
32679 +#endif
32680 + dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
32681 +
32682 + dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
32683 + DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
32684 + dwc_otg_device, dwc_otg_device->core_if);//GRAYG
32685 +
32686 + if (!dwc_otg_device->core_if) {
32687 + dev_err(&_dev->dev, "CIL initialization failed!\n");
32688 + retval = -ENOMEM;
32689 + goto fail;
32690 + }
32691 +
32692 + dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
32693 + /*
32694 + * Attempt to ensure this device is really a DWC_otg Controller.
32695 + * Read and verify the SNPSID register contents. The value should be
32696 + * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",
32697 + * as in "OTG version 2.XX" or "OTG version 3.XX".
32698 + */
32699 +
32700 + if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) &&
32701 + ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
32702 + dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
32703 + dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
32704 + retval = -EINVAL;
32705 + goto fail;
32706 + }
32707 +
32708 + /*
32709 + * Validate parameter values.
32710 + */
32711 + dev_dbg(&_dev->dev, "Calling set_parameters\n");
32712 + if (set_parameters(dwc_otg_device->core_if)) {
32713 + retval = -EINVAL;
32714 + goto fail;
32715 + }
32716 +
32717 + /*
32718 + * Create Device Attributes in sysfs
32719 + */
32720 + dev_dbg(&_dev->dev, "Calling attr_create\n");
32721 + dwc_otg_attr_create(_dev);
32722 +
32723 + /*
32724 + * Disable the global interrupt until all the interrupt
32725 + * handlers are installed.
32726 + */
32727 + dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
32728 + dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
32729 +
32730 + /*
32731 + * Install the interrupt handler for the common interrupts before
32732 + * enabling common interrupts in core_init below.
32733 + */
32734 +
32735 +#if defined(PLATFORM_INTERFACE)
32736 + devirq = platform_get_irq(_dev, 0);
32737 +#else
32738 + devirq = _dev->irq;
32739 +#endif
32740 + DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
32741 + devirq);
32742 + dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
32743 + retval = request_irq(devirq, dwc_otg_common_irq,
32744 + IRQF_SHARED,
32745 + "dwc_otg", dwc_otg_device);
32746 + if (retval) {
32747 + DWC_ERROR("request of irq%d failed\n", devirq);
32748 + retval = -EBUSY;
32749 + goto fail;
32750 + } else {
32751 + dwc_otg_device->common_irq_installed = 1;
32752 + }
32753 +
32754 +#ifndef IRQF_TRIGGER_LOW
32755 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
32756 + dev_dbg(&_dev->dev, "Calling set_irq_type\n");
32757 + set_irq_type(devirq,
32758 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
32759 + IRQT_LOW
32760 +#else
32761 + IRQ_TYPE_LEVEL_LOW
32762 +#endif
32763 + );
32764 +#endif
32765 +#endif /*IRQF_TRIGGER_LOW*/
32766 +
32767 + /*
32768 + * Initialize the DWC_otg core.
32769 + */
32770 + dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
32771 + dwc_otg_core_init(dwc_otg_device->core_if);
32772 +
32773 +#ifndef DWC_HOST_ONLY
32774 + /*
32775 + * Initialize the PCD
32776 + */
32777 + dev_dbg(&_dev->dev, "Calling pcd_init\n");
32778 + retval = pcd_init(_dev);
32779 + if (retval != 0) {
32780 + DWC_ERROR("pcd_init failed\n");
32781 + dwc_otg_device->pcd = NULL;
32782 + goto fail;
32783 + }
32784 +#endif
32785 +#ifndef DWC_DEVICE_ONLY
32786 + /*
32787 + * Initialize the HCD
32788 + */
32789 + dev_dbg(&_dev->dev, "Calling hcd_init\n");
32790 + retval = hcd_init(_dev);
32791 + if (retval != 0) {
32792 + DWC_ERROR("hcd_init failed\n");
32793 + dwc_otg_device->hcd = NULL;
32794 + goto fail;
32795 + }
32796 +#endif
32797 + /* Recover from drvdata having been overwritten by hcd_init() */
32798 +#ifdef LM_INTERFACE
32799 + lm_set_drvdata(_dev, dwc_otg_device);
32800 +#elif defined(PLATFORM_INTERFACE)
32801 + platform_set_drvdata(_dev, dwc_otg_device);
32802 +#elif defined(PCI_INTERFACE)
32803 + pci_set_drvdata(_dev, dwc_otg_device);
32804 + dwc_otg_device->os_dep.pcidev = _dev;
32805 +#endif
32806 +
32807 + /*
32808 + * Enable the global interrupt after all the interrupt
32809 + * handlers are installed if there is no ADP support else
32810 + * perform initial actions required for Internal ADP logic.
32811 + */
32812 + if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
32813 + dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
32814 + dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
32815 + dev_dbg(&_dev->dev, "Done\n");
32816 + } else
32817 + dwc_otg_adp_start(dwc_otg_device->core_if,
32818 + dwc_otg_is_host_mode(dwc_otg_device->core_if));
32819 +
32820 + return 0;
32821 +
32822 +fail:
32823 + dwc_otg_driver_remove(_dev);
32824 + return retval;
32825 +}
32826 +
32827 +/**
32828 + * This structure defines the methods to be called by a bus driver
32829 + * during the lifecycle of a device on that bus. Both drivers and
32830 + * devices are registered with a bus driver. The bus driver matches
32831 + * devices to drivers based on information in the device and driver
32832 + * structures.
32833 + *
32834 + * The probe function is called when the bus driver matches a device
32835 + * to this driver. The remove function is called when a device is
32836 + * unregistered with the bus driver.
32837 + */
32838 +#ifdef LM_INTERFACE
32839 +static struct lm_driver dwc_otg_driver = {
32840 + .drv = {.name = (char *)dwc_driver_name,},
32841 + .probe = dwc_otg_driver_probe,
32842 + .remove = dwc_otg_driver_remove,
32843 + // 'suspend' and 'resume' absent
32844 +};
32845 +#elif defined(PCI_INTERFACE)
32846 +static const struct pci_device_id pci_ids[] = { {
32847 + PCI_DEVICE(0x16c3, 0xabcd),
32848 + .driver_data =
32849 + (unsigned long)0xdeadbeef,
32850 + }, { /* end: all zeroes */ }
32851 +};
32852 +
32853 +MODULE_DEVICE_TABLE(pci, pci_ids);
32854 +
32855 +/* pci driver glue; this is a "new style" PCI driver module */
32856 +static struct pci_driver dwc_otg_driver = {
32857 + .name = "dwc_otg",
32858 + .id_table = pci_ids,
32859 +
32860 + .probe = dwc_otg_driver_probe,
32861 + .remove = dwc_otg_driver_remove,
32862 +
32863 + .driver = {
32864 + .name = (char *)dwc_driver_name,
32865 + },
32866 +};
32867 +#elif defined(PLATFORM_INTERFACE)
32868 +static struct platform_device_id platform_ids[] = {
32869 + {
32870 + .name = "bcm2708_usb",
32871 + .driver_data = (kernel_ulong_t) 0xdeadbeef,
32872 + },
32873 + { /* end: all zeroes */ }
32874 +};
32875 +MODULE_DEVICE_TABLE(platform, platform_ids);
32876 +
32877 +static struct platform_driver dwc_otg_driver = {
32878 + .driver = {
32879 + .name = (char *)dwc_driver_name,
32880 + },
32881 + .id_table = platform_ids,
32882 +
32883 + .probe = dwc_otg_driver_probe,
32884 + .remove = dwc_otg_driver_remove,
32885 + // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early'
32886 +};
32887 +#endif
32888 +
32889 +/**
32890 + * This function is called when the dwc_otg_driver is installed with the
32891 + * insmod command. It registers the dwc_otg_driver structure with the
32892 + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
32893 + * to be called. In addition, the bus driver will automatically expose
32894 + * attributes defined for the device and driver in the special sysfs file
32895 + * system.
32896 + *
32897 + * @return
32898 + */
32899 +static int __init dwc_otg_driver_init(void)
32900 +{
32901 + int retval = 0;
32902 + int error;
32903 + struct device_driver *drv;
32904 + printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
32905 + DWC_DRIVER_VERSION,
32906 +#ifdef LM_INTERFACE
32907 + "logicmodule");
32908 + retval = lm_driver_register(&dwc_otg_driver);
32909 + drv = &dwc_otg_driver.drv;
32910 +#elif defined(PCI_INTERFACE)
32911 + "pci");
32912 + retval = pci_register_driver(&dwc_otg_driver);
32913 + drv = &dwc_otg_driver.driver;
32914 +#elif defined(PLATFORM_INTERFACE)
32915 + "platform");
32916 + retval = platform_driver_register(&dwc_otg_driver);
32917 + drv = &dwc_otg_driver.driver;
32918 +#endif
32919 + if (retval < 0) {
32920 + printk(KERN_ERR "%s retval=%d\n", __func__, retval);
32921 + return retval;
32922 + }
32923 + printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
32924 + printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");
32925 +
32926 + error = driver_create_file(drv, &driver_attr_version);
32927 +#ifdef DEBUG
32928 + error = driver_create_file(drv, &driver_attr_debuglevel);
32929 +#endif
32930 + return retval;
32931 +}
32932 +
32933 +module_init(dwc_otg_driver_init);
32934 +
32935 +/**
32936 + * This function is called when the driver is removed from the kernel
32937 + * with the rmmod command. The driver unregisters itself with its bus
32938 + * driver.
32939 + *
32940 + */
32941 +static void __exit dwc_otg_driver_cleanup(void)
32942 +{
32943 + printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
32944 +
32945 +#ifdef LM_INTERFACE
32946 + driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
32947 + driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
32948 + lm_driver_unregister(&dwc_otg_driver);
32949 +#elif defined(PCI_INTERFACE)
32950 + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
32951 + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
32952 + pci_unregister_driver(&dwc_otg_driver);
32953 +#elif defined(PLATFORM_INTERFACE)
32954 + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
32955 + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
32956 + platform_driver_unregister(&dwc_otg_driver);
32957 +#endif
32958 +
32959 + printk(KERN_INFO "%s module removed\n", dwc_driver_name);
32960 +}
32961 +
32962 +module_exit(dwc_otg_driver_cleanup);
32963 +
32964 +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
32965 +MODULE_AUTHOR("Synopsys Inc.");
32966 +MODULE_LICENSE("GPL");
32967 +
32968 +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
32969 +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
32970 +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
32971 +MODULE_PARM_DESC(opt, "OPT Mode");
32972 +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
32973 +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
32974 +
32975 +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
32976 + 0444);
32977 +MODULE_PARM_DESC(dma_desc_enable,
32978 + "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
32979 +
32980 +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
32981 + 0444);
32982 +MODULE_PARM_DESC(dma_burst_size,
32983 + "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
32984 +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
32985 +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
32986 +module_param_named(host_support_fs_ls_low_power,
32987 + dwc_otg_module_params.host_support_fs_ls_low_power, int,
32988 + 0444);
32989 +MODULE_PARM_DESC(host_support_fs_ls_low_power,
32990 + "Support Low Power w/FS or LS 0=Support 1=Don't Support");
32991 +module_param_named(host_ls_low_power_phy_clk,
32992 + dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
32993 +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
32994 + "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
32995 +module_param_named(enable_dynamic_fifo,
32996 + dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
32997 +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
32998 +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
32999 + 0444);
33000 +MODULE_PARM_DESC(data_fifo_size,
33001 + "Total number of words in the data FIFO memory 32-32768");
33002 +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
33003 + int, 0444);
33004 +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33005 +module_param_named(dev_nperio_tx_fifo_size,
33006 + dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
33007 +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
33008 + "Number of words in the non-periodic Tx FIFO 16-32768");
33009 +module_param_named(dev_perio_tx_fifo_size_1,
33010 + dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
33011 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
33012 + "Number of words in the periodic Tx FIFO 4-768");
33013 +module_param_named(dev_perio_tx_fifo_size_2,
33014 + dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
33015 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
33016 + "Number of words in the periodic Tx FIFO 4-768");
33017 +module_param_named(dev_perio_tx_fifo_size_3,
33018 + dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
33019 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
33020 + "Number of words in the periodic Tx FIFO 4-768");
33021 +module_param_named(dev_perio_tx_fifo_size_4,
33022 + dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
33023 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
33024 + "Number of words in the periodic Tx FIFO 4-768");
33025 +module_param_named(dev_perio_tx_fifo_size_5,
33026 + dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
33027 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
33028 + "Number of words in the periodic Tx FIFO 4-768");
33029 +module_param_named(dev_perio_tx_fifo_size_6,
33030 + dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
33031 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
33032 + "Number of words in the periodic Tx FIFO 4-768");
33033 +module_param_named(dev_perio_tx_fifo_size_7,
33034 + dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
33035 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
33036 + "Number of words in the periodic Tx FIFO 4-768");
33037 +module_param_named(dev_perio_tx_fifo_size_8,
33038 + dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
33039 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
33040 + "Number of words in the periodic Tx FIFO 4-768");
33041 +module_param_named(dev_perio_tx_fifo_size_9,
33042 + dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
33043 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
33044 + "Number of words in the periodic Tx FIFO 4-768");
33045 +module_param_named(dev_perio_tx_fifo_size_10,
33046 + dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
33047 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
33048 + "Number of words in the periodic Tx FIFO 4-768");
33049 +module_param_named(dev_perio_tx_fifo_size_11,
33050 + dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
33051 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
33052 + "Number of words in the periodic Tx FIFO 4-768");
33053 +module_param_named(dev_perio_tx_fifo_size_12,
33054 + dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
33055 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
33056 + "Number of words in the periodic Tx FIFO 4-768");
33057 +module_param_named(dev_perio_tx_fifo_size_13,
33058 + dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
33059 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
33060 + "Number of words in the periodic Tx FIFO 4-768");
33061 +module_param_named(dev_perio_tx_fifo_size_14,
33062 + dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
33063 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
33064 + "Number of words in the periodic Tx FIFO 4-768");
33065 +module_param_named(dev_perio_tx_fifo_size_15,
33066 + dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
33067 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
33068 + "Number of words in the periodic Tx FIFO 4-768");
33069 +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
33070 + int, 0444);
33071 +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33072 +module_param_named(host_nperio_tx_fifo_size,
33073 + dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
33074 +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
33075 + "Number of words in the non-periodic Tx FIFO 16-32768");
33076 +module_param_named(host_perio_tx_fifo_size,
33077 + dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
33078 +MODULE_PARM_DESC(host_perio_tx_fifo_size,
33079 + "Number of words in the host periodic Tx FIFO 16-32768");
33080 +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
33081 + int, 0444);
33082 +/** @todo Set the max to 512K, modify checks */
33083 +MODULE_PARM_DESC(max_transfer_size,
33084 + "The maximum transfer size supported in bytes 2047-65535");
33085 +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
33086 + int, 0444);
33087 +MODULE_PARM_DESC(max_packet_count,
33088 + "The maximum number of packets in a transfer 15-511");
33089 +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
33090 + 0444);
33091 +MODULE_PARM_DESC(host_channels,
33092 + "The number of host channel registers to use 1-16");
33093 +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
33094 + 0444);
33095 +MODULE_PARM_DESC(dev_endpoints,
33096 + "The number of endpoints in addition to EP0 available for device mode 1-15");
33097 +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
33098 +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
33099 +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
33100 + 0444);
33101 +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
33102 +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
33103 +MODULE_PARM_DESC(phy_ulpi_ddr,
33104 + "ULPI at double or single data rate 0=Single 1=Double");
33105 +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
33106 + int, 0444);
33107 +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
33108 + "ULPI PHY using internal or external vbus 0=Internal");
33109 +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
33110 +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
33111 +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
33112 +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
33113 +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
33114 +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
33115 +module_param_named(debug, g_dbg_lvl, int, 0444);
33116 +MODULE_PARM_DESC(debug, "");
33117 +
33118 +module_param_named(en_multiple_tx_fifo,
33119 + dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
33120 +MODULE_PARM_DESC(en_multiple_tx_fifo,
33121 + "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
33122 +module_param_named(dev_tx_fifo_size_1,
33123 + dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
33124 +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
33125 +module_param_named(dev_tx_fifo_size_2,
33126 + dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
33127 +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
33128 +module_param_named(dev_tx_fifo_size_3,
33129 + dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
33130 +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
33131 +module_param_named(dev_tx_fifo_size_4,
33132 + dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
33133 +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
33134 +module_param_named(dev_tx_fifo_size_5,
33135 + dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
33136 +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
33137 +module_param_named(dev_tx_fifo_size_6,
33138 + dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
33139 +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
33140 +module_param_named(dev_tx_fifo_size_7,
33141 + dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
33142 +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
33143 +module_param_named(dev_tx_fifo_size_8,
33144 + dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
33145 +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
33146 +module_param_named(dev_tx_fifo_size_9,
33147 + dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
33148 +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
33149 +module_param_named(dev_tx_fifo_size_10,
33150 + dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
33151 +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
33152 +module_param_named(dev_tx_fifo_size_11,
33153 + dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
33154 +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
33155 +module_param_named(dev_tx_fifo_size_12,
33156 + dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
33157 +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
33158 +module_param_named(dev_tx_fifo_size_13,
33159 + dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
33160 +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
33161 +module_param_named(dev_tx_fifo_size_14,
33162 + dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
33163 +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
33164 +module_param_named(dev_tx_fifo_size_15,
33165 + dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
33166 +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
33167 +
33168 +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
33169 +MODULE_PARM_DESC(thr_ctl,
33170 + "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
33171 +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
33172 + 0444);
33173 +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
33174 +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
33175 + 0444);
33176 +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
33177 +
33178 +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
33179 +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
33180 +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
33181 +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
33182 +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
33183 +MODULE_PARM_DESC(ic_usb_cap,
33184 + "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
33185 +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,
33186 + 0444);
33187 +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
33188 +module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);
33189 +MODULE_PARM_DESC(power_down, "Power Down Mode");
33190 +module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);
33191 +MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
33192 +module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
33193 +MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
33194 +module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
33195 +MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
33196 +module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
33197 +MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
33198 +module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
33199 +MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
33200 +module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
33201 +MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
33202 +module_param(microframe_schedule, bool, 0444);
33203 +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
33204 +
33205 +module_param(fiq_fix_enable, bool, 0444);
33206 +MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
33207 +module_param(nak_holdoff_enable, bool, 0444);
33208 +MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");
33209 +
33210 +/** @page "Module Parameters"
33211 + *
33212 + * The following parameters may be specified when starting the module.
33213 + * These parameters define how the DWC_otg controller should be
33214 + * configured. Parameter values are passed to the CIL initialization
33215 + * function dwc_otg_cil_init
33216 + *
33217 + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
33218 + *
33219 +
33220 + <table>
33221 + <tr><td>Parameter Name</td><td>Meaning</td></tr>
33222 +
33223 + <tr>
33224 + <td>otg_cap</td>
33225 + <td>Specifies the OTG capabilities. The driver will automatically detect the
33226 + value for this parameter if none is specified.
33227 + - 0: HNP and SRP capable (default, if available)
33228 + - 1: SRP Only capable
33229 + - 2: No HNP/SRP capable
33230 + </td></tr>
33231 +
33232 + <tr>
33233 + <td>dma_enable</td>
33234 + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
33235 + The driver will automatically detect the value for this parameter if none is
33236 + specified.
33237 + - 0: Slave
33238 + - 1: DMA (default, if available)
33239 + </td></tr>
33240 +
33241 + <tr>
33242 + <td>dma_burst_size</td>
33243 + <td>The DMA Burst size (applicable only for External DMA Mode).
33244 + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
33245 + </td></tr>
33246 +
33247 + <tr>
33248 + <td>speed</td>
33249 + <td>Specifies the maximum speed of operation in host and device mode. The
33250 + actual speed depends on the speed of the attached device and the value of
33251 + phy_type.
33252 + - 0: High Speed (default)
33253 + - 1: Full Speed
33254 + </td></tr>
33255 +
33256 + <tr>
33257 + <td>host_support_fs_ls_low_power</td>
33258 + <td>Specifies whether low power mode is supported when attached to a Full
33259 + Speed or Low Speed device in host mode.
33260 + - 0: Don't support low power mode (default)
33261 + - 1: Support low power mode
33262 + </td></tr>
33263 +
33264 + <tr>
33265 + <td>host_ls_low_power_phy_clk</td>
33266 + <td>Specifies the PHY clock rate in low power mode when connected to a Low
33267 + Speed device in host mode. This parameter is applicable only if
33268 + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
33269 + - 0: 48 MHz (default)
33270 + - 1: 6 MHz
33271 + </td></tr>
33272 +
33273 + <tr>
33274 + <td>enable_dynamic_fifo</td>
33275 + <td> Specifies whether FIFOs may be resized by the driver software.
33276 + - 0: Use cC FIFO size parameters
33277 + - 1: Allow dynamic FIFO sizing (default)
33278 + </td></tr>
33279 +
33280 + <tr>
33281 + <td>data_fifo_size</td>
33282 + <td>Total number of 4-byte words in the data FIFO memory. This memory
33283 + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
33284 + - Values: 32 to 32768 (default 8192)
33285 +
33286 + Note: The total FIFO memory depth in the FPGA configuration is 8192.
33287 + </td></tr>
33288 +
33289 + <tr>
33290 + <td>dev_rx_fifo_size</td>
33291 + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
33292 + FIFO sizing is enabled.
33293 + - Values: 16 to 32768 (default 1064)
33294 + </td></tr>
33295 +
33296 + <tr>
33297 + <td>dev_nperio_tx_fifo_size</td>
33298 + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
33299 + dynamic FIFO sizing is enabled.
33300 + - Values: 16 to 32768 (default 1024)
33301 + </td></tr>
33302 +
33303 + <tr>
33304 + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
33305 + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
33306 + when dynamic FIFO sizing is enabled.
33307 + - Values: 4 to 768 (default 256)
33308 + </td></tr>
33309 +
33310 + <tr>
33311 + <td>host_rx_fifo_size</td>
33312 + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
33313 + sizing is enabled.
33314 + - Values: 16 to 32768 (default 1024)
33315 + </td></tr>
33316 +
33317 + <tr>
33318 + <td>host_nperio_tx_fifo_size</td>
33319 + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
33320 + dynamic FIFO sizing is enabled in the core.
33321 + - Values: 16 to 32768 (default 1024)
33322 + </td></tr>
33323 +
33324 + <tr>
33325 + <td>host_perio_tx_fifo_size</td>
33326 + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
33327 + sizing is enabled.
33328 + - Values: 16 to 32768 (default 1024)
33329 + </td></tr>
33330 +
33331 + <tr>
33332 + <td>max_transfer_size</td>
33333 + <td>The maximum transfer size supported in bytes.
33334 + - Values: 2047 to 65,535 (default 65,535)
33335 + </td></tr>
33336 +
33337 + <tr>
33338 + <td>max_packet_count</td>
33339 + <td>The maximum number of packets in a transfer.
33340 + - Values: 15 to 511 (default 511)
33341 + </td></tr>
33342 +
33343 + <tr>
33344 + <td>host_channels</td>
33345 + <td>The number of host channel registers to use.
33346 + - Values: 1 to 16 (default 12)
33347 +
33348 + Note: The FPGA configuration supports a maximum of 12 host channels.
33349 + </td></tr>
33350 +
33351 + <tr>
33352 + <td>dev_endpoints</td>
33353 + <td>The number of endpoints in addition to EP0 available for device mode
33354 + operations.
33355 + - Values: 1 to 15 (default 6 IN and OUT)
33356 +
33357 + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
33358 + addition to EP0.
33359 + </td></tr>
33360 +
33361 + <tr>
33362 + <td>phy_type</td>
33363 + <td>Specifies the type of PHY interface to use. By default, the driver will
33364 + automatically detect the phy_type.
33365 + - 0: Full Speed
33366 + - 1: UTMI+ (default, if available)
33367 + - 2: ULPI
33368 + </td></tr>
33369 +
33370 + <tr>
33371 + <td>phy_utmi_width</td>
33372 + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
33373 + phy_type of UTMI+. Also, this parameter is applicable only if the
33374 + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
33375 + core has been configured to work at either data path width.
33376 + - Values: 8 or 16 bits (default 16)
33377 + </td></tr>
33378 +
33379 + <tr>
33380 + <td>phy_ulpi_ddr</td>
33381 + <td>Specifies whether the ULPI operates at double or single data rate. This
33382 + parameter is only applicable if phy_type is ULPI.
33383 + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
33384 + - 1: double data rate ULPI interface with 4 bit wide data bus
33385 + </td></tr>
33386 +
33387 + <tr>
33388 + <td>i2c_enable</td>
33389 + <td>Specifies whether to use the I2C interface for full speed PHY. This
33390 + parameter is only applicable if PHY_TYPE is FS.
33391 + - 0: Disabled (default)
33392 + - 1: Enabled
33393 + </td></tr>
33394 +
33395 + <tr>
33396 + <td>ulpi_fs_ls</td>
33397 + <td>Specifies whether to use ULPI FS/LS mode only.
33398 + - 0: Disabled (default)
33399 + - 1: Enabled
33400 + </td></tr>
33401 +
33402 + <tr>
33403 + <td>ts_dline</td>
33404 + <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.
33405 + - 0: Disabled (default)
33406 + - 1: Enabled
33407 + </td></tr>
33408 +
33409 + <tr>
33410 + <td>en_multiple_tx_fifo</td>
33411 + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
33412 + The driver will automatically detect the value for this parameter if none is
33413 + specified.
33414 + - 0: Disabled
33415 + - 1: Enabled (default, if available)
33416 + </td></tr>
33417 +
33418 + <tr>
33419 + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
33420 + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
33421 + when dynamic FIFO sizing is enabled.
33422 + - Values: 4 to 768 (default 256)
33423 + </td></tr>
33424 +
33425 + <tr>
33426 + <td>tx_thr_length</td>
33427 + <td>Transmit Threshold length in 32 bit double words
33428 + - Values: 8 to 128 (default 64)
33429 + </td></tr>
33430 +
33431 + <tr>
33432 + <td>rx_thr_length</td>
33433 + <td>Receive Threshold length in 32 bit double words
33434 + - Values: 8 to 128 (default 64)
33435 + </td></tr>
33436 +
33437 +<tr>
33438 + <td>thr_ctl</td>
33439 + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
33440 + this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
33441 + Rx transfers accordingly.
33442 + The driver will automatically detect the value for this parameter if none is
33443 + specified.
33444 + - Values: 0 to 7 (default 0)
33445 + Bit values indicate:
33446 + - 0: Thresholding disabled
33447 + - 1: Thresholding enabled
33448 + </td></tr>
33449 +
33450 +<tr>
33451 + <td>dma_desc_enable</td>
33452 + <td>Specifies whether to enable Descriptor DMA mode.
33453 + The driver will automatically detect the value for this parameter if none is
33454 + specified.
33455 + - 0: Descriptor DMA disabled
33456 + - 1: Descriptor DMA (default, if available)
33457 + </td></tr>
33458 +
33459 +<tr>
33460 + <td>mpi_enable</td>
33461 + <td>Specifies whether to enable MPI enhancement mode.
33462 + The driver will automatically detect the value for this parameter if none is
33463 + specified.
33464 + - 0: MPI disabled (default)
33465 + - 1: MPI enable
33466 + </td></tr>
33467 +
33468 +<tr>
33469 + <td>pti_enable</td>
33470 + <td>Specifies whether to enable PTI enhancement support.
33471 + The driver will automatically detect the value for this parameter if none is
33472 + specified.
33473 + - 0: PTI disabled (default)
33474 + - 1: PTI enable
33475 + </td></tr>
33476 +
33477 +<tr>
33478 + <td>lpm_enable</td>
33479 + <td>Specifies whether to enable LPM support.
33480 + The driver will automatically detect the value for this parameter if none is
33481 + specified.
33482 + - 0: LPM disabled
33483 + - 1: LPM enable (default, if available)
33484 + </td></tr>
33485 +
33486 +<tr>
33487 + <td>ic_usb_cap</td>
33488 + <td>Specifies whether to enable IC_USB capability.
33489 + The driver will automatically detect the value for this parameter if none is
33490 + specified.
33491 + - 0: IC_USB disabled (default, if available)
33492 + - 1: IC_USB enable
33493 + </td></tr>
33494 +
33495 +<tr>
33496 + <td>ahb_thr_ratio</td>
33497 + <td>Specifies AHB Threshold ratio.
33498 + - Values: 0 to 3 (default 0)
33499 + </td></tr>
33500 +
33501 +<tr>
33502 + <td>power_down</td>
33503 + <td>Specifies Power Down(Hibernation) Mode.
33504 + The driver will automatically detect the value for this parameter if none is
33505 + specified.
33506 + - 0: Power Down disabled (default)
33507 + - 2: Power Down enabled
33508 + </td></tr>
33509 +
33510 + <tr>
33511 + <td>reload_ctl</td>
33512 + <td>Specifies whether dynamic reloading of the HFIR register is allowed during
33513 + run time. The driver will automatically detect the value for this parameter if
33514 + none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0
33515 + the core might misbehave.
33516 + - 0: Reload Control disabled (default)
33517 + - 1: Reload Control enabled
33518 + </td></tr>
33519 +
33520 + <tr>
33521 + <td>dev_out_nak</td>
33522 + <td>Specifies whether Device OUT NAK enhancement enabled or no.
33523 + The driver will automatically detect the value for this parameter if
33524 + none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33525 + - 0: The core does not set NAK after Bulk OUT transfer complete (default)
33526 + - 1: The core sets NAK after Bulk OUT transfer complete
33527 + </td></tr>
33528 +
33529 + <tr>
33530 + <td>cont_on_bna</td>
33531 + <td>Specifies whether Enable Continue on BNA enabled or no.
33532 + After receiving BNA interrupt the core disables the endpoint,when the
33533 + endpoint is re-enabled by the application the
33534 + - 0: Core starts processing from the DOEPDMA descriptor (default)
33535 + - 1: Core starts processing from the descriptor which received the BNA.
33536 + This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33537 + </td></tr>
33538 +
33539 + <tr>
33540 + <td>ahb_single</td>
33541 + <td>This bit when programmed supports SINGLE transfers for remainder data
33542 + in a transfer for DMA mode of operation.
33543 + - 0: The remainder data will be sent using INCR burst size (default)
33544 + - 1: The remainder data will be sent using SINGLE burst size.
33545 + </td></tr>
33546 +
33547 +<tr>
33548 + <td>adp_enable</td>
33549 + <td>Specifies whether ADP feature is enabled.
33550 + The driver will automatically detect the value for this parameter if none is
33551 + specified.
33552 + - 0: ADP feature disabled (default)
33553 + - 1: ADP feature enabled
33554 + </td></tr>
33555 +
33556 + <tr>
33557 + <td>otg_ver</td>
33558 + <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
33559 + USB OTG device.
33560 + - 0: OTG 2.0 support disabled (default)
33561 + - 1: OTG 2.0 support enabled
33562 + </td></tr>
33563 +
33564 +*/
33565 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33566 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100
33567 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2013-07-06 15:25:50.000000000 +0100
33568 @@ -0,0 +1,86 @@
33569 +/* ==========================================================================
33570 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
33571 + * $Revision: #19 $
33572 + * $Date: 2010/11/15 $
33573 + * $Change: 1627671 $
33574 + *
33575 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33576 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33577 + * otherwise expressly agreed to in writing between Synopsys and you.
33578 + *
33579 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33580 + * any End User Software License Agreement or Agreement for Licensed Product
33581 + * with Synopsys or any supplement thereto. You are permitted to use and
33582 + * redistribute this Software in source and binary forms, with or without
33583 + * modification, provided that redistributions of source code must retain this
33584 + * notice. You may not view, use, disclose, copy or distribute this file or
33585 + * any information contained herein except pursuant to this license grant from
33586 + * Synopsys. If you do not agree with this notice, including the disclaimer
33587 + * below, then you are not authorized to use the Software.
33588 + *
33589 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33590 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33591 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33592 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33593 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33594 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33595 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33596 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33597 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33598 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33599 + * DAMAGE.
33600 + * ========================================================================== */
33601 +
33602 +#ifndef __DWC_OTG_DRIVER_H__
33603 +#define __DWC_OTG_DRIVER_H__
33604 +
33605 +/** @file
33606 + * This file contains the interface to the Linux driver.
33607 + */
33608 +#include "dwc_otg_os_dep.h"
33609 +#include "dwc_otg_core_if.h"
33610 +
33611 +/* Type declarations */
33612 +struct dwc_otg_pcd;
33613 +struct dwc_otg_hcd;
33614 +
33615 +/**
33616 + * This structure is a wrapper that encapsulates the driver components used to
33617 + * manage a single DWC_otg controller.
33618 + */
33619 +typedef struct dwc_otg_device {
33620 + /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE
33621 + * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD
33622 + * require this. */
33623 + struct os_dependent os_dep;
33624 +
33625 + /** Pointer to the core interface structure. */
33626 + dwc_otg_core_if_t *core_if;
33627 +
33628 + /** Pointer to the PCD structure. */
33629 + struct dwc_otg_pcd *pcd;
33630 +
33631 + /** Pointer to the HCD structure. */
33632 + struct dwc_otg_hcd *hcd;
33633 +
33634 + /** Flag to indicate whether the common IRQ handler is installed. */
33635 + uint8_t common_irq_installed;
33636 +
33637 +} dwc_otg_device_t;
33638 +
33639 +/*We must clear S3C24XX_EINTPEND external interrupt register
33640 + * because after clearing in this register trigerred IRQ from
33641 + * H/W core in kernel interrupt can be occured again before OTG
33642 + * handlers clear all IRQ sources of Core registers because of
33643 + * timing latencies and Low Level IRQ Type.
33644 + */
33645 +#ifdef CONFIG_MACH_IPMATE
33646 +#define S3C2410X_CLEAR_EINTPEND() \
33647 +do { \
33648 + __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
33649 +} while (0)
33650 +#else
33651 +#define S3C2410X_CLEAR_EINTPEND() do { } while (0)
33652 +#endif
33653 +
33654 +#endif
33655 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33656 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100
33657 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2013-07-06 15:25:50.000000000 +0100
33658 @@ -0,0 +1,3533 @@
33659 +
33660 +/* ==========================================================================
33661 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
33662 + * $Revision: #104 $
33663 + * $Date: 2011/10/24 $
33664 + * $Change: 1871159 $
33665 + *
33666 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33667 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33668 + * otherwise expressly agreed to in writing between Synopsys and you.
33669 + *
33670 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33671 + * any End User Software License Agreement or Agreement for Licensed Product
33672 + * with Synopsys or any supplement thereto. You are permitted to use and
33673 + * redistribute this Software in source and binary forms, with or without
33674 + * modification, provided that redistributions of source code must retain this
33675 + * notice. You may not view, use, disclose, copy or distribute this file or
33676 + * any information contained herein except pursuant to this license grant from
33677 + * Synopsys. If you do not agree with this notice, including the disclaimer
33678 + * below, then you are not authorized to use the Software.
33679 + *
33680 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33681 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33682 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33683 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33684 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33685 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33686 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33687 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33688 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33689 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33690 + * DAMAGE.
33691 + * ========================================================================== */
33692 +#ifndef DWC_DEVICE_ONLY
33693 +
33694 +/** @file
33695 + * This file implements HCD Core. All code in this file is portable and doesn't
33696 + * use any OS specific functions.
33697 + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
33698 + * header file.
33699 + */
33700 +
33701 +#include <linux/usb.h>
33702 +#include <linux/usb/hcd.h>
33703 +
33704 +#include "dwc_otg_hcd.h"
33705 +#include "dwc_otg_regs.h"
33706 +
33707 +extern bool microframe_schedule, nak_holdoff_enable;
33708 +
33709 +//#define DEBUG_HOST_CHANNELS
33710 +#ifdef DEBUG_HOST_CHANNELS
33711 +static int last_sel_trans_num_per_scheduled = 0;
33712 +static int last_sel_trans_num_nonper_scheduled = 0;
33713 +static int last_sel_trans_num_avail_hc_at_start = 0;
33714 +static int last_sel_trans_num_avail_hc_at_end = 0;
33715 +#endif /* DEBUG_HOST_CHANNELS */
33716 +
33717 +extern int g_next_sched_frame, g_np_count, g_np_sent;
33718 +
33719 +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
33720 +{
33721 + return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
33722 +}
33723 +
33724 +/**
33725 + * Connection timeout function. An OTG host is required to display a
33726 + * message if the device does not connect within 10 seconds.
33727 + */
33728 +void dwc_otg_hcd_connect_timeout(void *ptr)
33729 +{
33730 + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
33731 + DWC_PRINTF("Connect Timeout\n");
33732 + __DWC_ERROR("Device Not Connected/Responding\n");
33733 +}
33734 +
33735 +#if defined(DEBUG)
33736 +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
33737 +{
33738 + if (qh->channel != NULL) {
33739 + dwc_hc_t *hc = qh->channel;
33740 + dwc_list_link_t *item;
33741 + dwc_otg_qh_t *qh_item;
33742 + int num_channels = hcd->core_if->core_params->host_channels;
33743 + int i;
33744 +
33745 + dwc_otg_hc_regs_t *hc_regs;
33746 + hcchar_data_t hcchar;
33747 + hcsplt_data_t hcsplt;
33748 + hctsiz_data_t hctsiz;
33749 + uint32_t hcdma;
33750 +
33751 + hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
33752 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
33753 + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
33754 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
33755 + hcdma = DWC_READ_REG32(&hc_regs->hcdma);
33756 +
33757 + DWC_PRINTF(" Assigned to channel %p:\n", hc);
33758 + DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
33759 + hcsplt.d32);
33760 + DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
33761 + hcdma);
33762 + DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
33763 + hc->dev_addr, hc->ep_num, hc->ep_is_in);
33764 + DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
33765 + DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
33766 + DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
33767 + DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
33768 + DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
33769 + DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
33770 + DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
33771 + DWC_PRINTF(" qh: %p\n", hc->qh);
33772 + DWC_PRINTF(" NP inactive sched:\n");
33773 + DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
33774 + qh_item =
33775 + DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
33776 + DWC_PRINTF(" %p\n", qh_item);
33777 + }
33778 + DWC_PRINTF(" NP active sched:\n");
33779 + DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
33780 + qh_item =
33781 + DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
33782 + DWC_PRINTF(" %p\n", qh_item);
33783 + }
33784 + DWC_PRINTF(" Channels: \n");
33785 + for (i = 0; i < num_channels; i++) {
33786 + dwc_hc_t *hc = hcd->hc_ptr_array[i];
33787 + DWC_PRINTF(" %2d: %p\n", i, hc);
33788 + }
33789 + }
33790 +}
33791 +#else
33792 +#define dump_channel_info(hcd, qh)
33793 +#endif /* DEBUG */
33794 +
33795 +/**
33796 + * Work queue function for starting the HCD when A-Cable is connected.
33797 + * The hcd_start() must be called in a process context.
33798 + */
33799 +static void hcd_start_func(void *_vp)
33800 +{
33801 + dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
33802 +
33803 + DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
33804 + if (hcd) {
33805 + hcd->fops->start(hcd);
33806 + }
33807 +}
33808 +
33809 +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
33810 +{
33811 +#ifdef DEBUG
33812 + int i;
33813 + int num_channels = hcd->core_if->core_params->host_channels;
33814 + for (i = 0; i < num_channels; i++) {
33815 + DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
33816 + }
33817 +#endif
33818 +}
33819 +
33820 +static void del_timers(dwc_otg_hcd_t * hcd)
33821 +{
33822 + del_xfer_timers(hcd);
33823 + DWC_TIMER_CANCEL(hcd->conn_timer);
33824 +}
33825 +
33826 +/**
33827 + * Processes all the URBs in a single list of QHs. Completes them with
33828 + * -ETIMEDOUT and frees the QTD.
33829 + */
33830 +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
33831 +{
33832 + dwc_list_link_t *qh_item;
33833 + dwc_otg_qh_t *qh;
33834 + dwc_otg_qtd_t *qtd, *qtd_tmp;
33835 +
33836 + DWC_LIST_FOREACH(qh_item, qh_list) {
33837 + qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
33838 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
33839 + &qh->qtd_list, qtd_list_entry) {
33840 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
33841 + if (qtd->urb != NULL) {
33842 + hcd->fops->complete(hcd, qtd->urb->priv,
33843 + qtd->urb, -DWC_E_TIMEOUT);
33844 + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
33845 + }
33846 +
33847 + }
33848 + }
33849 +}
33850 +
33851 +/**
33852 + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
33853 + * and periodic schedules. The QTD associated with each URB is removed from
33854 + * the schedule and freed. This function may be called when a disconnect is
33855 + * detected or when the HCD is being stopped.
33856 + */
33857 +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
33858 +{
33859 + kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
33860 + kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
33861 + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
33862 + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
33863 + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
33864 + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
33865 +}
33866 +
33867 +/**
33868 + * Start the connection timer. An OTG host is required to display a
33869 + * message if the device does not connect within 10 seconds. The
33870 + * timer is deleted if a port connect interrupt occurs before the
33871 + * timer expires.
33872 + */
33873 +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
33874 +{
33875 + DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
33876 +}
33877 +
33878 +/**
33879 + * HCD Callback function for disconnect of the HCD.
33880 + *
33881 + * @param p void pointer to the <code>struct usb_hcd</code>
33882 + */
33883 +static int32_t dwc_otg_hcd_session_start_cb(void *p)
33884 +{
33885 + dwc_otg_hcd_t *dwc_otg_hcd;
33886 + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
33887 + dwc_otg_hcd = p;
33888 + dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
33889 + return 1;
33890 +}
33891 +
33892 +/**
33893 + * HCD Callback function for starting the HCD when A-Cable is
33894 + * connected.
33895 + *
33896 + * @param p void pointer to the <code>struct usb_hcd</code>
33897 + */
33898 +static int32_t dwc_otg_hcd_start_cb(void *p)
33899 +{
33900 + dwc_otg_hcd_t *dwc_otg_hcd = p;
33901 + dwc_otg_core_if_t *core_if;
33902 + hprt0_data_t hprt0;
33903 +
33904 + core_if = dwc_otg_hcd->core_if;
33905 +
33906 + if (core_if->op_state == B_HOST) {
33907 + /*
33908 + * Reset the port. During a HNP mode switch the reset
33909 + * needs to occur within 1ms and have a duration of at
33910 + * least 50ms.
33911 + */
33912 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
33913 + hprt0.b.prtrst = 1;
33914 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
33915 + }
33916 + DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
33917 + hcd_start_func, dwc_otg_hcd, 50,
33918 + "start hcd");
33919 +
33920 + return 1;
33921 +}
33922 +
33923 +/**
33924 + * HCD Callback function for disconnect of the HCD.
33925 + *
33926 + * @param p void pointer to the <code>struct usb_hcd</code>
33927 + */
33928 +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
33929 +{
33930 + gintsts_data_t intr;
33931 + dwc_otg_hcd_t *dwc_otg_hcd = p;
33932 +
33933 + /*
33934 + * Set status flags for the hub driver.
33935 + */
33936 + dwc_otg_hcd->flags.b.port_connect_status_change = 1;
33937 + dwc_otg_hcd->flags.b.port_connect_status = 0;
33938 +
33939 + /*
33940 + * Shutdown any transfers in process by clearing the Tx FIFO Empty
33941 + * interrupt mask and status bits and disabling subsequent host
33942 + * channel interrupts.
33943 + */
33944 + intr.d32 = 0;
33945 + intr.b.nptxfempty = 1;
33946 + intr.b.ptxfempty = 1;
33947 + intr.b.hcintr = 1;
33948 + DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
33949 + intr.d32, 0);
33950 + DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
33951 + intr.d32, 0);
33952 +
33953 + del_timers(dwc_otg_hcd);
33954 +
33955 + /*
33956 + * Turn off the vbus power only if the core has transitioned to device
33957 + * mode. If still in host mode, need to keep power on to detect a
33958 + * reconnection.
33959 + */
33960 + if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
33961 + if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
33962 + hprt0_data_t hprt0 = {.d32 = 0 };
33963 + DWC_PRINTF("Disconnect: PortPower off\n");
33964 + hprt0.b.prtpwr = 0;
33965 + DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
33966 + hprt0.d32);
33967 + }
33968 +
33969 + dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
33970 + }
33971 +
33972 + /* Respond with an error status to all URBs in the schedule. */
33973 + kill_all_urbs(dwc_otg_hcd);
33974 +
33975 + if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
33976 + /* Clean up any host channels that were in use. */
33977 + int num_channels;
33978 + int i;
33979 + dwc_hc_t *channel;
33980 + dwc_otg_hc_regs_t *hc_regs;
33981 + hcchar_data_t hcchar;
33982 +
33983 + num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
33984 +
33985 + if (!dwc_otg_hcd->core_if->dma_enable) {
33986 + /* Flush out any channel requests in slave mode. */
33987 + for (i = 0; i < num_channels; i++) {
33988 + channel = dwc_otg_hcd->hc_ptr_array[i];
33989 + if (DWC_CIRCLEQ_EMPTY_ENTRY
33990 + (channel, hc_list_entry)) {
33991 + hc_regs =
33992 + dwc_otg_hcd->core_if->
33993 + host_if->hc_regs[i];
33994 + hcchar.d32 =
33995 + DWC_READ_REG32(&hc_regs->hcchar);
33996 + if (hcchar.b.chen) {
33997 + hcchar.b.chen = 0;
33998 + hcchar.b.chdis = 1;
33999 + hcchar.b.epdir = 0;
34000 + DWC_WRITE_REG32
34001 + (&hc_regs->hcchar,
34002 + hcchar.d32);
34003 + }
34004 + }
34005 + }
34006 + }
34007 +
34008 + for (i = 0; i < num_channels; i++) {
34009 + channel = dwc_otg_hcd->hc_ptr_array[i];
34010 + if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
34011 + hc_regs =
34012 + dwc_otg_hcd->core_if->host_if->hc_regs[i];
34013 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34014 + if (hcchar.b.chen) {
34015 + /* Halt the channel. */
34016 + hcchar.b.chdis = 1;
34017 + DWC_WRITE_REG32(&hc_regs->hcchar,
34018 + hcchar.d32);
34019 + }
34020 +
34021 + dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
34022 + channel);
34023 + DWC_CIRCLEQ_INSERT_TAIL
34024 + (&dwc_otg_hcd->free_hc_list, channel,
34025 + hc_list_entry);
34026 + /*
34027 + * Added for Descriptor DMA to prevent channel double cleanup
34028 + * in release_channel_ddma(). Which called from ep_disable
34029 + * when device disconnect.
34030 + */
34031 + channel->qh = NULL;
34032 + }
34033 + }
34034 + }
34035 +
34036 + if (dwc_otg_hcd->fops->disconnect) {
34037 + dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
34038 + }
34039 +
34040 + return 1;
34041 +}
34042 +
34043 +/**
34044 + * HCD Callback function for stopping the HCD.
34045 + *
34046 + * @param p void pointer to the <code>struct usb_hcd</code>
34047 + */
34048 +static int32_t dwc_otg_hcd_stop_cb(void *p)
34049 +{
34050 + dwc_otg_hcd_t *dwc_otg_hcd = p;
34051 +
34052 + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34053 + dwc_otg_hcd_stop(dwc_otg_hcd);
34054 + return 1;
34055 +}
34056 +
34057 +#ifdef CONFIG_USB_DWC_OTG_LPM
34058 +/**
34059 + * HCD Callback function for sleep of HCD.
34060 + *
34061 + * @param p void pointer to the <code>struct usb_hcd</code>
34062 + */
34063 +static int dwc_otg_hcd_sleep_cb(void *p)
34064 +{
34065 + dwc_otg_hcd_t *hcd = p;
34066 +
34067 + dwc_otg_hcd_free_hc_from_lpm(hcd);
34068 +
34069 + return 0;
34070 +}
34071 +#endif
34072 +
34073 +
34074 +/**
34075 + * HCD Callback function for Remote Wakeup.
34076 + *
34077 + * @param p void pointer to the <code>struct usb_hcd</code>
34078 + */
34079 +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
34080 +{
34081 + dwc_otg_hcd_t *hcd = p;
34082 +
34083 + if (hcd->core_if->lx_state == DWC_OTG_L2) {
34084 + hcd->flags.b.port_suspend_change = 1;
34085 + }
34086 +#ifdef CONFIG_USB_DWC_OTG_LPM
34087 + else {
34088 + hcd->flags.b.port_l1_change = 1;
34089 + }
34090 +#endif
34091 + return 0;
34092 +}
34093 +
34094 +/**
34095 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
34096 + * stopped.
34097 + */
34098 +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
34099 +{
34100 + hprt0_data_t hprt0 = {.d32 = 0 };
34101 +
34102 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
34103 +
34104 + /*
34105 + * The root hub should be disconnected before this function is called.
34106 + * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
34107 + * and the QH lists (via ..._hcd_endpoint_disable).
34108 + */
34109 +
34110 + /* Turn off all host-specific interrupts. */
34111 + dwc_otg_disable_host_interrupts(hcd->core_if);
34112 +
34113 + /* Turn off the vbus power */
34114 + DWC_PRINTF("PortPower off\n");
34115 + hprt0.b.prtpwr = 0;
34116 + DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
34117 + dwc_mdelay(1);
34118 +}
34119 +
34120 +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
34121 + dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
34122 + int atomic_alloc)
34123 +{
34124 + dwc_irqflags_t flags;
34125 + int retval = 0;
34126 + uint8_t needs_scheduling = 0;
34127 + dwc_otg_transaction_type_e tr_type;
34128 + dwc_otg_qtd_t *qtd;
34129 + gintmsk_data_t intr_mask = {.d32 = 0 };
34130 +
34131 +#ifdef DEBUG /* integrity checks (Broadcom) */
34132 + if (NULL == hcd->core_if) {
34133 + DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
34134 + /* No longer connected. */
34135 + return -DWC_E_INVALID;
34136 + }
34137 +#endif
34138 + if (!hcd->flags.b.port_connect_status) {
34139 + /* No longer connected. */
34140 + DWC_ERROR("Not connected\n");
34141 + return -DWC_E_NO_DEVICE;
34142 + }
34143 +
34144 + qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
34145 + if (qtd == NULL) {
34146 + DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
34147 + return -DWC_E_NO_MEMORY;
34148 + }
34149 +#ifdef DEBUG /* integrity checks (Broadcom) */
34150 + if (qtd->urb == NULL) {
34151 + DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
34152 + return -DWC_E_NO_MEMORY;
34153 + }
34154 + if (qtd->urb->priv == NULL) {
34155 + DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
34156 + return -DWC_E_NO_MEMORY;
34157 + }
34158 +#endif
34159 + intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
34160 + if(!intr_mask.b.sofintr) needs_scheduling = 1;
34161 + if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))
34162 + /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
34163 + needs_scheduling = 0;
34164 +
34165 + retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
34166 + // creates a new queue in ep_handle if it doesn't exist already
34167 + if (retval < 0) {
34168 + DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
34169 + "Error status %d\n", retval);
34170 + dwc_otg_hcd_qtd_free(qtd);
34171 + return retval;
34172 + }
34173 +
34174 + if(needs_scheduling) {
34175 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34176 + tr_type = dwc_otg_hcd_select_transactions(hcd);
34177 + if (tr_type != DWC_OTG_TRANSACTION_NONE) {
34178 + dwc_otg_hcd_queue_transactions(hcd, tr_type);
34179 + }
34180 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34181 + }
34182 + return retval;
34183 +}
34184 +
34185 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
34186 + dwc_otg_hcd_urb_t * dwc_otg_urb)
34187 +{
34188 + dwc_otg_qh_t *qh;
34189 + dwc_otg_qtd_t *urb_qtd;
34190 + BUG_ON(!hcd);
34191 + BUG_ON(!dwc_otg_urb);
34192 +
34193 +#ifdef DEBUG /* integrity checks (Broadcom) */
34194 +
34195 + if (hcd == NULL) {
34196 + DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
34197 + return -DWC_E_INVALID;
34198 + }
34199 + if (dwc_otg_urb == NULL) {
34200 + DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
34201 + return -DWC_E_INVALID;
34202 + }
34203 + if (dwc_otg_urb->qtd == NULL) {
34204 + DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
34205 + return -DWC_E_INVALID;
34206 + }
34207 + urb_qtd = dwc_otg_urb->qtd;
34208 + BUG_ON(!urb_qtd);
34209 + if (urb_qtd->qh == NULL) {
34210 + DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
34211 + return -DWC_E_INVALID;
34212 + }
34213 +#else
34214 + urb_qtd = dwc_otg_urb->qtd;
34215 + BUG_ON(!urb_qtd);
34216 +#endif
34217 + qh = urb_qtd->qh;
34218 + BUG_ON(!qh);
34219 + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
34220 + if (urb_qtd->in_process) {
34221 + dump_channel_info(hcd, qh);
34222 + }
34223 + }
34224 +#ifdef DEBUG /* integrity checks (Broadcom) */
34225 + if (hcd->core_if == NULL) {
34226 + DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
34227 + return -DWC_E_INVALID;
34228 + }
34229 +#endif
34230 + if (urb_qtd->in_process && qh->channel) {
34231 + /* The QTD is in process (it has been assigned to a channel). */
34232 + if (hcd->flags.b.port_connect_status) {
34233 + /*
34234 + * If still connected (i.e. in host mode), halt the
34235 + * channel so it can be used for other transfers. If
34236 + * no longer connected, the host registers can't be
34237 + * written to halt the channel since the core is in
34238 + * device mode.
34239 + */
34240 + dwc_otg_hc_halt(hcd->core_if, qh->channel,
34241 + DWC_OTG_HC_XFER_URB_DEQUEUE);
34242 + }
34243 + }
34244 +
34245 + /*
34246 + * Free the QTD and clean up the associated QH. Leave the QH in the
34247 + * schedule if it has any remaining QTDs.
34248 + */
34249 +
34250 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
34251 + "delete %sQueue handler\n",
34252 + hcd->core_if->dma_desc_enable?"DMA ":"");
34253 + if (!hcd->core_if->dma_desc_enable) {
34254 + uint8_t b = urb_qtd->in_process;
34255 + dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34256 + if (b) {
34257 + dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
34258 + qh->channel = NULL;
34259 + } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
34260 + dwc_otg_hcd_qh_remove(hcd, qh);
34261 + }
34262 + } else {
34263 + dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34264 + }
34265 + return 0;
34266 +}
34267 +
34268 +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
34269 + int retry)
34270 +{
34271 + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34272 + int retval = 0;
34273 + dwc_irqflags_t flags;
34274 +
34275 + if (retry < 0) {
34276 + retval = -DWC_E_INVALID;
34277 + goto done;
34278 + }
34279 +
34280 + if (!qh) {
34281 + retval = -DWC_E_INVALID;
34282 + goto done;
34283 + }
34284 +
34285 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34286 +
34287 + while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
34288 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34289 + retry--;
34290 + dwc_msleep(5);
34291 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34292 + }
34293 +
34294 + dwc_otg_hcd_qh_remove(hcd, qh);
34295 +
34296 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34297 + /*
34298 + * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
34299 + * and qh_free to prevent stack dump on DWC_DMA_FREE() with
34300 + * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
34301 + * and dwc_otg_hcd_frame_list_alloc().
34302 + */
34303 + dwc_otg_hcd_qh_free(hcd, qh);
34304 +
34305 +done:
34306 + return retval;
34307 +}
34308 +
34309 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
34310 +int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
34311 +{
34312 + int retval = 0;
34313 + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34314 + if (!qh)
34315 + return -DWC_E_INVALID;
34316 +
34317 + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
34318 + return retval;
34319 +}
34320 +#endif
34321 +
34322 +/**
34323 + * HCD Callback structure for handling mode switching.
34324 + */
34325 +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
34326 + .start = dwc_otg_hcd_start_cb,
34327 + .stop = dwc_otg_hcd_stop_cb,
34328 + .disconnect = dwc_otg_hcd_disconnect_cb,
34329 + .session_start = dwc_otg_hcd_session_start_cb,
34330 + .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
34331 +#ifdef CONFIG_USB_DWC_OTG_LPM
34332 + .sleep = dwc_otg_hcd_sleep_cb,
34333 +#endif
34334 + .p = 0,
34335 +};
34336 +
34337 +/**
34338 + * Reset tasklet function
34339 + */
34340 +static void reset_tasklet_func(void *data)
34341 +{
34342 + dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
34343 + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
34344 + hprt0_data_t hprt0;
34345 +
34346 + DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
34347 +
34348 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
34349 + hprt0.b.prtrst = 1;
34350 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34351 + dwc_mdelay(60);
34352 +
34353 + hprt0.b.prtrst = 0;
34354 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34355 + dwc_otg_hcd->flags.b.port_reset_change = 1;
34356 +}
34357 +
34358 +static void completion_tasklet_func(void *ptr)
34359 +{
34360 + dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;
34361 + struct urb *urb;
34362 + urb_tq_entry_t *item;
34363 + dwc_irqflags_t flags;
34364 +
34365 + /* This could just be spin_lock_irq */
34366 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34367 + while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
34368 + item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
34369 + urb = item->urb;
34370 + DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,
34371 + urb_tq_entries);
34372 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34373 + DWC_FREE(item);
34374 +
34375 + usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
34376 +
34377 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34378 + }
34379 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34380 + return;
34381 +}
34382 +
34383 +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34384 +{
34385 + dwc_list_link_t *item;
34386 + dwc_otg_qh_t *qh;
34387 + dwc_irqflags_t flags;
34388 +
34389 + if (!qh_list->next) {
34390 + /* The list hasn't been initialized yet. */
34391 + return;
34392 + }
34393 + /*
34394 + * Hold spinlock here. Not needed in that case if bellow
34395 + * function is being called from ISR
34396 + */
34397 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34398 + /* Ensure there are no QTDs or URBs left. */
34399 + kill_urbs_in_qh_list(hcd, qh_list);
34400 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34401 +
34402 + DWC_LIST_FOREACH(item, qh_list) {
34403 + qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34404 + dwc_otg_hcd_qh_remove_and_free(hcd, qh);
34405 + }
34406 +}
34407 +
34408 +/**
34409 + * Exit from Hibernation if Host did not detect SRP from connected SRP capable
34410 + * Device during SRP time by host power up.
34411 + */
34412 +void dwc_otg_hcd_power_up(void *ptr)
34413 +{
34414 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
34415 + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
34416 +
34417 + DWC_PRINTF("%s called\n", __FUNCTION__);
34418 +
34419 + if (!core_if->hibernation_suspend) {
34420 + DWC_PRINTF("Already exited from Hibernation\n");
34421 + return;
34422 + }
34423 +
34424 + /* Switch on the voltage to the core */
34425 + gpwrdn.b.pwrdnswtch = 1;
34426 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34427 + dwc_udelay(10);
34428 +
34429 + /* Reset the core */
34430 + gpwrdn.d32 = 0;
34431 + gpwrdn.b.pwrdnrstn = 1;
34432 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34433 + dwc_udelay(10);
34434 +
34435 + /* Disable power clamps */
34436 + gpwrdn.d32 = 0;
34437 + gpwrdn.b.pwrdnclmp = 1;
34438 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34439 +
34440 + /* Remove reset the core signal */
34441 + gpwrdn.d32 = 0;
34442 + gpwrdn.b.pwrdnrstn = 1;
34443 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
34444 + dwc_udelay(10);
34445 +
34446 + /* Disable PMU interrupt */
34447 + gpwrdn.d32 = 0;
34448 + gpwrdn.b.pmuintsel = 1;
34449 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34450 +
34451 + core_if->hibernation_suspend = 0;
34452 +
34453 + /* Disable PMU */
34454 + gpwrdn.d32 = 0;
34455 + gpwrdn.b.pmuactv = 1;
34456 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34457 + dwc_udelay(10);
34458 +
34459 + /* Enable VBUS */
34460 + gpwrdn.d32 = 0;
34461 + gpwrdn.b.dis_vbus = 1;
34462 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34463 +
34464 + core_if->op_state = A_HOST;
34465 + dwc_otg_core_init(core_if);
34466 + dwc_otg_enable_global_interrupts(core_if);
34467 + cil_hcd_start(core_if);
34468 +}
34469 +
34470 +/**
34471 + * Frees secondary storage associated with the dwc_otg_hcd structure contained
34472 + * in the struct usb_hcd field.
34473 + */
34474 +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
34475 +{
34476 + int i;
34477 +
34478 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
34479 +
34480 + del_timers(dwc_otg_hcd);
34481 +
34482 + /* Free memory for QH/QTD lists */
34483 + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
34484 + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
34485 + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
34486 + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
34487 + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
34488 + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
34489 +
34490 + /* Free memory for the host channels. */
34491 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
34492 + dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
34493 +
34494 +#ifdef DEBUG
34495 + if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
34496 + DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
34497 + }
34498 +#endif
34499 + if (hc != NULL) {
34500 + DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
34501 + i, hc);
34502 + DWC_FREE(hc);
34503 + }
34504 + }
34505 +
34506 + if (dwc_otg_hcd->core_if->dma_enable) {
34507 + if (dwc_otg_hcd->status_buf_dma) {
34508 + DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
34509 + dwc_otg_hcd->status_buf,
34510 + dwc_otg_hcd->status_buf_dma);
34511 + }
34512 + } else if (dwc_otg_hcd->status_buf != NULL) {
34513 + DWC_FREE(dwc_otg_hcd->status_buf);
34514 + }
34515 + DWC_SPINLOCK_FREE(dwc_otg_hcd->channel_lock);
34516 + DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
34517 + /* Set core_if's lock pointer to NULL */
34518 + dwc_otg_hcd->core_if->lock = NULL;
34519 +
34520 + DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
34521 + DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
34522 + DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
34523 +
34524 +#ifdef DWC_DEV_SRPCAP
34525 + if (dwc_otg_hcd->core_if->power_down == 2 &&
34526 + dwc_otg_hcd->core_if->pwron_timer) {
34527 + DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
34528 + }
34529 +#endif
34530 + DWC_FREE(dwc_otg_hcd);
34531 +}
34532 +
34533 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
34534 +
34535 +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
34536 +{
34537 + int retval = 0;
34538 + int num_channels;
34539 + int i;
34540 + dwc_hc_t *channel;
34541 +
34542 + hcd->lock = DWC_SPINLOCK_ALLOC();
34543 + hcd->channel_lock = DWC_SPINLOCK_ALLOC();
34544 + DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
34545 + hcd, core_if);
34546 + if (!hcd->lock) {
34547 + DWC_ERROR("Could not allocate lock for pcd");
34548 + DWC_FREE(hcd);
34549 + retval = -DWC_E_NO_MEMORY;
34550 + goto out;
34551 + }
34552 + hcd->core_if = core_if;
34553 +
34554 + /* Register the HCD CIL Callbacks */
34555 + dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
34556 + &hcd_cil_callbacks, hcd);
34557 +
34558 + /* Initialize the non-periodic schedule. */
34559 + DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
34560 + DWC_LIST_INIT(&hcd->non_periodic_sched_active);
34561 +
34562 + /* Initialize the periodic schedule. */
34563 + DWC_LIST_INIT(&hcd->periodic_sched_inactive);
34564 + DWC_LIST_INIT(&hcd->periodic_sched_ready);
34565 + DWC_LIST_INIT(&hcd->periodic_sched_assigned);
34566 + DWC_LIST_INIT(&hcd->periodic_sched_queued);
34567 + DWC_TAILQ_INIT(&hcd->completed_urb_list);
34568 + /*
34569 + * Create a host channel descriptor for each host channel implemented
34570 + * in the controller. Initialize the channel descriptor array.
34571 + */
34572 + DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
34573 + num_channels = hcd->core_if->core_params->host_channels;
34574 + DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
34575 + for (i = 0; i < num_channels; i++) {
34576 + channel = DWC_ALLOC(sizeof(dwc_hc_t));
34577 + if (channel == NULL) {
34578 + retval = -DWC_E_NO_MEMORY;
34579 + DWC_ERROR("%s: host channel allocation failed\n",
34580 + __func__);
34581 + dwc_otg_hcd_free(hcd);
34582 + goto out;
34583 + }
34584 + channel->hc_num = i;
34585 + hcd->hc_ptr_array[i] = channel;
34586 +#ifdef DEBUG
34587 + hcd->core_if->hc_xfer_timer[i] =
34588 + DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
34589 + &hcd->core_if->hc_xfer_info[i]);
34590 +#endif
34591 + DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
34592 + channel);
34593 + }
34594 +
34595 + /* Initialize the Connection timeout timer. */
34596 + hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
34597 + dwc_otg_hcd_connect_timeout, 0);
34598 +
34599 + printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
34600 + if (microframe_schedule)
34601 + init_hcd_usecs(hcd);
34602 +
34603 + /* Initialize reset tasklet. */
34604 + hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
34605 +
34606 + hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",
34607 + completion_tasklet_func, hcd);
34608 +#ifdef DWC_DEV_SRPCAP
34609 + if (hcd->core_if->power_down == 2) {
34610 + /* Initialize Power on timer for Host power up in case hibernation */
34611 + hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
34612 + dwc_otg_hcd_power_up, core_if);
34613 + }
34614 +#endif
34615 +
34616 + /*
34617 + * Allocate space for storing data on status transactions. Normally no
34618 + * data is sent, but this space acts as a bit bucket. This must be
34619 + * done after usb_add_hcd since that function allocates the DMA buffer
34620 + * pool.
34621 + */
34622 + if (hcd->core_if->dma_enable) {
34623 + hcd->status_buf =
34624 + DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
34625 + &hcd->status_buf_dma);
34626 + } else {
34627 + hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
34628 + }
34629 + if (!hcd->status_buf) {
34630 + retval = -DWC_E_NO_MEMORY;
34631 + DWC_ERROR("%s: status_buf allocation failed\n", __func__);
34632 + dwc_otg_hcd_free(hcd);
34633 + goto out;
34634 + }
34635 +
34636 + hcd->otg_port = 1;
34637 + hcd->frame_list = NULL;
34638 + hcd->frame_list_dma = 0;
34639 + hcd->periodic_qh_count = 0;
34640 +out:
34641 + return retval;
34642 +}
34643 +
34644 +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
34645 +{
34646 + /* Turn off all host-specific interrupts. */
34647 + dwc_otg_disable_host_interrupts(hcd->core_if);
34648 +
34649 + dwc_otg_hcd_free(hcd);
34650 +}
34651 +
34652 +/**
34653 + * Initializes dynamic portions of the DWC_otg HCD state.
34654 + */
34655 +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
34656 +{
34657 + int num_channels;
34658 + int i;
34659 + dwc_hc_t *channel;
34660 + dwc_hc_t *channel_tmp;
34661 +
34662 + hcd->flags.d32 = 0;
34663 +
34664 + hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
34665 + if (!microframe_schedule) {
34666 + hcd->non_periodic_channels = 0;
34667 + hcd->periodic_channels = 0;
34668 + } else {
34669 + hcd->available_host_channels = hcd->core_if->core_params->host_channels;
34670 + }
34671 + /*
34672 + * Put all channels in the free channel list and clean up channel
34673 + * states.
34674 + */
34675 + DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
34676 + &hcd->free_hc_list, hc_list_entry) {
34677 + DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
34678 + }
34679 +
34680 + num_channels = hcd->core_if->core_params->host_channels;
34681 + for (i = 0; i < num_channels; i++) {
34682 + channel = hcd->hc_ptr_array[i];
34683 + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
34684 + hc_list_entry);
34685 + dwc_otg_hc_cleanup(hcd->core_if, channel);
34686 + }
34687 +
34688 + /* Initialize the DWC core for host mode operation. */
34689 + dwc_otg_core_host_init(hcd->core_if);
34690 +
34691 + /* Set core_if's lock pointer to the hcd->lock */
34692 + hcd->core_if->lock = hcd->lock;
34693 +}
34694 +
34695 +/**
34696 + * Assigns transactions from a QTD to a free host channel and initializes the
34697 + * host channel to perform the transactions. The host channel is removed from
34698 + * the free list.
34699 + *
34700 + * @param hcd The HCD state structure.
34701 + * @param qh Transactions from the first QTD for this QH are selected and
34702 + * assigned to a free host channel.
34703 + */
34704 +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34705 +{
34706 + dwc_hc_t *hc;
34707 + dwc_otg_qtd_t *qtd;
34708 + dwc_otg_hcd_urb_t *urb;
34709 + void* ptr = NULL;
34710 +
34711 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34712 +
34713 + urb = qtd->urb;
34714 +
34715 + DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
34716 +
34717 + if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
34718 + urb->actual_length = urb->length;
34719 +
34720 +
34721 + hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
34722 +
34723 + /* Remove the host channel from the free list. */
34724 + DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
34725 +
34726 + qh->channel = hc;
34727 +
34728 + qtd->in_process = 1;
34729 +
34730 + /*
34731 + * Use usb_pipedevice to determine device address. This address is
34732 + * 0 before the SET_ADDRESS command and the correct address afterward.
34733 + */
34734 + hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
34735 + hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
34736 + hc->speed = qh->dev_speed;
34737 + hc->max_packet = dwc_max_packet(qh->maxp);
34738 +
34739 + hc->xfer_started = 0;
34740 + hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
34741 + hc->error_state = (qtd->error_count > 0);
34742 + hc->halt_on_queue = 0;
34743 + hc->halt_pending = 0;
34744 + hc->requests = 0;
34745 +
34746 + /*
34747 + * The following values may be modified in the transfer type section
34748 + * below. The xfer_len value may be reduced when the transfer is
34749 + * started to accommodate the max widths of the XferSize and PktCnt
34750 + * fields in the HCTSIZn register.
34751 + */
34752 +
34753 + hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
34754 + if (hc->ep_is_in) {
34755 + hc->do_ping = 0;
34756 + } else {
34757 + hc->do_ping = qh->ping_state;
34758 + }
34759 +
34760 + hc->data_pid_start = qh->data_toggle;
34761 + hc->multi_count = 1;
34762 +
34763 + if (hcd->core_if->dma_enable) {
34764 + hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
34765 +
34766 + /* For non-dword aligned case */
34767 + if (((unsigned long)hc->xfer_buff & 0x3)
34768 + && !hcd->core_if->dma_desc_enable) {
34769 + ptr = (uint8_t *) urb->buf + urb->actual_length;
34770 + }
34771 + } else {
34772 + hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
34773 + }
34774 + hc->xfer_len = urb->length - urb->actual_length;
34775 + hc->xfer_count = 0;
34776 +
34777 + /*
34778 + * Set the split attributes
34779 + */
34780 + hc->do_split = 0;
34781 + if (qh->do_split) {
34782 + uint32_t hub_addr, port_addr;
34783 + hc->do_split = 1;
34784 + hc->xact_pos = qtd->isoc_split_pos;
34785 + hc->complete_split = qtd->complete_split;
34786 + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
34787 + hc->hub_addr = (uint8_t) hub_addr;
34788 + hc->port_addr = (uint8_t) port_addr;
34789 + }
34790 +
34791 + switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
34792 + case UE_CONTROL:
34793 + hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
34794 + switch (qtd->control_phase) {
34795 + case DWC_OTG_CONTROL_SETUP:
34796 + DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n");
34797 + hc->do_ping = 0;
34798 + hc->ep_is_in = 0;
34799 + hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
34800 + if (hcd->core_if->dma_enable) {
34801 + hc->xfer_buff = (uint8_t *) urb->setup_dma;
34802 + } else {
34803 + hc->xfer_buff = (uint8_t *) urb->setup_packet;
34804 + }
34805 + hc->xfer_len = 8;
34806 + ptr = NULL;
34807 + break;
34808 + case DWC_OTG_CONTROL_DATA:
34809 + DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
34810 + hc->data_pid_start = qtd->data_toggle;
34811 + break;
34812 + case DWC_OTG_CONTROL_STATUS:
34813 + /*
34814 + * Direction is opposite of data direction or IN if no
34815 + * data.
34816 + */
34817 + DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n");
34818 + if (urb->length == 0) {
34819 + hc->ep_is_in = 1;
34820 + } else {
34821 + hc->ep_is_in =
34822 + dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
34823 + }
34824 + if (hc->ep_is_in) {
34825 + hc->do_ping = 0;
34826 + }
34827 +
34828 + hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
34829 +
34830 + hc->xfer_len = 0;
34831 + if (hcd->core_if->dma_enable) {
34832 + hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
34833 + } else {
34834 + hc->xfer_buff = (uint8_t *) hcd->status_buf;
34835 + }
34836 + ptr = NULL;
34837 + break;
34838 + }
34839 + break;
34840 + case UE_BULK:
34841 + hc->ep_type = DWC_OTG_EP_TYPE_BULK;
34842 + break;
34843 + case UE_INTERRUPT:
34844 + hc->ep_type = DWC_OTG_EP_TYPE_INTR;
34845 + break;
34846 + case UE_ISOCHRONOUS:
34847 + {
34848 + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
34849 +
34850 + hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
34851 +
34852 + if (hcd->core_if->dma_desc_enable)
34853 + break;
34854 +
34855 + frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
34856 +
34857 + frame_desc->status = 0;
34858 +
34859 + if (hcd->core_if->dma_enable) {
34860 + hc->xfer_buff = (uint8_t *) urb->dma;
34861 + } else {
34862 + hc->xfer_buff = (uint8_t *) urb->buf;
34863 + }
34864 + hc->xfer_buff +=
34865 + frame_desc->offset + qtd->isoc_split_offset;
34866 + hc->xfer_len =
34867 + frame_desc->length - qtd->isoc_split_offset;
34868 +
34869 + /* For non-dword aligned buffers */
34870 + if (((unsigned long)hc->xfer_buff & 0x3)
34871 + && hcd->core_if->dma_enable) {
34872 + ptr =
34873 + (uint8_t *) urb->buf + frame_desc->offset +
34874 + qtd->isoc_split_offset;
34875 + } else
34876 + ptr = NULL;
34877 +
34878 + if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
34879 + if (hc->xfer_len <= 188) {
34880 + hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
34881 + } else {
34882 + hc->xact_pos =
34883 + DWC_HCSPLIT_XACTPOS_BEGIN;
34884 + }
34885 + }
34886 + }
34887 + break;
34888 + }
34889 + /* non DWORD-aligned buffer case */
34890 + if (ptr) {
34891 + uint32_t buf_size;
34892 + if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
34893 + buf_size = hcd->core_if->core_params->max_transfer_size;
34894 + } else {
34895 + buf_size = 4096;
34896 + }
34897 + if (!qh->dw_align_buf) {
34898 + qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
34899 + &qh->dw_align_buf_dma);
34900 + if (!qh->dw_align_buf) {
34901 + DWC_ERROR
34902 + ("%s: Failed to allocate memory to handle "
34903 + "non-dword aligned buffer case\n",
34904 + __func__);
34905 + return;
34906 + }
34907 + }
34908 + if (!hc->ep_is_in) {
34909 + dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
34910 + }
34911 + hc->align_buff = qh->dw_align_buf_dma;
34912 + } else {
34913 + hc->align_buff = 0;
34914 + }
34915 +
34916 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
34917 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
34918 + /*
34919 + * This value may be modified when the transfer is started to
34920 + * reflect the actual transfer length.
34921 + */
34922 + hc->multi_count = dwc_hb_mult(qh->maxp);
34923 + }
34924 +
34925 + if (hcd->core_if->dma_desc_enable)
34926 + hc->desc_list_addr = qh->desc_list_dma;
34927 +
34928 + dwc_otg_hc_init(hcd->core_if, hc);
34929 + hc->qh = qh;
34930 +}
34931 +
34932 +/**
34933 + * This function selects transactions from the HCD transfer schedule and
34934 + * assigns them to available host channels. It is called from HCD interrupt
34935 + * handler functions.
34936 + *
34937 + * @param hcd The HCD state structure.
34938 + *
34939 + * @return The types of new transactions that were assigned to host channels.
34940 + */
34941 +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
34942 +{
34943 + dwc_list_link_t *qh_ptr;
34944 + dwc_otg_qh_t *qh;
34945 + int num_channels;
34946 + dwc_irqflags_t flags;
34947 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
34948 + dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
34949 +
34950 +#ifdef DEBUG_SOF
34951 + DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
34952 +#endif
34953 +
34954 +#ifdef DEBUG_HOST_CHANNELS
34955 + last_sel_trans_num_per_scheduled = 0;
34956 + last_sel_trans_num_nonper_scheduled = 0;
34957 + last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
34958 +#endif /* DEBUG_HOST_CHANNELS */
34959 +
34960 + /* Process entries in the periodic ready list. */
34961 + qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
34962 +
34963 + while (qh_ptr != &hcd->periodic_sched_ready &&
34964 + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
34965 + if (microframe_schedule) {
34966 + // Make sure we leave one channel for non periodic transactions.
34967 + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
34968 + if (hcd->available_host_channels <= 1) {
34969 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
34970 + break;
34971 + }
34972 + hcd->available_host_channels--;
34973 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
34974 +#ifdef DEBUG_HOST_CHANNELS
34975 + last_sel_trans_num_per_scheduled++;
34976 +#endif /* DEBUG_HOST_CHANNELS */
34977 + }
34978 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
34979 + assign_and_init_hc(hcd, qh);
34980 +
34981 + /*
34982 + * Move the QH from the periodic ready schedule to the
34983 + * periodic assigned schedule.
34984 + */
34985 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
34986 + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
34987 + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
34988 + &qh->qh_list_entry);
34989 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
34990 +
34991 + ret_val = DWC_OTG_TRANSACTION_PERIODIC;
34992 + }
34993 +
34994 + /*
34995 + * Process entries in the inactive portion of the non-periodic
34996 + * schedule. Some free host channels may not be used if they are
34997 + * reserved for periodic transfers.
34998 + */
34999 + qh_ptr = hcd->non_periodic_sched_inactive.next;
35000 + num_channels = hcd->core_if->core_params->host_channels;
35001 + while (qh_ptr != &hcd->non_periodic_sched_inactive &&
35002 + (microframe_schedule || hcd->non_periodic_channels <
35003 + num_channels - hcd->periodic_channels) &&
35004 + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35005 +
35006 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35007 +
35008 + /*
35009 + * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
35010 + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
35011 + * cheeky devices that just hold off using NAKs
35012 + */
35013 + if (nak_holdoff_enable && qh->do_split) {
35014 + if (qh->nak_frame != 0xffff &&
35015 + dwc_full_frame_num(qh->nak_frame) ==
35016 + dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
35017 + /*
35018 + * Revisit: Need to avoid trampling on periodic scheduling.
35019 + * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
35020 + * but if this behaviour is changed then periodic endpoints will get a slower
35021 + * polling rate.
35022 + */
35023 + g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
35024 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
35025 + continue;
35026 + } else {
35027 + qh->nak_frame = 0xffff;
35028 + }
35029 + }
35030 + if (microframe_schedule) {
35031 + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35032 + if (hcd->available_host_channels < 1) {
35033 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35034 + break;
35035 + }
35036 + hcd->available_host_channels--;
35037 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35038 +#ifdef DEBUG_HOST_CHANNELS
35039 + last_sel_trans_num_nonper_scheduled++;
35040 +#endif /* DEBUG_HOST_CHANNELS */
35041 + }
35042 +
35043 + assign_and_init_hc(hcd, qh);
35044 +
35045 + /*
35046 + * Move the QH from the non-periodic inactive schedule to the
35047 + * non-periodic active schedule.
35048 + */
35049 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
35050 + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35051 + DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
35052 + &qh->qh_list_entry);
35053 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35054 +
35055 + g_np_sent++;
35056 +
35057 + if (ret_val == DWC_OTG_TRANSACTION_NONE) {
35058 + ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
35059 + } else {
35060 + ret_val = DWC_OTG_TRANSACTION_ALL;
35061 + }
35062 +
35063 + if (!microframe_schedule)
35064 + hcd->non_periodic_channels++;
35065 + }
35066 +
35067 +#ifdef DEBUG_HOST_CHANNELS
35068 + last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
35069 +#endif /* DEBUG_HOST_CHANNELS */
35070 + return ret_val;
35071 +}
35072 +
35073 +/**
35074 + * Attempts to queue a single transaction request for a host channel
35075 + * associated with either a periodic or non-periodic transfer. This function
35076 + * assumes that there is space available in the appropriate request queue. For
35077 + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
35078 + * is available in the appropriate Tx FIFO.
35079 + *
35080 + * @param hcd The HCD state structure.
35081 + * @param hc Host channel descriptor associated with either a periodic or
35082 + * non-periodic transfer.
35083 + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
35084 + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
35085 + * transfers.
35086 + *
35087 + * @return 1 if a request is queued and more requests may be needed to
35088 + * complete the transfer, 0 if no more requests are required for this
35089 + * transfer, -1 if there is insufficient space in the Tx FIFO.
35090 + */
35091 +static int queue_transaction(dwc_otg_hcd_t * hcd,
35092 + dwc_hc_t * hc, uint16_t fifo_dwords_avail)
35093 +{
35094 + int retval;
35095 +
35096 + if (hcd->core_if->dma_enable) {
35097 + if (hcd->core_if->dma_desc_enable) {
35098 + if (!hc->xfer_started
35099 + || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
35100 + dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
35101 + hc->qh->ping_state = 0;
35102 + }
35103 + } else if (!hc->xfer_started) {
35104 + dwc_otg_hc_start_transfer(hcd->core_if, hc);
35105 + hc->qh->ping_state = 0;
35106 + }
35107 + retval = 0;
35108 + } else if (hc->halt_pending) {
35109 + /* Don't queue a request if the channel has been halted. */
35110 + retval = 0;
35111 + } else if (hc->halt_on_queue) {
35112 + dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
35113 + retval = 0;
35114 + } else if (hc->do_ping) {
35115 + if (!hc->xfer_started) {
35116 + dwc_otg_hc_start_transfer(hcd->core_if, hc);
35117 + }
35118 + retval = 0;
35119 + } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
35120 + if ((fifo_dwords_avail * 4) >= hc->max_packet) {
35121 + if (!hc->xfer_started) {
35122 + dwc_otg_hc_start_transfer(hcd->core_if, hc);
35123 + retval = 1;
35124 + } else {
35125 + retval =
35126 + dwc_otg_hc_continue_transfer(hcd->core_if,
35127 + hc);
35128 + }
35129 + } else {
35130 + retval = -1;
35131 + }
35132 + } else {
35133 + if (!hc->xfer_started) {
35134 + dwc_otg_hc_start_transfer(hcd->core_if, hc);
35135 + retval = 1;
35136 + } else {
35137 + retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
35138 + }
35139 + }
35140 +
35141 + return retval;
35142 +}
35143 +
35144 +/**
35145 + * Processes periodic channels for the next frame and queues transactions for
35146 + * these channels to the DWC_otg controller. After queueing transactions, the
35147 + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
35148 + * to queue as Periodic Tx FIFO or request queue space becomes available.
35149 + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
35150 + */
35151 +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
35152 +{
35153 + hptxsts_data_t tx_status;
35154 + dwc_list_link_t *qh_ptr;
35155 + dwc_otg_qh_t *qh;
35156 + int status;
35157 + int no_queue_space = 0;
35158 + int no_fifo_space = 0;
35159 +
35160 + dwc_otg_host_global_regs_t *host_regs;
35161 + host_regs = hcd->core_if->host_if->host_global_regs;
35162 +
35163 + DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
35164 +#ifdef DEBUG
35165 + tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35166 + DWC_DEBUGPL(DBG_HCDV,
35167 + " P Tx Req Queue Space Avail (before queue): %d\n",
35168 + tx_status.b.ptxqspcavail);
35169 + DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n",
35170 + tx_status.b.ptxfspcavail);
35171 +#endif
35172 +
35173 + qh_ptr = hcd->periodic_sched_assigned.next;
35174 + while (qh_ptr != &hcd->periodic_sched_assigned) {
35175 + tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35176 + if (tx_status.b.ptxqspcavail == 0) {
35177 + no_queue_space = 1;
35178 + break;
35179 + }
35180 +
35181 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35182 +
35183 + /*
35184 + * Set a flag if we're queuing high-bandwidth in slave mode.
35185 + * The flag prevents any halts to get into the request queue in
35186 + * the middle of multiple high-bandwidth packets getting queued.
35187 + */
35188 + if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
35189 + hcd->core_if->queuing_high_bandwidth = 1;
35190 + }
35191 + status =
35192 + queue_transaction(hcd, qh->channel,
35193 + tx_status.b.ptxfspcavail);
35194 + if (status < 0) {
35195 + no_fifo_space = 1;
35196 + break;
35197 + }
35198 +
35199 + /*
35200 + * In Slave mode, stay on the current transfer until there is
35201 + * nothing more to do or the high-bandwidth request count is
35202 + * reached. In DMA mode, only need to queue one request. The
35203 + * controller automatically handles multiple packets for
35204 + * high-bandwidth transfers.
35205 + */
35206 + if (hcd->core_if->dma_enable || status == 0 ||
35207 + qh->channel->requests == qh->channel->multi_count) {
35208 + qh_ptr = qh_ptr->next;
35209 + /*
35210 + * Move the QH from the periodic assigned schedule to
35211 + * the periodic queued schedule.
35212 + */
35213 + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
35214 + &qh->qh_list_entry);
35215 +
35216 + /* done queuing high bandwidth */
35217 + hcd->core_if->queuing_high_bandwidth = 0;
35218 + }
35219 + }
35220 +
35221 + if (!hcd->core_if->dma_enable) {
35222 + dwc_otg_core_global_regs_t *global_regs;
35223 + gintmsk_data_t intr_mask = {.d32 = 0 };
35224 +
35225 + global_regs = hcd->core_if->core_global_regs;
35226 + intr_mask.b.ptxfempty = 1;
35227 +#ifdef DEBUG
35228 + tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35229 + DWC_DEBUGPL(DBG_HCDV,
35230 + " P Tx Req Queue Space Avail (after queue): %d\n",
35231 + tx_status.b.ptxqspcavail);
35232 + DWC_DEBUGPL(DBG_HCDV,
35233 + " P Tx FIFO Space Avail (after queue): %d\n",
35234 + tx_status.b.ptxfspcavail);
35235 +#endif
35236 + if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
35237 + no_queue_space || no_fifo_space) {
35238 + /*
35239 + * May need to queue more transactions as the request
35240 + * queue or Tx FIFO empties. Enable the periodic Tx
35241 + * FIFO empty interrupt. (Always use the half-empty
35242 + * level to ensure that new requests are loaded as
35243 + * soon as possible.)
35244 + */
35245 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35246 + intr_mask.d32);
35247 + } else {
35248 + /*
35249 + * Disable the Tx FIFO empty interrupt since there are
35250 + * no more transactions that need to be queued right
35251 + * now. This function is called from interrupt
35252 + * handlers to queue more transactions as transfer
35253 + * states change.
35254 + */
35255 + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35256 + 0);
35257 + }
35258 + }
35259 +}
35260 +
35261 +/**
35262 + * Processes active non-periodic channels and queues transactions for these
35263 + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
35264 + * FIFO Empty interrupt is enabled if there are more transactions to queue as
35265 + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
35266 + * FIFO Empty interrupt is disabled.
35267 + */
35268 +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
35269 +{
35270 + gnptxsts_data_t tx_status;
35271 + dwc_list_link_t *orig_qh_ptr;
35272 + dwc_otg_qh_t *qh;
35273 + int status;
35274 + int no_queue_space = 0;
35275 + int no_fifo_space = 0;
35276 + int more_to_do = 0;
35277 +
35278 + dwc_otg_core_global_regs_t *global_regs =
35279 + hcd->core_if->core_global_regs;
35280 +
35281 + DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
35282 +#ifdef DEBUG
35283 + tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35284 + DWC_DEBUGPL(DBG_HCDV,
35285 + " NP Tx Req Queue Space Avail (before queue): %d\n",
35286 + tx_status.b.nptxqspcavail);
35287 + DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n",
35288 + tx_status.b.nptxfspcavail);
35289 +#endif
35290 + /*
35291 + * Keep track of the starting point. Skip over the start-of-list
35292 + * entry.
35293 + */
35294 + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35295 + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35296 + }
35297 + orig_qh_ptr = hcd->non_periodic_qh_ptr;
35298 +
35299 + /*
35300 + * Process once through the active list or until no more space is
35301 + * available in the request queue or the Tx FIFO.
35302 + */
35303 + do {
35304 + tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35305 + if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
35306 + no_queue_space = 1;
35307 + break;
35308 + }
35309 +
35310 + qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
35311 + qh_list_entry);
35312 + status =
35313 + queue_transaction(hcd, qh->channel,
35314 + tx_status.b.nptxfspcavail);
35315 +
35316 + if (status > 0) {
35317 + more_to_do = 1;
35318 + } else if (status < 0) {
35319 + no_fifo_space = 1;
35320 + break;
35321 + }
35322 +
35323 + /* Advance to next QH, skipping start-of-list entry. */
35324 + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35325 + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35326 + hcd->non_periodic_qh_ptr =
35327 + hcd->non_periodic_qh_ptr->next;
35328 + }
35329 +
35330 + } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
35331 +
35332 + if (!hcd->core_if->dma_enable) {
35333 + gintmsk_data_t intr_mask = {.d32 = 0 };
35334 + intr_mask.b.nptxfempty = 1;
35335 +
35336 +#ifdef DEBUG
35337 + tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35338 + DWC_DEBUGPL(DBG_HCDV,
35339 + " NP Tx Req Queue Space Avail (after queue): %d\n",
35340 + tx_status.b.nptxqspcavail);
35341 + DWC_DEBUGPL(DBG_HCDV,
35342 + " NP Tx FIFO Space Avail (after queue): %d\n",
35343 + tx_status.b.nptxfspcavail);
35344 +#endif
35345 + if (more_to_do || no_queue_space || no_fifo_space) {
35346 + /*
35347 + * May need to queue more transactions as the request
35348 + * queue or Tx FIFO empties. Enable the non-periodic
35349 + * Tx FIFO empty interrupt. (Always use the half-empty
35350 + * level to ensure that new requests are loaded as
35351 + * soon as possible.)
35352 + */
35353 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35354 + intr_mask.d32);
35355 + } else {
35356 + /*
35357 + * Disable the Tx FIFO empty interrupt since there are
35358 + * no more transactions that need to be queued right
35359 + * now. This function is called from interrupt
35360 + * handlers to queue more transactions as transfer
35361 + * states change.
35362 + */
35363 + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35364 + 0);
35365 + }
35366 + }
35367 +}
35368 +
35369 +/**
35370 + * This function processes the currently active host channels and queues
35371 + * transactions for these channels to the DWC_otg controller. It is called
35372 + * from HCD interrupt handler functions.
35373 + *
35374 + * @param hcd The HCD state structure.
35375 + * @param tr_type The type(s) of transactions to queue (non-periodic,
35376 + * periodic, or both).
35377 + */
35378 +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
35379 + dwc_otg_transaction_type_e tr_type)
35380 +{
35381 +#ifdef DEBUG_SOF
35382 + DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
35383 +#endif
35384 + /* Process host channels associated with periodic transfers. */
35385 + if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
35386 + tr_type == DWC_OTG_TRANSACTION_ALL) &&
35387 + !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
35388 +
35389 + process_periodic_channels(hcd);
35390 + }
35391 +
35392 + /* Process host channels associated with non-periodic transfers. */
35393 + if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
35394 + tr_type == DWC_OTG_TRANSACTION_ALL) {
35395 + if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
35396 + process_non_periodic_channels(hcd);
35397 + } else {
35398 + /*
35399 + * Ensure NP Tx FIFO empty interrupt is disabled when
35400 + * there are no non-periodic transfers to process.
35401 + */
35402 + gintmsk_data_t gintmsk = {.d32 = 0 };
35403 + gintmsk.b.nptxfempty = 1;
35404 + DWC_MODIFY_REG32(&hcd->core_if->
35405 + core_global_regs->gintmsk, gintmsk.d32,
35406 + 0);
35407 + }
35408 + }
35409 +}
35410 +
35411 +#ifdef DWC_HS_ELECT_TST
35412 +/*
35413 + * Quick and dirty hack to implement the HS Electrical Test
35414 + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
35415 + *
35416 + * This code was copied from our userspace app "hset". It sends a
35417 + * Get Device Descriptor control sequence in two parts, first the
35418 + * Setup packet by itself, followed some time later by the In and
35419 + * Ack packets. Rather than trying to figure out how to add this
35420 + * functionality to the normal driver code, we just hijack the
35421 + * hardware, using these two function to drive the hardware
35422 + * directly.
35423 + */
35424 +
35425 +static dwc_otg_core_global_regs_t *global_regs;
35426 +static dwc_otg_host_global_regs_t *hc_global_regs;
35427 +static dwc_otg_hc_regs_t *hc_regs;
35428 +static uint32_t *data_fifo;
35429 +
35430 +static void do_setup(void)
35431 +{
35432 + gintsts_data_t gintsts;
35433 + hctsiz_data_t hctsiz;
35434 + hcchar_data_t hcchar;
35435 + haint_data_t haint;
35436 + hcint_data_t hcint;
35437 +
35438 + /* Enable HAINTs */
35439 + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35440 +
35441 + /* Enable HCINTs */
35442 + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35443 +
35444 + /* Read GINTSTS */
35445 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35446 +
35447 + /* Read HAINT */
35448 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35449 +
35450 + /* Read HCINT */
35451 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35452 +
35453 + /* Read HCCHAR */
35454 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35455 +
35456 + /* Clear HCINT */
35457 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35458 +
35459 + /* Clear HAINT */
35460 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35461 +
35462 + /* Clear GINTSTS */
35463 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35464 +
35465 + /* Read GINTSTS */
35466 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35467 +
35468 + /*
35469 + * Send Setup packet (Get Device Descriptor)
35470 + */
35471 +
35472 + /* Make sure channel is disabled */
35473 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35474 + if (hcchar.b.chen) {
35475 + hcchar.b.chdis = 1;
35476 +// hcchar.b.chen = 1;
35477 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35478 + //sleep(1);
35479 + dwc_mdelay(1000);
35480 +
35481 + /* Read GINTSTS */
35482 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35483 +
35484 + /* Read HAINT */
35485 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35486 +
35487 + /* Read HCINT */
35488 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35489 +
35490 + /* Read HCCHAR */
35491 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35492 +
35493 + /* Clear HCINT */
35494 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35495 +
35496 + /* Clear HAINT */
35497 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35498 +
35499 + /* Clear GINTSTS */
35500 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35501 +
35502 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35503 + }
35504 +
35505 + /* Set HCTSIZ */
35506 + hctsiz.d32 = 0;
35507 + hctsiz.b.xfersize = 8;
35508 + hctsiz.b.pktcnt = 1;
35509 + hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
35510 + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35511 +
35512 + /* Set HCCHAR */
35513 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35514 + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35515 + hcchar.b.epdir = 0;
35516 + hcchar.b.epnum = 0;
35517 + hcchar.b.mps = 8;
35518 + hcchar.b.chen = 1;
35519 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35520 +
35521 + /* Fill FIFO with Setup data for Get Device Descriptor */
35522 + data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35523 + DWC_WRITE_REG32(data_fifo++, 0x01000680);
35524 + DWC_WRITE_REG32(data_fifo++, 0x00080000);
35525 +
35526 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35527 +
35528 + /* Wait for host channel interrupt */
35529 + do {
35530 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35531 + } while (gintsts.b.hcintr == 0);
35532 +
35533 + /* Disable HCINTs */
35534 + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35535 +
35536 + /* Disable HAINTs */
35537 + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35538 +
35539 + /* Read HAINT */
35540 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35541 +
35542 + /* Read HCINT */
35543 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35544 +
35545 + /* Read HCCHAR */
35546 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35547 +
35548 + /* Clear HCINT */
35549 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35550 +
35551 + /* Clear HAINT */
35552 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35553 +
35554 + /* Clear GINTSTS */
35555 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35556 +
35557 + /* Read GINTSTS */
35558 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35559 +}
35560 +
35561 +static void do_in_ack(void)
35562 +{
35563 + gintsts_data_t gintsts;
35564 + hctsiz_data_t hctsiz;
35565 + hcchar_data_t hcchar;
35566 + haint_data_t haint;
35567 + hcint_data_t hcint;
35568 + host_grxsts_data_t grxsts;
35569 +
35570 + /* Enable HAINTs */
35571 + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35572 +
35573 + /* Enable HCINTs */
35574 + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35575 +
35576 + /* Read GINTSTS */
35577 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35578 +
35579 + /* Read HAINT */
35580 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35581 +
35582 + /* Read HCINT */
35583 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35584 +
35585 + /* Read HCCHAR */
35586 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35587 +
35588 + /* Clear HCINT */
35589 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35590 +
35591 + /* Clear HAINT */
35592 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35593 +
35594 + /* Clear GINTSTS */
35595 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35596 +
35597 + /* Read GINTSTS */
35598 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35599 +
35600 + /*
35601 + * Receive Control In packet
35602 + */
35603 +
35604 + /* Make sure channel is disabled */
35605 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35606 + if (hcchar.b.chen) {
35607 + hcchar.b.chdis = 1;
35608 + hcchar.b.chen = 1;
35609 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35610 + //sleep(1);
35611 + dwc_mdelay(1000);
35612 +
35613 + /* Read GINTSTS */
35614 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35615 +
35616 + /* Read HAINT */
35617 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35618 +
35619 + /* Read HCINT */
35620 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35621 +
35622 + /* Read HCCHAR */
35623 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35624 +
35625 + /* Clear HCINT */
35626 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35627 +
35628 + /* Clear HAINT */
35629 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35630 +
35631 + /* Clear GINTSTS */
35632 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35633 +
35634 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35635 + }
35636 +
35637 + /* Set HCTSIZ */
35638 + hctsiz.d32 = 0;
35639 + hctsiz.b.xfersize = 8;
35640 + hctsiz.b.pktcnt = 1;
35641 + hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35642 + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35643 +
35644 + /* Set HCCHAR */
35645 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35646 + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35647 + hcchar.b.epdir = 1;
35648 + hcchar.b.epnum = 0;
35649 + hcchar.b.mps = 8;
35650 + hcchar.b.chen = 1;
35651 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35652 +
35653 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35654 +
35655 + /* Wait for receive status queue interrupt */
35656 + do {
35657 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35658 + } while (gintsts.b.rxstsqlvl == 0);
35659 +
35660 + /* Read RXSTS */
35661 + grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35662 +
35663 + /* Clear RXSTSQLVL in GINTSTS */
35664 + gintsts.d32 = 0;
35665 + gintsts.b.rxstsqlvl = 1;
35666 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35667 +
35668 + switch (grxsts.b.pktsts) {
35669 + case DWC_GRXSTS_PKTSTS_IN:
35670 + /* Read the data into the host buffer */
35671 + if (grxsts.b.bcnt > 0) {
35672 + int i;
35673 + int word_count = (grxsts.b.bcnt + 3) / 4;
35674 +
35675 + data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35676 +
35677 + for (i = 0; i < word_count; i++) {
35678 + (void)DWC_READ_REG32(data_fifo++);
35679 + }
35680 + }
35681 + break;
35682 +
35683 + default:
35684 + break;
35685 + }
35686 +
35687 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35688 +
35689 + /* Wait for receive status queue interrupt */
35690 + do {
35691 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35692 + } while (gintsts.b.rxstsqlvl == 0);
35693 +
35694 + /* Read RXSTS */
35695 + grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35696 +
35697 + /* Clear RXSTSQLVL in GINTSTS */
35698 + gintsts.d32 = 0;
35699 + gintsts.b.rxstsqlvl = 1;
35700 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35701 +
35702 + switch (grxsts.b.pktsts) {
35703 + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
35704 + break;
35705 +
35706 + default:
35707 + break;
35708 + }
35709 +
35710 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35711 +
35712 + /* Wait for host channel interrupt */
35713 + do {
35714 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35715 + } while (gintsts.b.hcintr == 0);
35716 +
35717 + /* Read HAINT */
35718 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35719 +
35720 + /* Read HCINT */
35721 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35722 +
35723 + /* Read HCCHAR */
35724 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35725 +
35726 + /* Clear HCINT */
35727 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35728 +
35729 + /* Clear HAINT */
35730 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35731 +
35732 + /* Clear GINTSTS */
35733 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35734 +
35735 + /* Read GINTSTS */
35736 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35737 +
35738 +// usleep(100000);
35739 +// mdelay(100);
35740 + dwc_mdelay(1);
35741 +
35742 + /*
35743 + * Send handshake packet
35744 + */
35745 +
35746 + /* Read HAINT */
35747 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35748 +
35749 + /* Read HCINT */
35750 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35751 +
35752 + /* Read HCCHAR */
35753 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35754 +
35755 + /* Clear HCINT */
35756 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35757 +
35758 + /* Clear HAINT */
35759 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35760 +
35761 + /* Clear GINTSTS */
35762 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35763 +
35764 + /* Read GINTSTS */
35765 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35766 +
35767 + /* Make sure channel is disabled */
35768 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35769 + if (hcchar.b.chen) {
35770 + hcchar.b.chdis = 1;
35771 + hcchar.b.chen = 1;
35772 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35773 + //sleep(1);
35774 + dwc_mdelay(1000);
35775 +
35776 + /* Read GINTSTS */
35777 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35778 +
35779 + /* Read HAINT */
35780 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35781 +
35782 + /* Read HCINT */
35783 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35784 +
35785 + /* Read HCCHAR */
35786 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35787 +
35788 + /* Clear HCINT */
35789 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35790 +
35791 + /* Clear HAINT */
35792 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35793 +
35794 + /* Clear GINTSTS */
35795 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35796 +
35797 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35798 + }
35799 +
35800 + /* Set HCTSIZ */
35801 + hctsiz.d32 = 0;
35802 + hctsiz.b.xfersize = 0;
35803 + hctsiz.b.pktcnt = 1;
35804 + hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35805 + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35806 +
35807 + /* Set HCCHAR */
35808 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35809 + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35810 + hcchar.b.epdir = 0;
35811 + hcchar.b.epnum = 0;
35812 + hcchar.b.mps = 8;
35813 + hcchar.b.chen = 1;
35814 + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35815 +
35816 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35817 +
35818 + /* Wait for host channel interrupt */
35819 + do {
35820 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35821 + } while (gintsts.b.hcintr == 0);
35822 +
35823 + /* Disable HCINTs */
35824 + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35825 +
35826 + /* Disable HAINTs */
35827 + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35828 +
35829 + /* Read HAINT */
35830 + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35831 +
35832 + /* Read HCINT */
35833 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35834 +
35835 + /* Read HCCHAR */
35836 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35837 +
35838 + /* Clear HCINT */
35839 + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35840 +
35841 + /* Clear HAINT */
35842 + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35843 +
35844 + /* Clear GINTSTS */
35845 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35846 +
35847 + /* Read GINTSTS */
35848 + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35849 +}
35850 +#endif
35851 +
35852 +/** Handles hub class-specific requests. */
35853 +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
35854 + uint16_t typeReq,
35855 + uint16_t wValue,
35856 + uint16_t wIndex, uint8_t * buf, uint16_t wLength)
35857 +{
35858 + int retval = 0;
35859 +
35860 + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
35861 + usb_hub_descriptor_t *hub_desc;
35862 + hprt0_data_t hprt0 = {.d32 = 0 };
35863 +
35864 + uint32_t port_status;
35865 +
35866 + switch (typeReq) {
35867 + case UCR_CLEAR_HUB_FEATURE:
35868 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35869 + "ClearHubFeature 0x%x\n", wValue);
35870 + switch (wValue) {
35871 + case UHF_C_HUB_LOCAL_POWER:
35872 + case UHF_C_HUB_OVER_CURRENT:
35873 + /* Nothing required here */
35874 + break;
35875 + default:
35876 + retval = -DWC_E_INVALID;
35877 + DWC_ERROR("DWC OTG HCD - "
35878 + "ClearHubFeature request %xh unknown\n",
35879 + wValue);
35880 + }
35881 + break;
35882 + case UCR_CLEAR_PORT_FEATURE:
35883 +#ifdef CONFIG_USB_DWC_OTG_LPM
35884 + if (wValue != UHF_PORT_L1)
35885 +#endif
35886 + if (!wIndex || wIndex > 1)
35887 + goto error;
35888 +
35889 + switch (wValue) {
35890 + case UHF_PORT_ENABLE:
35891 + DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
35892 + "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
35893 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
35894 + hprt0.b.prtena = 1;
35895 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35896 + break;
35897 + case UHF_PORT_SUSPEND:
35898 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35899 + "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
35900 +
35901 + if (core_if->power_down == 2) {
35902 + dwc_otg_host_hibernation_restore(core_if, 0, 0);
35903 + } else {
35904 + DWC_WRITE_REG32(core_if->pcgcctl, 0);
35905 + dwc_mdelay(5);
35906 +
35907 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
35908 + hprt0.b.prtres = 1;
35909 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35910 + hprt0.b.prtsusp = 0;
35911 + /* Clear Resume bit */
35912 + dwc_mdelay(100);
35913 + hprt0.b.prtres = 0;
35914 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35915 + }
35916 + break;
35917 +#ifdef CONFIG_USB_DWC_OTG_LPM
35918 + case UHF_PORT_L1:
35919 + {
35920 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
35921 + glpmcfg_data_t lpmcfg = {.d32 = 0 };
35922 +
35923 + lpmcfg.d32 =
35924 + DWC_READ_REG32(&core_if->
35925 + core_global_regs->glpmcfg);
35926 + lpmcfg.b.en_utmi_sleep = 0;
35927 + lpmcfg.b.hird_thres &= (~(1 << 4));
35928 + lpmcfg.b.prt_sleep_sts = 1;
35929 + DWC_WRITE_REG32(&core_if->
35930 + core_global_regs->glpmcfg,
35931 + lpmcfg.d32);
35932 +
35933 + /* Clear Enbl_L1Gating bit. */
35934 + pcgcctl.b.enbl_sleep_gating = 1;
35935 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
35936 + 0);
35937 +
35938 + dwc_mdelay(5);
35939 +
35940 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
35941 + hprt0.b.prtres = 1;
35942 + DWC_WRITE_REG32(core_if->host_if->hprt0,
35943 + hprt0.d32);
35944 + /* This bit will be cleared in wakeup interrupt handle */
35945 + break;
35946 + }
35947 +#endif
35948 + case UHF_PORT_POWER:
35949 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35950 + "ClearPortFeature USB_PORT_FEAT_POWER\n");
35951 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
35952 + hprt0.b.prtpwr = 0;
35953 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35954 + break;
35955 + case UHF_PORT_INDICATOR:
35956 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35957 + "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
35958 + /* Port inidicator not supported */
35959 + break;
35960 + case UHF_C_PORT_CONNECTION:
35961 + /* Clears drivers internal connect status change
35962 + * flag */
35963 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35964 + "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
35965 + dwc_otg_hcd->flags.b.port_connect_status_change = 0;
35966 + break;
35967 + case UHF_C_PORT_RESET:
35968 + /* Clears the driver's internal Port Reset Change
35969 + * flag */
35970 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35971 + "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
35972 + dwc_otg_hcd->flags.b.port_reset_change = 0;
35973 + break;
35974 + case UHF_C_PORT_ENABLE:
35975 + /* Clears the driver's internal Port
35976 + * Enable/Disable Change flag */
35977 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35978 + "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
35979 + dwc_otg_hcd->flags.b.port_enable_change = 0;
35980 + break;
35981 + case UHF_C_PORT_SUSPEND:
35982 + /* Clears the driver's internal Port Suspend
35983 + * Change flag, which is set when resume signaling on
35984 + * the host port is complete */
35985 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35986 + "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
35987 + dwc_otg_hcd->flags.b.port_suspend_change = 0;
35988 + break;
35989 +#ifdef CONFIG_USB_DWC_OTG_LPM
35990 + case UHF_C_PORT_L1:
35991 + dwc_otg_hcd->flags.b.port_l1_change = 0;
35992 + break;
35993 +#endif
35994 + case UHF_C_PORT_OVER_CURRENT:
35995 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35996 + "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
35997 + dwc_otg_hcd->flags.b.port_over_current_change = 0;
35998 + break;
35999 + default:
36000 + retval = -DWC_E_INVALID;
36001 + DWC_ERROR("DWC OTG HCD - "
36002 + "ClearPortFeature request %xh "
36003 + "unknown or unsupported\n", wValue);
36004 + }
36005 + break;
36006 + case UCR_GET_HUB_DESCRIPTOR:
36007 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36008 + "GetHubDescriptor\n");
36009 + hub_desc = (usb_hub_descriptor_t *) buf;
36010 + hub_desc->bDescLength = 9;
36011 + hub_desc->bDescriptorType = 0x29;
36012 + hub_desc->bNbrPorts = 1;
36013 + USETW(hub_desc->wHubCharacteristics, 0x08);
36014 + hub_desc->bPwrOn2PwrGood = 1;
36015 + hub_desc->bHubContrCurrent = 0;
36016 + hub_desc->DeviceRemovable[0] = 0;
36017 + hub_desc->DeviceRemovable[1] = 0xff;
36018 + break;
36019 + case UCR_GET_HUB_STATUS:
36020 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36021 + "GetHubStatus\n");
36022 + DWC_MEMSET(buf, 0, 4);
36023 + break;
36024 + case UCR_GET_PORT_STATUS:
36025 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36026 + "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
36027 + wIndex, dwc_otg_hcd->flags.d32);
36028 + if (!wIndex || wIndex > 1)
36029 + goto error;
36030 +
36031 + port_status = 0;
36032 +
36033 + if (dwc_otg_hcd->flags.b.port_connect_status_change)
36034 + port_status |= (1 << UHF_C_PORT_CONNECTION);
36035 +
36036 + if (dwc_otg_hcd->flags.b.port_enable_change)
36037 + port_status |= (1 << UHF_C_PORT_ENABLE);
36038 +
36039 + if (dwc_otg_hcd->flags.b.port_suspend_change)
36040 + port_status |= (1 << UHF_C_PORT_SUSPEND);
36041 +
36042 + if (dwc_otg_hcd->flags.b.port_l1_change)
36043 + port_status |= (1 << UHF_C_PORT_L1);
36044 +
36045 + if (dwc_otg_hcd->flags.b.port_reset_change) {
36046 + port_status |= (1 << UHF_C_PORT_RESET);
36047 + }
36048 +
36049 + if (dwc_otg_hcd->flags.b.port_over_current_change) {
36050 + DWC_WARN("Overcurrent change detected\n");
36051 + port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
36052 + }
36053 +
36054 + if (!dwc_otg_hcd->flags.b.port_connect_status) {
36055 + /*
36056 + * The port is disconnected, which means the core is
36057 + * either in device mode or it soon will be. Just
36058 + * return 0's for the remainder of the port status
36059 + * since the port register can't be read if the core
36060 + * is in device mode.
36061 + */
36062 + *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36063 + break;
36064 + }
36065 +
36066 + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
36067 + DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
36068 +
36069 + if (hprt0.b.prtconnsts)
36070 + port_status |= (1 << UHF_PORT_CONNECTION);
36071 +
36072 + if (hprt0.b.prtena)
36073 + port_status |= (1 << UHF_PORT_ENABLE);
36074 +
36075 + if (hprt0.b.prtsusp)
36076 + port_status |= (1 << UHF_PORT_SUSPEND);
36077 +
36078 + if (hprt0.b.prtovrcurract)
36079 + port_status |= (1 << UHF_PORT_OVER_CURRENT);
36080 +
36081 + if (hprt0.b.prtrst)
36082 + port_status |= (1 << UHF_PORT_RESET);
36083 +
36084 + if (hprt0.b.prtpwr)
36085 + port_status |= (1 << UHF_PORT_POWER);
36086 +
36087 + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
36088 + port_status |= (1 << UHF_PORT_HIGH_SPEED);
36089 + else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
36090 + port_status |= (1 << UHF_PORT_LOW_SPEED);
36091 +
36092 + if (hprt0.b.prttstctl)
36093 + port_status |= (1 << UHF_PORT_TEST);
36094 + if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
36095 + port_status |= (1 << UHF_PORT_L1);
36096 + }
36097 + /*
36098 + For Synopsys HW emulation of Power down wkup_control asserts the
36099 + hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
36100 + We intentionally tell the software that port is in L2Suspend state.
36101 + Only for STE.
36102 + */
36103 + if ((core_if->power_down == 2)
36104 + && (core_if->hibernation_suspend == 1)) {
36105 + port_status |= (1 << UHF_PORT_SUSPEND);
36106 + }
36107 + /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
36108 +
36109 + *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36110 +
36111 + break;
36112 + case UCR_SET_HUB_FEATURE:
36113 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36114 + "SetHubFeature\n");
36115 + /* No HUB features supported */
36116 + break;
36117 + case UCR_SET_PORT_FEATURE:
36118 + if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
36119 + goto error;
36120 +
36121 + if (!dwc_otg_hcd->flags.b.port_connect_status) {
36122 + /*
36123 + * The port is disconnected, which means the core is
36124 + * either in device mode or it soon will be. Just
36125 + * return without doing anything since the port
36126 + * register can't be written if the core is in device
36127 + * mode.
36128 + */
36129 + break;
36130 + }
36131 +
36132 + switch (wValue) {
36133 + case UHF_PORT_SUSPEND:
36134 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36135 + "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
36136 + if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
36137 + goto error;
36138 + }
36139 + if (core_if->power_down == 2) {
36140 + int timeout = 300;
36141 + dwc_irqflags_t flags;
36142 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
36143 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
36144 + gusbcfg_data_t gusbcfg = {.d32 = 0 };
36145 +#ifdef DWC_DEV_SRPCAP
36146 + int32_t otg_cap_param = core_if->core_params->otg_cap;
36147 +#endif
36148 + DWC_PRINTF("Preparing for complete power-off\n");
36149 +
36150 + /* Save registers before hibernation */
36151 + dwc_otg_save_global_regs(core_if);
36152 + dwc_otg_save_host_regs(core_if);
36153 +
36154 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36155 + hprt0.b.prtsusp = 1;
36156 + hprt0.b.prtena = 0;
36157 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36158 + /* Spin hprt0.b.prtsusp to became 1 */
36159 + do {
36160 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36161 + if (hprt0.b.prtsusp) {
36162 + break;
36163 + }
36164 + dwc_mdelay(1);
36165 + } while (--timeout);
36166 + if (!timeout) {
36167 + DWC_WARN("Suspend wasn't genereted\n");
36168 + }
36169 + dwc_udelay(10);
36170 +
36171 + /*
36172 + * We need to disable interrupts to prevent servicing of any IRQ
36173 + * during going to hibernation
36174 + */
36175 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36176 + core_if->lx_state = DWC_OTG_L2;
36177 +#ifdef DWC_DEV_SRPCAP
36178 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36179 + hprt0.b.prtpwr = 0;
36180 + hprt0.b.prtena = 0;
36181 + DWC_WRITE_REG32(core_if->host_if->hprt0,
36182 + hprt0.d32);
36183 +#endif
36184 + gusbcfg.d32 =
36185 + DWC_READ_REG32(&core_if->core_global_regs->
36186 + gusbcfg);
36187 + if (gusbcfg.b.ulpi_utmi_sel == 1) {
36188 + /* ULPI interface */
36189 + /* Suspend the Phy Clock */
36190 + pcgcctl.d32 = 0;
36191 + pcgcctl.b.stoppclk = 1;
36192 + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36193 + pcgcctl.d32);
36194 + dwc_udelay(10);
36195 + gpwrdn.b.pmuactv = 1;
36196 + DWC_MODIFY_REG32(&core_if->
36197 + core_global_regs->
36198 + gpwrdn, 0, gpwrdn.d32);
36199 + } else {
36200 + /* UTMI+ Interface */
36201 + gpwrdn.b.pmuactv = 1;
36202 + DWC_MODIFY_REG32(&core_if->
36203 + core_global_regs->
36204 + gpwrdn, 0, gpwrdn.d32);
36205 + dwc_udelay(10);
36206 + pcgcctl.b.stoppclk = 1;
36207 + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
36208 + dwc_udelay(10);
36209 + }
36210 +#ifdef DWC_DEV_SRPCAP
36211 + gpwrdn.d32 = 0;
36212 + gpwrdn.b.dis_vbus = 1;
36213 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36214 + gpwrdn, 0, gpwrdn.d32);
36215 +#endif
36216 + gpwrdn.d32 = 0;
36217 + gpwrdn.b.pmuintsel = 1;
36218 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36219 + gpwrdn, 0, gpwrdn.d32);
36220 + dwc_udelay(10);
36221 +
36222 + gpwrdn.d32 = 0;
36223 +#ifdef DWC_DEV_SRPCAP
36224 + gpwrdn.b.srp_det_msk = 1;
36225 +#endif
36226 + gpwrdn.b.disconn_det_msk = 1;
36227 + gpwrdn.b.lnstchng_msk = 1;
36228 + gpwrdn.b.sts_chngint_msk = 1;
36229 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36230 + gpwrdn, 0, gpwrdn.d32);
36231 + dwc_udelay(10);
36232 +
36233 + /* Enable Power Down Clamp and all interrupts in GPWRDN */
36234 + gpwrdn.d32 = 0;
36235 + gpwrdn.b.pwrdnclmp = 1;
36236 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36237 + gpwrdn, 0, gpwrdn.d32);
36238 + dwc_udelay(10);
36239 +
36240 + /* Switch off VDD */
36241 + gpwrdn.d32 = 0;
36242 + gpwrdn.b.pwrdnswtch = 1;
36243 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36244 + gpwrdn, 0, gpwrdn.d32);
36245 +
36246 +#ifdef DWC_DEV_SRPCAP
36247 + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
36248 + {
36249 + core_if->pwron_timer_started = 1;
36250 + DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
36251 + }
36252 +#endif
36253 + /* Save gpwrdn register for further usage if stschng interrupt */
36254 + core_if->gr_backup->gpwrdn_local =
36255 + DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
36256 +
36257 + /* Set flag to indicate that we are in hibernation */
36258 + core_if->hibernation_suspend = 1;
36259 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
36260 +
36261 + DWC_PRINTF("Host hibernation completed\n");
36262 + // Exit from case statement
36263 + break;
36264 +
36265 + }
36266 + if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
36267 + dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36268 + gotgctl_data_t gotgctl = {.d32 = 0 };
36269 + gotgctl.b.hstsethnpen = 1;
36270 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36271 + gotgctl, 0, gotgctl.d32);
36272 + core_if->op_state = A_SUSPEND;
36273 + }
36274 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36275 + hprt0.b.prtsusp = 1;
36276 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36277 + {
36278 + dwc_irqflags_t flags;
36279 + /* Update lx_state */
36280 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36281 + core_if->lx_state = DWC_OTG_L2;
36282 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
36283 + }
36284 + /* Suspend the Phy Clock */
36285 + {
36286 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
36287 + pcgcctl.b.stoppclk = 1;
36288 + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36289 + pcgcctl.d32);
36290 + dwc_udelay(10);
36291 + }
36292 +
36293 + /* For HNP the bus must be suspended for at least 200ms. */
36294 + if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36295 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
36296 + pcgcctl.b.stoppclk = 1;
36297 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36298 + dwc_mdelay(200);
36299 + }
36300 +
36301 + /** @todo - check how sw can wait for 1 sec to check asesvld??? */
36302 +#if 0 //vahrama !!!!!!!!!!!!!!!!!!
36303 + if (core_if->adp_enable) {
36304 + gotgctl_data_t gotgctl = {.d32 = 0 };
36305 + gpwrdn_data_t gpwrdn;
36306 +
36307 + while (gotgctl.b.asesvld == 1) {
36308 + gotgctl.d32 =
36309 + DWC_READ_REG32(&core_if->
36310 + core_global_regs->
36311 + gotgctl);
36312 + dwc_mdelay(100);
36313 + }
36314 +
36315 + /* Enable Power Down Logic */
36316 + gpwrdn.d32 = 0;
36317 + gpwrdn.b.pmuactv = 1;
36318 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36319 + gpwrdn, 0, gpwrdn.d32);
36320 +
36321 + /* Unmask SRP detected interrupt from Power Down Logic */
36322 + gpwrdn.d32 = 0;
36323 + gpwrdn.b.srp_det_msk = 1;
36324 + DWC_MODIFY_REG32(&core_if->core_global_regs->
36325 + gpwrdn, 0, gpwrdn.d32);
36326 +
36327 + dwc_otg_adp_probe_start(core_if);
36328 + }
36329 +#endif
36330 + break;
36331 + case UHF_PORT_POWER:
36332 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36333 + "SetPortFeature - USB_PORT_FEAT_POWER\n");
36334 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36335 + hprt0.b.prtpwr = 1;
36336 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36337 + break;
36338 + case UHF_PORT_RESET:
36339 + if ((core_if->power_down == 2)
36340 + && (core_if->hibernation_suspend == 1)) {
36341 + /* If we are going to exit from Hibernated
36342 + * state via USB RESET.
36343 + */
36344 + dwc_otg_host_hibernation_restore(core_if, 0, 1);
36345 + } else {
36346 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36347 +
36348 + DWC_DEBUGPL(DBG_HCD,
36349 + "DWC OTG HCD HUB CONTROL - "
36350 + "SetPortFeature - USB_PORT_FEAT_RESET\n");
36351 + {
36352 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
36353 + pcgcctl.b.enbl_sleep_gating = 1;
36354 + pcgcctl.b.stoppclk = 1;
36355 + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36356 + DWC_WRITE_REG32(core_if->pcgcctl, 0);
36357 + }
36358 +#ifdef CONFIG_USB_DWC_OTG_LPM
36359 + {
36360 + glpmcfg_data_t lpmcfg;
36361 + lpmcfg.d32 =
36362 + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36363 + if (lpmcfg.b.prt_sleep_sts) {
36364 + lpmcfg.b.en_utmi_sleep = 0;
36365 + lpmcfg.b.hird_thres &= (~(1 << 4));
36366 + DWC_WRITE_REG32
36367 + (&core_if->core_global_regs->glpmcfg,
36368 + lpmcfg.d32);
36369 + dwc_mdelay(1);
36370 + }
36371 + }
36372 +#endif
36373 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36374 + /* Clear suspend bit if resetting from suspended state. */
36375 + hprt0.b.prtsusp = 0;
36376 + /* When B-Host the Port reset bit is set in
36377 + * the Start HCD Callback function, so that
36378 + * the reset is started within 1ms of the HNP
36379 + * success interrupt. */
36380 + if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
36381 + hprt0.b.prtpwr = 1;
36382 + hprt0.b.prtrst = 1;
36383 + DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
36384 + DWC_WRITE_REG32(core_if->host_if->hprt0,
36385 + hprt0.d32);
36386 + }
36387 + /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
36388 + dwc_mdelay(60);
36389 + hprt0.b.prtrst = 0;
36390 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36391 + core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
36392 + }
36393 + break;
36394 +#ifdef DWC_HS_ELECT_TST
36395 + case UHF_PORT_TEST:
36396 + {
36397 + uint32_t t;
36398 + gintmsk_data_t gintmsk;
36399 +
36400 + t = (wIndex >> 8); /* MSB wIndex USB */
36401 + DWC_DEBUGPL(DBG_HCD,
36402 + "DWC OTG HCD HUB CONTROL - "
36403 + "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
36404 + t);
36405 + DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
36406 + if (t < 6) {
36407 + hprt0.d32 = dwc_otg_read_hprt0(core_if);
36408 + hprt0.b.prttstctl = t;
36409 + DWC_WRITE_REG32(core_if->host_if->hprt0,
36410 + hprt0.d32);
36411 + } else {
36412 + /* Setup global vars with reg addresses (quick and
36413 + * dirty hack, should be cleaned up)
36414 + */
36415 + global_regs = core_if->core_global_regs;
36416 + hc_global_regs =
36417 + core_if->host_if->host_global_regs;
36418 + hc_regs =
36419 + (dwc_otg_hc_regs_t *) ((char *)
36420 + global_regs +
36421 + 0x500);
36422 + data_fifo =
36423 + (uint32_t *) ((char *)global_regs +
36424 + 0x1000);
36425 +
36426 + if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */
36427 + /* Save current interrupt mask */
36428 + gintmsk.d32 =
36429 + DWC_READ_REG32
36430 + (&global_regs->gintmsk);
36431 +
36432 + /* Disable all interrupts while we muck with
36433 + * the hardware directly
36434 + */
36435 + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36436 +
36437 + /* 15 second delay per the test spec */
36438 + dwc_mdelay(15000);
36439 +
36440 + /* Drive suspend on the root port */
36441 + hprt0.d32 =
36442 + dwc_otg_read_hprt0(core_if);
36443 + hprt0.b.prtsusp = 1;
36444 + hprt0.b.prtres = 0;
36445 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36446 +
36447 + /* 15 second delay per the test spec */
36448 + dwc_mdelay(15000);
36449 +
36450 + /* Drive resume on the root port */
36451 + hprt0.d32 =
36452 + dwc_otg_read_hprt0(core_if);
36453 + hprt0.b.prtsusp = 0;
36454 + hprt0.b.prtres = 1;
36455 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36456 + dwc_mdelay(100);
36457 +
36458 + /* Clear the resume bit */
36459 + hprt0.b.prtres = 0;
36460 + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36461 +
36462 + /* Restore interrupts */
36463 + DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36464 + } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
36465 + /* Save current interrupt mask */
36466 + gintmsk.d32 =
36467 + DWC_READ_REG32
36468 + (&global_regs->gintmsk);
36469 +
36470 + /* Disable all interrupts while we muck with
36471 + * the hardware directly
36472 + */
36473 + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36474 +
36475 + /* 15 second delay per the test spec */
36476 + dwc_mdelay(15000);
36477 +
36478 + /* Send the Setup packet */
36479 + do_setup();
36480 +
36481 + /* 15 second delay so nothing else happens for awhile */
36482 + dwc_mdelay(15000);
36483 +
36484 + /* Restore interrupts */
36485 + DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36486 + } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
36487 + /* Save current interrupt mask */
36488 + gintmsk.d32 =
36489 + DWC_READ_REG32
36490 + (&global_regs->gintmsk);
36491 +
36492 + /* Disable all interrupts while we muck with
36493 + * the hardware directly
36494 + */
36495 + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36496 +
36497 + /* Send the Setup packet */
36498 + do_setup();
36499 +
36500 + /* 15 second delay so nothing else happens for awhile */
36501 + dwc_mdelay(15000);
36502 +
36503 + /* Send the In and Ack packets */
36504 + do_in_ack();
36505 +
36506 + /* 15 second delay so nothing else happens for awhile */
36507 + dwc_mdelay(15000);
36508 +
36509 + /* Restore interrupts */
36510 + DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36511 + }
36512 + }
36513 + break;
36514 + }
36515 +#endif /* DWC_HS_ELECT_TST */
36516 +
36517 + case UHF_PORT_INDICATOR:
36518 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36519 + "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
36520 + /* Not supported */
36521 + break;
36522 + default:
36523 + retval = -DWC_E_INVALID;
36524 + DWC_ERROR("DWC OTG HCD - "
36525 + "SetPortFeature request %xh "
36526 + "unknown or unsupported\n", wValue);
36527 + break;
36528 + }
36529 + break;
36530 +#ifdef CONFIG_USB_DWC_OTG_LPM
36531 + case UCR_SET_AND_TEST_PORT_FEATURE:
36532 + if (wValue != UHF_PORT_L1) {
36533 + goto error;
36534 + }
36535 + {
36536 + int portnum, hird, devaddr, remwake;
36537 + glpmcfg_data_t lpmcfg;
36538 + uint32_t time_usecs;
36539 + gintsts_data_t gintsts;
36540 + gintmsk_data_t gintmsk;
36541 +
36542 + if (!dwc_otg_get_param_lpm_enable(core_if)) {
36543 + goto error;
36544 + }
36545 + if (wValue != UHF_PORT_L1 || wLength != 1) {
36546 + goto error;
36547 + }
36548 + /* Check if the port currently is in SLEEP state */
36549 + lpmcfg.d32 =
36550 + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36551 + if (lpmcfg.b.prt_sleep_sts) {
36552 + DWC_INFO("Port is already in sleep mode\n");
36553 + buf[0] = 0; /* Return success */
36554 + break;
36555 + }
36556 +
36557 + portnum = wIndex & 0xf;
36558 + hird = (wIndex >> 4) & 0xf;
36559 + devaddr = (wIndex >> 8) & 0x7f;
36560 + remwake = (wIndex >> 15);
36561 +
36562 + if (portnum != 1) {
36563 + retval = -DWC_E_INVALID;
36564 + DWC_WARN
36565 + ("Wrong port number(%d) in SetandTestPortFeature request\n",
36566 + portnum);
36567 + break;
36568 + }
36569 +
36570 + DWC_PRINTF
36571 + ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
36572 + portnum, hird, devaddr, remwake);
36573 + /* Disable LPM interrupt */
36574 + gintmsk.d32 = 0;
36575 + gintmsk.b.lpmtranrcvd = 1;
36576 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
36577 + gintmsk.d32, 0);
36578 +
36579 + if (dwc_otg_hcd_send_lpm
36580 + (dwc_otg_hcd, devaddr, hird, remwake)) {
36581 + retval = -DWC_E_INVALID;
36582 + break;
36583 + }
36584 +
36585 + time_usecs = 10 * (lpmcfg.b.retry_count + 1);
36586 + /* We will consider timeout if time_usecs microseconds pass,
36587 + * and we don't receive LPM transaction status.
36588 + * After receiving non-error responce(ACK/NYET/STALL) from device,
36589 + * core will set lpmtranrcvd bit.
36590 + */
36591 + do {
36592 + gintsts.d32 =
36593 + DWC_READ_REG32(&core_if->core_global_regs->gintsts);
36594 + if (gintsts.b.lpmtranrcvd) {
36595 + break;
36596 + }
36597 + dwc_udelay(1);
36598 + } while (--time_usecs);
36599 + /* lpm_int bit will be cleared in LPM interrupt handler */
36600 +
36601 + /* Now fill status
36602 + * 0x00 - Success
36603 + * 0x10 - NYET
36604 + * 0x11 - Timeout
36605 + */
36606 + if (!gintsts.b.lpmtranrcvd) {
36607 + buf[0] = 0x3; /* Completion code is Timeout */
36608 + dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
36609 + } else {
36610 + lpmcfg.d32 =
36611 + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36612 + if (lpmcfg.b.lpm_resp == 0x3) {
36613 + /* ACK responce from the device */
36614 + buf[0] = 0x00; /* Success */
36615 + } else if (lpmcfg.b.lpm_resp == 0x2) {
36616 + /* NYET responce from the device */
36617 + buf[0] = 0x2;
36618 + } else {
36619 + /* Otherwise responce with Timeout */
36620 + buf[0] = 0x3;
36621 + }
36622 + }
36623 + DWC_PRINTF("Device responce to LPM trans is %x\n",
36624 + lpmcfg.b.lpm_resp);
36625 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
36626 + gintmsk.d32);
36627 +
36628 + break;
36629 + }
36630 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36631 + default:
36632 +error:
36633 + retval = -DWC_E_INVALID;
36634 + DWC_WARN("DWC OTG HCD - "
36635 + "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
36636 + typeReq, wIndex, wValue);
36637 + break;
36638 + }
36639 +
36640 + return retval;
36641 +}
36642 +
36643 +#ifdef CONFIG_USB_DWC_OTG_LPM
36644 +/** Returns index of host channel to perform LPM transaction. */
36645 +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
36646 +{
36647 + dwc_otg_core_if_t *core_if = hcd->core_if;
36648 + dwc_hc_t *hc;
36649 + hcchar_data_t hcchar;
36650 + gintmsk_data_t gintmsk = {.d32 = 0 };
36651 +
36652 + if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
36653 + DWC_PRINTF("No free channel to select for LPM transaction\n");
36654 + return -1;
36655 + }
36656 +
36657 + hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
36658 +
36659 + /* Mask host channel interrupts. */
36660 + gintmsk.b.hcintr = 1;
36661 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
36662 +
36663 + /* Fill fields that core needs for LPM transaction */
36664 + hcchar.b.devaddr = devaddr;
36665 + hcchar.b.epnum = 0;
36666 + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36667 + hcchar.b.mps = 64;
36668 + hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
36669 + hcchar.b.epdir = 0; /* OUT */
36670 + DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
36671 + hcchar.d32);
36672 +
36673 + /* Remove the host channel from the free list. */
36674 + DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
36675 +
36676 + DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
36677 +
36678 + return hc->hc_num;
36679 +}
36680 +
36681 +/** Release hc after performing LPM transaction */
36682 +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
36683 +{
36684 + dwc_hc_t *hc;
36685 + glpmcfg_data_t lpmcfg;
36686 + uint8_t hc_num;
36687 +
36688 + lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36689 + hc_num = lpmcfg.b.lpm_chan_index;
36690 +
36691 + hc = hcd->hc_ptr_array[hc_num];
36692 +
36693 + DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
36694 + /* Return host channel to free list */
36695 + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
36696 +}
36697 +
36698 +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
36699 + uint8_t bRemoteWake)
36700 +{
36701 + glpmcfg_data_t lpmcfg;
36702 + pcgcctl_data_t pcgcctl = {.d32 = 0 };
36703 + int channel;
36704 +
36705 + channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
36706 + if (channel < 0) {
36707 + return channel;
36708 + }
36709 +
36710 + pcgcctl.b.enbl_sleep_gating = 1;
36711 + DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
36712 +
36713 + /* Read LPM config register */
36714 + lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36715 +
36716 + /* Program LPM transaction fields */
36717 + lpmcfg.b.rem_wkup_en = bRemoteWake;
36718 + lpmcfg.b.hird = hird;
36719 + lpmcfg.b.hird_thres = 0x1c;
36720 + lpmcfg.b.lpm_chan_index = channel;
36721 + lpmcfg.b.en_utmi_sleep = 1;
36722 + /* Program LPM config register */
36723 + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36724 +
36725 + /* Send LPM transaction */
36726 + lpmcfg.b.send_lpm = 1;
36727 + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36728 +
36729 + return 0;
36730 +}
36731 +
36732 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36733 +
36734 +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
36735 +{
36736 + int retval;
36737 +
36738 + if (port != 1) {
36739 + return -DWC_E_INVALID;
36740 + }
36741 +
36742 + retval = (hcd->flags.b.port_connect_status_change ||
36743 + hcd->flags.b.port_reset_change ||
36744 + hcd->flags.b.port_enable_change ||
36745 + hcd->flags.b.port_suspend_change ||
36746 + hcd->flags.b.port_over_current_change);
36747 +#ifdef DEBUG
36748 + if (retval) {
36749 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
36750 + " Root port status changed\n");
36751 + DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
36752 + hcd->flags.b.port_connect_status_change);
36753 + DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
36754 + hcd->flags.b.port_reset_change);
36755 + DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
36756 + hcd->flags.b.port_enable_change);
36757 + DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
36758 + hcd->flags.b.port_suspend_change);
36759 + DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
36760 + hcd->flags.b.port_over_current_change);
36761 + }
36762 +#endif
36763 + return retval;
36764 +}
36765 +
36766 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
36767 +{
36768 + hfnum_data_t hfnum;
36769 + hfnum.d32 =
36770 + DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
36771 + hfnum);
36772 +
36773 +#ifdef DEBUG_SOF
36774 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
36775 + hfnum.b.frnum);
36776 +#endif
36777 + return hfnum.b.frnum;
36778 +}
36779 +
36780 +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
36781 + struct dwc_otg_hcd_function_ops *fops)
36782 +{
36783 + int retval = 0;
36784 +
36785 + hcd->fops = fops;
36786 + if (!dwc_otg_is_device_mode(hcd->core_if) &&
36787 + (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
36788 + dwc_otg_hcd_reinit(hcd);
36789 + } else {
36790 + retval = -DWC_E_NO_DEVICE;
36791 + }
36792 +
36793 + return retval;
36794 +}
36795 +
36796 +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
36797 +{
36798 + return hcd->priv;
36799 +}
36800 +
36801 +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
36802 +{
36803 + hcd->priv = priv_data;
36804 +}
36805 +
36806 +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
36807 +{
36808 + return hcd->otg_port;
36809 +}
36810 +
36811 +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
36812 +{
36813 + uint32_t is_b_host;
36814 + if (hcd->core_if->op_state == B_HOST) {
36815 + is_b_host = 1;
36816 + } else {
36817 + is_b_host = 0;
36818 + }
36819 +
36820 + return is_b_host;
36821 +}
36822 +
36823 +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
36824 + int iso_desc_count, int atomic_alloc)
36825 +{
36826 + dwc_otg_hcd_urb_t *dwc_otg_urb;
36827 + uint32_t size;
36828 +
36829 + size =
36830 + sizeof(*dwc_otg_urb) +
36831 + iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
36832 + if (atomic_alloc)
36833 + dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
36834 + else
36835 + dwc_otg_urb = DWC_ALLOC(size);
36836 +
36837 + if (dwc_otg_urb)
36838 + dwc_otg_urb->packet_count = iso_desc_count;
36839 + else {
36840 + DWC_ERROR("**** DWC OTG HCD URB alloc - "
36841 + "%salloc of %db failed\n",
36842 + atomic_alloc?"atomic ":"", size);
36843 + }
36844 + return dwc_otg_urb;
36845 +}
36846 +
36847 +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
36848 + uint8_t dev_addr, uint8_t ep_num,
36849 + uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
36850 +{
36851 + dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
36852 + ep_type, ep_dir, mps);
36853 +#if 0
36854 + DWC_PRINTF
36855 + ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
36856 + dev_addr, ep_num, ep_dir, ep_type, mps);
36857 +#endif
36858 +}
36859 +
36860 +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
36861 + void *urb_handle, void *buf, dwc_dma_t dma,
36862 + uint32_t buflen, void *setup_packet,
36863 + dwc_dma_t setup_dma, uint32_t flags,
36864 + uint16_t interval)
36865 +{
36866 + dwc_otg_urb->priv = urb_handle;
36867 + dwc_otg_urb->buf = buf;
36868 + dwc_otg_urb->dma = dma;
36869 + dwc_otg_urb->length = buflen;
36870 + dwc_otg_urb->setup_packet = setup_packet;
36871 + dwc_otg_urb->setup_dma = setup_dma;
36872 + dwc_otg_urb->flags = flags;
36873 + dwc_otg_urb->interval = interval;
36874 + dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
36875 +}
36876 +
36877 +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
36878 +{
36879 + return dwc_otg_urb->status;
36880 +}
36881 +
36882 +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
36883 +{
36884 + return dwc_otg_urb->actual_length;
36885 +}
36886 +
36887 +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
36888 +{
36889 + return dwc_otg_urb->error_count;
36890 +}
36891 +
36892 +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
36893 + int desc_num, uint32_t offset,
36894 + uint32_t length)
36895 +{
36896 + dwc_otg_urb->iso_descs[desc_num].offset = offset;
36897 + dwc_otg_urb->iso_descs[desc_num].length = length;
36898 +}
36899 +
36900 +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
36901 + int desc_num)
36902 +{
36903 + return dwc_otg_urb->iso_descs[desc_num].status;
36904 +}
36905 +
36906 +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
36907 + dwc_otg_urb, int desc_num)
36908 +{
36909 + return dwc_otg_urb->iso_descs[desc_num].actual_length;
36910 +}
36911 +
36912 +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
36913 +{
36914 + int allocated = 0;
36915 + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
36916 +
36917 + if (qh) {
36918 + if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
36919 + allocated = 1;
36920 + }
36921 + }
36922 + return allocated;
36923 +}
36924 +
36925 +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
36926 +{
36927 + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
36928 + int freed = 0;
36929 + DWC_ASSERT(qh, "qh is not allocated\n");
36930 +
36931 + if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
36932 + freed = 1;
36933 + }
36934 +
36935 + return freed;
36936 +}
36937 +
36938 +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
36939 +{
36940 + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
36941 + DWC_ASSERT(qh, "qh is not allocated\n");
36942 + return qh->usecs;
36943 +}
36944 +
36945 +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
36946 +{
36947 +#ifdef DEBUG
36948 + int num_channels;
36949 + int i;
36950 + gnptxsts_data_t np_tx_status;
36951 + hptxsts_data_t p_tx_status;
36952 +
36953 + num_channels = hcd->core_if->core_params->host_channels;
36954 + DWC_PRINTF("\n");
36955 + DWC_PRINTF
36956 + ("************************************************************\n");
36957 + DWC_PRINTF("HCD State:\n");
36958 + DWC_PRINTF(" Num channels: %d\n", num_channels);
36959 + for (i = 0; i < num_channels; i++) {
36960 + dwc_hc_t *hc = hcd->hc_ptr_array[i];
36961 + DWC_PRINTF(" Channel %d:\n", i);
36962 + DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
36963 + hc->dev_addr, hc->ep_num, hc->ep_is_in);
36964 + DWC_PRINTF(" speed: %d\n", hc->speed);
36965 + DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
36966 + DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
36967 + DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
36968 + DWC_PRINTF(" multi_count: %d\n", hc->multi_count);
36969 + DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
36970 + DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
36971 + DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
36972 + DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count);
36973 + DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue);
36974 + DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending);
36975 + DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
36976 + DWC_PRINTF(" do_split: %d\n", hc->do_split);
36977 + DWC_PRINTF(" complete_split: %d\n", hc->complete_split);
36978 + DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr);
36979 + DWC_PRINTF(" port_addr: %d\n", hc->port_addr);
36980 + DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos);
36981 + DWC_PRINTF(" requests: %d\n", hc->requests);
36982 + DWC_PRINTF(" qh: %p\n", hc->qh);
36983 + if (hc->xfer_started) {
36984 + hfnum_data_t hfnum;
36985 + hcchar_data_t hcchar;
36986 + hctsiz_data_t hctsiz;
36987 + hcint_data_t hcint;
36988 + hcintmsk_data_t hcintmsk;
36989 + hfnum.d32 =
36990 + DWC_READ_REG32(&hcd->core_if->
36991 + host_if->host_global_regs->hfnum);
36992 + hcchar.d32 =
36993 + DWC_READ_REG32(&hcd->core_if->host_if->
36994 + hc_regs[i]->hcchar);
36995 + hctsiz.d32 =
36996 + DWC_READ_REG32(&hcd->core_if->host_if->
36997 + hc_regs[i]->hctsiz);
36998 + hcint.d32 =
36999 + DWC_READ_REG32(&hcd->core_if->host_if->
37000 + hc_regs[i]->hcint);
37001 + hcintmsk.d32 =
37002 + DWC_READ_REG32(&hcd->core_if->host_if->
37003 + hc_regs[i]->hcintmsk);
37004 + DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32);
37005 + DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32);
37006 + DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32);
37007 + DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32);
37008 + DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32);
37009 + }
37010 + if (hc->xfer_started && hc->qh) {
37011 + dwc_otg_qtd_t *qtd;
37012 + dwc_otg_hcd_urb_t *urb;
37013 +
37014 + DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
37015 + if (!qtd->in_process)
37016 + break;
37017 +
37018 + urb = qtd->urb;
37019 + DWC_PRINTF(" URB Info:\n");
37020 + DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb);
37021 + if (urb) {
37022 + DWC_PRINTF(" Dev: %d, EP: %d %s\n",
37023 + dwc_otg_hcd_get_dev_addr(&urb->
37024 + pipe_info),
37025 + dwc_otg_hcd_get_ep_num(&urb->
37026 + pipe_info),
37027 + dwc_otg_hcd_is_pipe_in(&urb->
37028 + pipe_info) ?
37029 + "IN" : "OUT");
37030 + DWC_PRINTF(" Max packet size: %d\n",
37031 + dwc_otg_hcd_get_mps(&urb->
37032 + pipe_info));
37033 + DWC_PRINTF(" transfer_buffer: %p\n",
37034 + urb->buf);
37035 + DWC_PRINTF(" transfer_dma: %p\n",
37036 + (void *)urb->dma);
37037 + DWC_PRINTF(" transfer_buffer_length: %d\n",
37038 + urb->length);
37039 + DWC_PRINTF(" actual_length: %d\n",
37040 + urb->actual_length);
37041 + }
37042 + }
37043 + }
37044 + }
37045 + DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels);
37046 + DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels);
37047 + DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs);
37048 + np_tx_status.d32 =
37049 + DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
37050 + DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n",
37051 + np_tx_status.b.nptxqspcavail);
37052 + DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n",
37053 + np_tx_status.b.nptxfspcavail);
37054 + p_tx_status.d32 =
37055 + DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
37056 + DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n",
37057 + p_tx_status.b.ptxqspcavail);
37058 + DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
37059 + dwc_otg_hcd_dump_frrem(hcd);
37060 + dwc_otg_dump_global_registers(hcd->core_if);
37061 + dwc_otg_dump_host_registers(hcd->core_if);
37062 + DWC_PRINTF
37063 + ("************************************************************\n");
37064 + DWC_PRINTF("\n");
37065 +#endif
37066 +}
37067 +
37068 +#ifdef DEBUG
37069 +void dwc_print_setup_data(uint8_t * setup)
37070 +{
37071 + int i;
37072 + if (CHK_DEBUG_LEVEL(DBG_HCD)) {
37073 + DWC_PRINTF("Setup Data = MSB ");
37074 + for (i = 7; i >= 0; i--)
37075 + DWC_PRINTF("%02x ", setup[i]);
37076 + DWC_PRINTF("\n");
37077 + DWC_PRINTF(" bmRequestType Tranfer = %s\n",
37078 + (setup[0] & 0x80) ? "Device-to-Host" :
37079 + "Host-to-Device");
37080 + DWC_PRINTF(" bmRequestType Type = ");
37081 + switch ((setup[0] & 0x60) >> 5) {
37082 + case 0:
37083 + DWC_PRINTF("Standard\n");
37084 + break;
37085 + case 1:
37086 + DWC_PRINTF("Class\n");
37087 + break;
37088 + case 2:
37089 + DWC_PRINTF("Vendor\n");
37090 + break;
37091 + case 3:
37092 + DWC_PRINTF("Reserved\n");
37093 + break;
37094 + }
37095 + DWC_PRINTF(" bmRequestType Recipient = ");
37096 + switch (setup[0] & 0x1f) {
37097 + case 0:
37098 + DWC_PRINTF("Device\n");
37099 + break;
37100 + case 1:
37101 + DWC_PRINTF("Interface\n");
37102 + break;
37103 + case 2:
37104 + DWC_PRINTF("Endpoint\n");
37105 + break;
37106 + case 3:
37107 + DWC_PRINTF("Other\n");
37108 + break;
37109 + default:
37110 + DWC_PRINTF("Reserved\n");
37111 + break;
37112 + }
37113 + DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]);
37114 + DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
37115 + DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
37116 + DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
37117 + }
37118 +}
37119 +#endif
37120 +
37121 +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
37122 +{
37123 +#if 0
37124 + DWC_PRINTF("Frame remaining at SOF:\n");
37125 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37126 + hcd->frrem_samples, hcd->frrem_accum,
37127 + (hcd->frrem_samples > 0) ?
37128 + hcd->frrem_accum / hcd->frrem_samples : 0);
37129 +
37130 + DWC_PRINTF("\n");
37131 + DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
37132 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37133 + hcd->core_if->hfnum_7_samples,
37134 + hcd->core_if->hfnum_7_frrem_accum,
37135 + (hcd->core_if->hfnum_7_samples >
37136 + 0) ? hcd->core_if->hfnum_7_frrem_accum /
37137 + hcd->core_if->hfnum_7_samples : 0);
37138 + DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
37139 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37140 + hcd->core_if->hfnum_0_samples,
37141 + hcd->core_if->hfnum_0_frrem_accum,
37142 + (hcd->core_if->hfnum_0_samples >
37143 + 0) ? hcd->core_if->hfnum_0_frrem_accum /
37144 + hcd->core_if->hfnum_0_samples : 0);
37145 + DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
37146 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37147 + hcd->core_if->hfnum_other_samples,
37148 + hcd->core_if->hfnum_other_frrem_accum,
37149 + (hcd->core_if->hfnum_other_samples >
37150 + 0) ? hcd->core_if->hfnum_other_frrem_accum /
37151 + hcd->core_if->hfnum_other_samples : 0);
37152 +
37153 + DWC_PRINTF("\n");
37154 + DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
37155 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37156 + hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
37157 + (hcd->hfnum_7_samples_a > 0) ?
37158 + hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
37159 + DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
37160 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37161 + hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
37162 + (hcd->hfnum_0_samples_a > 0) ?
37163 + hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
37164 + DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
37165 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37166 + hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
37167 + (hcd->hfnum_other_samples_a > 0) ?
37168 + hcd->hfnum_other_frrem_accum_a /
37169 + hcd->hfnum_other_samples_a : 0);
37170 +
37171 + DWC_PRINTF("\n");
37172 + DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
37173 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37174 + hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
37175 + (hcd->hfnum_7_samples_b > 0) ?
37176 + hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
37177 + DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
37178 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37179 + hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
37180 + (hcd->hfnum_0_samples_b > 0) ?
37181 + hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
37182 + DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
37183 + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
37184 + hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
37185 + (hcd->hfnum_other_samples_b > 0) ?
37186 + hcd->hfnum_other_frrem_accum_b /
37187 + hcd->hfnum_other_samples_b : 0);
37188 +#endif
37189 +}
37190 +
37191 +#endif /* DWC_DEVICE_ONLY */
37192 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
37193 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100
37194 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2013-07-06 15:25:50.000000000 +0100
37195 @@ -0,0 +1,1132 @@
37196 +/*==========================================================================
37197 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
37198 + * $Revision: #10 $
37199 + * $Date: 2011/10/20 $
37200 + * $Change: 1869464 $
37201 + *
37202 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
37203 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
37204 + * otherwise expressly agreed to in writing between Synopsys and you.
37205 + *
37206 + * The Software IS NOT an item of Licensed Software or Licensed Product under
37207 + * any End User Software License Agreement or Agreement for Licensed Product
37208 + * with Synopsys or any supplement thereto. You are permitted to use and
37209 + * redistribute this Software in source and binary forms, with or without
37210 + * modification, provided that redistributions of source code must retain this
37211 + * notice. You may not view, use, disclose, copy or distribute this file or
37212 + * any information contained herein except pursuant to this license grant from
37213 + * Synopsys. If you do not agree with this notice, including the disclaimer
37214 + * below, then you are not authorized to use the Software.
37215 + *
37216 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
37217 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37218 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37219 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
37220 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37221 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37222 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37223 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37224 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37225 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
37226 + * DAMAGE.
37227 + * ========================================================================== */
37228 +#ifndef DWC_DEVICE_ONLY
37229 +
37230 +/** @file
37231 + * This file contains Descriptor DMA support implementation for host mode.
37232 + */
37233 +
37234 +#include "dwc_otg_hcd.h"
37235 +#include "dwc_otg_regs.h"
37236 +
37237 +extern bool microframe_schedule;
37238 +
37239 +static inline uint8_t frame_list_idx(uint16_t frame)
37240 +{
37241 + return (frame & (MAX_FRLIST_EN_NUM - 1));
37242 +}
37243 +
37244 +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
37245 +{
37246 + return (idx + inc) &
37247 + (((speed ==
37248 + DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
37249 + MAX_DMA_DESC_NUM_GENERIC) - 1);
37250 +}
37251 +
37252 +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
37253 +{
37254 + return (idx - inc) &
37255 + (((speed ==
37256 + DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
37257 + MAX_DMA_DESC_NUM_GENERIC) - 1);
37258 +}
37259 +
37260 +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
37261 +{
37262 + return (((qh->ep_type == UE_ISOCHRONOUS)
37263 + && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))
37264 + ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);
37265 +}
37266 +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
37267 +{
37268 + return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)
37269 + ? ((qh->interval + 8 - 1) / 8)
37270 + : qh->interval);
37271 +}
37272 +
37273 +static int desc_list_alloc(dwc_otg_qh_t * qh)
37274 +{
37275 + int retval = 0;
37276 +
37277 + qh->desc_list = (dwc_otg_host_dma_desc_t *)
37278 + DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
37279 + &qh->desc_list_dma);
37280 +
37281 + if (!qh->desc_list) {
37282 + retval = -DWC_E_NO_MEMORY;
37283 + DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
37284 +
37285 + }
37286 +
37287 + dwc_memset(qh->desc_list, 0x00,
37288 + sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
37289 +
37290 + qh->n_bytes =
37291 + (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));
37292 +
37293 + if (!qh->n_bytes) {
37294 + retval = -DWC_E_NO_MEMORY;
37295 + DWC_ERROR
37296 + ("%s: Failed to allocate array for descriptors' size actual values\n",
37297 + __func__);
37298 +
37299 + }
37300 + return retval;
37301 +
37302 +}
37303 +
37304 +static void desc_list_free(dwc_otg_qh_t * qh)
37305 +{
37306 + if (qh->desc_list) {
37307 + DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,
37308 + qh->desc_list_dma);
37309 + qh->desc_list = NULL;
37310 + }
37311 +
37312 + if (qh->n_bytes) {
37313 + DWC_FREE(qh->n_bytes);
37314 + qh->n_bytes = NULL;
37315 + }
37316 +}
37317 +
37318 +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
37319 +{
37320 + int retval = 0;
37321 + if (hcd->frame_list)
37322 + return 0;
37323 +
37324 + hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,
37325 + &hcd->frame_list_dma);
37326 + if (!hcd->frame_list) {
37327 + retval = -DWC_E_NO_MEMORY;
37328 + DWC_ERROR("%s: Frame List allocation failed\n", __func__);
37329 + }
37330 +
37331 + dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
37332 +
37333 + return retval;
37334 +}
37335 +
37336 +static void frame_list_free(dwc_otg_hcd_t * hcd)
37337 +{
37338 + if (!hcd->frame_list)
37339 + return;
37340 +
37341 + DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
37342 + hcd->frame_list = NULL;
37343 +}
37344 +
37345 +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
37346 +{
37347 +
37348 + hcfg_data_t hcfg;
37349 +
37350 + hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
37351 +
37352 + if (hcfg.b.perschedena) {
37353 + /* already enabled */
37354 + return;
37355 + }
37356 +
37357 + DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,
37358 + hcd->frame_list_dma);
37359 +
37360 + switch (fr_list_en) {
37361 + case 64:
37362 + hcfg.b.frlisten = 3;
37363 + break;
37364 + case 32:
37365 + hcfg.b.frlisten = 2;
37366 + break;
37367 + case 16:
37368 + hcfg.b.frlisten = 1;
37369 + break;
37370 + case 8:
37371 + hcfg.b.frlisten = 0;
37372 + break;
37373 + default:
37374 + break;
37375 + }
37376 +
37377 + hcfg.b.perschedena = 1;
37378 +
37379 + DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
37380 + DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
37381 +
37382 +}
37383 +
37384 +static void per_sched_disable(dwc_otg_hcd_t * hcd)
37385 +{
37386 + hcfg_data_t hcfg;
37387 +
37388 + hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
37389 +
37390 + if (!hcfg.b.perschedena) {
37391 + /* already disabled */
37392 + return;
37393 + }
37394 + hcfg.b.perschedena = 0;
37395 +
37396 + DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
37397 + DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
37398 +}
37399 +
37400 +/*
37401 + * Activates/Deactivates FrameList entries for the channel
37402 + * based on endpoint servicing period.
37403 + */
37404 +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
37405 +{
37406 + uint16_t i, j, inc;
37407 + dwc_hc_t *hc = NULL;
37408 +
37409 + if (!qh->channel) {
37410 + DWC_ERROR("qh->channel = %p", qh->channel);
37411 + return;
37412 + }
37413 +
37414 + if (!hcd) {
37415 + DWC_ERROR("------hcd = %p", hcd);
37416 + return;
37417 + }
37418 +
37419 + if (!hcd->frame_list) {
37420 + DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);
37421 + return;
37422 + }
37423 +
37424 + hc = qh->channel;
37425 + inc = frame_incr_val(qh);
37426 + if (qh->ep_type == UE_ISOCHRONOUS)
37427 + i = frame_list_idx(qh->sched_frame);
37428 + else
37429 + i = 0;
37430 +
37431 + j = i;
37432 + do {
37433 + if (enable)
37434 + hcd->frame_list[j] |= (1 << hc->hc_num);
37435 + else
37436 + hcd->frame_list[j] &= ~(1 << hc->hc_num);
37437 + j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
37438 + }
37439 + while (j != i);
37440 + if (!enable)
37441 + return;
37442 + hc->schinfo = 0;
37443 + if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
37444 + j = 1;
37445 + /* TODO - check this */
37446 + inc = (8 + qh->interval - 1) / qh->interval;
37447 + for (i = 0; i < inc; i++) {
37448 + hc->schinfo |= j;
37449 + j = j << qh->interval;
37450 + }
37451 + } else {
37452 + hc->schinfo = 0xff;
37453 + }
37454 +}
37455 +
37456 +#if 1
37457 +void dump_frame_list(dwc_otg_hcd_t * hcd)
37458 +{
37459 + int i = 0;
37460 + DWC_PRINTF("--FRAME LIST (hex) --\n");
37461 + for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
37462 + DWC_PRINTF("%x\t", hcd->frame_list[i]);
37463 + if (!(i % 8) && i)
37464 + DWC_PRINTF("\n");
37465 + }
37466 + DWC_PRINTF("\n----\n");
37467 +
37468 +}
37469 +#endif
37470 +
37471 +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
37472 +{
37473 + dwc_irqflags_t flags;
37474 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
37475 +
37476 + dwc_hc_t *hc = qh->channel;
37477 + if (dwc_qh_is_non_per(qh)) {
37478 + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
37479 + if (!microframe_schedule)
37480 + hcd->non_periodic_channels--;
37481 + else
37482 + hcd->available_host_channels++;
37483 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
37484 + } else
37485 + update_frame_list(hcd, qh, 0);
37486 +
37487 + /*
37488 + * The condition is added to prevent double cleanup try in case of device
37489 + * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
37490 + */
37491 + if (hc->qh) {
37492 + dwc_otg_hc_cleanup(hcd->core_if, hc);
37493 + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
37494 + hc->qh = NULL;
37495 + }
37496 +
37497 + qh->channel = NULL;
37498 + qh->ntd = 0;
37499 +
37500 + if (qh->desc_list) {
37501 + dwc_memset(qh->desc_list, 0x00,
37502 + sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
37503 + }
37504 +}
37505 +
37506 +/**
37507 + * Initializes a QH structure's Descriptor DMA related members.
37508 + * Allocates memory for descriptor list.
37509 + * On first periodic QH, allocates memory for FrameList
37510 + * and enables periodic scheduling.
37511 + *
37512 + * @param hcd The HCD state structure for the DWC OTG controller.
37513 + * @param qh The QH to init.
37514 + *
37515 + * @return 0 if successful, negative error code otherwise.
37516 + */
37517 +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
37518 +{
37519 + int retval = 0;
37520 +
37521 + if (qh->do_split) {
37522 + DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
37523 + return -1;
37524 + }
37525 +
37526 + retval = desc_list_alloc(qh);
37527 +
37528 + if ((retval == 0)
37529 + && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
37530 + if (!hcd->frame_list) {
37531 + retval = frame_list_alloc(hcd);
37532 + /* Enable periodic schedule on first periodic QH */
37533 + if (retval == 0)
37534 + per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
37535 + }
37536 + }
37537 +
37538 + qh->ntd = 0;
37539 +
37540 + return retval;
37541 +}
37542 +
37543 +/**
37544 + * Frees descriptor list memory associated with the QH.
37545 + * If QH is periodic and the last, frees FrameList memory
37546 + * and disables periodic scheduling.
37547 + *
37548 + * @param hcd The HCD state structure for the DWC OTG controller.
37549 + * @param qh The QH to init.
37550 + */
37551 +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
37552 +{
37553 + desc_list_free(qh);
37554 +
37555 + /*
37556 + * Channel still assigned due to some reasons.
37557 + * Seen on Isoc URB dequeue. Channel halted but no subsequent
37558 + * ChHalted interrupt to release the channel. Afterwards
37559 + * when it comes here from endpoint disable routine
37560 + * channel remains assigned.
37561 + */
37562 + if (qh->channel)
37563 + release_channel_ddma(hcd, qh);
37564 +
37565 + if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)
37566 + && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {
37567 +
37568 + per_sched_disable(hcd);
37569 + frame_list_free(hcd);
37570 + }
37571 +}
37572 +
37573 +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
37574 +{
37575 + if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
37576 + /*
37577 + * Descriptor set(8 descriptors) index
37578 + * which is 8-aligned.
37579 + */
37580 + return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
37581 + } else {
37582 + return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
37583 + }
37584 +}
37585 +
37586 +/*
37587 + * Determine starting frame for Isochronous transfer.
37588 + * Few frames skipped to prevent race condition with HC.
37589 + */
37590 +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
37591 + uint8_t * skip_frames)
37592 +{
37593 + uint16_t frame = 0;
37594 + hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
37595 +
37596 + /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
37597 +
37598 + /*
37599 + * skip_frames is used to limit activated descriptors number
37600 + * to avoid the situation when HC services the last activated
37601 + * descriptor firstly.
37602 + * Example for FS:
37603 + * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
37604 + * corresponding to curr_frame+1, the descriptor corresponding to frame 2
37605 + * will be fetched. If the number of descriptors is max=64 (or greather) the
37606 + * list will be fully programmed with Active descriptors and it is possible
37607 + * case(rare) that the latest descriptor(considering rollback) corresponding
37608 + * to frame 2 will be serviced first. HS case is more probable because, in fact,
37609 + * up to 11 uframes(16 in the code) may be skipped.
37610 + */
37611 + if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
37612 + /*
37613 + * Consider uframe counter also, to start xfer asap.
37614 + * If half of the frame elapsed skip 2 frames otherwise
37615 + * just 1 frame.
37616 + * Starting descriptor index must be 8-aligned, so
37617 + * if the current frame is near to complete the next one
37618 + * is skipped as well.
37619 + */
37620 +
37621 + if (dwc_micro_frame_num(hcd->frame_number) >= 5) {
37622 + *skip_frames = 2 * 8;
37623 + frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
37624 + } else {
37625 + *skip_frames = 1 * 8;
37626 + frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
37627 + }
37628 +
37629 + frame = dwc_full_frame_num(frame);
37630 + } else {
37631 + /*
37632 + * Two frames are skipped for FS - the current and the next.
37633 + * But for descriptor programming, 1 frame(descriptor) is enough,
37634 + * see example above.
37635 + */
37636 + *skip_frames = 1;
37637 + frame = dwc_frame_num_inc(hcd->frame_number, 2);
37638 + }
37639 +
37640 + return frame;
37641 +}
37642 +
37643 +/*
37644 + * Calculate initial descriptor index for isochronous transfer
37645 + * based on scheduled frame.
37646 + */
37647 +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
37648 +{
37649 + uint16_t frame = 0, fr_idx, fr_idx_tmp;
37650 + uint8_t skip_frames = 0;
37651 + /*
37652 + * With current ISOC processing algorithm the channel is being
37653 + * released when no more QTDs in the list(qh->ntd == 0).
37654 + * Thus this function is called only when qh->ntd == 0 and qh->channel == 0.
37655 + *
37656 + * So qh->channel != NULL branch is not used and just not removed from the
37657 + * source file. It is required for another possible approach which is,
37658 + * do not disable and release the channel when ISOC session completed,
37659 + * just move QH to inactive schedule until new QTD arrives.
37660 + * On new QTD, the QH moved back to 'ready' schedule,
37661 + * starting frame and therefore starting desc_index are recalculated.
37662 + * In this case channel is released only on ep_disable.
37663 + */
37664 +
37665 + /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
37666 + if (qh->channel) {
37667 + frame = calc_starting_frame(hcd, qh, &skip_frames);
37668 + /*
37669 + * Calculate initial descriptor index based on FrameList current bitmap
37670 + * and servicing period.
37671 + */
37672 + fr_idx_tmp = frame_list_idx(frame);
37673 + fr_idx =
37674 + (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -
37675 + fr_idx_tmp)
37676 + % frame_incr_val(qh);
37677 + fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
37678 + } else {
37679 + qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);
37680 + fr_idx = frame_list_idx(qh->sched_frame);
37681 + }
37682 +
37683 + qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);
37684 +
37685 + return skip_frames;
37686 +}
37687 +
37688 +#define ISOC_URB_GIVEBACK_ASAP
37689 +
37690 +#define MAX_ISOC_XFER_SIZE_FS 1023
37691 +#define MAX_ISOC_XFER_SIZE_HS 3072
37692 +#define DESCNUM_THRESHOLD 4
37693 +
37694 +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
37695 + uint8_t skip_frames)
37696 +{
37697 + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
37698 + dwc_otg_qtd_t *qtd;
37699 + dwc_otg_host_dma_desc_t *dma_desc;
37700 + uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
37701 +
37702 + idx = qh->td_last;
37703 + inc = qh->interval;
37704 + n_desc = 0;
37705 +
37706 + ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
37707 + if (skip_frames && !qh->channel)
37708 + ntd_max = ntd_max - skip_frames / qh->interval;
37709 +
37710 + max_xfer_size =
37711 + (qh->dev_speed ==
37712 + DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :
37713 + MAX_ISOC_XFER_SIZE_FS;
37714 +
37715 + DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
37716 + while ((qh->ntd < ntd_max)
37717 + && (qtd->isoc_frame_index_last <
37718 + qtd->urb->packet_count)) {
37719 +
37720 + dma_desc = &qh->desc_list[idx];
37721 + dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
37722 +
37723 + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
37724 +
37725 + if (frame_desc->length > max_xfer_size)
37726 + qh->n_bytes[idx] = max_xfer_size;
37727 + else
37728 + qh->n_bytes[idx] = frame_desc->length;
37729 + dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
37730 + dma_desc->status.b_isoc.a = 1;
37731 + dma_desc->status.b_isoc.sts = 0;
37732 +
37733 + dma_desc->buf = qtd->urb->dma + frame_desc->offset;
37734 +
37735 + qh->ntd++;
37736 +
37737 + qtd->isoc_frame_index_last++;
37738 +
37739 +#ifdef ISOC_URB_GIVEBACK_ASAP
37740 + /*
37741 + * Set IOC for each descriptor corresponding to the
37742 + * last frame of the URB.
37743 + */
37744 + if (qtd->isoc_frame_index_last ==
37745 + qtd->urb->packet_count)
37746 + dma_desc->status.b_isoc.ioc = 1;
37747 +
37748 +#endif
37749 + idx = desclist_idx_inc(idx, inc, qh->dev_speed);
37750 + n_desc++;
37751 +
37752 + }
37753 + qtd->in_process = 1;
37754 + }
37755 +
37756 + qh->td_last = idx;
37757 +
37758 +#ifdef ISOC_URB_GIVEBACK_ASAP
37759 + /* Set IOC for the last descriptor if descriptor list is full */
37760 + if (qh->ntd == ntd_max) {
37761 + idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
37762 + qh->desc_list[idx].status.b_isoc.ioc = 1;
37763 + }
37764 +#else
37765 + /*
37766 + * Set IOC bit only for one descriptor.
37767 + * Always try to be ahead of HW processing,
37768 + * i.e. on IOC generation driver activates next descriptors but
37769 + * core continues to process descriptors followed the one with IOC set.
37770 + */
37771 +
37772 + if (n_desc > DESCNUM_THRESHOLD) {
37773 + /*
37774 + * Move IOC "up". Required even if there is only one QTD
37775 + * in the list, cause QTDs migth continue to be queued,
37776 + * but during the activation it was only one queued.
37777 + * Actually more than one QTD might be in the list if this function called
37778 + * from XferCompletion - QTDs was queued during HW processing of the previous
37779 + * descriptor chunk.
37780 + */
37781 + idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
37782 + } else {
37783 + /*
37784 + * Set the IOC for the latest descriptor
37785 + * if either number of descriptor is not greather than threshold
37786 + * or no more new descriptors activated.
37787 + */
37788 + idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
37789 + }
37790 +
37791 + qh->desc_list[idx].status.b_isoc.ioc = 1;
37792 +#endif
37793 +}
37794 +
37795 +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
37796 +{
37797 +
37798 + dwc_hc_t *hc;
37799 + dwc_otg_host_dma_desc_t *dma_desc;
37800 + dwc_otg_qtd_t *qtd;
37801 + int num_packets, len, n_desc = 0;
37802 +
37803 + hc = qh->channel;
37804 +
37805 + /*
37806 + * Start with hc->xfer_buff initialized in
37807 + * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
37808 + * this pointer re-assigned to the buffer of the currently processed QTD.
37809 + * For non-SG request there is always one QTD active.
37810 + */
37811 +
37812 + DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
37813 +
37814 + if (n_desc) {
37815 + /* SG request - more than 1 QTDs */
37816 + hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
37817 + hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
37818 + }
37819 +
37820 + qtd->n_desc = 0;
37821 +
37822 + do {
37823 + dma_desc = &qh->desc_list[n_desc];
37824 + len = hc->xfer_len;
37825 +
37826 + if (len > MAX_DMA_DESC_SIZE)
37827 + len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
37828 +
37829 + if (hc->ep_is_in) {
37830 + if (len > 0) {
37831 + num_packets = (len + hc->max_packet - 1) / hc->max_packet;
37832 + } else {
37833 + /* Need 1 packet for transfer length of 0. */
37834 + num_packets = 1;
37835 + }
37836 + /* Always program an integral # of max packets for IN transfers. */
37837 + len = num_packets * hc->max_packet;
37838 + }
37839 +
37840 + dma_desc->status.b.n_bytes = len;
37841 +
37842 + qh->n_bytes[n_desc] = len;
37843 +
37844 + if ((qh->ep_type == UE_CONTROL)
37845 + && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
37846 + dma_desc->status.b.sup = 1; /* Setup Packet */
37847 +
37848 + dma_desc->status.b.a = 1; /* Active descriptor */
37849 + dma_desc->status.b.sts = 0;
37850 +
37851 + dma_desc->buf =
37852 + ((unsigned long)hc->xfer_buff & 0xffffffff);
37853 +
37854 + /*
37855 + * Last descriptor(or single) of IN transfer
37856 + * with actual size less than MaxPacket.
37857 + */
37858 + if (len > hc->xfer_len) {
37859 + hc->xfer_len = 0;
37860 + } else {
37861 + hc->xfer_buff += len;
37862 + hc->xfer_len -= len;
37863 + }
37864 +
37865 + qtd->n_desc++;
37866 + n_desc++;
37867 + }
37868 + while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
37869 +
37870 +
37871 + qtd->in_process = 1;
37872 +
37873 + if (qh->ep_type == UE_CONTROL)
37874 + break;
37875 +
37876 + if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
37877 + break;
37878 + }
37879 +
37880 + if (n_desc) {
37881 + /* Request Transfer Complete interrupt for the last descriptor */
37882 + qh->desc_list[n_desc - 1].status.b.ioc = 1;
37883 + /* End of List indicator */
37884 + qh->desc_list[n_desc - 1].status.b.eol = 1;
37885 +
37886 + hc->ntd = n_desc;
37887 + }
37888 +}
37889 +
37890 +/**
37891 + * For Control and Bulk endpoints initializes descriptor list
37892 + * and starts the transfer.
37893 + *
37894 + * For Interrupt and Isochronous endpoints initializes descriptor list
37895 + * then updates FrameList, marking appropriate entries as active.
37896 + * In case of Isochronous, the starting descriptor index is calculated based
37897 + * on the scheduled frame, but only on the first transfer descriptor within a session.
37898 + * Then starts the transfer via enabling the channel.
37899 + * For Isochronous endpoint the channel is not halted on XferComplete
37900 + * interrupt so remains assigned to the endpoint(QH) until session is done.
37901 + *
37902 + * @param hcd The HCD state structure for the DWC OTG controller.
37903 + * @param qh The QH to init.
37904 + *
37905 + * @return 0 if successful, negative error code otherwise.
37906 + */
37907 +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
37908 +{
37909 + /* Channel is already assigned */
37910 + dwc_hc_t *hc = qh->channel;
37911 + uint8_t skip_frames = 0;
37912 +
37913 + switch (hc->ep_type) {
37914 + case DWC_OTG_EP_TYPE_CONTROL:
37915 + case DWC_OTG_EP_TYPE_BULK:
37916 + init_non_isoc_dma_desc(hcd, qh);
37917 +
37918 + dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
37919 + break;
37920 + case DWC_OTG_EP_TYPE_INTR:
37921 + init_non_isoc_dma_desc(hcd, qh);
37922 +
37923 + update_frame_list(hcd, qh, 1);
37924 +
37925 + dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
37926 + break;
37927 + case DWC_OTG_EP_TYPE_ISOC:
37928 +
37929 + if (!qh->ntd)
37930 + skip_frames = recalc_initial_desc_idx(hcd, qh);
37931 +
37932 + init_isoc_dma_desc(hcd, qh, skip_frames);
37933 +
37934 + if (!hc->xfer_started) {
37935 +
37936 + update_frame_list(hcd, qh, 1);
37937 +
37938 + /*
37939 + * Always set to max, instead of actual size.
37940 + * Otherwise ntd will be changed with
37941 + * channel being enabled. Not recommended.
37942 + *
37943 + */
37944 + hc->ntd = max_desc_num(qh);
37945 + /* Enable channel only once for ISOC */
37946 + dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
37947 + }
37948 +
37949 + break;
37950 + default:
37951 +
37952 + break;
37953 + }
37954 +}
37955 +
37956 +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
37957 + dwc_hc_t * hc,
37958 + dwc_otg_hc_regs_t * hc_regs,
37959 + dwc_otg_halt_status_e halt_status)
37960 +{
37961 + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
37962 + dwc_otg_qtd_t *qtd, *qtd_tmp;
37963 + dwc_otg_qh_t *qh;
37964 + dwc_otg_host_dma_desc_t *dma_desc;
37965 + uint16_t idx, remain;
37966 + uint8_t urb_compl;
37967 +
37968 + qh = hc->qh;
37969 + idx = qh->td_first;
37970 +
37971 + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
37972 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
37973 + qtd->in_process = 0;
37974 + return;
37975 + } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||
37976 + (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
37977 + /*
37978 + * Channel is halted in these error cases.
37979 + * Considered as serious issues.
37980 + * Complete all URBs marking all frames as failed,
37981 + * irrespective whether some of the descriptors(frames) succeeded or no.
37982 + * Pass error code to completion routine as well, to
37983 + * update urb->status, some of class drivers might use it to stop
37984 + * queing transfer requests.
37985 + */
37986 + int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)
37987 + ? (-DWC_E_IO)
37988 + : (-DWC_E_OVERFLOW);
37989 +
37990 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
37991 + for (idx = 0; idx < qtd->urb->packet_count; idx++) {
37992 + frame_desc = &qtd->urb->iso_descs[idx];
37993 + frame_desc->status = err;
37994 + }
37995 + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
37996 + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
37997 + }
37998 + return;
37999 + }
38000 +
38001 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
38002 +
38003 + if (!qtd->in_process)
38004 + break;
38005 +
38006 + urb_compl = 0;
38007 +
38008 + do {
38009 +
38010 + dma_desc = &qh->desc_list[idx];
38011 +
38012 + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
38013 + remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
38014 +
38015 + if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
38016 + /*
38017 + * XactError or, unable to complete all the transactions
38018 + * in the scheduled micro-frame/frame,
38019 + * both indicated by DMA_DESC_STS_PKTERR.
38020 + */
38021 + qtd->urb->error_count++;
38022 + frame_desc->actual_length = qh->n_bytes[idx] - remain;
38023 + frame_desc->status = -DWC_E_PROTOCOL;
38024 + } else {
38025 + /* Success */
38026 +
38027 + frame_desc->actual_length = qh->n_bytes[idx] - remain;
38028 + frame_desc->status = 0;
38029 + }
38030 +
38031 + if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
38032 + /*
38033 + * urb->status is not used for isoc transfers here.
38034 + * The individual frame_desc status are used instead.
38035 + */
38036 +
38037 + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
38038 + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
38039 +
38040 + /*
38041 + * This check is necessary because urb_dequeue can be called
38042 + * from urb complete callback(sound driver example).
38043 + * All pending URBs are dequeued there, so no need for
38044 + * further processing.
38045 + */
38046 + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
38047 + return;
38048 + }
38049 +
38050 + urb_compl = 1;
38051 +
38052 + }
38053 +
38054 + qh->ntd--;
38055 +
38056 + /* Stop if IOC requested descriptor reached */
38057 + if (dma_desc->status.b_isoc.ioc) {
38058 + idx = desclist_idx_inc(idx, qh->interval, hc->speed);
38059 + goto stop_scan;
38060 + }
38061 +
38062 + idx = desclist_idx_inc(idx, qh->interval, hc->speed);
38063 +
38064 + if (urb_compl)
38065 + break;
38066 + }
38067 + while (idx != qh->td_first);
38068 + }
38069 +stop_scan:
38070 + qh->td_first = idx;
38071 +}
38072 +
38073 +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
38074 + dwc_hc_t * hc,
38075 + dwc_otg_qtd_t * qtd,
38076 + dwc_otg_host_dma_desc_t * dma_desc,
38077 + dwc_otg_halt_status_e halt_status,
38078 + uint32_t n_bytes, uint8_t * xfer_done)
38079 +{
38080 +
38081 + uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
38082 + dwc_otg_hcd_urb_t *urb = qtd->urb;
38083 +
38084 + if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
38085 + urb->status = -DWC_E_IO;
38086 + return 1;
38087 + }
38088 + if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
38089 + switch (halt_status) {
38090 + case DWC_OTG_HC_XFER_STALL:
38091 + urb->status = -DWC_E_PIPE;
38092 + break;
38093 + case DWC_OTG_HC_XFER_BABBLE_ERR:
38094 + urb->status = -DWC_E_OVERFLOW;
38095 + break;
38096 + case DWC_OTG_HC_XFER_XACT_ERR:
38097 + urb->status = -DWC_E_PROTOCOL;
38098 + break;
38099 + default:
38100 + DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
38101 + halt_status);
38102 + break;
38103 + }
38104 + return 1;
38105 + }
38106 +
38107 + if (dma_desc->status.b.a == 1) {
38108 + DWC_DEBUGPL(DBG_HCDV,
38109 + "Active descriptor encountered on channel %d\n",
38110 + hc->hc_num);
38111 + return 0;
38112 + }
38113 +
38114 + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
38115 + if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
38116 + urb->actual_length += n_bytes - remain;
38117 + if (remain || urb->actual_length == urb->length) {
38118 + /*
38119 + * For Control Data stage do not set urb->status=0 to prevent
38120 + * URB callback. Set it when Status phase done. See below.
38121 + */
38122 + *xfer_done = 1;
38123 + }
38124 +
38125 + } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
38126 + urb->status = 0;
38127 + *xfer_done = 1;
38128 + }
38129 + /* No handling for SETUP stage */
38130 + } else {
38131 + /* BULK and INTR */
38132 + urb->actual_length += n_bytes - remain;
38133 + if (remain || urb->actual_length == urb->length) {
38134 + urb->status = 0;
38135 + *xfer_done = 1;
38136 + }
38137 + }
38138 +
38139 + return 0;
38140 +}
38141 +
38142 +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
38143 + dwc_hc_t * hc,
38144 + dwc_otg_hc_regs_t * hc_regs,
38145 + dwc_otg_halt_status_e halt_status)
38146 +{
38147 + dwc_otg_hcd_urb_t *urb = NULL;
38148 + dwc_otg_qtd_t *qtd, *qtd_tmp;
38149 + dwc_otg_qh_t *qh;
38150 + dwc_otg_host_dma_desc_t *dma_desc;
38151 + uint32_t n_bytes, n_desc, i;
38152 + uint8_t failed = 0, xfer_done;
38153 +
38154 + n_desc = 0;
38155 +
38156 + qh = hc->qh;
38157 +
38158 + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
38159 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
38160 + qtd->in_process = 0;
38161 + }
38162 + return;
38163 + }
38164 +
38165 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
38166 +
38167 + urb = qtd->urb;
38168 +
38169 + n_bytes = 0;
38170 + xfer_done = 0;
38171 +
38172 + for (i = 0; i < qtd->n_desc; i++) {
38173 + dma_desc = &qh->desc_list[n_desc];
38174 +
38175 + n_bytes = qh->n_bytes[n_desc];
38176 +
38177 + failed =
38178 + update_non_isoc_urb_state_ddma(hcd, hc, qtd,
38179 + dma_desc,
38180 + halt_status, n_bytes,
38181 + &xfer_done);
38182 +
38183 + if (failed
38184 + || (xfer_done
38185 + && (urb->status != -DWC_E_IN_PROGRESS))) {
38186 +
38187 + hcd->fops->complete(hcd, urb->priv, urb,
38188 + urb->status);
38189 + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
38190 +
38191 + if (failed)
38192 + goto stop_scan;
38193 + } else if (qh->ep_type == UE_CONTROL) {
38194 + if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
38195 + if (urb->length > 0) {
38196 + qtd->control_phase = DWC_OTG_CONTROL_DATA;
38197 + } else {
38198 + qtd->control_phase = DWC_OTG_CONTROL_STATUS;
38199 + }
38200 + DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n");
38201 + } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
38202 + if (xfer_done) {
38203 + qtd->control_phase = DWC_OTG_CONTROL_STATUS;
38204 + DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n");
38205 + } else if (i + 1 == qtd->n_desc) {
38206 + /*
38207 + * Last descriptor for Control data stage which is
38208 + * not completed yet.
38209 + */
38210 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
38211 + }
38212 + }
38213 + }
38214 +
38215 + n_desc++;
38216 + }
38217 +
38218 + }
38219 +
38220 +stop_scan:
38221 +
38222 + if (qh->ep_type != UE_CONTROL) {
38223 + /*
38224 + * Resetting the data toggle for bulk
38225 + * and interrupt endpoints in case of stall. See handle_hc_stall_intr()
38226 + */
38227 + if (halt_status == DWC_OTG_HC_XFER_STALL)
38228 + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
38229 + else
38230 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
38231 + }
38232 +
38233 + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
38234 + hcint_data_t hcint;
38235 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
38236 + if (hcint.b.nyet) {
38237 + /*
38238 + * Got a NYET on the last transaction of the transfer. It
38239 + * means that the endpoint should be in the PING state at the
38240 + * beginning of the next transfer.
38241 + */
38242 + qh->ping_state = 1;
38243 + clear_hc_int(hc_regs, nyet);
38244 + }
38245 +
38246 + }
38247 +
38248 +}
38249 +
38250 +/**
38251 + * This function is called from interrupt handlers.
38252 + * Scans the descriptor list, updates URB's status and
38253 + * calls completion routine for the URB if it's done.
38254 + * Releases the channel to be used by other transfers.
38255 + * In case of Isochronous endpoint the channel is not halted until
38256 + * the end of the session, i.e. QTD list is empty.
38257 + * If periodic channel released the FrameList is updated accordingly.
38258 + *
38259 + * Calls transaction selection routines to activate pending transfers.
38260 + *
38261 + * @param hcd The HCD state structure for the DWC OTG controller.
38262 + * @param hc Host channel, the transfer is completed on.
38263 + * @param hc_regs Host channel registers.
38264 + * @param halt_status Reason the channel is being halted,
38265 + * or just XferComplete for isochronous transfer
38266 + */
38267 +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
38268 + dwc_hc_t * hc,
38269 + dwc_otg_hc_regs_t * hc_regs,
38270 + dwc_otg_halt_status_e halt_status)
38271 +{
38272 + uint8_t continue_isoc_xfer = 0;
38273 + dwc_otg_transaction_type_e tr_type;
38274 + dwc_otg_qh_t *qh = hc->qh;
38275 +
38276 + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
38277 +
38278 + complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
38279 +
38280 + /* Release the channel if halted or session completed */
38281 + if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
38282 + DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
38283 +
38284 + /* Halt the channel if session completed */
38285 + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
38286 + dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
38287 + }
38288 +
38289 + release_channel_ddma(hcd, qh);
38290 + dwc_otg_hcd_qh_remove(hcd, qh);
38291 + } else {
38292 + /* Keep in assigned schedule to continue transfer */
38293 + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
38294 + &qh->qh_list_entry);
38295 + continue_isoc_xfer = 1;
38296 +
38297 + }
38298 + /** @todo Consider the case when period exceeds FrameList size.
38299 + * Frame Rollover interrupt should be used.
38300 + */
38301 + } else {
38302 + /* Scan descriptor list to complete the URB(s), then release the channel */
38303 + complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
38304 +
38305 + release_channel_ddma(hcd, qh);
38306 + dwc_otg_hcd_qh_remove(hcd, qh);
38307 +
38308 + if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
38309 + /* Add back to inactive non-periodic schedule on normal completion */
38310 + dwc_otg_hcd_qh_add(hcd, qh);
38311 + }
38312 +
38313 + }
38314 + tr_type = dwc_otg_hcd_select_transactions(hcd);
38315 + if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
38316 + if (continue_isoc_xfer) {
38317 + if (tr_type == DWC_OTG_TRANSACTION_NONE) {
38318 + tr_type = DWC_OTG_TRANSACTION_PERIODIC;
38319 + } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
38320 + tr_type = DWC_OTG_TRANSACTION_ALL;
38321 + }
38322 + }
38323 + dwc_otg_hcd_queue_transactions(hcd, tr_type);
38324 + }
38325 +}
38326 +
38327 +#endif /* DWC_DEVICE_ONLY */
38328 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
38329 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100
38330 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2013-07-06 15:25:50.000000000 +0100
38331 @@ -0,0 +1,839 @@
38332 +/* ==========================================================================
38333 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
38334 + * $Revision: #58 $
38335 + * $Date: 2011/09/15 $
38336 + * $Change: 1846647 $
38337 + *
38338 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
38339 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
38340 + * otherwise expressly agreed to in writing between Synopsys and you.
38341 + *
38342 + * The Software IS NOT an item of Licensed Software or Licensed Product under
38343 + * any End User Software License Agreement or Agreement for Licensed Product
38344 + * with Synopsys or any supplement thereto. You are permitted to use and
38345 + * redistribute this Software in source and binary forms, with or without
38346 + * modification, provided that redistributions of source code must retain this
38347 + * notice. You may not view, use, disclose, copy or distribute this file or
38348 + * any information contained herein except pursuant to this license grant from
38349 + * Synopsys. If you do not agree with this notice, including the disclaimer
38350 + * below, then you are not authorized to use the Software.
38351 + *
38352 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
38353 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38354 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38355 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
38356 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38357 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38358 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38359 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38360 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38361 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38362 + * DAMAGE.
38363 + * ========================================================================== */
38364 +#ifndef DWC_DEVICE_ONLY
38365 +#ifndef __DWC_HCD_H__
38366 +#define __DWC_HCD_H__
38367 +
38368 +#include "dwc_otg_os_dep.h"
38369 +#include "usb.h"
38370 +#include "dwc_otg_hcd_if.h"
38371 +#include "dwc_otg_core_if.h"
38372 +#include "dwc_list.h"
38373 +#include "dwc_otg_cil.h"
38374 +
38375 +/**
38376 + * @file
38377 + *
38378 + * This file contains the structures, constants, and interfaces for
38379 + * the Host Contoller Driver (HCD).
38380 + *
38381 + * The Host Controller Driver (HCD) is responsible for translating requests
38382 + * from the USB Driver into the appropriate actions on the DWC_otg controller.
38383 + * It isolates the USBD from the specifics of the controller by providing an
38384 + * API to the USBD.
38385 + */
38386 +
38387 +struct dwc_otg_hcd_pipe_info {
38388 + uint8_t dev_addr;
38389 + uint8_t ep_num;
38390 + uint8_t pipe_type;
38391 + uint8_t pipe_dir;
38392 + uint16_t mps;
38393 +};
38394 +
38395 +struct dwc_otg_hcd_iso_packet_desc {
38396 + uint32_t offset;
38397 + uint32_t length;
38398 + uint32_t actual_length;
38399 + uint32_t status;
38400 +};
38401 +
38402 +struct dwc_otg_qtd;
38403 +
38404 +struct dwc_otg_hcd_urb {
38405 + void *priv;
38406 + struct dwc_otg_qtd *qtd;
38407 + void *buf;
38408 + dwc_dma_t dma;
38409 + void *setup_packet;
38410 + dwc_dma_t setup_dma;
38411 + uint32_t length;
38412 + uint32_t actual_length;
38413 + uint32_t status;
38414 + uint32_t error_count;
38415 + uint32_t packet_count;
38416 + uint32_t flags;
38417 + uint16_t interval;
38418 + struct dwc_otg_hcd_pipe_info pipe_info;
38419 + struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
38420 +};
38421 +
38422 +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
38423 +{
38424 + return pipe->ep_num;
38425 +}
38426 +
38427 +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
38428 + *pipe)
38429 +{
38430 + return pipe->pipe_type;
38431 +}
38432 +
38433 +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
38434 +{
38435 + return pipe->mps;
38436 +}
38437 +
38438 +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
38439 + *pipe)
38440 +{
38441 + return pipe->dev_addr;
38442 +}
38443 +
38444 +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
38445 + *pipe)
38446 +{
38447 + return (pipe->pipe_type == UE_ISOCHRONOUS);
38448 +}
38449 +
38450 +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
38451 + *pipe)
38452 +{
38453 + return (pipe->pipe_type == UE_INTERRUPT);
38454 +}
38455 +
38456 +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
38457 + *pipe)
38458 +{
38459 + return (pipe->pipe_type == UE_BULK);
38460 +}
38461 +
38462 +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
38463 + *pipe)
38464 +{
38465 + return (pipe->pipe_type == UE_CONTROL);
38466 +}
38467 +
38468 +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
38469 +{
38470 + return (pipe->pipe_dir == UE_DIR_IN);
38471 +}
38472 +
38473 +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
38474 + *pipe)
38475 +{
38476 + return (!dwc_otg_hcd_is_pipe_in(pipe));
38477 +}
38478 +
38479 +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
38480 + uint8_t devaddr, uint8_t ep_num,
38481 + uint8_t pipe_type, uint8_t pipe_dir,
38482 + uint16_t mps)
38483 +{
38484 + pipe->dev_addr = devaddr;
38485 + pipe->ep_num = ep_num;
38486 + pipe->pipe_type = pipe_type;
38487 + pipe->pipe_dir = pipe_dir;
38488 + pipe->mps = mps;
38489 +}
38490 +
38491 +/**
38492 + * Phases for control transfers.
38493 + */
38494 +typedef enum dwc_otg_control_phase {
38495 + DWC_OTG_CONTROL_SETUP,
38496 + DWC_OTG_CONTROL_DATA,
38497 + DWC_OTG_CONTROL_STATUS
38498 +} dwc_otg_control_phase_e;
38499 +
38500 +/** Transaction types. */
38501 +typedef enum dwc_otg_transaction_type {
38502 + DWC_OTG_TRANSACTION_NONE,
38503 + DWC_OTG_TRANSACTION_PERIODIC,
38504 + DWC_OTG_TRANSACTION_NON_PERIODIC,
38505 + DWC_OTG_TRANSACTION_ALL
38506 +} dwc_otg_transaction_type_e;
38507 +
38508 +struct dwc_otg_qh;
38509 +
38510 +/**
38511 + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
38512 + * interrupt, or isochronous transfer. A single QTD is created for each URB
38513 + * (of one of these types) submitted to the HCD. The transfer associated with
38514 + * a QTD may require one or multiple transactions.
38515 + *
38516 + * A QTD is linked to a Queue Head, which is entered in either the
38517 + * non-periodic or periodic schedule for execution. When a QTD is chosen for
38518 + * execution, some or all of its transactions may be executed. After
38519 + * execution, the state of the QTD is updated. The QTD may be retired if all
38520 + * its transactions are complete or if an error occurred. Otherwise, it
38521 + * remains in the schedule so more transactions can be executed later.
38522 + */
38523 +typedef struct dwc_otg_qtd {
38524 + /**
38525 + * Determines the PID of the next data packet for the data phase of
38526 + * control transfers. Ignored for other transfer types.<br>
38527 + * One of the following values:
38528 + * - DWC_OTG_HC_PID_DATA0
38529 + * - DWC_OTG_HC_PID_DATA1
38530 + */
38531 + uint8_t data_toggle;
38532 +
38533 + /** Current phase for control transfers (Setup, Data, or Status). */
38534 + dwc_otg_control_phase_e control_phase;
38535 +
38536 + /** Keep track of the current split type
38537 + * for FS/LS endpoints on a HS Hub */
38538 + uint8_t complete_split;
38539 +
38540 + /** How many bytes transferred during SSPLIT OUT */
38541 + uint32_t ssplit_out_xfer_count;
38542 +
38543 + /**
38544 + * Holds the number of bus errors that have occurred for a transaction
38545 + * within this transfer.
38546 + */
38547 + uint8_t error_count;
38548 +
38549 + /**
38550 + * Index of the next frame descriptor for an isochronous transfer. A
38551 + * frame descriptor describes the buffer position and length of the
38552 + * data to be transferred in the next scheduled (micro)frame of an
38553 + * isochronous transfer. It also holds status for that transaction.
38554 + * The frame index starts at 0.
38555 + */
38556 + uint16_t isoc_frame_index;
38557 +
38558 + /** Position of the ISOC split on full/low speed */
38559 + uint8_t isoc_split_pos;
38560 +
38561 + /** Position of the ISOC split in the buffer for the current frame */
38562 + uint16_t isoc_split_offset;
38563 +
38564 + /** URB for this transfer */
38565 + struct dwc_otg_hcd_urb *urb;
38566 +
38567 + struct dwc_otg_qh *qh;
38568 +
38569 + /** This list of QTDs */
38570 + DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
38571 +
38572 + /** Indicates if this QTD is currently processed by HW. */
38573 + uint8_t in_process;
38574 +
38575 + /** Number of DMA descriptors for this QTD */
38576 + uint8_t n_desc;
38577 +
38578 + /**
38579 + * Last activated frame(packet) index.
38580 + * Used in Descriptor DMA mode only.
38581 + */
38582 + uint16_t isoc_frame_index_last;
38583 +
38584 +} dwc_otg_qtd_t;
38585 +
38586 +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
38587 +
38588 +/**
38589 + * A Queue Head (QH) holds the static characteristics of an endpoint and
38590 + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
38591 + * be entered in either the non-periodic or periodic schedule.
38592 + */
38593 +typedef struct dwc_otg_qh {
38594 + /**
38595 + * Endpoint type.
38596 + * One of the following values:
38597 + * - UE_CONTROL
38598 + * - UE_BULK
38599 + * - UE_INTERRUPT
38600 + * - UE_ISOCHRONOUS
38601 + */
38602 + uint8_t ep_type;
38603 + uint8_t ep_is_in;
38604 +
38605 + /** wMaxPacketSize Field of Endpoint Descriptor. */
38606 + uint16_t maxp;
38607 +
38608 + /**
38609 + * Device speed.
38610 + * One of the following values:
38611 + * - DWC_OTG_EP_SPEED_LOW
38612 + * - DWC_OTG_EP_SPEED_FULL
38613 + * - DWC_OTG_EP_SPEED_HIGH
38614 + */
38615 + uint8_t dev_speed;
38616 +
38617 + /**
38618 + * Determines the PID of the next data packet for non-control
38619 + * transfers. Ignored for control transfers.<br>
38620 + * One of the following values:
38621 + * - DWC_OTG_HC_PID_DATA0
38622 + * - DWC_OTG_HC_PID_DATA1
38623 + */
38624 + uint8_t data_toggle;
38625 +
38626 + /** Ping state if 1. */
38627 + uint8_t ping_state;
38628 +
38629 + /**
38630 + * List of QTDs for this QH.
38631 + */
38632 + struct dwc_otg_qtd_list qtd_list;
38633 +
38634 + /** Host channel currently processing transfers for this QH. */
38635 + struct dwc_hc *channel;
38636 +
38637 + /** Full/low speed endpoint on high-speed hub requires split. */
38638 + uint8_t do_split;
38639 +
38640 + /** @name Periodic schedule information */
38641 + /** @{ */
38642 +
38643 + /** Bandwidth in microseconds per (micro)frame. */
38644 + uint16_t usecs;
38645 +
38646 + /** Interval between transfers in (micro)frames. */
38647 + uint16_t interval;
38648 +
38649 + /**
38650 + * (micro)frame to initialize a periodic transfer. The transfer
38651 + * executes in the following (micro)frame.
38652 + */
38653 + uint16_t sched_frame;
38654 +
38655 + /*
38656 + ** Frame a NAK was received on this queue head, used to minimise NAK retransmission
38657 + */
38658 + uint16_t nak_frame;
38659 +
38660 + /** (micro)frame at which last start split was initialized. */
38661 + uint16_t start_split_frame;
38662 +
38663 + /** @} */
38664 +
38665 + /**
38666 + * Used instead of original buffer if
38667 + * it(physical address) is not dword-aligned.
38668 + */
38669 + uint8_t *dw_align_buf;
38670 + dwc_dma_t dw_align_buf_dma;
38671 +
38672 + /** Entry for QH in either the periodic or non-periodic schedule. */
38673 + dwc_list_link_t qh_list_entry;
38674 +
38675 + /** @name Descriptor DMA support */
38676 + /** @{ */
38677 +
38678 + /** Descriptor List. */
38679 + dwc_otg_host_dma_desc_t *desc_list;
38680 +
38681 + /** Descriptor List physical address. */
38682 + dwc_dma_t desc_list_dma;
38683 +
38684 + /**
38685 + * Xfer Bytes array.
38686 + * Each element corresponds to a descriptor and indicates
38687 + * original XferSize size value for the descriptor.
38688 + */
38689 + uint32_t *n_bytes;
38690 +
38691 + /** Actual number of transfer descriptors in a list. */
38692 + uint16_t ntd;
38693 +
38694 + /** First activated isochronous transfer descriptor index. */
38695 + uint8_t td_first;
38696 + /** Last activated isochronous transfer descriptor index. */
38697 + uint8_t td_last;
38698 +
38699 + /** @} */
38700 +
38701 +
38702 + uint16_t speed;
38703 + uint16_t frame_usecs[8];
38704 +} dwc_otg_qh_t;
38705 +
38706 +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
38707 +
38708 +typedef struct urb_tq_entry {
38709 + struct urb *urb;
38710 + DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;
38711 +} urb_tq_entry_t;
38712 +
38713 +DWC_TAILQ_HEAD(urb_list, urb_tq_entry);
38714 +
38715 +/**
38716 + * This structure holds the state of the HCD, including the non-periodic and
38717 + * periodic schedules.
38718 + */
38719 +struct dwc_otg_hcd {
38720 + /** The DWC otg device pointer */
38721 + struct dwc_otg_device *otg_dev;
38722 + /** DWC OTG Core Interface Layer */
38723 + dwc_otg_core_if_t *core_if;
38724 +
38725 + /** Function HCD driver callbacks */
38726 + struct dwc_otg_hcd_function_ops *fops;
38727 +
38728 + /** Internal DWC HCD Flags */
38729 + volatile union dwc_otg_hcd_internal_flags {
38730 + uint32_t d32;
38731 + struct {
38732 + unsigned port_connect_status_change:1;
38733 + unsigned port_connect_status:1;
38734 + unsigned port_reset_change:1;
38735 + unsigned port_enable_change:1;
38736 + unsigned port_suspend_change:1;
38737 + unsigned port_over_current_change:1;
38738 + unsigned port_l1_change:1;
38739 + unsigned reserved:26;
38740 + } b;
38741 + } flags;
38742 +
38743 + /**
38744 + * Inactive items in the non-periodic schedule. This is a list of
38745 + * Queue Heads. Transfers associated with these Queue Heads are not
38746 + * currently assigned to a host channel.
38747 + */
38748 + dwc_list_link_t non_periodic_sched_inactive;
38749 +
38750 + /**
38751 + * Active items in the non-periodic schedule. This is a list of
38752 + * Queue Heads. Transfers associated with these Queue Heads are
38753 + * currently assigned to a host channel.
38754 + */
38755 + dwc_list_link_t non_periodic_sched_active;
38756 +
38757 + /**
38758 + * Pointer to the next Queue Head to process in the active
38759 + * non-periodic schedule.
38760 + */
38761 + dwc_list_link_t *non_periodic_qh_ptr;
38762 +
38763 + /**
38764 + * Inactive items in the periodic schedule. This is a list of QHs for
38765 + * periodic transfers that are _not_ scheduled for the next frame.
38766 + * Each QH in the list has an interval counter that determines when it
38767 + * needs to be scheduled for execution. This scheduling mechanism
38768 + * allows only a simple calculation for periodic bandwidth used (i.e.
38769 + * must assume that all periodic transfers may need to execute in the
38770 + * same frame). However, it greatly simplifies scheduling and should
38771 + * be sufficient for the vast majority of OTG hosts, which need to
38772 + * connect to a small number of peripherals at one time.
38773 + *
38774 + * Items move from this list to periodic_sched_ready when the QH
38775 + * interval counter is 0 at SOF.
38776 + */
38777 + dwc_list_link_t periodic_sched_inactive;
38778 +
38779 + /**
38780 + * List of periodic QHs that are ready for execution in the next
38781 + * frame, but have not yet been assigned to host channels.
38782 + *
38783 + * Items move from this list to periodic_sched_assigned as host
38784 + * channels become available during the current frame.
38785 + */
38786 + dwc_list_link_t periodic_sched_ready;
38787 +
38788 + /**
38789 + * List of periodic QHs to be executed in the next frame that are
38790 + * assigned to host channels.
38791 + *
38792 + * Items move from this list to periodic_sched_queued as the
38793 + * transactions for the QH are queued to the DWC_otg controller.
38794 + */
38795 + dwc_list_link_t periodic_sched_assigned;
38796 +
38797 + /**
38798 + * List of periodic QHs that have been queued for execution.
38799 + *
38800 + * Items move from this list to either periodic_sched_inactive or
38801 + * periodic_sched_ready when the channel associated with the transfer
38802 + * is released. If the interval for the QH is 1, the item moves to
38803 + * periodic_sched_ready because it must be rescheduled for the next
38804 + * frame. Otherwise, the item moves to periodic_sched_inactive.
38805 + */
38806 + dwc_list_link_t periodic_sched_queued;
38807 +
38808 + /**
38809 + * Total bandwidth claimed so far for periodic transfers. This value
38810 + * is in microseconds per (micro)frame. The assumption is that all
38811 + * periodic transfers may occur in the same (micro)frame.
38812 + */
38813 + uint16_t periodic_usecs;
38814 +
38815 + /**
38816 + * Total bandwidth claimed so far for all periodic transfers
38817 + * in a frame.
38818 + * This will include a mixture of HS and FS transfers.
38819 + * Units are microseconds per (micro)frame.
38820 + * We have a budget per frame and have to schedule
38821 + * transactions accordingly.
38822 + * Watch out for the fact that things are actually scheduled for the
38823 + * "next frame".
38824 + */
38825 + uint16_t frame_usecs[8];
38826 +
38827 +
38828 + /**
38829 + * Frame number read from the core at SOF. The value ranges from 0 to
38830 + * DWC_HFNUM_MAX_FRNUM.
38831 + */
38832 + uint16_t frame_number;
38833 +
38834 + /**
38835 + * Count of periodic QHs, if using several eps. For SOF enable/disable.
38836 + */
38837 + uint16_t periodic_qh_count;
38838 +
38839 + /**
38840 + * Free host channels in the controller. This is a list of
38841 + * dwc_hc_t items.
38842 + */
38843 + struct hc_list free_hc_list;
38844 + /**
38845 + * Number of host channels assigned to periodic transfers. Currently
38846 + * assuming that there is a dedicated host channel for each periodic
38847 + * transaction and at least one host channel available for
38848 + * non-periodic transactions.
38849 + */
38850 + int periodic_channels; /* microframe_schedule==0 */
38851 +
38852 + /**
38853 + * Number of host channels assigned to non-periodic transfers.
38854 + */
38855 + int non_periodic_channels; /* microframe_schedule==0 */
38856 +
38857 + /**
38858 + * Number of host channels assigned to non-periodic transfers.
38859 + */
38860 + int available_host_channels;
38861 +
38862 + /**
38863 + * Array of pointers to the host channel descriptors. Allows accessing
38864 + * a host channel descriptor given the host channel number. This is
38865 + * useful in interrupt handlers.
38866 + */
38867 + struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
38868 +
38869 + /**
38870 + * Buffer to use for any data received during the status phase of a
38871 + * control transfer. Normally no data is transferred during the status
38872 + * phase. This buffer is used as a bit bucket.
38873 + */
38874 + uint8_t *status_buf;
38875 +
38876 + /**
38877 + * DMA address for status_buf.
38878 + */
38879 + dma_addr_t status_buf_dma;
38880 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
38881 +
38882 + /**
38883 + * Connection timer. An OTG host must display a message if the device
38884 + * does not connect. Started when the VBus power is turned on via
38885 + * sysfs attribute "buspower".
38886 + */
38887 + dwc_timer_t *conn_timer;
38888 +
38889 + /* Tasket to do a reset */
38890 + dwc_tasklet_t *reset_tasklet;
38891 +
38892 + dwc_tasklet_t *completion_tasklet;
38893 + struct urb_list completed_urb_list;
38894 +
38895 + /* */
38896 + dwc_spinlock_t *lock;
38897 + dwc_spinlock_t *channel_lock;
38898 + /**
38899 + * Private data that could be used by OS wrapper.
38900 + */
38901 + void *priv;
38902 +
38903 + uint8_t otg_port;
38904 +
38905 + /** Frame List */
38906 + uint32_t *frame_list;
38907 +
38908 + /** Frame List DMA address */
38909 + dma_addr_t frame_list_dma;
38910 +
38911 +#ifdef DEBUG
38912 + uint32_t frrem_samples;
38913 + uint64_t frrem_accum;
38914 +
38915 + uint32_t hfnum_7_samples_a;
38916 + uint64_t hfnum_7_frrem_accum_a;
38917 + uint32_t hfnum_0_samples_a;
38918 + uint64_t hfnum_0_frrem_accum_a;
38919 + uint32_t hfnum_other_samples_a;
38920 + uint64_t hfnum_other_frrem_accum_a;
38921 +
38922 + uint32_t hfnum_7_samples_b;
38923 + uint64_t hfnum_7_frrem_accum_b;
38924 + uint32_t hfnum_0_samples_b;
38925 + uint64_t hfnum_0_frrem_accum_b;
38926 + uint32_t hfnum_other_samples_b;
38927 + uint64_t hfnum_other_frrem_accum_b;
38928 +#endif
38929 +};
38930 +
38931 +/** @name Transaction Execution Functions */
38932 +/** @{ */
38933 +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
38934 + * hcd);
38935 +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
38936 + dwc_otg_transaction_type_e tr_type);
38937 +
38938 +/** @} */
38939 +
38940 +/** @name Interrupt Handler Functions */
38941 +/** @{ */
38942 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38943 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t);
38944 +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
38945 + dwc_otg_hcd);
38946 +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
38947 + dwc_otg_hcd);
38948 +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
38949 + dwc_otg_hcd);
38950 +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
38951 + dwc_otg_hcd);
38952 +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38953 +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
38954 + dwc_otg_hcd);
38955 +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38956 +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38957 +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
38958 + uint32_t num);
38959 +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38960 +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
38961 + dwc_otg_hcd);
38962 +/** @} */
38963 +
38964 +/** @name Schedule Queue Functions */
38965 +/** @{ */
38966 +
38967 +/* Implemented in dwc_otg_hcd_queue.c */
38968 +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
38969 + dwc_otg_hcd_urb_t * urb, int atomic_alloc);
38970 +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38971 +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38972 +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38973 +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38974 + int sched_csplit);
38975 +
38976 +/** Remove and free a QH */
38977 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
38978 + dwc_otg_qh_t * qh)
38979 +{
38980 + dwc_irqflags_t flags;
38981 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
38982 + dwc_otg_hcd_qh_remove(hcd, qh);
38983 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
38984 + dwc_otg_hcd_qh_free(hcd, qh);
38985 +}
38986 +
38987 +/** Allocates memory for a QH structure.
38988 + * @return Returns the memory allocate or NULL on error. */
38989 +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
38990 +{
38991 + if (atomic_alloc)
38992 + return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
38993 + else
38994 + return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
38995 +}
38996 +
38997 +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
38998 + int atomic_alloc);
38999 +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
39000 +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
39001 + dwc_otg_qh_t ** qh, int atomic_alloc);
39002 +
39003 +/** Allocates memory for a QTD structure.
39004 + * @return Returns the memory allocate or NULL on error. */
39005 +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
39006 +{
39007 + if (atomic_alloc)
39008 + return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
39009 + else
39010 + return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
39011 +}
39012 +
39013 +/** Frees the memory for a QTD structure. QTD should already be removed from
39014 + * list.
39015 + * @param qtd QTD to free.*/
39016 +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
39017 +{
39018 + DWC_FREE(qtd);
39019 +}
39020 +
39021 +/** Removes a QTD from list.
39022 + * @param hcd HCD instance.
39023 + * @param qtd QTD to remove from list.
39024 + * @param qh QTD belongs to.
39025 + */
39026 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
39027 + dwc_otg_qtd_t * qtd,
39028 + dwc_otg_qh_t * qh)
39029 +{
39030 + DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
39031 +}
39032 +
39033 +/** Remove and free a QTD
39034 + * Need to disable IRQ and hold hcd lock while calling this function out of
39035 + * interrupt servicing chain */
39036 +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
39037 + dwc_otg_qtd_t * qtd,
39038 + dwc_otg_qh_t * qh)
39039 +{
39040 + dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
39041 + dwc_otg_hcd_qtd_free(qtd);
39042 +}
39043 +
39044 +/** @} */
39045 +
39046 +/** @name Descriptor DMA Supporting Functions */
39047 +/** @{ */
39048 +
39049 +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
39050 +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
39051 + dwc_hc_t * hc,
39052 + dwc_otg_hc_regs_t * hc_regs,
39053 + dwc_otg_halt_status_e halt_status);
39054 +
39055 +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
39056 +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
39057 +
39058 +/** @} */
39059 +
39060 +/** @name Internal Functions */
39061 +/** @{ */
39062 +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
39063 +/** @} */
39064 +
39065 +#ifdef CONFIG_USB_DWC_OTG_LPM
39066 +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
39067 + uint8_t devaddr);
39068 +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
39069 +#endif
39070 +
39071 +/** Gets the QH that contains the list_head */
39072 +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
39073 +
39074 +/** Gets the QTD that contains the list_head */
39075 +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
39076 +
39077 +/** Check if QH is non-periodic */
39078 +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
39079 + (_qh_ptr_->ep_type == UE_CONTROL))
39080 +
39081 +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
39082 +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
39083 +
39084 +/** Packet size for any kind of endpoint descriptor */
39085 +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
39086 +
39087 +/**
39088 + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
39089 + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
39090 + * frame number when the max frame number is reached.
39091 + */
39092 +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
39093 +{
39094 + return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
39095 + (DWC_HFNUM_MAX_FRNUM >> 1);
39096 +}
39097 +
39098 +/**
39099 + * Returns true if _frame1 is greater than _frame2. The comparison is done
39100 + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
39101 + * number when the max frame number is reached.
39102 + */
39103 +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
39104 +{
39105 + return (frame1 != frame2) &&
39106 + (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
39107 + (DWC_HFNUM_MAX_FRNUM >> 1));
39108 +}
39109 +
39110 +/**
39111 + * Increments _frame by the amount specified by _inc. The addition is done
39112 + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
39113 + */
39114 +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
39115 +{
39116 + return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
39117 +}
39118 +
39119 +static inline uint16_t dwc_full_frame_num(uint16_t frame)
39120 +{
39121 + return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
39122 +}
39123 +
39124 +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
39125 +{
39126 + return frame & 0x7;
39127 +}
39128 +
39129 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
39130 + dwc_otg_hc_regs_t * hc_regs,
39131 + dwc_otg_qtd_t * qtd);
39132 +
39133 +#ifdef DEBUG
39134 +/**
39135 + * Macro to sample the remaining PHY clocks left in the current frame. This
39136 + * may be used during debugging to determine the average time it takes to
39137 + * execute sections of code. There are two possible sample points, "a" and
39138 + * "b", so the _letter argument must be one of these values.
39139 + *
39140 + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
39141 + * example, "cat /sys/devices/lm0/hcd_frrem".
39142 + */
39143 +#define dwc_sample_frrem(_hcd, _qh, _letter) \
39144 +{ \
39145 + hfnum_data_t hfnum; \
39146 + dwc_otg_qtd_t *qtd; \
39147 + qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
39148 + if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
39149 + hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
39150 + switch (hfnum.b.frnum & 0x7) { \
39151 + case 7: \
39152 + _hcd->hfnum_7_samples_##_letter++; \
39153 + _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
39154 + break; \
39155 + case 0: \
39156 + _hcd->hfnum_0_samples_##_letter++; \
39157 + _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
39158 + break; \
39159 + default: \
39160 + _hcd->hfnum_other_samples_##_letter++; \
39161 + _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
39162 + break; \
39163 + } \
39164 + } \
39165 +}
39166 +#else
39167 +#define dwc_sample_frrem(_hcd, _qh, _letter)
39168 +#endif
39169 +#endif
39170 +#endif /* DWC_DEVICE_ONLY */
39171 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39172 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100
39173 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2013-07-06 15:25:50.000000000 +0100
39174 @@ -0,0 +1,417 @@
39175 +/* ==========================================================================
39176 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
39177 + * $Revision: #12 $
39178 + * $Date: 2011/10/26 $
39179 + * $Change: 1873028 $
39180 + *
39181 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39182 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39183 + * otherwise expressly agreed to in writing between Synopsys and you.
39184 + *
39185 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39186 + * any End User Software License Agreement or Agreement for Licensed Product
39187 + * with Synopsys or any supplement thereto. You are permitted to use and
39188 + * redistribute this Software in source and binary forms, with or without
39189 + * modification, provided that redistributions of source code must retain this
39190 + * notice. You may not view, use, disclose, copy or distribute this file or
39191 + * any information contained herein except pursuant to this license grant from
39192 + * Synopsys. If you do not agree with this notice, including the disclaimer
39193 + * below, then you are not authorized to use the Software.
39194 + *
39195 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39196 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39197 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39198 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39199 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39200 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39201 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39202 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39203 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39204 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39205 + * DAMAGE.
39206 + * ========================================================================== */
39207 +#ifndef DWC_DEVICE_ONLY
39208 +#ifndef __DWC_HCD_IF_H__
39209 +#define __DWC_HCD_IF_H__
39210 +
39211 +#include "dwc_otg_core_if.h"
39212 +
39213 +/** @file
39214 + * This file defines DWC_OTG HCD Core API.
39215 + */
39216 +
39217 +struct dwc_otg_hcd;
39218 +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
39219 +
39220 +struct dwc_otg_hcd_urb;
39221 +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
39222 +
39223 +/** @name HCD Function Driver Callbacks */
39224 +/** @{ */
39225 +
39226 +/** This function is called whenever core switches to host mode. */
39227 +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
39228 +
39229 +/** This function is called when device has been disconnected */
39230 +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
39231 +
39232 +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
39233 +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39234 + void *urb_handle,
39235 + uint32_t * hub_addr,
39236 + uint32_t * port_addr);
39237 +/** Via this function HCD core gets device speed */
39238 +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39239 + void *urb_handle);
39240 +
39241 +/** This function is called when urb is completed */
39242 +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
39243 + void *urb_handle,
39244 + dwc_otg_hcd_urb_t * dwc_otg_urb,
39245 + int32_t status);
39246 +
39247 +/** Via this function HCD core gets b_hnp_enable parameter */
39248 +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
39249 +
39250 +struct dwc_otg_hcd_function_ops {
39251 + dwc_otg_hcd_start_cb_t start;
39252 + dwc_otg_hcd_disconnect_cb_t disconnect;
39253 + dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
39254 + dwc_otg_hcd_speed_from_urb_cb_t speed;
39255 + dwc_otg_hcd_complete_urb_cb_t complete;
39256 + dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
39257 +};
39258 +/** @} */
39259 +
39260 +/** @name HCD Core API */
39261 +/** @{ */
39262 +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
39263 +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
39264 +
39265 +/** This function should be called to initiate HCD Core.
39266 + *
39267 + * @param hcd The HCD
39268 + * @param core_if The DWC_OTG Core
39269 + *
39270 + * Returns -DWC_E_NO_MEMORY if no enough memory.
39271 + * Returns 0 on success
39272 + */
39273 +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
39274 +
39275 +/** Frees HCD
39276 + *
39277 + * @param hcd The HCD
39278 + */
39279 +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
39280 +
39281 +/** This function should be called on every hardware interrupt.
39282 + *
39283 + * @param dwc_otg_hcd The HCD
39284 + *
39285 + * Returns non zero if interrupt is handled
39286 + * Return 0 if interrupt is not handled
39287 + */
39288 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
39289 +
39290 +/** This function is used to handle the fast interrupt
39291 + *
39292 + */
39293 +extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);
39294 +
39295 +/**
39296 + * Returns private data set by
39297 + * dwc_otg_hcd_set_priv_data function.
39298 + *
39299 + * @param hcd The HCD
39300 + */
39301 +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
39302 +
39303 +/**
39304 + * Set private data.
39305 + *
39306 + * @param hcd The HCD
39307 + * @param priv_data pointer to be stored in private data
39308 + */
39309 +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
39310 +
39311 +/**
39312 + * This function initializes the HCD Core.
39313 + *
39314 + * @param hcd The HCD
39315 + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
39316 + *
39317 + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
39318 + * Returns 0 on success
39319 + */
39320 +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
39321 + struct dwc_otg_hcd_function_ops *fops);
39322 +
39323 +/**
39324 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
39325 + * stopped.
39326 + *
39327 + * @param hcd The HCD
39328 + */
39329 +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
39330 +
39331 +/**
39332 + * Handles hub class-specific requests.
39333 + *
39334 + * @param dwc_otg_hcd The HCD
39335 + * @param typeReq Request Type
39336 + * @param wValue wValue from control request
39337 + * @param wIndex wIndex from control request
39338 + * @param buf data buffer
39339 + * @param wLength data buffer length
39340 + *
39341 + * Returns -DWC_E_INVALID if invalid argument is passed
39342 + * Returns 0 on success
39343 + */
39344 +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
39345 + uint16_t typeReq, uint16_t wValue,
39346 + uint16_t wIndex, uint8_t * buf,
39347 + uint16_t wLength);
39348 +
39349 +/**
39350 + * Returns otg port number.
39351 + *
39352 + * @param hcd The HCD
39353 + */
39354 +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
39355 +
39356 +/**
39357 + * Returns OTG version - either 1.3 or 2.0.
39358 + *
39359 + * @param core_if The core_if structure pointer
39360 + */
39361 +extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
39362 +
39363 +/**
39364 + * Returns 1 if currently core is acting as B host, and 0 otherwise.
39365 + *
39366 + * @param hcd The HCD
39367 + */
39368 +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
39369 +
39370 +/**
39371 + * Returns current frame number.
39372 + *
39373 + * @param hcd The HCD
39374 + */
39375 +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
39376 +
39377 +/**
39378 + * Dumps hcd state.
39379 + *
39380 + * @param hcd The HCD
39381 + */
39382 +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
39383 +
39384 +/**
39385 + * Dump the average frame remaining at SOF. This can be used to
39386 + * determine average interrupt latency. Frame remaining is also shown for
39387 + * start transfer and two additional sample points.
39388 + * Currently this function is not implemented.
39389 + *
39390 + * @param hcd The HCD
39391 + */
39392 +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
39393 +
39394 +/**
39395 + * Sends LPM transaction to the local device.
39396 + *
39397 + * @param hcd The HCD
39398 + * @param devaddr Device Address
39399 + * @param hird Host initiated resume duration
39400 + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
39401 + *
39402 + * Returns negative value if sending LPM transaction was not succeeded.
39403 + * Returns 0 on success.
39404 + */
39405 +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
39406 + uint8_t hird, uint8_t bRemoteWake);
39407 +
39408 +/* URB interface */
39409 +
39410 +/**
39411 + * Allocates memory for dwc_otg_hcd_urb structure.
39412 + * Allocated memory should be freed by call of DWC_FREE.
39413 + *
39414 + * @param hcd The HCD
39415 + * @param iso_desc_count Count of ISOC descriptors
39416 + * @param atomic_alloc Specefies whether to perform atomic allocation.
39417 + */
39418 +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
39419 + int iso_desc_count,
39420 + int atomic_alloc);
39421 +
39422 +/**
39423 + * Set pipe information in URB.
39424 + *
39425 + * @param hcd_urb DWC_OTG URB
39426 + * @param devaddr Device Address
39427 + * @param ep_num Endpoint Number
39428 + * @param ep_type Endpoint Type
39429 + * @param ep_dir Endpoint Direction
39430 + * @param mps Max Packet Size
39431 + */
39432 +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
39433 + uint8_t devaddr, uint8_t ep_num,
39434 + uint8_t ep_type, uint8_t ep_dir,
39435 + uint16_t mps);
39436 +
39437 +/* Transfer flags */
39438 +#define URB_GIVEBACK_ASAP 0x1
39439 +#define URB_SEND_ZERO_PACKET 0x2
39440 +
39441 +/**
39442 + * Sets dwc_otg_hcd_urb parameters.
39443 + *
39444 + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
39445 + * @param urb_handle Unique handle for request, this will be passed back
39446 + * to function driver in completion callback.
39447 + * @param buf The buffer for the data
39448 + * @param dma The DMA buffer for the data
39449 + * @param buflen Transfer length
39450 + * @param sp Buffer for setup data
39451 + * @param sp_dma DMA address of setup data buffer
39452 + * @param flags Transfer flags
39453 + * @param interval Polling interval for interrupt or isochronous transfers.
39454 + */
39455 +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
39456 + void *urb_handle, void *buf,
39457 + dwc_dma_t dma, uint32_t buflen, void *sp,
39458 + dwc_dma_t sp_dma, uint32_t flags,
39459 + uint16_t interval);
39460 +
39461 +/** Gets status from dwc_otg_hcd_urb
39462 + *
39463 + * @param dwc_otg_urb DWC_OTG URB
39464 + */
39465 +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
39466 +
39467 +/** Gets actual length from dwc_otg_hcd_urb
39468 + *
39469 + * @param dwc_otg_urb DWC_OTG URB
39470 + */
39471 +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
39472 + dwc_otg_urb);
39473 +
39474 +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
39475 + *
39476 + * @param dwc_otg_urb DWC_OTG URB
39477 + */
39478 +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
39479 + dwc_otg_urb);
39480 +
39481 +/** Set ISOC descriptor offset and length
39482 + *
39483 + * @param dwc_otg_urb DWC_OTG URB
39484 + * @param desc_num ISOC descriptor number
39485 + * @param offset Offset from beginig of buffer.
39486 + * @param length Transaction length
39487 + */
39488 +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
39489 + int desc_num, uint32_t offset,
39490 + uint32_t length);
39491 +
39492 +/** Get status of ISOC descriptor, specified by desc_num
39493 + *
39494 + * @param dwc_otg_urb DWC_OTG URB
39495 + * @param desc_num ISOC descriptor number
39496 + */
39497 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
39498 + dwc_otg_urb, int desc_num);
39499 +
39500 +/** Get actual length of ISOC descriptor, specified by desc_num
39501 + *
39502 + * @param dwc_otg_urb DWC_OTG URB
39503 + * @param desc_num ISOC descriptor number
39504 + */
39505 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
39506 + dwc_otg_urb,
39507 + int desc_num);
39508 +
39509 +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
39510 + *
39511 + * @param dwc_otg_hcd The HCD
39512 + * @param dwc_otg_urb DWC_OTG URB
39513 + * @param ep_handle Out parameter for returning endpoint handle
39514 + * @param atomic_alloc Flag to do atomic allocation if needed
39515 + *
39516 + * Returns -DWC_E_NO_DEVICE if no device is connected.
39517 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
39518 + * Returns 0 on success.
39519 + */
39520 +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
39521 + dwc_otg_hcd_urb_t * dwc_otg_urb,
39522 + void **ep_handle, int atomic_alloc);
39523 +
39524 +/** De-queue the specified URB
39525 + *
39526 + * @param dwc_otg_hcd The HCD
39527 + * @param dwc_otg_urb DWC_OTG URB
39528 + */
39529 +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
39530 + dwc_otg_hcd_urb_t * dwc_otg_urb);
39531 +
39532 +/** Frees resources in the DWC_otg controller related to a given endpoint.
39533 + * Any URBs for the endpoint must already be dequeued.
39534 + *
39535 + * @param hcd The HCD
39536 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39537 + * @param retry Number of retries if there are queued transfers.
39538 + *
39539 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39540 + * Returns 0 on success
39541 + */
39542 +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
39543 + int retry);
39544 +
39545 +/* Resets the data toggle in qh structure. This function can be called from
39546 + * usb_clear_halt routine.
39547 + *
39548 + * @param hcd The HCD
39549 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39550 + *
39551 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39552 + * Returns 0 on success
39553 + */
39554 +extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);
39555 +
39556 +/** Returns 1 if status of specified port is changed and 0 otherwise.
39557 + *
39558 + * @param hcd The HCD
39559 + * @param port Port number
39560 + */
39561 +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
39562 +
39563 +/** Call this function to check if bandwidth was allocated for specified endpoint.
39564 + * Only for ISOC and INTERRUPT endpoints.
39565 + *
39566 + * @param hcd The HCD
39567 + * @param ep_handle Endpoint handle
39568 + */
39569 +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
39570 + void *ep_handle);
39571 +
39572 +/** Call this function to check if bandwidth was freed for specified endpoint.
39573 + *
39574 + * @param hcd The HCD
39575 + * @param ep_handle Endpoint handle
39576 + */
39577 +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
39578 +
39579 +/** Returns bandwidth allocated for specified endpoint in microseconds.
39580 + * Only for ISOC and INTERRUPT endpoints.
39581 + *
39582 + * @param hcd The HCD
39583 + * @param ep_handle Endpoint handle
39584 + */
39585 +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
39586 + void *ep_handle);
39587 +
39588 +/** @} */
39589 +
39590 +#endif /* __DWC_HCD_IF_H__ */
39591 +#endif /* DWC_DEVICE_ONLY */
39592 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39593 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100
39594 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2013-07-06 15:25:50.000000000 +0100
39595 @@ -0,0 +1,2258 @@
39596 +/* ==========================================================================
39597 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
39598 + * $Revision: #89 $
39599 + * $Date: 2011/10/20 $
39600 + * $Change: 1869487 $
39601 + *
39602 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39603 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39604 + * otherwise expressly agreed to in writing between Synopsys and you.
39605 + *
39606 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39607 + * any End User Software License Agreement or Agreement for Licensed Product
39608 + * with Synopsys or any supplement thereto. You are permitted to use and
39609 + * redistribute this Software in source and binary forms, with or without
39610 + * modification, provided that redistributions of source code must retain this
39611 + * notice. You may not view, use, disclose, copy or distribute this file or
39612 + * any information contained herein except pursuant to this license grant from
39613 + * Synopsys. If you do not agree with this notice, including the disclaimer
39614 + * below, then you are not authorized to use the Software.
39615 + *
39616 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39617 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39618 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39619 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39620 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39621 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39622 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39623 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39624 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39625 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39626 + * DAMAGE.
39627 + * ========================================================================== */
39628 +#ifndef DWC_DEVICE_ONLY
39629 +
39630 +#include "dwc_otg_hcd.h"
39631 +#include "dwc_otg_regs.h"
39632 +#include "dwc_otg_mphi_fix.h"
39633 +
39634 +#include <linux/jiffies.h>
39635 +#include <mach/hardware.h>
39636 +
39637 +
39638 +extern bool microframe_schedule;
39639 +
39640 +/** @file
39641 + * This file contains the implementation of the HCD Interrupt handlers.
39642 + */
39643 +
39644 +/*
39645 + * Some globals to communicate between the FIQ and INTERRUPT
39646 + */
39647 +
39648 +void * dummy_send;
39649 +mphi_regs_t c_mphi_regs;
39650 +int fiq_done, int_done;
39651 +int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected;
39652 +static int mphi_int_count = 0 ;
39653 +
39654 +extern bool fiq_fix_enable, nak_holdoff_enable;
39655 +
39656 +hcchar_data_t nak_hcchar;
39657 +hctsiz_data_t nak_hctsiz;
39658 +hcsplt_data_t nak_hcsplt;
39659 +int nak_count;
39660 +
39661 +void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void)
39662 +{
39663 + gintsts_data_t gintsts;
39664 + hfnum_data_t hfnum;
39665 +
39666 + /* entry takes care to store registers we will be treading on here */
39667 + asm __volatile__ (
39668 + "mov ip, sp ;"
39669 + /* stash FIQ and normal regs */
39670 + "stmdb sp!, {r0-r12, lr};"
39671 + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
39672 + "sub fp, ip, #256 ;"
39673 + );
39674 +
39675 + fiq_done++;
39676 + gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18);
39677 + hfnum.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x408);
39678 +
39679 + if(gintsts.d32)
39680 + {
39681 + if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
39682 + {
39683 + /*
39684 + * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
39685 + * g_next_sched_frame is the next frame we have periodic packets for
39686 + *
39687 + * if neither of these are required for this frame then just clear the interrupt
39688 + */
39689 + gintsts.d32 = 0;
39690 + gintsts.b.sofintr = 1;
39691 + FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32);
39692 +
39693 + g_work_expected = 0;
39694 + }
39695 + else
39696 + {
39697 + g_work_expected = 1;
39698 + /* To enable the MPHI interrupt (INT 32)
39699 + */
39700 + FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
39701 + FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
39702 +
39703 + mphi_int_count++;
39704 + /* Clear the USB global interrupt so we don't just sit in the FIQ */
39705 + FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0);
39706 +
39707 + }
39708 + }
39709 + mb();
39710 +
39711 + /* exit back to normal mode restoring everything */
39712 + asm __volatile__ (
39713 + /* return FIQ regs back to pristine state
39714 + * and get normal regs back
39715 + */
39716 + "ldmia sp!, {r0-r12, lr};"
39717 +
39718 + /* return */
39719 + "subs pc, lr, #4;"
39720 + );
39721 +}
39722 +
39723 +/** This function handles interrupts for the HCD. */
39724 +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39725 +{
39726 + int retval = 0;
39727 + static int last_time;
39728 +
39729 + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
39730 + gintsts_data_t gintsts;
39731 + hfnum_data_t hfnum;
39732 +
39733 +#ifdef DEBUG
39734 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
39735 +
39736 +#endif
39737 +
39738 + /* Exit from ISR if core is hibernated */
39739 + if (core_if->hibernation_suspend == 1) {
39740 + goto exit_handler_routine;
39741 + }
39742 + DWC_SPINLOCK(dwc_otg_hcd->lock);
39743 + /* Check if HOST Mode */
39744 + if (dwc_otg_is_host_mode(core_if)) {
39745 + gintsts.d32 = dwc_otg_read_core_intr(core_if);
39746 + if (!gintsts.d32) {
39747 + goto exit_handler_routine;
39748 + }
39749 +#ifdef DEBUG
39750 + /* Don't print debug message in the interrupt handler on SOF */
39751 +#ifndef DEBUG_SOF
39752 + if (gintsts.d32 != DWC_SOF_INTR_MASK)
39753 +#endif
39754 + DWC_DEBUGPL(DBG_HCDI, "\n");
39755 +#endif
39756 +
39757 +#ifdef DEBUG
39758 +#ifndef DEBUG_SOF
39759 + if (gintsts.d32 != DWC_SOF_INTR_MASK)
39760 +#endif
39761 + DWC_DEBUGPL(DBG_HCDI,
39762 + "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
39763 + gintsts.d32, core_if);
39764 +#endif
39765 + hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
39766 + if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
39767 + {
39768 + /* Note, we should never get here if the FIQ is doing it's job properly*/
39769 + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
39770 + }
39771 + else if (gintsts.b.sofintr) {
39772 + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
39773 + }
39774 + if (gintsts.b.rxstsqlvl) {
39775 + retval |=
39776 + dwc_otg_hcd_handle_rx_status_q_level_intr
39777 + (dwc_otg_hcd);
39778 + }
39779 + if (gintsts.b.nptxfempty) {
39780 + retval |=
39781 + dwc_otg_hcd_handle_np_tx_fifo_empty_intr
39782 + (dwc_otg_hcd);
39783 + }
39784 + if (gintsts.b.i2cintr) {
39785 + /** @todo Implement i2cintr handler. */
39786 + }
39787 + if (gintsts.b.portintr) {
39788 + retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
39789 + }
39790 + if (gintsts.b.hcintr) {
39791 + retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
39792 + }
39793 + if (gintsts.b.ptxfempty) {
39794 + retval |=
39795 + dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
39796 + (dwc_otg_hcd);
39797 + }
39798 +#ifdef DEBUG
39799 +#ifndef DEBUG_SOF
39800 + if (gintsts.d32 != DWC_SOF_INTR_MASK)
39801 +#endif
39802 + {
39803 + DWC_DEBUGPL(DBG_HCDI,
39804 + "DWC OTG HCD Finished Servicing Interrupts\n");
39805 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
39806 + DWC_READ_REG32(&global_regs->gintsts));
39807 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
39808 + DWC_READ_REG32(&global_regs->gintmsk));
39809 + }
39810 +#endif
39811 +
39812 +#ifdef DEBUG
39813 +#ifndef DEBUG_SOF
39814 + if (gintsts.d32 != DWC_SOF_INTR_MASK)
39815 +#endif
39816 + DWC_DEBUGPL(DBG_HCDI, "\n");
39817 +#endif
39818 +
39819 + }
39820 +
39821 +exit_handler_routine:
39822 +
39823 + if (fiq_fix_enable)
39824 + {
39825 + /* Clear the MPHI interrupt */
39826 + DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
39827 + if (mphi_int_count >= 60)
39828 + {
39829 + DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
39830 + while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
39831 + ;
39832 + DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
39833 + mphi_int_count = 0;
39834 + }
39835 + int_done++;
39836 + if((jiffies / HZ) > last_time)
39837 + {
39838 + /* Once a second output the fiq and irq numbers, useful for debug */
39839 + last_time = jiffies / HZ;
39840 + DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
39841 + }
39842 +
39843 + /* Re-Enable FIQ interrupt from USB peripheral */
39844 + DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
39845 + }
39846 +
39847 + DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39848 + return retval;
39849 +}
39850 +
39851 +#ifdef DWC_TRACK_MISSED_SOFS
39852 +
39853 +#warning Compiling code to track missed SOFs
39854 +#define FRAME_NUM_ARRAY_SIZE 1000
39855 +/**
39856 + * This function is for debug only.
39857 + */
39858 +static inline void track_missed_sofs(uint16_t curr_frame_number)
39859 +{
39860 + static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
39861 + static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
39862 + static int frame_num_idx = 0;
39863 + static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
39864 + static int dumped_frame_num_array = 0;
39865 +
39866 + if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
39867 + if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
39868 + curr_frame_number) {
39869 + frame_num_array[frame_num_idx] = curr_frame_number;
39870 + last_frame_num_array[frame_num_idx++] = last_frame_num;
39871 + }
39872 + } else if (!dumped_frame_num_array) {
39873 + int i;
39874 + DWC_PRINTF("Frame Last Frame\n");
39875 + DWC_PRINTF("----- ----------\n");
39876 + for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
39877 + DWC_PRINTF("0x%04x 0x%04x\n",
39878 + frame_num_array[i], last_frame_num_array[i]);
39879 + }
39880 + dumped_frame_num_array = 1;
39881 + }
39882 + last_frame_num = curr_frame_number;
39883 +}
39884 +#endif
39885 +
39886 +/**
39887 + * Handles the start-of-frame interrupt in host mode. Non-periodic
39888 + * transactions may be queued to the DWC_otg controller for the current
39889 + * (micro)frame. Periodic transactions may be queued to the controller for the
39890 + * next (micro)frame.
39891 + */
39892 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected)
39893 +{
39894 + hfnum_data_t hfnum;
39895 + dwc_list_link_t *qh_entry;
39896 + dwc_otg_qh_t *qh;
39897 + dwc_otg_transaction_type_e tr_type;
39898 + gintsts_data_t gintsts = {.d32 = 0 };
39899 + int did_something = 0;
39900 + int32_t next_sched_frame = -1;
39901 +
39902 + hfnum.d32 =
39903 + DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
39904 +
39905 +#ifdef DEBUG_SOF
39906 + DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
39907 +#endif
39908 + hcd->frame_number = hfnum.b.frnum;
39909 +
39910 +#ifdef DEBUG
39911 + hcd->frrem_accum += hfnum.b.frrem;
39912 + hcd->frrem_samples++;
39913 +#endif
39914 +
39915 +#ifdef DWC_TRACK_MISSED_SOFS
39916 + track_missed_sofs(hcd->frame_number);
39917 +#endif
39918 + /* Determine whether any periodic QHs should be executed. */
39919 + qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
39920 + while (qh_entry != &hcd->periodic_sched_inactive) {
39921 + qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
39922 + qh_entry = qh_entry->next;
39923 + if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
39924 + /*
39925 + * Move QH to the ready list to be executed next
39926 + * (micro)frame.
39927 + */
39928 + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
39929 + &qh->qh_list_entry);
39930 +
39931 + did_something = 1;
39932 + }
39933 + else
39934 + {
39935 + if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
39936 + {
39937 + next_sched_frame = qh->sched_frame;
39938 + }
39939 + }
39940 + }
39941 +
39942 + g_next_sched_frame = next_sched_frame;
39943 +
39944 + tr_type = dwc_otg_hcd_select_transactions(hcd);
39945 + if (tr_type != DWC_OTG_TRANSACTION_NONE) {
39946 + dwc_otg_hcd_queue_transactions(hcd, tr_type);
39947 + did_something = 1;
39948 + }
39949 + if(work_expected && !did_something)
39950 + DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
39951 + if(!work_expected && did_something)
39952 + DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
39953 +
39954 +
39955 + /* Clear interrupt */
39956 + gintsts.b.sofintr = 1;
39957 + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
39958 +
39959 + return 1;
39960 +}
39961 +
39962 +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
39963 + * least one packet in the Rx FIFO. The packets are moved from the FIFO to
39964 + * memory if the DWC_otg controller is operating in Slave mode. */
39965 +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39966 +{
39967 + host_grxsts_data_t grxsts;
39968 + dwc_hc_t *hc = NULL;
39969 +
39970 + DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
39971 +
39972 + grxsts.d32 =
39973 + DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
39974 +
39975 + hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
39976 + if (!hc) {
39977 + DWC_ERROR("Unable to get corresponding channel\n");
39978 + return 0;
39979 + }
39980 +
39981 + /* Packet Status */
39982 + DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum);
39983 + DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt);
39984 + DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
39985 + hc->data_pid_start);
39986 + DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts);
39987 +
39988 + switch (grxsts.b.pktsts) {
39989 + case DWC_GRXSTS_PKTSTS_IN:
39990 + /* Read the data into the host buffer. */
39991 + if (grxsts.b.bcnt > 0) {
39992 + dwc_otg_read_packet(dwc_otg_hcd->core_if,
39993 + hc->xfer_buff, grxsts.b.bcnt);
39994 +
39995 + /* Update the HC fields for the next packet received. */
39996 + hc->xfer_count += grxsts.b.bcnt;
39997 + hc->xfer_buff += grxsts.b.bcnt;
39998 + }
39999 +
40000 + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
40001 + case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
40002 + case DWC_GRXSTS_PKTSTS_CH_HALTED:
40003 + /* Handled in interrupt, just ignore data */
40004 + break;
40005 + default:
40006 + DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
40007 + grxsts.b.pktsts);
40008 + break;
40009 + }
40010 +
40011 + return 1;
40012 +}
40013 +
40014 +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
40015 + * data packets may be written to the FIFO for OUT transfers. More requests
40016 + * may be written to the non-periodic request queue for IN transfers. This
40017 + * interrupt is enabled only in Slave mode. */
40018 +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40019 +{
40020 + DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
40021 + dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
40022 + DWC_OTG_TRANSACTION_NON_PERIODIC);
40023 + return 1;
40024 +}
40025 +
40026 +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
40027 + * packets may be written to the FIFO for OUT transfers. More requests may be
40028 + * written to the periodic request queue for IN transfers. This interrupt is
40029 + * enabled only in Slave mode. */
40030 +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40031 +{
40032 + DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
40033 + dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
40034 + DWC_OTG_TRANSACTION_PERIODIC);
40035 + return 1;
40036 +}
40037 +
40038 +/** There are multiple conditions that can cause a port interrupt. This function
40039 + * determines which interrupt conditions have occurred and handles them
40040 + * appropriately. */
40041 +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40042 +{
40043 + int retval = 0;
40044 + hprt0_data_t hprt0;
40045 + hprt0_data_t hprt0_modify;
40046 +
40047 + hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40048 + hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40049 +
40050 + /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
40051 + * GINTSTS */
40052 +
40053 + hprt0_modify.b.prtena = 0;
40054 + hprt0_modify.b.prtconndet = 0;
40055 + hprt0_modify.b.prtenchng = 0;
40056 + hprt0_modify.b.prtovrcurrchng = 0;
40057 +
40058 + /* Port Connect Detected
40059 + * Set flag and clear if detected */
40060 + if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
40061 + // Dont modify port status if we are in hibernation state
40062 + hprt0_modify.b.prtconndet = 1;
40063 + hprt0_modify.b.prtenchng = 1;
40064 + DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40065 + hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40066 + return retval;
40067 + }
40068 +
40069 + if (hprt0.b.prtconndet) {
40070 + /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
40071 + if (dwc_otg_hcd->core_if->adp_enable &&
40072 + dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
40073 + DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
40074 + DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
40075 + dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40076 + /* TODO - check if this is required, as
40077 + * host initialization was already performed
40078 + * after initial ADP probing
40079 + */
40080 + /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40081 + dwc_otg_core_init(dwc_otg_hcd->core_if);
40082 + dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
40083 + cil_hcd_start(dwc_otg_hcd->core_if);*/
40084 + } else {
40085 +
40086 + DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
40087 + "Port Connect Detected--\n", hprt0.d32);
40088 + dwc_otg_hcd->flags.b.port_connect_status_change = 1;
40089 + dwc_otg_hcd->flags.b.port_connect_status = 1;
40090 + hprt0_modify.b.prtconndet = 1;
40091 +
40092 + /* B-Device has connected, Delete the connection timer. */
40093 + DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
40094 + }
40095 + /* The Hub driver asserts a reset when it sees port connect
40096 + * status change flag */
40097 + retval |= 1;
40098 + }
40099 +
40100 + /* Port Enable Changed
40101 + * Clear if detected - Set internal flag if disabled */
40102 + if (hprt0.b.prtenchng) {
40103 + DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
40104 + "Port Enable Changed--\n", hprt0.d32);
40105 + hprt0_modify.b.prtenchng = 1;
40106 + if (hprt0.b.prtena == 1) {
40107 + hfir_data_t hfir;
40108 + int do_reset = 0;
40109 + dwc_otg_core_params_t *params =
40110 + dwc_otg_hcd->core_if->core_params;
40111 + dwc_otg_core_global_regs_t *global_regs =
40112 + dwc_otg_hcd->core_if->core_global_regs;
40113 + dwc_otg_host_if_t *host_if =
40114 + dwc_otg_hcd->core_if->host_if;
40115 +
40116 + /* Every time when port enables calculate
40117 + * HFIR.FrInterval
40118 + */
40119 + hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
40120 + hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
40121 + DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
40122 +
40123 + /* Check if we need to adjust the PHY clock speed for
40124 + * low power and adjust it */
40125 + if (params->host_support_fs_ls_low_power) {
40126 + gusbcfg_data_t usbcfg;
40127 +
40128 + usbcfg.d32 =
40129 + DWC_READ_REG32(&global_regs->gusbcfg);
40130 +
40131 + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
40132 + || hprt0.b.prtspd ==
40133 + DWC_HPRT0_PRTSPD_FULL_SPEED) {
40134 + /*
40135 + * Low power
40136 + */
40137 + hcfg_data_t hcfg;
40138 + if (usbcfg.b.phylpwrclksel == 0) {
40139 + /* Set PHY low power clock select for FS/LS devices */
40140 + usbcfg.b.phylpwrclksel = 1;
40141 + DWC_WRITE_REG32
40142 + (&global_regs->gusbcfg,
40143 + usbcfg.d32);
40144 + do_reset = 1;
40145 + }
40146 +
40147 + hcfg.d32 =
40148 + DWC_READ_REG32
40149 + (&host_if->host_global_regs->hcfg);
40150 +
40151 + if (hprt0.b.prtspd ==
40152 + DWC_HPRT0_PRTSPD_LOW_SPEED
40153 + && params->host_ls_low_power_phy_clk
40154 + ==
40155 + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
40156 + {
40157 + /* 6 MHZ */
40158 + DWC_DEBUGPL(DBG_CIL,
40159 + "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
40160 + if (hcfg.b.fslspclksel !=
40161 + DWC_HCFG_6_MHZ) {
40162 + hcfg.b.fslspclksel =
40163 + DWC_HCFG_6_MHZ;
40164 + DWC_WRITE_REG32
40165 + (&host_if->host_global_regs->hcfg,
40166 + hcfg.d32);
40167 + do_reset = 1;
40168 + }
40169 + } else {
40170 + /* 48 MHZ */
40171 + DWC_DEBUGPL(DBG_CIL,
40172 + "FS_PHY programming HCFG to 48 MHz ()\n");
40173 + if (hcfg.b.fslspclksel !=
40174 + DWC_HCFG_48_MHZ) {
40175 + hcfg.b.fslspclksel =
40176 + DWC_HCFG_48_MHZ;
40177 + DWC_WRITE_REG32
40178 + (&host_if->host_global_regs->hcfg,
40179 + hcfg.d32);
40180 + do_reset = 1;
40181 + }
40182 + }
40183 + } else {
40184 + /*
40185 + * Not low power
40186 + */
40187 + if (usbcfg.b.phylpwrclksel == 1) {
40188 + usbcfg.b.phylpwrclksel = 0;
40189 + DWC_WRITE_REG32
40190 + (&global_regs->gusbcfg,
40191 + usbcfg.d32);
40192 + do_reset = 1;
40193 + }
40194 + }
40195 +
40196 + if (do_reset) {
40197 + DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
40198 + }
40199 + }
40200 +
40201 + if (!do_reset) {
40202 + /* Port has been enabled set the reset change flag */
40203 + dwc_otg_hcd->flags.b.port_reset_change = 1;
40204 + }
40205 + } else {
40206 + dwc_otg_hcd->flags.b.port_enable_change = 1;
40207 + }
40208 + retval |= 1;
40209 + }
40210 +
40211 + /** Overcurrent Change Interrupt */
40212 + if (hprt0.b.prtovrcurrchng) {
40213 + DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
40214 + "Port Overcurrent Changed--\n", hprt0.d32);
40215 + dwc_otg_hcd->flags.b.port_over_current_change = 1;
40216 + hprt0_modify.b.prtovrcurrchng = 1;
40217 + retval |= 1;
40218 + }
40219 +
40220 + /* Clear Port Interrupts */
40221 + DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40222 +
40223 + return retval;
40224 +}
40225 +
40226 +/** This interrupt indicates that one or more host channels has a pending
40227 + * interrupt. There are multiple conditions that can cause each host channel
40228 + * interrupt. This function determines which conditions have occurred for each
40229 + * host channel interrupt and handles them appropriately. */
40230 +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40231 +{
40232 + int i;
40233 + int retval = 0;
40234 + haint_data_t haint;
40235 +
40236 + /* Clear appropriate bits in HCINTn to clear the interrupt bit in
40237 + * GINTSTS */
40238 +
40239 + haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
40240 +
40241 + for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
40242 + if (haint.b2.chint & (1 << i)) {
40243 + retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
40244 + }
40245 + }
40246 +
40247 + return retval;
40248 +}
40249 +
40250 +/**
40251 + * Gets the actual length of a transfer after the transfer halts. _halt_status
40252 + * holds the reason for the halt.
40253 + *
40254 + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
40255 + * *short_read is set to 1 upon return if less than the requested
40256 + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
40257 + * return. short_read may also be NULL on entry, in which case it remains
40258 + * unchanged.
40259 + */
40260 +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
40261 + dwc_otg_hc_regs_t * hc_regs,
40262 + dwc_otg_qtd_t * qtd,
40263 + dwc_otg_halt_status_e halt_status,
40264 + int *short_read)
40265 +{
40266 + hctsiz_data_t hctsiz;
40267 + uint32_t length;
40268 +
40269 + if (short_read != NULL) {
40270 + *short_read = 0;
40271 + }
40272 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40273 +
40274 + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
40275 + if (hc->ep_is_in) {
40276 + length = hc->xfer_len - hctsiz.b.xfersize;
40277 + if (short_read != NULL) {
40278 + *short_read = (hctsiz.b.xfersize != 0);
40279 + }
40280 + } else if (hc->qh->do_split) {
40281 + length = qtd->ssplit_out_xfer_count;
40282 + } else {
40283 + length = hc->xfer_len;
40284 + }
40285 + } else {
40286 + /*
40287 + * Must use the hctsiz.pktcnt field to determine how much data
40288 + * has been transferred. This field reflects the number of
40289 + * packets that have been transferred via the USB. This is
40290 + * always an integral number of packets if the transfer was
40291 + * halted before its normal completion. (Can't use the
40292 + * hctsiz.xfersize field because that reflects the number of
40293 + * bytes transferred via the AHB, not the USB).
40294 + */
40295 + length =
40296 + (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
40297 + }
40298 +
40299 + return length;
40300 +}
40301 +
40302 +/**
40303 + * Updates the state of the URB after a Transfer Complete interrupt on the
40304 + * host channel. Updates the actual_length field of the URB based on the
40305 + * number of bytes transferred via the host channel. Sets the URB status
40306 + * if the data transfer is finished.
40307 + *
40308 + * @return 1 if the data transfer specified by the URB is completely finished,
40309 + * 0 otherwise.
40310 + */
40311 +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
40312 + dwc_otg_hc_regs_t * hc_regs,
40313 + dwc_otg_hcd_urb_t * urb,
40314 + dwc_otg_qtd_t * qtd)
40315 +{
40316 + int xfer_done = 0;
40317 + int short_read = 0;
40318 +
40319 + int xfer_length;
40320 +
40321 + xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
40322 + DWC_OTG_HC_XFER_COMPLETE,
40323 + &short_read);
40324 +
40325 +
40326 + /* non DWORD-aligned buffer case handling. */
40327 + if (hc->align_buff && xfer_length && hc->ep_is_in) {
40328 + dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40329 + xfer_length);
40330 + }
40331 +
40332 + urb->actual_length += xfer_length;
40333 +
40334 + if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
40335 + (urb->flags & URB_SEND_ZERO_PACKET)
40336 + && (urb->actual_length == urb->length)
40337 + && !(urb->length % hc->max_packet)) {
40338 + xfer_done = 0;
40339 + } else if (short_read || urb->actual_length >= urb->length) {
40340 + xfer_done = 1;
40341 + urb->status = 0;
40342 + }
40343 +
40344 +#ifdef DEBUG
40345 + {
40346 + hctsiz_data_t hctsiz;
40347 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40348 + DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40349 + __func__, (hc->ep_is_in ? "IN" : "OUT"),
40350 + hc->hc_num);
40351 + DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len);
40352 + DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n",
40353 + hctsiz.b.xfersize);
40354 + DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
40355 + urb->length);
40356 + DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
40357 + urb->actual_length);
40358 + DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n",
40359 + short_read, xfer_done);
40360 + }
40361 +#endif
40362 +
40363 + return xfer_done;
40364 +}
40365 +
40366 +/*
40367 + * Save the starting data toggle for the next transfer. The data toggle is
40368 + * saved in the QH for non-control transfers and it's saved in the QTD for
40369 + * control transfers.
40370 + */
40371 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
40372 + dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
40373 +{
40374 + hctsiz_data_t hctsiz;
40375 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40376 +
40377 + if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
40378 + dwc_otg_qh_t *qh = hc->qh;
40379 + if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40380 + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
40381 + } else {
40382 + qh->data_toggle = DWC_OTG_HC_PID_DATA1;
40383 + }
40384 + } else {
40385 + if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40386 + qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
40387 + } else {
40388 + qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
40389 + }
40390 + }
40391 +}
40392 +
40393 +/**
40394 + * Updates the state of an Isochronous URB when the transfer is stopped for
40395 + * any reason. The fields of the current entry in the frame descriptor array
40396 + * are set based on the transfer state and the input _halt_status. Completes
40397 + * the Isochronous URB if all the URB frames have been completed.
40398 + *
40399 + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
40400 + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
40401 + */
40402 +static dwc_otg_halt_status_e
40403 +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
40404 + dwc_hc_t * hc,
40405 + dwc_otg_hc_regs_t * hc_regs,
40406 + dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40407 +{
40408 + dwc_otg_hcd_urb_t *urb = qtd->urb;
40409 + dwc_otg_halt_status_e ret_val = halt_status;
40410 + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40411 +
40412 + frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
40413 + switch (halt_status) {
40414 + case DWC_OTG_HC_XFER_COMPLETE:
40415 + frame_desc->status = 0;
40416 + frame_desc->actual_length =
40417 + get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40418 +
40419 + /* non DWORD-aligned buffer case handling. */
40420 + if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40421 + dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40422 + hc->qh->dw_align_buf, frame_desc->actual_length);
40423 + }
40424 +
40425 + break;
40426 + case DWC_OTG_HC_XFER_FRAME_OVERRUN:
40427 + urb->error_count++;
40428 + if (hc->ep_is_in) {
40429 + frame_desc->status = -DWC_E_NO_STREAM_RES;
40430 + } else {
40431 + frame_desc->status = -DWC_E_COMMUNICATION;
40432 + }
40433 + frame_desc->actual_length = 0;
40434 + break;
40435 + case DWC_OTG_HC_XFER_BABBLE_ERR:
40436 + urb->error_count++;
40437 + frame_desc->status = -DWC_E_OVERFLOW;
40438 + /* Don't need to update actual_length in this case. */
40439 + break;
40440 + case DWC_OTG_HC_XFER_XACT_ERR:
40441 + urb->error_count++;
40442 + frame_desc->status = -DWC_E_PROTOCOL;
40443 + frame_desc->actual_length =
40444 + get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40445 +
40446 + /* non DWORD-aligned buffer case handling. */
40447 + if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40448 + dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40449 + hc->qh->dw_align_buf, frame_desc->actual_length);
40450 + }
40451 + /* Skip whole frame */
40452 + if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
40453 + hc->ep_is_in && hcd->core_if->dma_enable) {
40454 + qtd->complete_split = 0;
40455 + qtd->isoc_split_offset = 0;
40456 + }
40457 +
40458 + break;
40459 + default:
40460 + DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
40461 + break;
40462 + }
40463 + if (++qtd->isoc_frame_index == urb->packet_count) {
40464 + /*
40465 + * urb->status is not used for isoc transfers.
40466 + * The individual frame_desc statuses are used instead.
40467 + */
40468 + hcd->fops->complete(hcd, urb->priv, urb, 0);
40469 + ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
40470 + } else {
40471 + ret_val = DWC_OTG_HC_XFER_COMPLETE;
40472 + }
40473 + return ret_val;
40474 +}
40475 +
40476 +/**
40477 + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
40478 + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
40479 + * still linked to the QH, the QH is added to the end of the inactive
40480 + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
40481 + * schedule if no more QTDs are linked to the QH.
40482 + */
40483 +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
40484 +{
40485 + int continue_split = 0;
40486 + dwc_otg_qtd_t *qtd;
40487 +
40488 + DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
40489 +
40490 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
40491 +
40492 + if (qtd->complete_split) {
40493 + continue_split = 1;
40494 + } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
40495 + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
40496 + continue_split = 1;
40497 + }
40498 +
40499 + if (free_qtd) {
40500 + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
40501 + continue_split = 0;
40502 + }
40503 +
40504 + qh->channel = NULL;
40505 + dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
40506 +}
40507 +
40508 +/**
40509 + * Releases a host channel for use by other transfers. Attempts to select and
40510 + * queue more transactions since at least one host channel is available.
40511 + *
40512 + * @param hcd The HCD state structure.
40513 + * @param hc The host channel to release.
40514 + * @param qtd The QTD associated with the host channel. This QTD may be freed
40515 + * if the transfer is complete or an error has occurred.
40516 + * @param halt_status Reason the channel is being released. This status
40517 + * determines the actions taken by this function.
40518 + */
40519 +static void release_channel(dwc_otg_hcd_t * hcd,
40520 + dwc_hc_t * hc,
40521 + dwc_otg_qtd_t * qtd,
40522 + dwc_otg_halt_status_e halt_status)
40523 +{
40524 + dwc_otg_transaction_type_e tr_type;
40525 + int free_qtd;
40526 + dwc_irqflags_t flags;
40527 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
40528 +
40529 + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
40530 + __func__, hc->hc_num, halt_status, hc->xfer_len);
40531 +
40532 + switch (halt_status) {
40533 + case DWC_OTG_HC_XFER_URB_COMPLETE:
40534 + free_qtd = 1;
40535 + break;
40536 + case DWC_OTG_HC_XFER_AHB_ERR:
40537 + case DWC_OTG_HC_XFER_STALL:
40538 + case DWC_OTG_HC_XFER_BABBLE_ERR:
40539 + free_qtd = 1;
40540 + break;
40541 + case DWC_OTG_HC_XFER_XACT_ERR:
40542 + if (qtd->error_count >= 3) {
40543 + DWC_DEBUGPL(DBG_HCDV,
40544 + " Complete URB with transaction error\n");
40545 + free_qtd = 1;
40546 + qtd->urb->status = -DWC_E_PROTOCOL;
40547 + hcd->fops->complete(hcd, qtd->urb->priv,
40548 + qtd->urb, -DWC_E_PROTOCOL);
40549 + } else {
40550 + free_qtd = 0;
40551 + }
40552 + break;
40553 + case DWC_OTG_HC_XFER_URB_DEQUEUE:
40554 + /*
40555 + * The QTD has already been removed and the QH has been
40556 + * deactivated. Don't want to do anything except release the
40557 + * host channel and try to queue more transfers.
40558 + */
40559 + goto cleanup;
40560 + case DWC_OTG_HC_XFER_NO_HALT_STATUS:
40561 + free_qtd = 0;
40562 + break;
40563 + case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
40564 + DWC_DEBUGPL(DBG_HCDV,
40565 + " Complete URB with I/O error\n");
40566 + free_qtd = 1;
40567 + qtd->urb->status = -DWC_E_IO;
40568 + hcd->fops->complete(hcd, qtd->urb->priv,
40569 + qtd->urb, -DWC_E_IO);
40570 + break;
40571 + default:
40572 + free_qtd = 0;
40573 + break;
40574 + }
40575 +
40576 + deactivate_qh(hcd, hc->qh, free_qtd);
40577 +
40578 +cleanup:
40579 + /*
40580 + * Release the host channel for use by other transfers. The cleanup
40581 + * function clears the channel interrupt enables and conditions, so
40582 + * there's no need to clear the Channel Halted interrupt separately.
40583 + */
40584 + dwc_otg_hc_cleanup(hcd->core_if, hc);
40585 + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
40586 +
40587 + if (!microframe_schedule) {
40588 + switch (hc->ep_type) {
40589 + case DWC_OTG_EP_TYPE_CONTROL:
40590 + case DWC_OTG_EP_TYPE_BULK:
40591 + hcd->non_periodic_channels--;
40592 + break;
40593 +
40594 + default:
40595 + /*
40596 + * Don't release reservations for periodic channels here.
40597 + * That's done when a periodic transfer is descheduled (i.e.
40598 + * when the QH is removed from the periodic schedule).
40599 + */
40600 + break;
40601 + }
40602 + } else {
40603 +
40604 + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
40605 + hcd->available_host_channels++;
40606 + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
40607 + }
40608 +
40609 + /* Try to queue more transfers now that there's a free channel. */
40610 + tr_type = dwc_otg_hcd_select_transactions(hcd);
40611 + if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40612 + dwc_otg_hcd_queue_transactions(hcd, tr_type);
40613 + }
40614 +}
40615 +
40616 +/**
40617 + * Halts a host channel. If the channel cannot be halted immediately because
40618 + * the request queue is full, this function ensures that the FIFO empty
40619 + * interrupt for the appropriate queue is enabled so that the halt request can
40620 + * be queued when there is space in the request queue.
40621 + *
40622 + * This function may also be called in DMA mode. In that case, the channel is
40623 + * simply released since the core always halts the channel automatically in
40624 + * DMA mode.
40625 + */
40626 +static void halt_channel(dwc_otg_hcd_t * hcd,
40627 + dwc_hc_t * hc,
40628 + dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40629 +{
40630 + if (hcd->core_if->dma_enable) {
40631 + release_channel(hcd, hc, qtd, halt_status);
40632 + return;
40633 + }
40634 +
40635 + /* Slave mode processing... */
40636 + dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
40637 +
40638 + if (hc->halt_on_queue) {
40639 + gintmsk_data_t gintmsk = {.d32 = 0 };
40640 + dwc_otg_core_global_regs_t *global_regs;
40641 + global_regs = hcd->core_if->core_global_regs;
40642 +
40643 + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
40644 + hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
40645 + /*
40646 + * Make sure the Non-periodic Tx FIFO empty interrupt
40647 + * is enabled so that the non-periodic schedule will
40648 + * be processed.
40649 + */
40650 + gintmsk.b.nptxfempty = 1;
40651 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40652 + } else {
40653 + /*
40654 + * Move the QH from the periodic queued schedule to
40655 + * the periodic assigned schedule. This allows the
40656 + * halt to be queued when the periodic schedule is
40657 + * processed.
40658 + */
40659 + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
40660 + &hc->qh->qh_list_entry);
40661 +
40662 + /*
40663 + * Make sure the Periodic Tx FIFO Empty interrupt is
40664 + * enabled so that the periodic schedule will be
40665 + * processed.
40666 + */
40667 + gintmsk.b.ptxfempty = 1;
40668 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40669 + }
40670 + }
40671 +}
40672 +
40673 +/**
40674 + * Performs common cleanup for non-periodic transfers after a Transfer
40675 + * Complete interrupt. This function should be called after any endpoint type
40676 + * specific handling is finished to release the host channel.
40677 + */
40678 +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
40679 + dwc_hc_t * hc,
40680 + dwc_otg_hc_regs_t * hc_regs,
40681 + dwc_otg_qtd_t * qtd,
40682 + dwc_otg_halt_status_e halt_status)
40683 +{
40684 + hcint_data_t hcint;
40685 +
40686 + qtd->error_count = 0;
40687 +
40688 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
40689 + if (hcint.b.nyet) {
40690 + /*
40691 + * Got a NYET on the last transaction of the transfer. This
40692 + * means that the endpoint should be in the PING state at the
40693 + * beginning of the next transfer.
40694 + */
40695 + hc->qh->ping_state = 1;
40696 + clear_hc_int(hc_regs, nyet);
40697 + }
40698 +
40699 + /*
40700 + * Always halt and release the host channel to make it available for
40701 + * more transfers. There may still be more phases for a control
40702 + * transfer or more data packets for a bulk transfer at this point,
40703 + * but the host channel is still halted. A channel will be reassigned
40704 + * to the transfer when the non-periodic schedule is processed after
40705 + * the channel is released. This allows transactions to be queued
40706 + * properly via dwc_otg_hcd_queue_transactions, which also enables the
40707 + * Tx FIFO Empty interrupt if necessary.
40708 + */
40709 + if (hc->ep_is_in) {
40710 + /*
40711 + * IN transfers in Slave mode require an explicit disable to
40712 + * halt the channel. (In DMA mode, this call simply releases
40713 + * the channel.)
40714 + */
40715 + halt_channel(hcd, hc, qtd, halt_status);
40716 + } else {
40717 + /*
40718 + * The channel is automatically disabled by the core for OUT
40719 + * transfers in Slave mode.
40720 + */
40721 + release_channel(hcd, hc, qtd, halt_status);
40722 + }
40723 +}
40724 +
40725 +/**
40726 + * Performs common cleanup for periodic transfers after a Transfer Complete
40727 + * interrupt. This function should be called after any endpoint type specific
40728 + * handling is finished to release the host channel.
40729 + */
40730 +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
40731 + dwc_hc_t * hc,
40732 + dwc_otg_hc_regs_t * hc_regs,
40733 + dwc_otg_qtd_t * qtd,
40734 + dwc_otg_halt_status_e halt_status)
40735 +{
40736 + hctsiz_data_t hctsiz;
40737 + qtd->error_count = 0;
40738 +
40739 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40740 + if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
40741 + /* Core halts channel in these cases. */
40742 + release_channel(hcd, hc, qtd, halt_status);
40743 + } else {
40744 + /* Flush any outstanding requests from the Tx queue. */
40745 + halt_channel(hcd, hc, qtd, halt_status);
40746 + }
40747 +}
40748 +
40749 +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
40750 + dwc_hc_t * hc,
40751 + dwc_otg_hc_regs_t * hc_regs,
40752 + dwc_otg_qtd_t * qtd)
40753 +{
40754 + uint32_t len;
40755 + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40756 + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
40757 +
40758 + len = get_actual_xfer_length(hc, hc_regs, qtd,
40759 + DWC_OTG_HC_XFER_COMPLETE, NULL);
40760 +
40761 + if (!len) {
40762 + qtd->complete_split = 0;
40763 + qtd->isoc_split_offset = 0;
40764 + return 0;
40765 + }
40766 + frame_desc->actual_length += len;
40767 +
40768 + if (hc->align_buff && len)
40769 + dwc_memcpy(qtd->urb->buf + frame_desc->offset +
40770 + qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
40771 + qtd->isoc_split_offset += len;
40772 +
40773 + if (frame_desc->length == frame_desc->actual_length) {
40774 + frame_desc->status = 0;
40775 + qtd->isoc_frame_index++;
40776 + qtd->complete_split = 0;
40777 + qtd->isoc_split_offset = 0;
40778 + }
40779 +
40780 + if (qtd->isoc_frame_index == qtd->urb->packet_count) {
40781 + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
40782 + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
40783 + } else {
40784 + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
40785 + }
40786 +
40787 + return 1; /* Indicates that channel released */
40788 +}
40789 +
40790 +/**
40791 + * Handles a host channel Transfer Complete interrupt. This handler may be
40792 + * called in either DMA mode or Slave mode.
40793 + */
40794 +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
40795 + dwc_hc_t * hc,
40796 + dwc_otg_hc_regs_t * hc_regs,
40797 + dwc_otg_qtd_t * qtd)
40798 +{
40799 + int urb_xfer_done;
40800 + dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
40801 + dwc_otg_hcd_urb_t *urb = qtd->urb;
40802 + int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40803 +
40804 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40805 + "Transfer Complete--\n", hc->hc_num);
40806 +
40807 + if (hcd->core_if->dma_desc_enable) {
40808 + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
40809 + if (pipe_type == UE_ISOCHRONOUS) {
40810 + /* Do not disable the interrupt, just clear it */
40811 + clear_hc_int(hc_regs, xfercomp);
40812 + return 1;
40813 + }
40814 + goto handle_xfercomp_done;
40815 + }
40816 +
40817 + /*
40818 + * Handle xfer complete on CSPLIT.
40819 + */
40820 +
40821 + if (hc->qh->do_split) {
40822 + if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
40823 + && hcd->core_if->dma_enable) {
40824 + if (qtd->complete_split
40825 + && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
40826 + qtd))
40827 + goto handle_xfercomp_done;
40828 + } else {
40829 + qtd->complete_split = 0;
40830 + }
40831 + }
40832 +
40833 + /* Update the QTD and URB states. */
40834 + switch (pipe_type) {
40835 + case UE_CONTROL:
40836 + switch (qtd->control_phase) {
40837 + case DWC_OTG_CONTROL_SETUP:
40838 + if (urb->length > 0) {
40839 + qtd->control_phase = DWC_OTG_CONTROL_DATA;
40840 + } else {
40841 + qtd->control_phase = DWC_OTG_CONTROL_STATUS;
40842 + }
40843 + DWC_DEBUGPL(DBG_HCDV,
40844 + " Control setup transaction done\n");
40845 + halt_status = DWC_OTG_HC_XFER_COMPLETE;
40846 + break;
40847 + case DWC_OTG_CONTROL_DATA:{
40848 + urb_xfer_done =
40849 + update_urb_state_xfer_comp(hc, hc_regs, urb,
40850 + qtd);
40851 + if (urb_xfer_done) {
40852 + qtd->control_phase =
40853 + DWC_OTG_CONTROL_STATUS;
40854 + DWC_DEBUGPL(DBG_HCDV,
40855 + " Control data transfer done\n");
40856 + } else {
40857 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40858 + }
40859 + halt_status = DWC_OTG_HC_XFER_COMPLETE;
40860 + break;
40861 + }
40862 + case DWC_OTG_CONTROL_STATUS:
40863 + DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n");
40864 + if (urb->status == -DWC_E_IN_PROGRESS) {
40865 + urb->status = 0;
40866 + }
40867 + hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40868 + halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40869 + break;
40870 + }
40871 +
40872 + complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40873 + break;
40874 + case UE_BULK:
40875 + DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n");
40876 + urb_xfer_done =
40877 + update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40878 + if (urb_xfer_done) {
40879 + hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40880 + halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40881 + } else {
40882 + halt_status = DWC_OTG_HC_XFER_COMPLETE;
40883 + }
40884 +
40885 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40886 + complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40887 + break;
40888 + case UE_INTERRUPT:
40889 + DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n");
40890 + urb_xfer_done =
40891 + update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40892 +
40893 + /*
40894 + * Interrupt URB is done on the first transfer complete
40895 + * interrupt.
40896 + */
40897 + if (urb_xfer_done) {
40898 + hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40899 + halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40900 + } else {
40901 + halt_status = DWC_OTG_HC_XFER_COMPLETE;
40902 + }
40903 +
40904 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40905 + complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40906 + break;
40907 + case UE_ISOCHRONOUS:
40908 + DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n");
40909 + if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
40910 + halt_status =
40911 + update_isoc_urb_state(hcd, hc, hc_regs, qtd,
40912 + DWC_OTG_HC_XFER_COMPLETE);
40913 + }
40914 + complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40915 + break;
40916 + }
40917 +
40918 +handle_xfercomp_done:
40919 + disable_hc_int(hc_regs, xfercompl);
40920 +
40921 + return 1;
40922 +}
40923 +
40924 +/**
40925 + * Handles a host channel STALL interrupt. This handler may be called in
40926 + * either DMA mode or Slave mode.
40927 + */
40928 +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
40929 + dwc_hc_t * hc,
40930 + dwc_otg_hc_regs_t * hc_regs,
40931 + dwc_otg_qtd_t * qtd)
40932 +{
40933 + dwc_otg_hcd_urb_t *urb = qtd->urb;
40934 + int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40935 +
40936 + DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
40937 + "STALL Received--\n", hc->hc_num);
40938 +
40939 + if (hcd->core_if->dma_desc_enable) {
40940 + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
40941 + goto handle_stall_done;
40942 + }
40943 +
40944 + if (pipe_type == UE_CONTROL) {
40945 + hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
40946 + }
40947 +
40948 + if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
40949 + hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
40950 + /*
40951 + * USB protocol requires resetting the data toggle for bulk
40952 + * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
40953 + * setup command is issued to the endpoint. Anticipate the
40954 + * CLEAR_FEATURE command since a STALL has occurred and reset
40955 + * the data toggle now.
40956 + */
40957 + hc->qh->data_toggle = 0;
40958 + }
40959 +
40960 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
40961 +
40962 +handle_stall_done:
40963 + disable_hc_int(hc_regs, stall);
40964 +
40965 + return 1;
40966 +}
40967 +
40968 +/*
40969 + * Updates the state of the URB when a transfer has been stopped due to an
40970 + * abnormal condition before the transfer completes. Modifies the
40971 + * actual_length field of the URB to reflect the number of bytes that have
40972 + * actually been transferred via the host channel.
40973 + */
40974 +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
40975 + dwc_otg_hc_regs_t * hc_regs,
40976 + dwc_otg_hcd_urb_t * urb,
40977 + dwc_otg_qtd_t * qtd,
40978 + dwc_otg_halt_status_e halt_status)
40979 +{
40980 + uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
40981 + halt_status, NULL);
40982 + /* non DWORD-aligned buffer case handling. */
40983 + if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
40984 + dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40985 + bytes_transferred);
40986 + }
40987 +
40988 + urb->actual_length += bytes_transferred;
40989 +
40990 +#ifdef DEBUG
40991 + {
40992 + hctsiz_data_t hctsiz;
40993 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40994 + DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40995 + __func__, (hc->ep_is_in ? "IN" : "OUT"),
40996 + hc->hc_num);
40997 + DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n",
40998 + hc->start_pkt_count);
40999 + DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
41000 + DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet);
41001 + DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n",
41002 + bytes_transferred);
41003 + DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
41004 + urb->actual_length);
41005 + DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
41006 + urb->length);
41007 + }
41008 +#endif
41009 +}
41010 +
41011 +/**
41012 + * Handles a host channel NAK interrupt. This handler may be called in either
41013 + * DMA mode or Slave mode.
41014 + */
41015 +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
41016 + dwc_hc_t * hc,
41017 + dwc_otg_hc_regs_t * hc_regs,
41018 + dwc_otg_qtd_t * qtd)
41019 +{
41020 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41021 + "NAK Received--\n", hc->hc_num);
41022 +
41023 + /*
41024 + * When we get bulk NAKs then remember this so we holdoff on this qh until
41025 + * the beginning of the next frame
41026 + */
41027 + switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41028 + case UE_BULK:
41029 + //case UE_INTERRUPT:
41030 + //case UE_CONTROL:
41031 + if (nak_holdoff_enable)
41032 + hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
41033 + }
41034 +
41035 + /*
41036 + * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
41037 + * interrupt. Re-start the SSPLIT transfer.
41038 + */
41039 + if (hc->do_split) {
41040 + if (hc->complete_split) {
41041 + qtd->error_count = 0;
41042 + }
41043 + qtd->complete_split = 0;
41044 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41045 + goto handle_nak_done;
41046 + }
41047 +
41048 + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41049 + case UE_CONTROL:
41050 + case UE_BULK:
41051 + if (hcd->core_if->dma_enable && hc->ep_is_in) {
41052 + /*
41053 + * NAK interrupts are enabled on bulk/control IN
41054 + * transfers in DMA mode for the sole purpose of
41055 + * resetting the error count after a transaction error
41056 + * occurs. The core will continue transferring data.
41057 + */
41058 + qtd->error_count = 0;
41059 + goto handle_nak_done;
41060 + }
41061 +
41062 + /*
41063 + * NAK interrupts normally occur during OUT transfers in DMA
41064 + * or Slave mode. For IN transfers, more requests will be
41065 + * queued as request queue space is available.
41066 + */
41067 + qtd->error_count = 0;
41068 +
41069 + if (!hc->qh->ping_state) {
41070 + update_urb_state_xfer_intr(hc, hc_regs,
41071 + qtd->urb, qtd,
41072 + DWC_OTG_HC_XFER_NAK);
41073 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41074 +
41075 + if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
41076 + hc->qh->ping_state = 1;
41077 + }
41078 +
41079 + /*
41080 + * Halt the channel so the transfer can be re-started from
41081 + * the appropriate point or the PING protocol will
41082 + * start/continue.
41083 + */
41084 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41085 + break;
41086 + case UE_INTERRUPT:
41087 + qtd->error_count = 0;
41088 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41089 + break;
41090 + case UE_ISOCHRONOUS:
41091 + /* Should never get called for isochronous transfers. */
41092 + DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
41093 + break;
41094 + }
41095 +
41096 +handle_nak_done:
41097 + disable_hc_int(hc_regs, nak);
41098 +
41099 + return 1;
41100 +}
41101 +
41102 +/**
41103 + * Handles a host channel ACK interrupt. This interrupt is enabled when
41104 + * performing the PING protocol in Slave mode, when errors occur during
41105 + * either Slave mode or DMA mode, and during Start Split transactions.
41106 + */
41107 +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
41108 + dwc_hc_t * hc,
41109 + dwc_otg_hc_regs_t * hc_regs,
41110 + dwc_otg_qtd_t * qtd)
41111 +{
41112 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41113 + "ACK Received--\n", hc->hc_num);
41114 +
41115 + if (hc->do_split) {
41116 + /*
41117 + * Handle ACK on SSPLIT.
41118 + * ACK should not occur in CSPLIT.
41119 + */
41120 + if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
41121 + qtd->ssplit_out_xfer_count = hc->xfer_len;
41122 + }
41123 + if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
41124 + /* Don't need complete for isochronous out transfers. */
41125 + qtd->complete_split = 1;
41126 + }
41127 +
41128 + /* ISOC OUT */
41129 + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41130 + switch (hc->xact_pos) {
41131 + case DWC_HCSPLIT_XACTPOS_ALL:
41132 + break;
41133 + case DWC_HCSPLIT_XACTPOS_END:
41134 + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
41135 + qtd->isoc_split_offset = 0;
41136 + break;
41137 + case DWC_HCSPLIT_XACTPOS_BEGIN:
41138 + case DWC_HCSPLIT_XACTPOS_MID:
41139 + /*
41140 + * For BEGIN or MID, calculate the length for
41141 + * the next microframe to determine the correct
41142 + * SSPLIT token, either MID or END.
41143 + */
41144 + {
41145 + struct dwc_otg_hcd_iso_packet_desc
41146 + *frame_desc;
41147 +
41148 + frame_desc =
41149 + &qtd->urb->
41150 + iso_descs[qtd->isoc_frame_index];
41151 + qtd->isoc_split_offset += 188;
41152 +
41153 + if ((frame_desc->length -
41154 + qtd->isoc_split_offset) <= 188) {
41155 + qtd->isoc_split_pos =
41156 + DWC_HCSPLIT_XACTPOS_END;
41157 + } else {
41158 + qtd->isoc_split_pos =
41159 + DWC_HCSPLIT_XACTPOS_MID;
41160 + }
41161 +
41162 + }
41163 + break;
41164 + }
41165 + } else {
41166 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41167 + }
41168 + } else {
41169 + qtd->error_count = 0;
41170 +
41171 + if (hc->qh->ping_state) {
41172 + hc->qh->ping_state = 0;
41173 + /*
41174 + * Halt the channel so the transfer can be re-started
41175 + * from the appropriate point. This only happens in
41176 + * Slave mode. In DMA mode, the ping_state is cleared
41177 + * when the transfer is started because the core
41178 + * automatically executes the PING, then the transfer.
41179 + */
41180 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41181 + }
41182 + }
41183 +
41184 + /*
41185 + * If the ACK occurred when _not_ in the PING state, let the channel
41186 + * continue transferring data after clearing the error count.
41187 + */
41188 +
41189 + disable_hc_int(hc_regs, ack);
41190 +
41191 + return 1;
41192 +}
41193 +
41194 +/**
41195 + * Handles a host channel NYET interrupt. This interrupt should only occur on
41196 + * Bulk and Control OUT endpoints and for complete split transactions. If a
41197 + * NYET occurs at the same time as a Transfer Complete interrupt, it is
41198 + * handled in the xfercomp interrupt handler, not here. This handler may be
41199 + * called in either DMA mode or Slave mode.
41200 + */
41201 +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
41202 + dwc_hc_t * hc,
41203 + dwc_otg_hc_regs_t * hc_regs,
41204 + dwc_otg_qtd_t * qtd)
41205 +{
41206 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41207 + "NYET Received--\n", hc->hc_num);
41208 +
41209 + /*
41210 + * NYET on CSPLIT
41211 + * re-do the CSPLIT immediately on non-periodic
41212 + */
41213 + if (hc->do_split && hc->complete_split) {
41214 + if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
41215 + && hcd->core_if->dma_enable) {
41216 + qtd->complete_split = 0;
41217 + qtd->isoc_split_offset = 0;
41218 + if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
41219 + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
41220 + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
41221 + }
41222 + else
41223 + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
41224 + goto handle_nyet_done;
41225 + }
41226 +
41227 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41228 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41229 + int frnum = dwc_otg_hcd_get_frame_number(hcd);
41230 +
41231 + if (dwc_full_frame_num(frnum) !=
41232 + dwc_full_frame_num(hc->qh->sched_frame)) {
41233 + /*
41234 + * No longer in the same full speed frame.
41235 + * Treat this as a transaction error.
41236 + */
41237 +#if 0
41238 + /** @todo Fix system performance so this can
41239 + * be treated as an error. Right now complete
41240 + * splits cannot be scheduled precisely enough
41241 + * due to other system activity, so this error
41242 + * occurs regularly in Slave mode.
41243 + */
41244 + qtd->error_count++;
41245 +#endif
41246 + qtd->complete_split = 0;
41247 + halt_channel(hcd, hc, qtd,
41248 + DWC_OTG_HC_XFER_XACT_ERR);
41249 + /** @todo add support for isoc release */
41250 + goto handle_nyet_done;
41251 + }
41252 + }
41253 +
41254 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41255 + goto handle_nyet_done;
41256 + }
41257 +
41258 + hc->qh->ping_state = 1;
41259 + qtd->error_count = 0;
41260 +
41261 + update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
41262 + DWC_OTG_HC_XFER_NYET);
41263 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41264 +
41265 + /*
41266 + * Halt the channel and re-start the transfer so the PING
41267 + * protocol will start.
41268 + */
41269 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41270 +
41271 +handle_nyet_done:
41272 + disable_hc_int(hc_regs, nyet);
41273 + return 1;
41274 +}
41275 +
41276 +/**
41277 + * Handles a host channel babble interrupt. This handler may be called in
41278 + * either DMA mode or Slave mode.
41279 + */
41280 +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
41281 + dwc_hc_t * hc,
41282 + dwc_otg_hc_regs_t * hc_regs,
41283 + dwc_otg_qtd_t * qtd)
41284 +{
41285 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41286 + "Babble Error--\n", hc->hc_num);
41287 +
41288 + if (hcd->core_if->dma_desc_enable) {
41289 + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41290 + DWC_OTG_HC_XFER_BABBLE_ERR);
41291 + goto handle_babble_done;
41292 + }
41293 +
41294 + if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
41295 + hcd->fops->complete(hcd, qtd->urb->priv,
41296 + qtd->urb, -DWC_E_OVERFLOW);
41297 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
41298 + } else {
41299 + dwc_otg_halt_status_e halt_status;
41300 + halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41301 + DWC_OTG_HC_XFER_BABBLE_ERR);
41302 + halt_channel(hcd, hc, qtd, halt_status);
41303 + }
41304 +
41305 +handle_babble_done:
41306 + disable_hc_int(hc_regs, bblerr);
41307 + return 1;
41308 +}
41309 +
41310 +/**
41311 + * Handles a host channel AHB error interrupt. This handler is only called in
41312 + * DMA mode.
41313 + */
41314 +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
41315 + dwc_hc_t * hc,
41316 + dwc_otg_hc_regs_t * hc_regs,
41317 + dwc_otg_qtd_t * qtd)
41318 +{
41319 + hcchar_data_t hcchar;
41320 + hcsplt_data_t hcsplt;
41321 + hctsiz_data_t hctsiz;
41322 + uint32_t hcdma;
41323 + char *pipetype, *speed;
41324 +
41325 + dwc_otg_hcd_urb_t *urb = qtd->urb;
41326 +
41327 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41328 + "AHB Error--\n", hc->hc_num);
41329 +
41330 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41331 + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41332 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41333 + hcdma = DWC_READ_REG32(&hc_regs->hcdma);
41334 +
41335 + DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
41336 + DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
41337 + DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
41338 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
41339 + DWC_ERROR(" Device address: %d\n",
41340 + dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
41341 + DWC_ERROR(" Endpoint: %d, %s\n",
41342 + dwc_otg_hcd_get_ep_num(&urb->pipe_info),
41343 + (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
41344 +
41345 + switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
41346 + case UE_CONTROL:
41347 + pipetype = "CONTROL";
41348 + break;
41349 + case UE_BULK:
41350 + pipetype = "BULK";
41351 + break;
41352 + case UE_INTERRUPT:
41353 + pipetype = "INTERRUPT";
41354 + break;
41355 + case UE_ISOCHRONOUS:
41356 + pipetype = "ISOCHRONOUS";
41357 + break;
41358 + default:
41359 + pipetype = "UNKNOWN";
41360 + break;
41361 + }
41362 +
41363 + DWC_ERROR(" Endpoint type: %s\n", pipetype);
41364 +
41365 + switch (hc->speed) {
41366 + case DWC_OTG_EP_SPEED_HIGH:
41367 + speed = "HIGH";
41368 + break;
41369 + case DWC_OTG_EP_SPEED_FULL:
41370 + speed = "FULL";
41371 + break;
41372 + case DWC_OTG_EP_SPEED_LOW:
41373 + speed = "LOW";
41374 + break;
41375 + default:
41376 + speed = "UNKNOWN";
41377 + break;
41378 + };
41379 +
41380 + DWC_ERROR(" Speed: %s\n", speed);
41381 +
41382 + DWC_ERROR(" Max packet size: %d\n",
41383 + dwc_otg_hcd_get_mps(&urb->pipe_info));
41384 + DWC_ERROR(" Data buffer length: %d\n", urb->length);
41385 + DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n",
41386 + urb->buf, (void *)urb->dma);
41387 + DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n",
41388 + urb->setup_packet, (void *)urb->setup_dma);
41389 + DWC_ERROR(" Interval: %d\n", urb->interval);
41390 +
41391 + /* Core haltes the channel for Descriptor DMA mode */
41392 + if (hcd->core_if->dma_desc_enable) {
41393 + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41394 + DWC_OTG_HC_XFER_AHB_ERR);
41395 + goto handle_ahberr_done;
41396 + }
41397 +
41398 + hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
41399 +
41400 + /*
41401 + * Force a channel halt. Don't call halt_channel because that won't
41402 + * write to the HCCHARn register in DMA mode to force the halt.
41403 + */
41404 + dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
41405 +handle_ahberr_done:
41406 + disable_hc_int(hc_regs, ahberr);
41407 + return 1;
41408 +}
41409 +
41410 +/**
41411 + * Handles a host channel transaction error interrupt. This handler may be
41412 + * called in either DMA mode or Slave mode.
41413 + */
41414 +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
41415 + dwc_hc_t * hc,
41416 + dwc_otg_hc_regs_t * hc_regs,
41417 + dwc_otg_qtd_t * qtd)
41418 +{
41419 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41420 + "Transaction Error--\n", hc->hc_num);
41421 +
41422 + if (hcd->core_if->dma_desc_enable) {
41423 + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41424 + DWC_OTG_HC_XFER_XACT_ERR);
41425 + goto handle_xacterr_done;
41426 + }
41427 +
41428 + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41429 + case UE_CONTROL:
41430 + case UE_BULK:
41431 + qtd->error_count++;
41432 + if (!hc->qh->ping_state) {
41433 +
41434 + update_urb_state_xfer_intr(hc, hc_regs,
41435 + qtd->urb, qtd,
41436 + DWC_OTG_HC_XFER_XACT_ERR);
41437 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41438 + if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
41439 + hc->qh->ping_state = 1;
41440 + }
41441 + }
41442 +
41443 + /*
41444 + * Halt the channel so the transfer can be re-started from
41445 + * the appropriate point or the PING protocol will start.
41446 + */
41447 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41448 + break;
41449 + case UE_INTERRUPT:
41450 + qtd->error_count++;
41451 + if (hc->do_split && hc->complete_split) {
41452 + qtd->complete_split = 0;
41453 + }
41454 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41455 + break;
41456 + case UE_ISOCHRONOUS:
41457 + {
41458 + dwc_otg_halt_status_e halt_status;
41459 + halt_status =
41460 + update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41461 + DWC_OTG_HC_XFER_XACT_ERR);
41462 +
41463 + halt_channel(hcd, hc, qtd, halt_status);
41464 + }
41465 + break;
41466 + }
41467 +handle_xacterr_done:
41468 + disable_hc_int(hc_regs, xacterr);
41469 +
41470 + return 1;
41471 +}
41472 +
41473 +/**
41474 + * Handles a host channel frame overrun interrupt. This handler may be called
41475 + * in either DMA mode or Slave mode.
41476 + */
41477 +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
41478 + dwc_hc_t * hc,
41479 + dwc_otg_hc_regs_t * hc_regs,
41480 + dwc_otg_qtd_t * qtd)
41481 +{
41482 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41483 + "Frame Overrun--\n", hc->hc_num);
41484 +
41485 + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41486 + case UE_CONTROL:
41487 + case UE_BULK:
41488 + break;
41489 + case UE_INTERRUPT:
41490 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
41491 + break;
41492 + case UE_ISOCHRONOUS:
41493 + {
41494 + dwc_otg_halt_status_e halt_status;
41495 + halt_status =
41496 + update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41497 + DWC_OTG_HC_XFER_FRAME_OVERRUN);
41498 +
41499 + halt_channel(hcd, hc, qtd, halt_status);
41500 + }
41501 + break;
41502 + }
41503 +
41504 + disable_hc_int(hc_regs, frmovrun);
41505 +
41506 + return 1;
41507 +}
41508 +
41509 +/**
41510 + * Handles a host channel data toggle error interrupt. This handler may be
41511 + * called in either DMA mode or Slave mode.
41512 + */
41513 +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
41514 + dwc_hc_t * hc,
41515 + dwc_otg_hc_regs_t * hc_regs,
41516 + dwc_otg_qtd_t * qtd)
41517 +{
41518 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41519 + "Data Toggle Error on %s transfer--\n",
41520 + hc->hc_num, (hc->ep_is_in ? "IN" : "OUT"));
41521 +
41522 + /* Data toggles on split transactions cause the hc to halt.
41523 + * restart transfer */
41524 + if(hc->qh->do_split)
41525 + {
41526 + qtd->error_count++;
41527 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41528 + update_urb_state_xfer_intr(hc, hc_regs,
41529 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41530 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41531 + } else if (hc->ep_is_in) {
41532 + qtd->error_count = 0;
41533 + }
41534 +
41535 + disable_hc_int(hc_regs, datatglerr);
41536 +
41537 + return 1;
41538 +}
41539 +
41540 +#ifdef DEBUG
41541 +/**
41542 + * This function is for debug only. It checks that a valid halt status is set
41543 + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
41544 + * taken and a warning is issued.
41545 + * @return 1 if halt status is ok, 0 otherwise.
41546 + */
41547 +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
41548 + dwc_hc_t * hc,
41549 + dwc_otg_hc_regs_t * hc_regs,
41550 + dwc_otg_qtd_t * qtd)
41551 +{
41552 + hcchar_data_t hcchar;
41553 + hctsiz_data_t hctsiz;
41554 + hcint_data_t hcint;
41555 + hcintmsk_data_t hcintmsk;
41556 + hcsplt_data_t hcsplt;
41557 +
41558 + if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
41559 + /*
41560 + * This code is here only as a check. This condition should
41561 + * never happen. Ignore the halt if it does occur.
41562 + */
41563 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41564 + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41565 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41566 + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41567 + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41568 + DWC_WARN
41569 + ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
41570 + "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
41571 + "hcint 0x%08x, hcintmsk 0x%08x, "
41572 + "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
41573 + hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
41574 + hcintmsk.d32, hcsplt.d32, qtd->complete_split);
41575 +
41576 + DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
41577 + __func__, hc->hc_num);
41578 + DWC_WARN("\n");
41579 + clear_hc_int(hc_regs, chhltd);
41580 + return 0;
41581 + }
41582 +
41583 + /*
41584 + * This code is here only as a check. hcchar.chdis should
41585 + * never be set when the halt interrupt occurs. Halt the
41586 + * channel again if it does occur.
41587 + */
41588 + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41589 + if (hcchar.b.chdis) {
41590 + DWC_WARN("%s: hcchar.chdis set unexpectedly, "
41591 + "hcchar 0x%08x, trying to halt again\n",
41592 + __func__, hcchar.d32);
41593 + clear_hc_int(hc_regs, chhltd);
41594 + hc->halt_pending = 0;
41595 + halt_channel(hcd, hc, qtd, hc->halt_status);
41596 + return 0;
41597 + }
41598 +
41599 + return 1;
41600 +}
41601 +#endif
41602 +
41603 +/**
41604 + * Handles a host Channel Halted interrupt in DMA mode. This handler
41605 + * determines the reason the channel halted and proceeds accordingly.
41606 + */
41607 +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
41608 + dwc_hc_t * hc,
41609 + dwc_otg_hc_regs_t * hc_regs,
41610 + dwc_otg_qtd_t * qtd)
41611 +{
41612 + hcint_data_t hcint;
41613 + hcintmsk_data_t hcintmsk;
41614 + int out_nak_enh = 0;
41615 +
41616 + /* For core with OUT NAK enhancement, the flow for high-
41617 + * speed CONTROL/BULK OUT is handled a little differently.
41618 + */
41619 + if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
41620 + if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
41621 + (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
41622 + hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
41623 + out_nak_enh = 1;
41624 + }
41625 + }
41626 +
41627 + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
41628 + (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
41629 + && !hcd->core_if->dma_desc_enable)) {
41630 + /*
41631 + * Just release the channel. A dequeue can happen on a
41632 + * transfer timeout. In the case of an AHB Error, the channel
41633 + * was forced to halt because there's no way to gracefully
41634 + * recover.
41635 + */
41636 + if (hcd->core_if->dma_desc_enable)
41637 + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41638 + hc->halt_status);
41639 + else
41640 + release_channel(hcd, hc, qtd, hc->halt_status);
41641 + return;
41642 + }
41643 +
41644 + /* Read the HCINTn register to determine the cause for the halt. */
41645 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41646 + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41647 +
41648 + if (hcint.b.xfercomp) {
41649 + /** @todo This is here because of a possible hardware bug. Spec
41650 + * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
41651 + * interrupt w/ACK bit set should occur, but I only see the
41652 + * XFERCOMP bit, even with it masked out. This is a workaround
41653 + * for that behavior. Should fix this when hardware is fixed.
41654 + */
41655 + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41656 + handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41657 + }
41658 + handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
41659 + } else if (hcint.b.stall) {
41660 + handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
41661 + } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
41662 + if (out_nak_enh) {
41663 + if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
41664 + DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
41665 + qtd->error_count = 0;
41666 + } else {
41667 + DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
41668 + }
41669 + }
41670 +
41671 + /*
41672 + * Must handle xacterr before nak or ack. Could get a xacterr
41673 + * at the same time as either of these on a BULK/CONTROL OUT
41674 + * that started with a PING. The xacterr takes precedence.
41675 + */
41676 + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41677 + } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
41678 + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41679 + } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
41680 + handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
41681 + } else if (hcint.b.bblerr) {
41682 + handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
41683 + } else if (hcint.b.frmovrun) {
41684 + handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
41685 + } else if (hcint.b.datatglerr) {
41686 + handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
41687 + } else if (!out_nak_enh) {
41688 + if (hcint.b.nyet) {
41689 + /*
41690 + * Must handle nyet before nak or ack. Could get a nyet at the
41691 + * same time as either of those on a BULK/CONTROL OUT that
41692 + * started with a PING. The nyet takes precedence.
41693 + */
41694 + handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
41695 + } else if (hcint.b.nak && !hcintmsk.b.nak) {
41696 + /*
41697 + * If nak is not masked, it's because a non-split IN transfer
41698 + * is in an error state. In that case, the nak is handled by
41699 + * the nak interrupt handler, not here. Handle nak here for
41700 + * BULK/CONTROL OUT transfers, which halt on a NAK to allow
41701 + * rewinding the buffer pointer.
41702 + */
41703 + handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
41704 + } else if (hcint.b.ack && !hcintmsk.b.ack) {
41705 + /*
41706 + * If ack is not masked, it's because a non-split IN transfer
41707 + * is in an error state. In that case, the ack is handled by
41708 + * the ack interrupt handler, not here. Handle ack here for
41709 + * split transfers. Start splits halt on ACK.
41710 + */
41711 + handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41712 + } else {
41713 + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41714 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41715 + /*
41716 + * A periodic transfer halted with no other channel
41717 + * interrupts set. Assume it was halted by the core
41718 + * because it could not be completed in its scheduled
41719 + * (micro)frame.
41720 + */
41721 +#ifdef DEBUG
41722 + DWC_PRINTF
41723 + ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
41724 + __func__, hc->hc_num);
41725 +#endif
41726 + halt_channel(hcd, hc, qtd,
41727 + DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
41728 + } else {
41729 + DWC_ERROR
41730 + ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
41731 + "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
41732 + __func__, hc->hc_num, hcint.d32,
41733 + DWC_READ_REG32(&hcd->
41734 + core_if->core_global_regs->
41735 + gintsts));
41736 + }
41737 +
41738 + }
41739 + } else {
41740 + DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
41741 + hcint.d32);
41742 + }
41743 +}
41744 +
41745 +/**
41746 + * Handles a host channel Channel Halted interrupt.
41747 + *
41748 + * In slave mode, this handler is called only when the driver specifically
41749 + * requests a halt. This occurs during handling other host channel interrupts
41750 + * (e.g. nak, xacterr, stall, nyet, etc.).
41751 + *
41752 + * In DMA mode, this is the interrupt that occurs when the core has finished
41753 + * processing a transfer on a channel. Other host channel interrupts (except
41754 + * ahberr) are disabled in DMA mode.
41755 + */
41756 +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
41757 + dwc_hc_t * hc,
41758 + dwc_otg_hc_regs_t * hc_regs,
41759 + dwc_otg_qtd_t * qtd)
41760 +{
41761 + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41762 + "Channel Halted--\n", hc->hc_num);
41763 +
41764 + if (hcd->core_if->dma_enable) {
41765 + handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
41766 + } else {
41767 +#ifdef DEBUG
41768 + if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
41769 + return 1;
41770 + }
41771 +#endif
41772 + release_channel(hcd, hc, qtd, hc->halt_status);
41773 + }
41774 +
41775 + return 1;
41776 +}
41777 +
41778 +/** Handles interrupt for a specific Host Channel */
41779 +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
41780 +{
41781 + int retval = 0;
41782 + hcint_data_t hcint;
41783 + hcintmsk_data_t hcintmsk;
41784 + dwc_hc_t *hc;
41785 + dwc_otg_hc_regs_t *hc_regs;
41786 + dwc_otg_qtd_t *qtd;
41787 +
41788 + DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
41789 +
41790 + hc = dwc_otg_hcd->hc_ptr_array[num];
41791 + hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
41792 + qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
41793 +
41794 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41795 + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41796 + DWC_DEBUGPL(DBG_HCDV,
41797 + " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
41798 + hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
41799 + hcint.d32 = hcint.d32 & hcintmsk.d32;
41800 +
41801 + if (!dwc_otg_hcd->core_if->dma_enable) {
41802 + if (hcint.b.chhltd && hcint.d32 != 0x2) {
41803 + hcint.b.chhltd = 0;
41804 + }
41805 + }
41806 +
41807 + if (hcint.b.xfercomp) {
41808 + retval |=
41809 + handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41810 + /*
41811 + * If NYET occurred at same time as Xfer Complete, the NYET is
41812 + * handled by the Xfer Complete interrupt handler. Don't want
41813 + * to call the NYET interrupt handler in this case.
41814 + */
41815 + hcint.b.nyet = 0;
41816 + }
41817 + if (hcint.b.chhltd) {
41818 + retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41819 + }
41820 + if (hcint.b.ahberr) {
41821 + retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41822 + }
41823 + if (hcint.b.stall) {
41824 + retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41825 + }
41826 + if (hcint.b.nak) {
41827 + retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41828 + }
41829 + if (hcint.b.ack) {
41830 + if(!hcint.b.chhltd)
41831 + retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41832 + }
41833 + if (hcint.b.nyet) {
41834 + retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41835 + }
41836 + if (hcint.b.xacterr) {
41837 + retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41838 + }
41839 + if (hcint.b.bblerr) {
41840 + retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41841 + }
41842 + if (hcint.b.frmovrun) {
41843 + retval |=
41844 + handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41845 + }
41846 + if (hcint.b.datatglerr) {
41847 + retval |=
41848 + handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41849 + }
41850 +
41851 + return retval;
41852 +}
41853 +#endif /* DWC_DEVICE_ONLY */
41854 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41855 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100
41856 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2013-07-06 15:25:50.000000000 +0100
41857 @@ -0,0 +1,955 @@
41858 +
41859 +/* ==========================================================================
41860 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
41861 + * $Revision: #20 $
41862 + * $Date: 2011/10/26 $
41863 + * $Change: 1872981 $
41864 + *
41865 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
41866 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
41867 + * otherwise expressly agreed to in writing between Synopsys and you.
41868 + *
41869 + * The Software IS NOT an item of Licensed Software or Licensed Product under
41870 + * any End User Software License Agreement or Agreement for Licensed Product
41871 + * with Synopsys or any supplement thereto. You are permitted to use and
41872 + * redistribute this Software in source and binary forms, with or without
41873 + * modification, provided that redistributions of source code must retain this
41874 + * notice. You may not view, use, disclose, copy or distribute this file or
41875 + * any information contained herein except pursuant to this license grant from
41876 + * Synopsys. If you do not agree with this notice, including the disclaimer
41877 + * below, then you are not authorized to use the Software.
41878 + *
41879 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
41880 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41881 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41882 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
41883 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41884 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41885 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41886 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41887 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41888 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41889 + * DAMAGE.
41890 + * ========================================================================== */
41891 +#ifndef DWC_DEVICE_ONLY
41892 +
41893 +/**
41894 + * @file
41895 + *
41896 + * This file contains the implementation of the HCD. In Linux, the HCD
41897 + * implements the hc_driver API.
41898 + */
41899 +#include <linux/kernel.h>
41900 +#include <linux/module.h>
41901 +#include <linux/moduleparam.h>
41902 +#include <linux/init.h>
41903 +#include <linux/device.h>
41904 +#include <linux/errno.h>
41905 +#include <linux/list.h>
41906 +#include <linux/interrupt.h>
41907 +#include <linux/string.h>
41908 +#include <linux/dma-mapping.h>
41909 +#include <linux/version.h>
41910 +#include <asm/io.h>
41911 +#include <asm/fiq.h>
41912 +#include <linux/usb.h>
41913 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
41914 +#include <../drivers/usb/core/hcd.h>
41915 +#else
41916 +#include <linux/usb/hcd.h>
41917 +#endif
41918 +
41919 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
41920 +#define USB_URB_EP_LINKING 1
41921 +#else
41922 +#define USB_URB_EP_LINKING 0
41923 +#endif
41924 +
41925 +#include "dwc_otg_hcd_if.h"
41926 +#include "dwc_otg_dbg.h"
41927 +#include "dwc_otg_driver.h"
41928 +#include "dwc_otg_hcd.h"
41929 +#include "dwc_otg_mphi_fix.h"
41930 +
41931 +/**
41932 + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
41933 + * qualified with its direction (possible 32 endpoints per device).
41934 + */
41935 +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
41936 + ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
41937 +
41938 +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
41939 +
41940 +extern bool fiq_fix_enable;
41941 +
41942 +/** @name Linux HC Driver API Functions */
41943 +/** @{ */
41944 +/* manage i/o requests, device state */
41945 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
41946 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41947 + struct usb_host_endpoint *ep,
41948 +#endif
41949 + struct urb *urb, gfp_t mem_flags);
41950 +
41951 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
41952 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41953 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
41954 +#endif
41955 +#else /* kernels at or post 2.6.30 */
41956 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,
41957 + struct urb *urb, int status);
41958 +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
41959 +
41960 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
41961 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
41962 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
41963 +#endif
41964 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
41965 +extern int hcd_start(struct usb_hcd *hcd);
41966 +extern void hcd_stop(struct usb_hcd *hcd);
41967 +static int get_frame_number(struct usb_hcd *hcd);
41968 +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
41969 +extern int hub_control(struct usb_hcd *hcd,
41970 + u16 typeReq,
41971 + u16 wValue, u16 wIndex, char *buf, u16 wLength);
41972 +
41973 +struct wrapper_priv_data {
41974 + dwc_otg_hcd_t *dwc_otg_hcd;
41975 +};
41976 +
41977 +/** @} */
41978 +
41979 +static struct hc_driver dwc_otg_hc_driver = {
41980 +
41981 + .description = dwc_otg_hcd_name,
41982 + .product_desc = "DWC OTG Controller",
41983 + .hcd_priv_size = sizeof(struct wrapper_priv_data),
41984 +
41985 + .irq = dwc_otg_hcd_irq,
41986 +
41987 + .flags = HCD_MEMORY | HCD_USB2,
41988 +
41989 + //.reset =
41990 + .start = hcd_start,
41991 + //.suspend =
41992 + //.resume =
41993 + .stop = hcd_stop,
41994 +
41995 + .urb_enqueue = dwc_otg_urb_enqueue,
41996 + .urb_dequeue = dwc_otg_urb_dequeue,
41997 + .endpoint_disable = endpoint_disable,
41998 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
41999 + .endpoint_reset = endpoint_reset,
42000 +#endif
42001 + .get_frame_number = get_frame_number,
42002 +
42003 + .hub_status_data = hub_status_data,
42004 + .hub_control = hub_control,
42005 + //.bus_suspend =
42006 + //.bus_resume =
42007 +};
42008 +
42009 +/** Gets the dwc_otg_hcd from a struct usb_hcd */
42010 +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
42011 +{
42012 + struct wrapper_priv_data *p;
42013 + p = (struct wrapper_priv_data *)(hcd->hcd_priv);
42014 + return p->dwc_otg_hcd;
42015 +}
42016 +
42017 +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
42018 +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
42019 +{
42020 + return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
42021 +}
42022 +
42023 +/** Gets the usb_host_endpoint associated with an URB. */
42024 +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
42025 +{
42026 + struct usb_device *dev = urb->dev;
42027 + int ep_num = usb_pipeendpoint(urb->pipe);
42028 +
42029 + if (usb_pipein(urb->pipe))
42030 + return dev->ep_in[ep_num];
42031 + else
42032 + return dev->ep_out[ep_num];
42033 +}
42034 +
42035 +static int _disconnect(dwc_otg_hcd_t * hcd)
42036 +{
42037 + struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42038 +
42039 + usb_hcd->self.is_b_host = 0;
42040 + return 0;
42041 +}
42042 +
42043 +static int _start(dwc_otg_hcd_t * hcd)
42044 +{
42045 + struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42046 +
42047 + usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
42048 + hcd_start(usb_hcd);
42049 +
42050 + return 0;
42051 +}
42052 +
42053 +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
42054 + uint32_t * port_addr)
42055 +{
42056 + struct urb *urb = (struct urb *)urb_handle;
42057 + struct usb_bus *bus;
42058 +#if 1 //GRAYG - temporary
42059 + if (NULL == urb_handle)
42060 + DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
42061 + if (NULL == urb->dev)
42062 + DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
42063 + if (NULL == port_addr)
42064 + DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
42065 +#endif
42066 + if (urb->dev->tt) {
42067 + if (NULL == urb->dev->tt->hub) {
42068 + DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
42069 + __func__); //GRAYG
42070 + //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
42071 + *hub_addr = 0; //GRAYG
42072 + // we probably shouldn't have a transaction translator if
42073 + // there's no associated hub?
42074 + } else {
42075 + bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
42076 + if (urb->dev->tt->hub == bus->root_hub)
42077 + *hub_addr = 0;
42078 + else
42079 + *hub_addr = urb->dev->tt->hub->devnum;
42080 + }
42081 + *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
42082 + } else {
42083 + *hub_addr = 0;
42084 + *port_addr = urb->dev->ttport;
42085 + }
42086 + return 0;
42087 +}
42088 +
42089 +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
42090 +{
42091 + struct urb *urb = (struct urb *)urb_handle;
42092 + return urb->dev->speed;
42093 +}
42094 +
42095 +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
42096 +{
42097 + struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42098 + return usb_hcd->self.b_hnp_enable;
42099 +}
42100 +
42101 +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42102 + struct urb *urb)
42103 +{
42104 + hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
42105 + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42106 + hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
42107 + } else {
42108 + hcd_to_bus(hcd)->bandwidth_int_reqs++;
42109 + }
42110 +}
42111 +
42112 +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42113 + struct urb *urb)
42114 +{
42115 + hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
42116 + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42117 + hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
42118 + } else {
42119 + hcd_to_bus(hcd)->bandwidth_int_reqs--;
42120 + }
42121 +}
42122 +
42123 +/**
42124 + * Sets the final status of an URB and returns it to the device driver. Any
42125 + * required cleanup of the URB is performed. The HCD lock should be held on
42126 + * entry.
42127 + */
42128 +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
42129 + dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
42130 +{
42131 + struct urb *urb = (struct urb *)urb_handle;
42132 + urb_tq_entry_t *new_entry;
42133 + int rc = 0;
42134 + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42135 + DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
42136 + __func__, urb, usb_pipedevice(urb->pipe),
42137 + usb_pipeendpoint(urb->pipe),
42138 + usb_pipein(urb->pipe) ? "IN" : "OUT", status);
42139 + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42140 + int i;
42141 + for (i = 0; i < urb->number_of_packets; i++) {
42142 + DWC_PRINTF(" ISO Desc %d status: %d\n",
42143 + i, urb->iso_frame_desc[i].status);
42144 + }
42145 + }
42146 + }
42147 + new_entry = DWC_ALLOC_ATOMIC(sizeof(urb_tq_entry_t));
42148 + urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
42149 + /* Convert status value. */
42150 + switch (status) {
42151 + case -DWC_E_PROTOCOL:
42152 + status = -EPROTO;
42153 + break;
42154 + case -DWC_E_IN_PROGRESS:
42155 + status = -EINPROGRESS;
42156 + break;
42157 + case -DWC_E_PIPE:
42158 + status = -EPIPE;
42159 + break;
42160 + case -DWC_E_IO:
42161 + status = -EIO;
42162 + break;
42163 + case -DWC_E_TIMEOUT:
42164 + status = -ETIMEDOUT;
42165 + break;
42166 + case -DWC_E_OVERFLOW:
42167 + status = -EOVERFLOW;
42168 + break;
42169 + default:
42170 + if (status) {
42171 + DWC_PRINTF("Uknown urb status %d\n", status);
42172 +
42173 + }
42174 + }
42175 +
42176 + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42177 + int i;
42178 +
42179 + urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
42180 + for (i = 0; i < urb->number_of_packets; ++i) {
42181 + urb->iso_frame_desc[i].actual_length =
42182 + dwc_otg_hcd_urb_get_iso_desc_actual_length
42183 + (dwc_otg_urb, i);
42184 + urb->iso_frame_desc[i].status =
42185 + dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
42186 + }
42187 + }
42188 +
42189 + urb->status = status;
42190 + urb->hcpriv = NULL;
42191 + if (!status) {
42192 + if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
42193 + (urb->actual_length < urb->transfer_buffer_length)) {
42194 + urb->status = -EREMOTEIO;
42195 + }
42196 + }
42197 +
42198 + if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
42199 + (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42200 + struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
42201 + if (ep) {
42202 + free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
42203 + dwc_otg_hcd_get_ep_bandwidth(hcd,
42204 + ep->hcpriv),
42205 + urb);
42206 + }
42207 + }
42208 +
42209 + DWC_FREE(dwc_otg_urb);
42210 + if (!new_entry) {
42211 + DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");
42212 + urb->status = -EPROTO;
42213 + /* don't schedule the tasklet -
42214 + * directly return the packet here with error. */
42215 +#if USB_URB_EP_LINKING
42216 + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
42217 +#endif
42218 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42219 + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
42220 +#else
42221 + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
42222 +#endif
42223 + } else {
42224 + new_entry->urb = urb;
42225 +#if USB_URB_EP_LINKING
42226 + rc = usb_hcd_check_unlink_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
42227 + if(0 == rc) {
42228 + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
42229 + }
42230 +#endif
42231 + if(0 == rc) {
42232 + DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
42233 + urb_tq_entries);
42234 + DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
42235 + }
42236 + }
42237 + return 0;
42238 +}
42239 +
42240 +static struct dwc_otg_hcd_function_ops hcd_fops = {
42241 + .start = _start,
42242 + .disconnect = _disconnect,
42243 + .hub_info = _hub_info,
42244 + .speed = _speed,
42245 + .complete = _complete,
42246 + .get_b_hnp_enable = _get_b_hnp_enable,
42247 +};
42248 +
42249 +static struct fiq_handler fh = {
42250 + .name = "usb_fiq",
42251 +};
42252 +static uint8_t fiqStack[1024];
42253 +
42254 +extern mphi_regs_t c_mphi_regs;
42255 +/**
42256 + * Initializes the HCD. This function allocates memory for and initializes the
42257 + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
42258 + * USB bus with the core and calls the hc_driver->start() function. It returns
42259 + * a negative error on failure.
42260 + */
42261 +int hcd_init(dwc_bus_dev_t *_dev)
42262 +{
42263 + struct usb_hcd *hcd = NULL;
42264 + dwc_otg_hcd_t *dwc_otg_hcd = NULL;
42265 + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42266 + int retval = 0;
42267 + u64 dmamask;
42268 + struct pt_regs regs;
42269 +
42270 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
42271 +
42272 + /* Set device flags indicating whether the HCD supports DMA. */
42273 + if (dwc_otg_is_dma_enable(otg_dev->core_if))
42274 + dmamask = DMA_BIT_MASK(32);
42275 + else
42276 + dmamask = 0;
42277 +
42278 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
42279 + dma_set_mask(&_dev->dev, dmamask);
42280 + dma_set_coherent_mask(&_dev->dev, dmamask);
42281 +#elif defined(PCI_INTERFACE)
42282 + pci_set_dma_mask(_dev, dmamask);
42283 + pci_set_consistent_dma_mask(_dev, dmamask);
42284 +#endif
42285 +
42286 + if (fiq_fix_enable)
42287 + {
42288 + // Set up fiq
42289 + claim_fiq(&fh);
42290 + set_fiq_handler(__FIQ_Branch, 4);
42291 + memset(&regs,0,sizeof(regs));
42292 + regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
42293 + regs.ARM_r9 = (long)0;
42294 + regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4;
42295 + set_fiq_regs(&regs);
42296 + }
42297 +
42298 + /*
42299 + * Allocate memory for the base HCD plus the DWC OTG HCD.
42300 + * Initialize the base HCD.
42301 + */
42302 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
42303 + hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
42304 +#else
42305 + hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
42306 + hcd->has_tt = 1;
42307 +// hcd->uses_new_polling = 1;
42308 +// hcd->poll_rh = 0;
42309 +#endif
42310 + if (!hcd) {
42311 + retval = -ENOMEM;
42312 + goto error1;
42313 + }
42314 +
42315 + hcd->regs = otg_dev->os_dep.base;
42316 +
42317 + if (fiq_fix_enable)
42318 + {
42319 + //Set the mphi periph to the required registers
42320 + c_mphi_regs.base = otg_dev->os_dep.mphi_base;
42321 + c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
42322 + c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
42323 + c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
42324 + c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
42325 +
42326 + //Enable mphi peripheral
42327 + writel((1<<31),c_mphi_regs.ctrl);
42328 +#ifdef DEBUG
42329 + if (readl(c_mphi_regs.ctrl) & 0x80000000)
42330 + DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
42331 + else
42332 + DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
42333 +#endif
42334 + // Enable FIQ interrupt from USB peripheral
42335 + enable_fiq(INTERRUPT_VC_USB);
42336 + }
42337 + /* Initialize the DWC OTG HCD. */
42338 + dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
42339 + if (!dwc_otg_hcd) {
42340 + goto error2;
42341 + }
42342 + ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
42343 + dwc_otg_hcd;
42344 + otg_dev->hcd = dwc_otg_hcd;
42345 +
42346 + if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
42347 + goto error2;
42348 + }
42349 +
42350 + otg_dev->hcd->otg_dev = otg_dev;
42351 + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
42352 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
42353 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later
42354 + hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
42355 +#endif
42356 + /* Don't support SG list at this point */
42357 + hcd->self.sg_tablesize = 0;
42358 +#endif
42359 + /*
42360 + * Finish generic HCD initialization and start the HCD. This function
42361 + * allocates the DMA buffer pool, registers the USB bus, requests the
42362 + * IRQ line, and calls hcd_start method.
42363 + */
42364 +#ifdef PLATFORM_INTERFACE
42365 + retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
42366 +#else
42367 + retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
42368 +#endif
42369 + if (retval < 0) {
42370 + goto error2;
42371 + }
42372 +
42373 + dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
42374 + return 0;
42375 +
42376 +error2:
42377 + usb_put_hcd(hcd);
42378 +error1:
42379 + return retval;
42380 +}
42381 +
42382 +/**
42383 + * Removes the HCD.
42384 + * Frees memory and resources associated with the HCD and deregisters the bus.
42385 + */
42386 +void hcd_remove(dwc_bus_dev_t *_dev)
42387 +{
42388 + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42389 + dwc_otg_hcd_t *dwc_otg_hcd;
42390 + struct usb_hcd *hcd;
42391 +
42392 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
42393 +
42394 + if (!otg_dev) {
42395 + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
42396 + return;
42397 + }
42398 +
42399 + dwc_otg_hcd = otg_dev->hcd;
42400 +
42401 + if (!dwc_otg_hcd) {
42402 + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
42403 + return;
42404 + }
42405 +
42406 + hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
42407 +
42408 + if (!hcd) {
42409 + DWC_DEBUGPL(DBG_ANY,
42410 + "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
42411 + __func__);
42412 + return;
42413 + }
42414 + usb_remove_hcd(hcd);
42415 + dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
42416 + dwc_otg_hcd_remove(dwc_otg_hcd);
42417 + usb_put_hcd(hcd);
42418 +}
42419 +
42420 +/* =========================================================================
42421 + * Linux HC Driver Functions
42422 + * ========================================================================= */
42423 +
42424 +/** Initializes the DWC_otg controller and its root hub and prepares it for host
42425 + * mode operation. Activates the root port. Returns 0 on success and a negative
42426 + * error code on failure. */
42427 +int hcd_start(struct usb_hcd *hcd)
42428 +{
42429 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42430 + struct usb_bus *bus;
42431 +
42432 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
42433 + bus = hcd_to_bus(hcd);
42434 +
42435 + hcd->state = HC_STATE_RUNNING;
42436 + if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
42437 + return 0;
42438 + }
42439 +
42440 + /* Initialize and connect root hub if one is not already attached */
42441 + if (bus->root_hub) {
42442 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
42443 + /* Inform the HUB driver to resume. */
42444 + usb_hcd_resume_root_hub(hcd);
42445 + }
42446 +
42447 + return 0;
42448 +}
42449 +
42450 +/**
42451 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
42452 + * stopped.
42453 + */
42454 +void hcd_stop(struct usb_hcd *hcd)
42455 +{
42456 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42457 +
42458 + dwc_otg_hcd_stop(dwc_otg_hcd);
42459 +}
42460 +
42461 +/** Returns the current frame number. */
42462 +static int get_frame_number(struct usb_hcd *hcd)
42463 +{
42464 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42465 +
42466 + return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
42467 +}
42468 +
42469 +#ifdef DEBUG
42470 +static void dump_urb_info(struct urb *urb, char *fn_name)
42471 +{
42472 + DWC_PRINTF("%s, urb %p\n", fn_name, urb);
42473 + DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe));
42474 + DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
42475 + (usb_pipein(urb->pipe) ? "IN" : "OUT"));
42476 + DWC_PRINTF(" Endpoint type: %s\n", ( {
42477 + char *pipetype;
42478 + switch (usb_pipetype(urb->pipe)) {
42479 +case PIPE_CONTROL:
42480 +pipetype = "CONTROL"; break; case PIPE_BULK:
42481 +pipetype = "BULK"; break; case PIPE_INTERRUPT:
42482 +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
42483 +pipetype = "ISOCHRONOUS"; break; default:
42484 + pipetype = "UNKNOWN"; break;};
42485 + pipetype;}
42486 + )) ;
42487 + DWC_PRINTF(" Speed: %s\n", ( {
42488 + char *speed; switch (urb->dev->speed) {
42489 +case USB_SPEED_HIGH:
42490 +speed = "HIGH"; break; case USB_SPEED_FULL:
42491 +speed = "FULL"; break; case USB_SPEED_LOW:
42492 +speed = "LOW"; break; default:
42493 + speed = "UNKNOWN"; break;};
42494 + speed;}
42495 + )) ;
42496 + DWC_PRINTF(" Max packet size: %d\n",
42497 + usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
42498 + DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length);
42499 + DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n",
42500 + urb->transfer_buffer, (void *)urb->transfer_dma);
42501 + DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n",
42502 + urb->setup_packet, (void *)urb->setup_dma);
42503 + DWC_PRINTF(" Interval: %d\n", urb->interval);
42504 + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42505 + int i;
42506 + for (i = 0; i < urb->number_of_packets; i++) {
42507 + DWC_PRINTF(" ISO Desc %d:\n", i);
42508 + DWC_PRINTF(" offset: %d, length %d\n",
42509 + urb->iso_frame_desc[i].offset,
42510 + urb->iso_frame_desc[i].length);
42511 + }
42512 + }
42513 +}
42514 +#endif
42515 +
42516 +/** Starts processing a USB transfer request specified by a USB Request Block
42517 + * (URB). mem_flags indicates the type of memory allocation to use while
42518 + * processing this URB. */
42519 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
42520 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42521 + struct usb_host_endpoint *ep,
42522 +#endif
42523 + struct urb *urb, gfp_t mem_flags)
42524 +{
42525 + int retval = 0;
42526 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
42527 + struct usb_host_endpoint *ep = urb->ep;
42528 +#endif
42529 +#if USB_URB_EP_LINKING
42530 + dwc_irqflags_t irqflags;
42531 +#endif
42532 + void **ref_ep_hcpriv = &ep->hcpriv;
42533 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42534 + dwc_otg_hcd_urb_t *dwc_otg_urb;
42535 + int i;
42536 + int alloc_bandwidth = 0;
42537 + uint8_t ep_type = 0;
42538 + uint32_t flags = 0;
42539 + void *buf;
42540 +
42541 +#ifdef DEBUG
42542 + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42543 + dump_urb_info(urb, "dwc_otg_urb_enqueue");
42544 + }
42545 +#endif
42546 +
42547 + if (!urb->transfer_buffer && urb->transfer_buffer_length)
42548 + return -EINVAL;
42549 +
42550 + if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
42551 + || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42552 + if (!dwc_otg_hcd_is_bandwidth_allocated
42553 + (dwc_otg_hcd, ref_ep_hcpriv)) {
42554 + alloc_bandwidth = 1;
42555 + }
42556 + }
42557 +
42558 + switch (usb_pipetype(urb->pipe)) {
42559 + case PIPE_CONTROL:
42560 + ep_type = USB_ENDPOINT_XFER_CONTROL;
42561 + break;
42562 + case PIPE_ISOCHRONOUS:
42563 + ep_type = USB_ENDPOINT_XFER_ISOC;
42564 + break;
42565 + case PIPE_BULK:
42566 + ep_type = USB_ENDPOINT_XFER_BULK;
42567 + break;
42568 + case PIPE_INTERRUPT:
42569 + ep_type = USB_ENDPOINT_XFER_INT;
42570 + break;
42571 + default:
42572 + DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));
42573 + }
42574 +
42575 + /* # of packets is often 0 - do we really need to call this then? */
42576 + dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
42577 + urb->number_of_packets,
42578 + mem_flags == GFP_ATOMIC ? 1 : 0);
42579 +
42580 + if(dwc_otg_urb == NULL)
42581 + return -ENOMEM;
42582 +
42583 + urb->hcpriv = dwc_otg_urb;
42584 + if (!dwc_otg_urb && urb->number_of_packets)
42585 + return -ENOMEM;
42586 +
42587 + dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
42588 + usb_pipeendpoint(urb->pipe), ep_type,
42589 + usb_pipein(urb->pipe),
42590 + usb_maxpacket(urb->dev, urb->pipe,
42591 + !(usb_pipein(urb->pipe))));
42592 +
42593 + buf = urb->transfer_buffer;
42594 + if (hcd->self.uses_dma) {
42595 + /*
42596 + * Calculate virtual address from physical address,
42597 + * because some class driver may not fill transfer_buffer.
42598 + * In Buffer DMA mode virual address is used,
42599 + * when handling non DWORD aligned buffers.
42600 + */
42601 + //buf = phys_to_virt(urb->transfer_dma);
42602 + // DMA addresses are bus addresses not physical addresses!
42603 + buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
42604 + }
42605 +
42606 + if (!(urb->transfer_flags & URB_NO_INTERRUPT))
42607 + flags |= URB_GIVEBACK_ASAP;
42608 + if (urb->transfer_flags & URB_ZERO_PACKET)
42609 + flags |= URB_SEND_ZERO_PACKET;
42610 +
42611 + dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
42612 + urb->transfer_dma,
42613 + urb->transfer_buffer_length,
42614 + urb->setup_packet,
42615 + urb->setup_dma, flags, urb->interval);
42616 +
42617 + for (i = 0; i < urb->number_of_packets; ++i) {
42618 + dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
42619 + urb->
42620 + iso_frame_desc[i].offset,
42621 + urb->
42622 + iso_frame_desc[i].length);
42623 + }
42624 +
42625 +#if USB_URB_EP_LINKING
42626 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42627 + retval = usb_hcd_link_urb_to_ep(hcd, urb);
42628 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42629 + if (0 == retval)
42630 +#endif
42631 + {
42632 + retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
42633 + /*(dwc_otg_qh_t **)*/
42634 + ref_ep_hcpriv,
42635 + mem_flags == GFP_ATOMIC ? 1 : 0);
42636 + if (0 == retval) {
42637 + if (alloc_bandwidth) {
42638 + allocate_bus_bandwidth(hcd,
42639 + dwc_otg_hcd_get_ep_bandwidth(
42640 + dwc_otg_hcd, *ref_ep_hcpriv),
42641 + urb);
42642 + }
42643 + } else {
42644 +#if USB_URB_EP_LINKING
42645 + dwc_irqflags_t irqflags;
42646 + DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
42647 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42648 + usb_hcd_unlink_urb_from_ep(hcd, urb);
42649 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42650 +#endif
42651 + if (retval == -DWC_E_NO_DEVICE) {
42652 + retval = -ENODEV;
42653 + }
42654 + }
42655 + }
42656 + return retval;
42657 +}
42658 +
42659 +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
42660 + * success. */
42661 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42662 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
42663 +#else
42664 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
42665 +#endif
42666 +{
42667 + dwc_irqflags_t flags;
42668 + dwc_otg_hcd_t *dwc_otg_hcd;
42669 + int rc;
42670 +
42671 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
42672 +
42673 + dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42674 +
42675 +#ifdef DEBUG
42676 + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42677 + dump_urb_info(urb, "dwc_otg_urb_dequeue");
42678 + }
42679 +#endif
42680 +
42681 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42682 + rc = usb_hcd_check_unlink_urb(hcd, urb, status);
42683 + if (0 == rc) {
42684 + if(urb->hcpriv != NULL) {
42685 + dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,
42686 + (dwc_otg_hcd_urb_t *)urb->hcpriv);
42687 +
42688 + DWC_FREE(urb->hcpriv);
42689 + urb->hcpriv = NULL;
42690 + }
42691 + }
42692 +
42693 + if (0 == rc) {
42694 + /* Higher layer software sets URB status. */
42695 +#if USB_URB_EP_LINKING
42696 + usb_hcd_unlink_urb_from_ep(hcd, urb);
42697 +#endif
42698 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42699 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42700 + usb_hcd_giveback_urb(hcd, urb);
42701 +#else
42702 + usb_hcd_giveback_urb(hcd, urb, status);
42703 +#endif
42704 + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42705 + DWC_PRINTF("Called usb_hcd_giveback_urb() \n");
42706 + DWC_PRINTF(" 1urb->status = %d\n", urb->status);
42707 + }
42708 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");
42709 + } else {
42710 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42711 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",
42712 + rc);
42713 + }
42714 +
42715 + return rc;
42716 +}
42717 +
42718 +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
42719 + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
42720 + * must already be dequeued. */
42721 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42722 +{
42723 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42724 +
42725 + DWC_DEBUGPL(DBG_HCD,
42726 + "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
42727 + "endpoint=%d\n", ep->desc.bEndpointAddress,
42728 + dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
42729 + dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
42730 + ep->hcpriv = NULL;
42731 +}
42732 +
42733 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42734 +/* Resets endpoint specific parameter values, in current version used to reset
42735 + * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
42736 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42737 +{
42738 + dwc_irqflags_t flags;
42739 + struct usb_device *udev = NULL;
42740 + int epnum = usb_endpoint_num(&ep->desc);
42741 + int is_out = usb_endpoint_dir_out(&ep->desc);
42742 + int is_control = usb_endpoint_xfer_control(&ep->desc);
42743 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42744 + struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);
42745 +
42746 + if (dev)
42747 + udev = to_usb_device(dev);
42748 + else
42749 + return;
42750 +
42751 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
42752 +
42753 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42754 + usb_settoggle(udev, epnum, is_out, 0);
42755 + if (is_control)
42756 + usb_settoggle(udev, epnum, !is_out, 0);
42757 +
42758 + if (ep->hcpriv) {
42759 + dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
42760 + }
42761 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42762 +}
42763 +#endif
42764 +
42765 +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
42766 + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
42767 + * interrupt.
42768 + *
42769 + * This function is called by the USB core when an interrupt occurs */
42770 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
42771 +{
42772 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42773 + int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
42774 + if (retval != 0) {
42775 + S3C2410X_CLEAR_EINTPEND();
42776 + }
42777 + return IRQ_RETVAL(retval);
42778 +}
42779 +
42780 +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
42781 + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
42782 + * is the status change indicator for the single root port. Returns 1 if either
42783 + * change indicator is 1, otherwise returns 0. */
42784 +int hub_status_data(struct usb_hcd *hcd, char *buf)
42785 +{
42786 + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42787 +
42788 + buf[0] = 0;
42789 + buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
42790 +
42791 + return (buf[0] != 0);
42792 +}
42793 +
42794 +/** Handles hub class-specific requests. */
42795 +int hub_control(struct usb_hcd *hcd,
42796 + u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
42797 +{
42798 + int retval;
42799 +
42800 + retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
42801 + typeReq, wValue, wIndex, buf, wLength);
42802 +
42803 + switch (retval) {
42804 + case -DWC_E_INVALID:
42805 + retval = -EINVAL;
42806 + break;
42807 + }
42808 +
42809 + return retval;
42810 +}
42811 +
42812 +#endif /* DWC_DEVICE_ONLY */
42813 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42814 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100
42815 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2013-07-06 15:25:50.000000000 +0100
42816 @@ -0,0 +1,958 @@
42817 +/* ==========================================================================
42818 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
42819 + * $Revision: #44 $
42820 + * $Date: 2011/10/26 $
42821 + * $Change: 1873028 $
42822 + *
42823 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42824 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
42825 + * otherwise expressly agreed to in writing between Synopsys and you.
42826 + *
42827 + * The Software IS NOT an item of Licensed Software or Licensed Product under
42828 + * any End User Software License Agreement or Agreement for Licensed Product
42829 + * with Synopsys or any supplement thereto. You are permitted to use and
42830 + * redistribute this Software in source and binary forms, with or without
42831 + * modification, provided that redistributions of source code must retain this
42832 + * notice. You may not view, use, disclose, copy or distribute this file or
42833 + * any information contained herein except pursuant to this license grant from
42834 + * Synopsys. If you do not agree with this notice, including the disclaimer
42835 + * below, then you are not authorized to use the Software.
42836 + *
42837 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
42838 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42839 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42840 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
42841 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42842 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42843 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42844 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42845 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42846 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
42847 + * DAMAGE.
42848 + * ========================================================================== */
42849 +#ifndef DWC_DEVICE_ONLY
42850 +
42851 +/**
42852 + * @file
42853 + *
42854 + * This file contains the functions to manage Queue Heads and Queue
42855 + * Transfer Descriptors.
42856 + */
42857 +
42858 +#include "dwc_otg_hcd.h"
42859 +#include "dwc_otg_regs.h"
42860 +
42861 +extern bool microframe_schedule;
42862 +
42863 +/**
42864 + * Free each QTD in the QH's QTD-list then free the QH. QH should already be
42865 + * removed from a list. QTD list should already be empty if called from URB
42866 + * Dequeue.
42867 + *
42868 + * @param hcd HCD instance.
42869 + * @param qh The QH to free.
42870 + */
42871 +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
42872 +{
42873 + dwc_otg_qtd_t *qtd, *qtd_tmp;
42874 +
42875 + /* Free each QTD in the QTD list */
42876 + DWC_SPINLOCK(hcd->lock);
42877 + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
42878 + DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
42879 + dwc_otg_hcd_qtd_free(qtd);
42880 + }
42881 +
42882 + if (hcd->core_if->dma_desc_enable) {
42883 + dwc_otg_hcd_qh_free_ddma(hcd, qh);
42884 + } else if (qh->dw_align_buf) {
42885 + uint32_t buf_size;
42886 + if (qh->ep_type == UE_ISOCHRONOUS) {
42887 + buf_size = 4096;
42888 + } else {
42889 + buf_size = hcd->core_if->core_params->max_transfer_size;
42890 + }
42891 + DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
42892 + }
42893 +
42894 + DWC_FREE(qh);
42895 + DWC_SPINUNLOCK(hcd->lock);
42896 + return;
42897 +}
42898 +
42899 +#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6)
42900 +#define HS_HOST_DELAY 5 /* nanoseconds */
42901 +#define FS_LS_HOST_DELAY 1000 /* nanoseconds */
42902 +#define HUB_LS_SETUP 333 /* nanoseconds */
42903 +#define NS_TO_US(ns) ((ns + 500) / 1000)
42904 + /* convert & round nanoseconds to microseconds */
42905 +
42906 +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)
42907 +{
42908 + unsigned long retval;
42909 +
42910 + switch (speed) {
42911 + case USB_SPEED_HIGH:
42912 + if (is_isoc) {
42913 + retval =
42914 + ((38 * 8 * 2083) +
42915 + (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42916 + HS_HOST_DELAY;
42917 + } else {
42918 + retval =
42919 + ((55 * 8 * 2083) +
42920 + (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42921 + HS_HOST_DELAY;
42922 + }
42923 + break;
42924 + case USB_SPEED_FULL:
42925 + if (is_isoc) {
42926 + retval =
42927 + (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42928 + if (is_in) {
42929 + retval = 7268 + FS_LS_HOST_DELAY + retval;
42930 + } else {
42931 + retval = 6265 + FS_LS_HOST_DELAY + retval;
42932 + }
42933 + } else {
42934 + retval =
42935 + (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42936 + retval = 9107 + FS_LS_HOST_DELAY + retval;
42937 + }
42938 + break;
42939 + case USB_SPEED_LOW:
42940 + if (is_in) {
42941 + retval =
42942 + (67667 * (31 + 10 * BitStuffTime(bytecount))) /
42943 + 1000;
42944 + retval =
42945 + 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42946 + retval;
42947 + } else {
42948 + retval =
42949 + (66700 * (31 + 10 * BitStuffTime(bytecount))) /
42950 + 1000;
42951 + retval =
42952 + 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42953 + retval;
42954 + }
42955 + break;
42956 + default:
42957 + DWC_WARN("Unknown device speed\n");
42958 + retval = -1;
42959 + }
42960 +
42961 + return NS_TO_US(retval);
42962 +}
42963 +
42964 +/**
42965 + * Initializes a QH structure.
42966 + *
42967 + * @param hcd The HCD state structure for the DWC OTG controller.
42968 + * @param qh The QH to init.
42969 + * @param urb Holds the information about the device/endpoint that we need
42970 + * to initialize the QH.
42971 + */
42972 +#define SCHEDULE_SLOP 10
42973 +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
42974 +{
42975 + char *speed, *type;
42976 + int dev_speed;
42977 + uint32_t hub_addr, hub_port;
42978 +
42979 + dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
42980 +
42981 + /* Initialize QH */
42982 + qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
42983 + qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
42984 +
42985 + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
42986 + qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
42987 + DWC_CIRCLEQ_INIT(&qh->qtd_list);
42988 + DWC_LIST_INIT(&qh->qh_list_entry);
42989 + qh->channel = NULL;
42990 +
42991 + /* FS/LS Enpoint on HS Hub
42992 + * NOT virtual root hub */
42993 + dev_speed = hcd->fops->speed(hcd, urb->priv);
42994 +
42995 + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
42996 + qh->do_split = 0;
42997 + if (microframe_schedule)
42998 + qh->speed = dev_speed;
42999 +
43000 + qh->nak_frame = 0xffff;
43001 +
43002 + if (((dev_speed == USB_SPEED_LOW) ||
43003 + (dev_speed == USB_SPEED_FULL)) &&
43004 + (hub_addr != 0 && hub_addr != 1)) {
43005 + DWC_DEBUGPL(DBG_HCD,
43006 + "QH init: EP %d: TT found at hub addr %d, for port %d\n",
43007 + dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
43008 + hub_port);
43009 + qh->do_split = 1;
43010 + }
43011 +
43012 + if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
43013 + /* Compute scheduling parameters once and save them. */
43014 + hprt0_data_t hprt;
43015 +
43016 + /** @todo Account for split transfers in the bus time. */
43017 + int bytecount =
43018 + dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
43019 +
43020 + qh->usecs =
43021 + calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
43022 + qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),
43023 + bytecount);
43024 + /* Start in a slightly future (micro)frame. */
43025 + qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
43026 + SCHEDULE_SLOP);
43027 + qh->interval = urb->interval;
43028 +
43029 +#if 0
43030 + /* Increase interrupt polling rate for debugging. */
43031 + if (qh->ep_type == UE_INTERRUPT) {
43032 + qh->interval = 8;
43033 + }
43034 +#endif
43035 + hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
43036 + if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
43037 + ((dev_speed == USB_SPEED_LOW) ||
43038 + (dev_speed == USB_SPEED_FULL))) {
43039 + qh->interval *= 8;
43040 + qh->sched_frame |= 0x7;
43041 + qh->start_split_frame = qh->sched_frame;
43042 + }
43043 +
43044 + }
43045 +
43046 + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
43047 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh);
43048 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n",
43049 + dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
43050 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n",
43051 + dwc_otg_hcd_get_ep_num(&urb->pipe_info),
43052 + dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
43053 + switch (dev_speed) {
43054 + case USB_SPEED_LOW:
43055 + qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
43056 + speed = "low";
43057 + break;
43058 + case USB_SPEED_FULL:
43059 + qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
43060 + speed = "full";
43061 + break;
43062 + case USB_SPEED_HIGH:
43063 + qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
43064 + speed = "high";
43065 + break;
43066 + default:
43067 + speed = "?";
43068 + break;
43069 + }
43070 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed);
43071 +
43072 + switch (qh->ep_type) {
43073 + case UE_ISOCHRONOUS:
43074 + type = "isochronous";
43075 + break;
43076 + case UE_INTERRUPT:
43077 + type = "interrupt";
43078 + break;
43079 + case UE_CONTROL:
43080 + type = "control";
43081 + break;
43082 + case UE_BULK:
43083 + type = "bulk";
43084 + break;
43085 + default:
43086 + type = "?";
43087 + break;
43088 + }
43089 +
43090 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type);
43091 +
43092 +#ifdef DEBUG
43093 + if (qh->ep_type == UE_INTERRUPT) {
43094 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
43095 + qh->usecs);
43096 + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
43097 + qh->interval);
43098 + }
43099 +#endif
43100 +
43101 +}
43102 +
43103 +/**
43104 + * This function allocates and initializes a QH.
43105 + *
43106 + * @param hcd The HCD state structure for the DWC OTG controller.
43107 + * @param urb Holds the information about the device/endpoint that we need
43108 + * to initialize the QH.
43109 + * @param atomic_alloc Flag to do atomic allocation if needed
43110 + *
43111 + * @return Returns pointer to the newly allocated QH, or NULL on error. */
43112 +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
43113 + dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43114 +{
43115 + dwc_otg_qh_t *qh;
43116 +
43117 + /* Allocate memory */
43118 + /** @todo add memflags argument */
43119 + qh = dwc_otg_hcd_qh_alloc(atomic_alloc);
43120 + if (qh == NULL) {
43121 + DWC_ERROR("qh allocation failed");
43122 + return NULL;
43123 + }
43124 +
43125 + qh_init(hcd, qh, urb);
43126 +
43127 + if (hcd->core_if->dma_desc_enable
43128 + && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
43129 + dwc_otg_hcd_qh_free(hcd, qh);
43130 + return NULL;
43131 + }
43132 +
43133 + return qh;
43134 +}
43135 +
43136 +/* microframe_schedule=0 start */
43137 +
43138 +/**
43139 + * Checks that a channel is available for a periodic transfer.
43140 + *
43141 + * @return 0 if successful, negative error code otherise.
43142 + */
43143 +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
43144 +{
43145 + /*
43146 + * Currently assuming that there is a dedicated host channnel for each
43147 + * periodic transaction plus at least one host channel for
43148 + * non-periodic transactions.
43149 + */
43150 + int status;
43151 + int num_channels;
43152 +
43153 + num_channels = hcd->core_if->core_params->host_channels;
43154 + if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)
43155 + && (hcd->periodic_channels < num_channels - 1)) {
43156 + status = 0;
43157 + } else {
43158 + DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
43159 + __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE
43160 + status = -DWC_E_NO_SPACE;
43161 + }
43162 +
43163 + return status;
43164 +}
43165 +
43166 +/**
43167 + * Checks that there is sufficient bandwidth for the specified QH in the
43168 + * periodic schedule. For simplicity, this calculation assumes that all the
43169 + * transfers in the periodic schedule may occur in the same (micro)frame.
43170 + *
43171 + * @param hcd The HCD state structure for the DWC OTG controller.
43172 + * @param qh QH containing periodic bandwidth required.
43173 + *
43174 + * @return 0 if successful, negative error code otherwise.
43175 + */
43176 +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43177 +{
43178 + int status;
43179 + int16_t max_claimed_usecs;
43180 +
43181 + status = 0;
43182 +
43183 + if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
43184 + /*
43185 + * High speed mode.
43186 + * Max periodic usecs is 80% x 125 usec = 100 usec.
43187 + */
43188 +
43189 + max_claimed_usecs = 100 - qh->usecs;
43190 + } else {
43191 + /*
43192 + * Full speed mode.
43193 + * Max periodic usecs is 90% x 1000 usec = 900 usec.
43194 + */
43195 + max_claimed_usecs = 900 - qh->usecs;
43196 + }
43197 +
43198 + if (hcd->periodic_usecs > max_claimed_usecs) {
43199 + DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE
43200 + status = -DWC_E_NO_SPACE;
43201 + }
43202 +
43203 + return status;
43204 +}
43205 +
43206 +/* microframe_schedule=0 end */
43207 +
43208 +/**
43209 + * Microframe scheduler
43210 + * track the total use in hcd->frame_usecs
43211 + * keep each qh use in qh->frame_usecs
43212 + * when surrendering the qh then donate the time back
43213 + */
43214 +const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
43215 +
43216 +/*
43217 + * called from dwc_otg_hcd.c:dwc_otg_hcd_init
43218 + */
43219 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
43220 +{
43221 + int i;
43222 + for (i=0; i<8; i++) {
43223 + _hcd->frame_usecs[i] = max_uframe_usecs[i];
43224 + }
43225 + return 0;
43226 +}
43227 +
43228 +static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43229 +{
43230 + int i;
43231 + unsigned short utime;
43232 + int t_left;
43233 + int ret;
43234 + int done;
43235 +
43236 + ret = -1;
43237 + utime = _qh->usecs;
43238 + t_left = utime;
43239 + i = 0;
43240 + done = 0;
43241 + while (done == 0) {
43242 + /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
43243 + if (utime <= _hcd->frame_usecs[i]) {
43244 + _hcd->frame_usecs[i] -= utime;
43245 + _qh->frame_usecs[i] += utime;
43246 + t_left -= utime;
43247 + ret = i;
43248 + done = 1;
43249 + return ret;
43250 + } else {
43251 + i++;
43252 + if (i == 8) {
43253 + done = 1;
43254 + ret = -1;
43255 + }
43256 + }
43257 + }
43258 + return ret;
43259 + }
43260 +
43261 +/*
43262 + * use this for FS apps that can span multiple uframes
43263 + */
43264 +static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43265 +{
43266 + int i;
43267 + int j;
43268 + unsigned short utime;
43269 + int t_left;
43270 + int ret;
43271 + int done;
43272 + unsigned short xtime;
43273 +
43274 + ret = -1;
43275 + utime = _qh->usecs;
43276 + t_left = utime;
43277 + i = 0;
43278 + done = 0;
43279 +loop:
43280 + while (done == 0) {
43281 + if(_hcd->frame_usecs[i] <= 0) {
43282 + i++;
43283 + if (i == 8) {
43284 + done = 1;
43285 + ret = -1;
43286 + }
43287 + goto loop;
43288 + }
43289 +
43290 + /*
43291 + * we need n consecutive slots
43292 + * so use j as a start slot j plus j+1 must be enough time (for now)
43293 + */
43294 + xtime= _hcd->frame_usecs[i];
43295 + for (j = i+1 ; j < 8 ; j++ ) {
43296 + /*
43297 + * if we add this frame remaining time to xtime we may
43298 + * be OK, if not we need to test j for a complete frame
43299 + */
43300 + if ((xtime+_hcd->frame_usecs[j]) < utime) {
43301 + if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
43302 + j = 8;
43303 + ret = -1;
43304 + continue;
43305 + }
43306 + }
43307 + if (xtime >= utime) {
43308 + ret = i;
43309 + j = 8; /* stop loop with a good value ret */
43310 + continue;
43311 + }
43312 + /* add the frame time to x time */
43313 + xtime += _hcd->frame_usecs[j];
43314 + /* we must have a fully available next frame or break */
43315 + if ((xtime < utime)
43316 + && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
43317 + ret = -1;
43318 + j = 8; /* stop loop with a bad value ret */
43319 + continue;
43320 + }
43321 + }
43322 + if (ret >= 0) {
43323 + t_left = utime;
43324 + for (j = i; (t_left>0) && (j < 8); j++ ) {
43325 + t_left -= _hcd->frame_usecs[j];
43326 + if ( t_left <= 0 ) {
43327 + _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
43328 + _hcd->frame_usecs[j]= -t_left;
43329 + ret = i;
43330 + done = 1;
43331 + } else {
43332 + _qh->frame_usecs[j] += _hcd->frame_usecs[j];
43333 + _hcd->frame_usecs[j] = 0;
43334 + }
43335 + }
43336 + } else {
43337 + i++;
43338 + if (i == 8) {
43339 + done = 1;
43340 + ret = -1;
43341 + }
43342 + }
43343 + }
43344 + return ret;
43345 +}
43346 +
43347 +static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43348 +{
43349 + int ret;
43350 + ret = -1;
43351 +
43352 + if (_qh->speed == USB_SPEED_HIGH) {
43353 + /* if this is a hs transaction we need a full frame */
43354 + ret = find_single_uframe(_hcd, _qh);
43355 + } else {
43356 + /* if this is a fs transaction we may need a sequence of frames */
43357 + ret = find_multi_uframe(_hcd, _qh);
43358 + }
43359 + return ret;
43360 +}
43361 +
43362 +/**
43363 + * Checks that the max transfer size allowed in a host channel is large enough
43364 + * to handle the maximum data transfer in a single (micro)frame for a periodic
43365 + * transfer.
43366 + *
43367 + * @param hcd The HCD state structure for the DWC OTG controller.
43368 + * @param qh QH for a periodic endpoint.
43369 + *
43370 + * @return 0 if successful, negative error code otherwise.
43371 + */
43372 +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43373 +{
43374 + int status;
43375 + uint32_t max_xfer_size;
43376 + uint32_t max_channel_xfer_size;
43377 +
43378 + status = 0;
43379 +
43380 + max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
43381 + max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
43382 +
43383 + if (max_xfer_size > max_channel_xfer_size) {
43384 + DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
43385 + __func__, max_xfer_size, max_channel_xfer_size); //NOTICE
43386 + status = -DWC_E_NO_SPACE;
43387 + }
43388 +
43389 + return status;
43390 +}
43391 +
43392 +
43393 +extern int g_next_sched_frame, g_np_count, g_np_sent;
43394 +
43395 +/**
43396 + * Schedules an interrupt or isochronous transfer in the periodic schedule.
43397 + *
43398 + * @param hcd The HCD state structure for the DWC OTG controller.
43399 + * @param qh QH for the periodic transfer. The QH should already contain the
43400 + * scheduling information.
43401 + *
43402 + * @return 0 if successful, negative error code otherwise.
43403 + */
43404 +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43405 +{
43406 + int status = 0;
43407 +
43408 + if (microframe_schedule) {
43409 + int frame;
43410 + status = find_uframe(hcd, qh);
43411 + frame = -1;
43412 + if (status == 0) {
43413 + frame = 7;
43414 + } else {
43415 + if (status > 0 )
43416 + frame = status-1;
43417 + }
43418 +
43419 + /* Set the new frame up */
43420 + if (frame > -1) {
43421 + qh->sched_frame &= ~0x7;
43422 + qh->sched_frame |= (frame & 7);
43423 + }
43424 +
43425 + if (status != -1)
43426 + status = 0;
43427 + } else {
43428 + status = periodic_channel_available(hcd);
43429 + if (status) {
43430 + DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE
43431 + return status;
43432 + }
43433 +
43434 + status = check_periodic_bandwidth(hcd, qh);
43435 + }
43436 + if (status) {
43437 + DWC_INFO("%s: Insufficient periodic bandwidth for "
43438 + "periodic transfer.\n", __func__);
43439 + return status;
43440 + }
43441 + status = check_max_xfer_size(hcd, qh);
43442 + if (status) {
43443 + DWC_INFO("%s: Channel max transfer size too small "
43444 + "for periodic transfer.\n", __func__);
43445 + return status;
43446 + }
43447 +
43448 + if (hcd->core_if->dma_desc_enable) {
43449 + /* Don't rely on SOF and start in ready schedule */
43450 + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
43451 + }
43452 + else {
43453 + if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
43454 + {
43455 + g_next_sched_frame = qh->sched_frame;
43456 +
43457 + }
43458 + /* Always start in the inactive schedule. */
43459 + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
43460 + }
43461 +
43462 + if (!microframe_schedule) {
43463 + /* Reserve the periodic channel. */
43464 + hcd->periodic_channels++;
43465 + }
43466 +
43467 + /* Update claimed usecs per (micro)frame. */
43468 + hcd->periodic_usecs += qh->usecs;
43469 +
43470 + return status;
43471 +}
43472 +
43473 +
43474 +/**
43475 + * This function adds a QH to either the non periodic or periodic schedule if
43476 + * it is not already in the schedule. If the QH is already in the schedule, no
43477 + * action is taken.
43478 + *
43479 + * @return 0 if successful, negative error code otherwise.
43480 + */
43481 +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43482 +{
43483 + int status = 0;
43484 + gintmsk_data_t intr_mask = {.d32 = 0 };
43485 +
43486 + if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43487 + /* QH already in a schedule. */
43488 + return status;
43489 + }
43490 +
43491 + /* Add the new QH to the appropriate schedule */
43492 + if (dwc_qh_is_non_per(qh)) {
43493 + /* Always start in the inactive schedule. */
43494 + DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
43495 + &qh->qh_list_entry);
43496 + g_np_count++;
43497 + } else {
43498 + status = schedule_periodic(hcd, qh);
43499 + if ( !hcd->periodic_qh_count ) {
43500 + intr_mask.b.sofintr = 1;
43501 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43502 + intr_mask.d32, intr_mask.d32);
43503 + }
43504 + hcd->periodic_qh_count++;
43505 + }
43506 +
43507 + return status;
43508 +}
43509 +
43510 +/**
43511 + * Removes an interrupt or isochronous transfer from the periodic schedule.
43512 + *
43513 + * @param hcd The HCD state structure for the DWC OTG controller.
43514 + * @param qh QH for the periodic transfer.
43515 + */
43516 +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43517 +{
43518 + int i;
43519 + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43520 +
43521 + /* Update claimed usecs per (micro)frame. */
43522 + hcd->periodic_usecs -= qh->usecs;
43523 +
43524 + if (!microframe_schedule) {
43525 + /* Release the periodic channel reservation. */
43526 + hcd->periodic_channels--;
43527 + } else {
43528 + for (i = 0; i < 8; i++) {
43529 + hcd->frame_usecs[i] += qh->frame_usecs[i];
43530 + qh->frame_usecs[i] = 0;
43531 + }
43532 + }
43533 +}
43534 +
43535 +/**
43536 + * Removes a QH from either the non-periodic or periodic schedule. Memory is
43537 + * not freed.
43538 + *
43539 + * @param hcd The HCD state structure.
43540 + * @param qh QH to remove from schedule. */
43541 +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43542 +{
43543 + gintmsk_data_t intr_mask = {.d32 = 0 };
43544 +
43545 + if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43546 + /* QH is not in a schedule. */
43547 + return;
43548 + }
43549 +
43550 + if (dwc_qh_is_non_per(qh)) {
43551 + if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
43552 + hcd->non_periodic_qh_ptr =
43553 + hcd->non_periodic_qh_ptr->next;
43554 + }
43555 + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43556 + } else {
43557 + deschedule_periodic(hcd, qh);
43558 + hcd->periodic_qh_count--;
43559 + if( !hcd->periodic_qh_count ) {
43560 + intr_mask.b.sofintr = 1;
43561 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43562 + intr_mask.d32, 0);
43563 + }
43564 + }
43565 +}
43566 +
43567 +/**
43568 + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
43569 + * non-periodic schedule. The QH is added to the inactive non-periodic
43570 + * schedule if any QTDs are still attached to the QH.
43571 + *
43572 + * For periodic QHs, the QH is removed from the periodic queued schedule. If
43573 + * there are any QTDs still attached to the QH, the QH is added to either the
43574 + * periodic inactive schedule or the periodic ready schedule and its next
43575 + * scheduled frame is calculated. The QH is placed in the ready schedule if
43576 + * the scheduled frame has been reached already. Otherwise it's placed in the
43577 + * inactive schedule. If there are no QTDs attached to the QH, the QH is
43578 + * completely removed from the periodic schedule.
43579 + */
43580 +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
43581 + int sched_next_periodic_split)
43582 +{
43583 + if (dwc_qh_is_non_per(qh)) {
43584 +
43585 + dwc_otg_qh_t *qh_tmp;
43586 + dwc_list_link_t *qh_list;
43587 + DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
43588 + {
43589 + qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
43590 + if(qh_tmp == qh)
43591 + {
43592 + /*
43593 + * FIQ is being disabled because this one nevers gets a np_count increment
43594 + * This is still not absolutely correct, but it should fix itself with
43595 + * just an unnecessary extra interrupt
43596 + */
43597 + g_np_sent = g_np_count;
43598 + }
43599 + }
43600 +
43601 +
43602 + dwc_otg_hcd_qh_remove(hcd, qh);
43603 + if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43604 + /* Add back to inactive non-periodic schedule. */
43605 + dwc_otg_hcd_qh_add(hcd, qh);
43606 + }
43607 + } else {
43608 + uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
43609 +
43610 + if (qh->do_split) {
43611 + /* Schedule the next continuing periodic split transfer */
43612 + if (sched_next_periodic_split) {
43613 +
43614 + qh->sched_frame = frame_number;
43615 +
43616 + if (dwc_frame_num_le(frame_number,
43617 + dwc_frame_num_inc
43618 + (qh->start_split_frame,
43619 + 1))) {
43620 + /*
43621 + * Allow one frame to elapse after start
43622 + * split microframe before scheduling
43623 + * complete split, but DONT if we are
43624 + * doing the next start split in the
43625 + * same frame for an ISOC out.
43626 + */
43627 + if ((qh->ep_type != UE_ISOCHRONOUS) ||
43628 + (qh->ep_is_in != 0)) {
43629 + qh->sched_frame =
43630 + dwc_frame_num_inc(qh->sched_frame, 1);
43631 + }
43632 + }
43633 + } else {
43634 + qh->sched_frame =
43635 + dwc_frame_num_inc(qh->start_split_frame,
43636 + qh->interval);
43637 + if (dwc_frame_num_le
43638 + (qh->sched_frame, frame_number)) {
43639 + qh->sched_frame = frame_number;
43640 + }
43641 + qh->sched_frame |= 0x7;
43642 + qh->start_split_frame = qh->sched_frame;
43643 + }
43644 + } else {
43645 + qh->sched_frame =
43646 + dwc_frame_num_inc(qh->sched_frame, qh->interval);
43647 + if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
43648 + qh->sched_frame = frame_number;
43649 + }
43650 + }
43651 +
43652 + if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43653 + dwc_otg_hcd_qh_remove(hcd, qh);
43654 + } else {
43655 + /*
43656 + * Remove from periodic_sched_queued and move to
43657 + * appropriate queue.
43658 + */
43659 + if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||
43660 + (!microframe_schedule && qh->sched_frame == frame_number)) {
43661 + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
43662 + &qh->qh_list_entry);
43663 + } else {
43664 + if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
43665 + {
43666 + g_next_sched_frame = qh->sched_frame;
43667 + }
43668 +
43669 + DWC_LIST_MOVE_HEAD
43670 + (&hcd->periodic_sched_inactive,
43671 + &qh->qh_list_entry);
43672 + }
43673 + }
43674 + }
43675 +}
43676 +
43677 +/**
43678 + * This function allocates and initializes a QTD.
43679 + *
43680 + * @param urb The URB to create a QTD from. Each URB-QTD pair will end up
43681 + * pointing to each other so each pair should have a unique correlation.
43682 + * @param atomic_alloc Flag to do atomic alloc if needed
43683 + *
43684 + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
43685 +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43686 +{
43687 + dwc_otg_qtd_t *qtd;
43688 +
43689 + qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);
43690 + if (qtd == NULL) {
43691 + return NULL;
43692 + }
43693 +
43694 + dwc_otg_hcd_qtd_init(qtd, urb);
43695 + return qtd;
43696 +}
43697 +
43698 +/**
43699 + * Initializes a QTD structure.
43700 + *
43701 + * @param qtd The QTD to initialize.
43702 + * @param urb The URB to use for initialization. */
43703 +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
43704 +{
43705 + dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
43706 + qtd->urb = urb;
43707 + if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
43708 + /*
43709 + * The only time the QTD data toggle is used is on the data
43710 + * phase of control transfers. This phase always starts with
43711 + * DATA1.
43712 + */
43713 + qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
43714 + qtd->control_phase = DWC_OTG_CONTROL_SETUP;
43715 + }
43716 +
43717 + /* start split */
43718 + qtd->complete_split = 0;
43719 + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
43720 + qtd->isoc_split_offset = 0;
43721 + qtd->in_process = 0;
43722 +
43723 + /* Store the qtd ptr in the urb to reference what QTD. */
43724 + urb->qtd = qtd;
43725 + return;
43726 +}
43727 +
43728 +/**
43729 + * This function adds a QTD to the QTD-list of a QH. It will find the correct
43730 + * QH to place the QTD into. If it does not find a QH, then it will create a
43731 + * new QH. If the QH to which the QTD is added is not currently scheduled, it
43732 + * is placed into the proper schedule based on its EP type.
43733 + *
43734 + * @param[in] qtd The QTD to add
43735 + * @param[in] hcd The DWC HCD structure
43736 + * @param[out] qh out parameter to return queue head
43737 + * @param atomic_alloc Flag to do atomic alloc if needed
43738 + *
43739 + * @return 0 if successful, negative error code otherwise.
43740 + */
43741 +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
43742 + dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
43743 +{
43744 + int retval = 0;
43745 + dwc_irqflags_t flags;
43746 +
43747 + dwc_otg_hcd_urb_t *urb = qtd->urb;
43748 +
43749 + /*
43750 + * Get the QH which holds the QTD-list to insert to. Create QH if it
43751 + * doesn't exist.
43752 + */
43753 + if (*qh == NULL) {
43754 + *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
43755 + if (*qh == NULL) {
43756 + retval = -DWC_E_NO_MEMORY;
43757 + goto done;
43758 + }
43759 + }
43760 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
43761 + retval = dwc_otg_hcd_qh_add(hcd, *qh);
43762 + if (retval == 0) {
43763 + DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
43764 + qtd_list_entry);
43765 + qtd->qh = *qh;
43766 + }
43767 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
43768 +
43769 +done:
43770 +
43771 + return retval;
43772 +}
43773 +
43774 +#endif /* DWC_DEVICE_ONLY */
43775 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
43776 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c 1970-01-01 01:00:00.000000000 +0100
43777 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c 2013-07-06 15:25:50.000000000 +0100
43778 @@ -0,0 +1,113 @@
43779 +#include "dwc_otg_regs.h"
43780 +#include "dwc_otg_dbg.h"
43781 +
43782 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
43783 +{
43784 + DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n"
43785 + "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n"
43786 + "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n"
43787 + "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n"
43788 + "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n"
43789 + "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n"
43790 + "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n"
43791 + "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n"
43792 + "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
43793 + function_name,
43794 + gintsts.b.curmode,
43795 + gintsts.b.modemismatch,
43796 + gintsts.b.otgintr,
43797 + gintsts.b.sofintr,
43798 + gintsts.b.rxstsqlvl,
43799 + gintsts.b.nptxfempty,
43800 + gintsts.b.ginnakeff,
43801 + gintsts.b.goutnakeff,
43802 + gintsts.b.ulpickint,
43803 + gintsts.b.i2cintr,
43804 + gintsts.b.erlysuspend,
43805 + gintsts.b.usbsuspend,
43806 + gintsts.b.usbreset,
43807 + gintsts.b.enumdone,
43808 + gintsts.b.isooutdrop,
43809 + gintsts.b.eopframe,
43810 + gintsts.b.restoredone,
43811 + gintsts.b.epmismatch,
43812 + gintsts.b.inepint,
43813 + gintsts.b.outepintr,
43814 + gintsts.b.incomplisoin,
43815 + gintsts.b.incomplisoout,
43816 + gintsts.b.fetsusp,
43817 + gintsts.b.resetdet,
43818 + gintsts.b.portintr,
43819 + gintsts.b.hcintr,
43820 + gintsts.b.ptxfempty,
43821 + gintsts.b.lpmtranrcvd,
43822 + gintsts.b.conidstschng,
43823 + gintsts.b.disconnect,
43824 + gintsts.b.sessreqintr,
43825 + gintsts.b.wkupintr);
43826 + return;
43827 +}
43828 +
43829 +void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
43830 +{
43831 + DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n"
43832 + "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n"
43833 + "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n"
43834 + "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n"
43835 + "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n"
43836 + "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n"
43837 + "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n"
43838 + "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n"
43839 + "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
43840 + function_name,
43841 + gintmsk.b.modemismatch,
43842 + gintmsk.b.otgintr,
43843 + gintmsk.b.sofintr,
43844 + gintmsk.b.rxstsqlvl,
43845 + gintmsk.b.nptxfempty,
43846 + gintmsk.b.ginnakeff,
43847 + gintmsk.b.goutnakeff,
43848 + gintmsk.b.ulpickint,
43849 + gintmsk.b.i2cintr,
43850 + gintmsk.b.erlysuspend,
43851 + gintmsk.b.usbsuspend,
43852 + gintmsk.b.usbreset,
43853 + gintmsk.b.enumdone,
43854 + gintmsk.b.isooutdrop,
43855 + gintmsk.b.eopframe,
43856 + gintmsk.b.restoredone,
43857 + gintmsk.b.epmismatch,
43858 + gintmsk.b.inepintr,
43859 + gintmsk.b.outepintr,
43860 + gintmsk.b.incomplisoin,
43861 + gintmsk.b.incomplisoout,
43862 + gintmsk.b.fetsusp,
43863 + gintmsk.b.resetdet,
43864 + gintmsk.b.portintr,
43865 + gintmsk.b.hcintr,
43866 + gintmsk.b.ptxfempty,
43867 + gintmsk.b.lpmtranrcvd,
43868 + gintmsk.b.conidstschng,
43869 + gintmsk.b.disconnect,
43870 + gintmsk.b.sessreqintr,
43871 + gintmsk.b.wkupintr);
43872 + return;
43873 +}
43874 +
43875 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
43876 +{
43877 + DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n"
43878 + "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n"
43879 + "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n"
43880 + "mvic: %1i\n",
43881 + function_name,
43882 + gotgint.b.sesenddet,
43883 + gotgint.b.sesreqsucstschng,
43884 + gotgint.b.hstnegsucstschng,
43885 + gotgint.b.hstnegdet,
43886 + gotgint.b.adevtoutchng,
43887 + gotgint.b.debdone,
43888 + gotgint.b.mvic);
43889 +
43890 + return;
43891 +}
43892 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
43893 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h 1970-01-01 01:00:00.000000000 +0100
43894 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h 2013-07-06 15:25:50.000000000 +0100
43895 @@ -0,0 +1,36 @@
43896 +#ifndef __DWC_OTG_MPHI_FIX_H__
43897 +#define __DWC_OTG_MPHI_FIX_H__
43898 +
43899 +#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_
43900 +#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_)
43901 +#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_)
43902 +#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_
43903 +
43904 +typedef struct {
43905 + volatile void* base;
43906 + volatile void* ctrl;
43907 + volatile void* outdda;
43908 + volatile void* outddb;
43909 + volatile void* intstat;
43910 +} mphi_regs_t;
43911 +
43912 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
43913 +void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
43914 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
43915 +
43916 +
43917 +
43918 +#ifdef DEBUG
43919 +#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
43920 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
43921 +#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
43922 +
43923 +#else
43924 +#define DWC_DBG_PRINT_CORE_INT(_arg_)
43925 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
43926 +#define DWC_DBG_PRINT_OTG_INT(_arg_)
43927 +
43928 +
43929 +#endif
43930 +
43931 +#endif
43932 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43933 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1970-01-01 01:00:00.000000000 +0100
43934 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2013-07-06 15:25:50.000000000 +0100
43935 @@ -0,0 +1,188 @@
43936 +#ifndef _DWC_OS_DEP_H_
43937 +#define _DWC_OS_DEP_H_
43938 +
43939 +/**
43940 + * @file
43941 + *
43942 + * This file contains OS dependent structures.
43943 + *
43944 + */
43945 +
43946 +#include <linux/kernel.h>
43947 +#include <linux/module.h>
43948 +#include <linux/moduleparam.h>
43949 +#include <linux/init.h>
43950 +#include <linux/device.h>
43951 +#include <linux/errno.h>
43952 +#include <linux/types.h>
43953 +#include <linux/slab.h>
43954 +#include <linux/list.h>
43955 +#include <linux/interrupt.h>
43956 +#include <linux/ctype.h>
43957 +#include <linux/string.h>
43958 +#include <linux/dma-mapping.h>
43959 +#include <linux/jiffies.h>
43960 +#include <linux/delay.h>
43961 +#include <linux/timer.h>
43962 +#include <linux/workqueue.h>
43963 +#include <linux/stat.h>
43964 +#include <linux/pci.h>
43965 +
43966 +#include <linux/version.h>
43967 +
43968 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
43969 +# include <linux/irq.h>
43970 +#endif
43971 +
43972 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
43973 +# include <linux/usb/ch9.h>
43974 +#else
43975 +# include <linux/usb_ch9.h>
43976 +#endif
43977 +
43978 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
43979 +# include <linux/usb/gadget.h>
43980 +#else
43981 +# include <linux/usb_gadget.h>
43982 +#endif
43983 +
43984 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
43985 +# include <asm/irq.h>
43986 +#endif
43987 +
43988 +#ifdef PCI_INTERFACE
43989 +# include <asm/io.h>
43990 +#endif
43991 +
43992 +#ifdef LM_INTERFACE
43993 +# include <asm/unaligned.h>
43994 +# include <asm/sizes.h>
43995 +# include <asm/param.h>
43996 +# include <asm/io.h>
43997 +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
43998 +# include <asm/arch/hardware.h>
43999 +# include <asm/arch/lm.h>
44000 +# include <asm/arch/irqs.h>
44001 +# include <asm/arch/regs-irq.h>
44002 +# else
44003 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
44004 + here we assume that the machine architecture provides definitions
44005 + in its own header
44006 +*/
44007 +# include <mach/lm.h>
44008 +# include <mach/hardware.h>
44009 +# endif
44010 +#endif
44011 +
44012 +#ifdef PLATFORM_INTERFACE
44013 +#include <linux/platform_device.h>
44014 +#include <asm/mach/map.h>
44015 +#endif
44016 +
44017 +/** The OS page size */
44018 +#define DWC_OS_PAGE_SIZE PAGE_SIZE
44019 +
44020 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
44021 +typedef int gfp_t;
44022 +#endif
44023 +
44024 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
44025 +# define IRQF_SHARED SA_SHIRQ
44026 +#endif
44027 +
44028 +typedef struct os_dependent {
44029 + /** Base address returned from ioremap() */
44030 + void *base;
44031 +
44032 + /** Register offset for Diagnostic API */
44033 + uint32_t reg_offset;
44034 +
44035 + /** Base address for MPHI peripheral */
44036 + void *mphi_base;
44037 +
44038 +#ifdef LM_INTERFACE
44039 + struct lm_device *lmdev;
44040 +#elif defined(PCI_INTERFACE)
44041 + struct pci_dev *pcidev;
44042 +
44043 + /** Start address of a PCI region */
44044 + resource_size_t rsrc_start;
44045 +
44046 + /** Length address of a PCI region */
44047 + resource_size_t rsrc_len;
44048 +#elif defined(PLATFORM_INTERFACE)
44049 + struct platform_device *platformdev;
44050 +#endif
44051 +
44052 +} os_dependent_t;
44053 +
44054 +#ifdef __cplusplus
44055 +}
44056 +#endif
44057 +
44058 +
44059 +
44060 +/* Type for the our device on the chosen bus */
44061 +#if defined(LM_INTERFACE)
44062 +typedef struct lm_device dwc_bus_dev_t;
44063 +#elif defined(PCI_INTERFACE)
44064 +typedef struct pci_dev dwc_bus_dev_t;
44065 +#elif defined(PLATFORM_INTERFACE)
44066 +typedef struct platform_device dwc_bus_dev_t;
44067 +#endif
44068 +
44069 +/* Helper macro to retrieve drvdata from the device on the chosen bus */
44070 +#if defined(LM_INTERFACE)
44071 +#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)
44072 +#elif defined(PCI_INTERFACE)
44073 +#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)
44074 +#elif defined(PLATFORM_INTERFACE)
44075 +#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)
44076 +#endif
44077 +
44078 +/**
44079 + * Helper macro returning the otg_device structure of a given struct device
44080 + *
44081 + * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
44082 + */
44083 +#ifdef LM_INTERFACE
44084 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
44085 + struct lm_device *lm_dev = \
44086 + container_of(_dev, struct lm_device, dev); \
44087 + _var = lm_get_drvdata(lm_dev); \
44088 + } while (0)
44089 +
44090 +#elif defined(PCI_INTERFACE)
44091 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
44092 + _var = dev_get_drvdata(_dev); \
44093 + } while (0)
44094 +
44095 +#elif defined(PLATFORM_INTERFACE)
44096 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
44097 + struct platform_device *platform_dev = \
44098 + container_of(_dev, struct platform_device, dev); \
44099 + _var = platform_get_drvdata(platform_dev); \
44100 + } while (0)
44101 +#endif
44102 +
44103 +
44104 +/**
44105 + * Helper macro returning the struct dev of the given struct os_dependent
44106 + *
44107 + * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)
44108 + */
44109 +#ifdef LM_INTERFACE
44110 +#define DWC_OTG_OS_GETDEV(_osdep) \
44111 + ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)
44112 +#elif defined(PCI_INTERFACE)
44113 +#define DWC_OTG_OS_GETDEV(_osdep) \
44114 + ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)
44115 +#elif defined(PLATFORM_INTERFACE)
44116 +#define DWC_OTG_OS_GETDEV(_osdep) \
44117 + ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)
44118 +#endif
44119 +
44120 +
44121 +
44122 +
44123 +#endif /* _DWC_OS_DEP_H_ */
44124 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
44125 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100
44126 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2013-07-06 15:25:50.000000000 +0100
44127 @@ -0,0 +1,2708 @@
44128 +/* ==========================================================================
44129 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
44130 + * $Revision: #101 $
44131 + * $Date: 2012/08/10 $
44132 + * $Change: 2047372 $
44133 + *
44134 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
44135 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
44136 + * otherwise expressly agreed to in writing between Synopsys and you.
44137 + *
44138 + * The Software IS NOT an item of Licensed Software or Licensed Product under
44139 + * any End User Software License Agreement or Agreement for Licensed Product
44140 + * with Synopsys or any supplement thereto. You are permitted to use and
44141 + * redistribute this Software in source and binary forms, with or without
44142 + * modification, provided that redistributions of source code must retain this
44143 + * notice. You may not view, use, disclose, copy or distribute this file or
44144 + * any information contained herein except pursuant to this license grant from
44145 + * Synopsys. If you do not agree with this notice, including the disclaimer
44146 + * below, then you are not authorized to use the Software.
44147 + *
44148 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
44149 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44150 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44151 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
44152 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
44153 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
44154 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
44155 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44156 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44157 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
44158 + * DAMAGE.
44159 + * ========================================================================== */
44160 +#ifndef DWC_HOST_ONLY
44161 +
44162 +/** @file
44163 + * This file implements PCD Core. All code in this file is portable and doesn't
44164 + * use any OS specific functions.
44165 + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
44166 + * header file, which can be used to implement OS specific PCD interface.
44167 + *
44168 + * An important function of the PCD is managing interrupts generated
44169 + * by the DWC_otg controller. The implementation of the DWC_otg device
44170 + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
44171 + *
44172 + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
44173 + * @todo Does it work when the request size is greater than DEPTSIZ
44174 + * transfer size
44175 + *
44176 + */
44177 +
44178 +#include "dwc_otg_pcd.h"
44179 +
44180 +#ifdef DWC_UTE_CFI
44181 +#include "dwc_otg_cfi.h"
44182 +
44183 +extern int init_cfi(cfiobject_t * cfiobj);
44184 +#endif
44185 +
44186 +/**
44187 + * Choose endpoint from ep arrays using usb_ep structure.
44188 + */
44189 +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
44190 +{
44191 + int i;
44192 + if (pcd->ep0.priv == handle) {
44193 + return &pcd->ep0;
44194 + }
44195 + for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
44196 + if (pcd->in_ep[i].priv == handle)
44197 + return &pcd->in_ep[i];
44198 + if (pcd->out_ep[i].priv == handle)
44199 + return &pcd->out_ep[i];
44200 + }
44201 +
44202 + return NULL;
44203 +}
44204 +
44205 +/**
44206 + * This function completes a request. It call's the request call back.
44207 + */
44208 +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
44209 + int32_t status)
44210 +{
44211 + unsigned stopped = ep->stopped;
44212 +
44213 + DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
44214 + DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
44215 +
44216 + /* don't modify queue heads during completion callback */
44217 + ep->stopped = 1;
44218 + /* spin_unlock/spin_lock now done in fops->complete() */
44219 + ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
44220 + req->actual);
44221 +
44222 + if (ep->pcd->request_pending > 0) {
44223 + --ep->pcd->request_pending;
44224 + }
44225 +
44226 + ep->stopped = stopped;
44227 + DWC_FREE(req);
44228 +}
44229 +
44230 +/**
44231 + * This function terminates all the requsts in the EP request queue.
44232 + */
44233 +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
44234 +{
44235 + dwc_otg_pcd_request_t *req;
44236 +
44237 + ep->stopped = 1;
44238 +
44239 + /* called with irqs blocked?? */
44240 + while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
44241 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
44242 + dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
44243 + }
44244 +}
44245 +
44246 +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
44247 + const struct dwc_otg_pcd_function_ops *fops)
44248 +{
44249 + pcd->fops = fops;
44250 +}
44251 +
44252 +/**
44253 + * PCD Callback function for initializing the PCD when switching to
44254 + * device mode.
44255 + *
44256 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44257 + */
44258 +static int32_t dwc_otg_pcd_start_cb(void *p)
44259 +{
44260 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44261 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
44262 +
44263 + /*
44264 + * Initialized the Core for Device mode.
44265 + */
44266 + if (dwc_otg_is_device_mode(core_if)) {
44267 + dwc_otg_core_dev_init(core_if);
44268 + /* Set core_if's lock pointer to the pcd->lock */
44269 + core_if->lock = pcd->lock;
44270 + }
44271 + return 1;
44272 +}
44273 +
44274 +/** CFI-specific buffer allocation function for EP */
44275 +#ifdef DWC_UTE_CFI
44276 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
44277 + size_t buflen, int flags)
44278 +{
44279 + dwc_otg_pcd_ep_t *ep;
44280 + ep = get_ep_from_handle(pcd, pep);
44281 + if (!ep) {
44282 + DWC_WARN("bad ep\n");
44283 + return -DWC_E_INVALID;
44284 + }
44285 +
44286 + return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
44287 + flags);
44288 +}
44289 +#else
44290 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
44291 + size_t buflen, int flags);
44292 +#endif
44293 +
44294 +/**
44295 + * PCD Callback function for notifying the PCD when resuming from
44296 + * suspend.
44297 + *
44298 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44299 + */
44300 +static int32_t dwc_otg_pcd_resume_cb(void *p)
44301 +{
44302 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44303 +
44304 + if (pcd->fops->resume) {
44305 + pcd->fops->resume(pcd);
44306 + }
44307 +
44308 + /* Stop the SRP timeout timer. */
44309 + if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
44310 + || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
44311 + if (GET_CORE_IF(pcd)->srp_timer_started) {
44312 + GET_CORE_IF(pcd)->srp_timer_started = 0;
44313 + DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
44314 + }
44315 + }
44316 + return 1;
44317 +}
44318 +
44319 +/**
44320 + * PCD Callback function for notifying the PCD device is suspended.
44321 + *
44322 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44323 + */
44324 +static int32_t dwc_otg_pcd_suspend_cb(void *p)
44325 +{
44326 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44327 +
44328 + if (pcd->fops->suspend) {
44329 + DWC_SPINUNLOCK(pcd->lock);
44330 + pcd->fops->suspend(pcd);
44331 + DWC_SPINLOCK(pcd->lock);
44332 + }
44333 +
44334 + return 1;
44335 +}
44336 +
44337 +/**
44338 + * PCD Callback function for stopping the PCD when switching to Host
44339 + * mode.
44340 + *
44341 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44342 + */
44343 +static int32_t dwc_otg_pcd_stop_cb(void *p)
44344 +{
44345 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44346 + extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
44347 +
44348 + dwc_otg_pcd_stop(pcd);
44349 + return 1;
44350 +}
44351 +
44352 +/**
44353 + * PCD Callback structure for handling mode switching.
44354 + */
44355 +static dwc_otg_cil_callbacks_t pcd_callbacks = {
44356 + .start = dwc_otg_pcd_start_cb,
44357 + .stop = dwc_otg_pcd_stop_cb,
44358 + .suspend = dwc_otg_pcd_suspend_cb,
44359 + .resume_wakeup = dwc_otg_pcd_resume_cb,
44360 + .p = 0, /* Set at registration */
44361 +};
44362 +
44363 +/**
44364 + * This function allocates a DMA Descriptor chain for the Endpoint
44365 + * buffer to be used for a transfer to/from the specified endpoint.
44366 + */
44367 +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
44368 + uint32_t count)
44369 +{
44370 + return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t),
44371 + dma_desc_addr);
44372 +}
44373 +
44374 +/**
44375 + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
44376 + */
44377 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
44378 + uint32_t dma_desc_addr, uint32_t count)
44379 +{
44380 + DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
44381 + dma_desc_addr);
44382 +}
44383 +
44384 +#ifdef DWC_EN_ISOC
44385 +
44386 +/**
44387 + * This function initializes a descriptor chain for Isochronous transfer
44388 + *
44389 + * @param core_if Programming view of DWC_otg controller.
44390 + * @param dwc_ep The EP to start the transfer on.
44391 + *
44392 + */
44393 +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
44394 + dwc_ep_t * dwc_ep)
44395 +{
44396 +
44397 + dsts_data_t dsts = {.d32 = 0 };
44398 + depctl_data_t depctl = {.d32 = 0 };
44399 + volatile uint32_t *addr;
44400 + int i, j;
44401 + uint32_t len;
44402 +
44403 + if (dwc_ep->is_in)
44404 + dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
44405 + else
44406 + dwc_ep->desc_cnt =
44407 + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44408 + dwc_ep->bInterval;
44409 +
44410 + /** Allocate descriptors for double buffering */
44411 + dwc_ep->iso_desc_addr =
44412 + dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
44413 + dwc_ep->desc_cnt * 2);
44414 + if (dwc_ep->desc_addr) {
44415 + DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
44416 + return;
44417 + }
44418 +
44419 + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44420 +
44421 + /** ISO OUT EP */
44422 + if (dwc_ep->is_in == 0) {
44423 + dev_dma_desc_sts_t sts = {.d32 = 0 };
44424 + dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44425 + dma_addr_t dma_ad;
44426 + uint32_t data_per_desc;
44427 + dwc_otg_dev_out_ep_regs_t *out_regs =
44428 + core_if->dev_if->out_ep_regs[dwc_ep->num];
44429 + int offset;
44430 +
44431 + addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
44432 + dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
44433 +
44434 + /** Buffer 0 descriptors setup */
44435 + dma_ad = dwc_ep->dma_addr0;
44436 +
44437 + sts.b_iso_out.bs = BS_HOST_READY;
44438 + sts.b_iso_out.rxsts = 0;
44439 + sts.b_iso_out.l = 0;
44440 + sts.b_iso_out.sp = 0;
44441 + sts.b_iso_out.ioc = 0;
44442 + sts.b_iso_out.pid = 0;
44443 + sts.b_iso_out.framenum = 0;
44444 +
44445 + offset = 0;
44446 + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44447 + i += dwc_ep->pkt_per_frm) {
44448 +
44449 + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44450 + uint32_t len = (j + 1) * dwc_ep->maxpacket;
44451 + if (len > dwc_ep->data_per_frame)
44452 + data_per_desc =
44453 + dwc_ep->data_per_frame -
44454 + j * dwc_ep->maxpacket;
44455 + else
44456 + data_per_desc = dwc_ep->maxpacket;
44457 + len = data_per_desc % 4;
44458 + if (len)
44459 + data_per_desc += 4 - len;
44460 +
44461 + sts.b_iso_out.rxbytes = data_per_desc;
44462 + dma_desc->buf = dma_ad;
44463 + dma_desc->status.d32 = sts.d32;
44464 +
44465 + offset += data_per_desc;
44466 + dma_desc++;
44467 + dma_ad += data_per_desc;
44468 + }
44469 + }
44470 +
44471 + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44472 + uint32_t len = (j + 1) * dwc_ep->maxpacket;
44473 + if (len > dwc_ep->data_per_frame)
44474 + data_per_desc =
44475 + dwc_ep->data_per_frame -
44476 + j * dwc_ep->maxpacket;
44477 + else
44478 + data_per_desc = dwc_ep->maxpacket;
44479 + len = data_per_desc % 4;
44480 + if (len)
44481 + data_per_desc += 4 - len;
44482 + sts.b_iso_out.rxbytes = data_per_desc;
44483 + dma_desc->buf = dma_ad;
44484 + dma_desc->status.d32 = sts.d32;
44485 +
44486 + offset += data_per_desc;
44487 + dma_desc++;
44488 + dma_ad += data_per_desc;
44489 + }
44490 +
44491 + sts.b_iso_out.ioc = 1;
44492 + len = (j + 1) * dwc_ep->maxpacket;
44493 + if (len > dwc_ep->data_per_frame)
44494 + data_per_desc =
44495 + dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
44496 + else
44497 + data_per_desc = dwc_ep->maxpacket;
44498 + len = data_per_desc % 4;
44499 + if (len)
44500 + data_per_desc += 4 - len;
44501 + sts.b_iso_out.rxbytes = data_per_desc;
44502 +
44503 + dma_desc->buf = dma_ad;
44504 + dma_desc->status.d32 = sts.d32;
44505 + dma_desc++;
44506 +
44507 + /** Buffer 1 descriptors setup */
44508 + sts.b_iso_out.ioc = 0;
44509 + dma_ad = dwc_ep->dma_addr1;
44510 +
44511 + offset = 0;
44512 + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44513 + i += dwc_ep->pkt_per_frm) {
44514 + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44515 + uint32_t len = (j + 1) * dwc_ep->maxpacket;
44516 + if (len > dwc_ep->data_per_frame)
44517 + data_per_desc =
44518 + dwc_ep->data_per_frame -
44519 + j * dwc_ep->maxpacket;
44520 + else
44521 + data_per_desc = dwc_ep->maxpacket;
44522 + len = data_per_desc % 4;
44523 + if (len)
44524 + data_per_desc += 4 - len;
44525 +
44526 + data_per_desc =
44527 + sts.b_iso_out.rxbytes = data_per_desc;
44528 + dma_desc->buf = dma_ad;
44529 + dma_desc->status.d32 = sts.d32;
44530 +
44531 + offset += data_per_desc;
44532 + dma_desc++;
44533 + dma_ad += data_per_desc;
44534 + }
44535 + }
44536 + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44537 + data_per_desc =
44538 + ((j + 1) * dwc_ep->maxpacket >
44539 + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44540 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44541 + data_per_desc +=
44542 + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44543 + sts.b_iso_out.rxbytes = data_per_desc;
44544 + dma_desc->buf = dma_ad;
44545 + dma_desc->status.d32 = sts.d32;
44546 +
44547 + offset += data_per_desc;
44548 + dma_desc++;
44549 + dma_ad += data_per_desc;
44550 + }
44551 +
44552 + sts.b_iso_out.ioc = 1;
44553 + sts.b_iso_out.l = 1;
44554 + data_per_desc =
44555 + ((j + 1) * dwc_ep->maxpacket >
44556 + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44557 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44558 + data_per_desc +=
44559 + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44560 + sts.b_iso_out.rxbytes = data_per_desc;
44561 +
44562 + dma_desc->buf = dma_ad;
44563 + dma_desc->status.d32 = sts.d32;
44564 +
44565 + dwc_ep->next_frame = 0;
44566 +
44567 + /** Write dma_ad into DOEPDMA register */
44568 + DWC_WRITE_REG32(&(out_regs->doepdma),
44569 + (uint32_t) dwc_ep->iso_dma_desc_addr);
44570 +
44571 + }
44572 + /** ISO IN EP */
44573 + else {
44574 + dev_dma_desc_sts_t sts = {.d32 = 0 };
44575 + dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44576 + dma_addr_t dma_ad;
44577 + dwc_otg_dev_in_ep_regs_t *in_regs =
44578 + core_if->dev_if->in_ep_regs[dwc_ep->num];
44579 + unsigned int frmnumber;
44580 + fifosize_data_t txfifosize, rxfifosize;
44581 +
44582 + txfifosize.d32 =
44583 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
44584 + dtxfsts);
44585 + rxfifosize.d32 =
44586 + DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
44587 +
44588 + addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
44589 +
44590 + dma_ad = dwc_ep->dma_addr0;
44591 +
44592 + dsts.d32 =
44593 + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44594 +
44595 + sts.b_iso_in.bs = BS_HOST_READY;
44596 + sts.b_iso_in.txsts = 0;
44597 + sts.b_iso_in.sp =
44598 + (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
44599 + sts.b_iso_in.ioc = 0;
44600 + sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
44601 +
44602 + frmnumber = dwc_ep->next_frame;
44603 +
44604 + sts.b_iso_in.framenum = frmnumber;
44605 + sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
44606 + sts.b_iso_in.l = 0;
44607 +
44608 + /** Buffer 0 descriptors setup */
44609 + for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
44610 + dma_desc->buf = dma_ad;
44611 + dma_desc->status.d32 = sts.d32;
44612 + dma_desc++;
44613 +
44614 + dma_ad += dwc_ep->data_per_frame;
44615 + sts.b_iso_in.framenum += dwc_ep->bInterval;
44616 + }
44617 +
44618 + sts.b_iso_in.ioc = 1;
44619 + dma_desc->buf = dma_ad;
44620 + dma_desc->status.d32 = sts.d32;
44621 + ++dma_desc;
44622 +
44623 + /** Buffer 1 descriptors setup */
44624 + sts.b_iso_in.ioc = 0;
44625 + dma_ad = dwc_ep->dma_addr1;
44626 +
44627 + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44628 + i += dwc_ep->pkt_per_frm) {
44629 + dma_desc->buf = dma_ad;
44630 + dma_desc->status.d32 = sts.d32;
44631 + dma_desc++;
44632 +
44633 + dma_ad += dwc_ep->data_per_frame;
44634 + sts.b_iso_in.framenum += dwc_ep->bInterval;
44635 +
44636 + sts.b_iso_in.ioc = 0;
44637 + }
44638 + sts.b_iso_in.ioc = 1;
44639 + sts.b_iso_in.l = 1;
44640 +
44641 + dma_desc->buf = dma_ad;
44642 + dma_desc->status.d32 = sts.d32;
44643 +
44644 + dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
44645 +
44646 + /** Write dma_ad into diepdma register */
44647 + DWC_WRITE_REG32(&(in_regs->diepdma),
44648 + (uint32_t) dwc_ep->iso_dma_desc_addr);
44649 + }
44650 + /** Enable endpoint, clear nak */
44651 + depctl.d32 = 0;
44652 + depctl.b.epena = 1;
44653 + depctl.b.usbactep = 1;
44654 + depctl.b.cnak = 1;
44655 +
44656 + DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44657 + depctl.d32 = DWC_READ_REG32(addr);
44658 +}
44659 +
44660 +/**
44661 + * This function initializes a descriptor chain for Isochronous transfer
44662 + *
44663 + * @param core_if Programming view of DWC_otg controller.
44664 + * @param ep The EP to start the transfer on.
44665 + *
44666 + */
44667 +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
44668 + dwc_ep_t * ep)
44669 +{
44670 + depctl_data_t depctl = {.d32 = 0 };
44671 + volatile uint32_t *addr;
44672 +
44673 + if (ep->is_in) {
44674 + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44675 + } else {
44676 + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44677 + }
44678 +
44679 + if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
44680 + return;
44681 + } else {
44682 + deptsiz_data_t deptsiz = {.d32 = 0 };
44683 +
44684 + ep->xfer_len =
44685 + ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
44686 + ep->pkt_cnt =
44687 + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44688 + ep->xfer_count = 0;
44689 + ep->xfer_buff =
44690 + (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44691 + ep->dma_addr =
44692 + (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44693 +
44694 + if (ep->is_in) {
44695 + /* Program the transfer size and packet count
44696 + * as follows: xfersize = N * maxpacket +
44697 + * short_packet pktcnt = N + (short_packet
44698 + * exist ? 1 : 0)
44699 + */
44700 + deptsiz.b.mc = ep->pkt_per_frm;
44701 + deptsiz.b.xfersize = ep->xfer_len;
44702 + deptsiz.b.pktcnt =
44703 + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44704 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
44705 + dieptsiz, deptsiz.d32);
44706 +
44707 + /* Write the DMA register */
44708 + DWC_WRITE_REG32(&
44709 + (core_if->dev_if->in_ep_regs[ep->num]->
44710 + diepdma), (uint32_t) ep->dma_addr);
44711 +
44712 + } else {
44713 + deptsiz.b.pktcnt =
44714 + (ep->xfer_len + (ep->maxpacket - 1)) /
44715 + ep->maxpacket;
44716 + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
44717 +
44718 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
44719 + doeptsiz, deptsiz.d32);
44720 +
44721 + /* Write the DMA register */
44722 + DWC_WRITE_REG32(&
44723 + (core_if->dev_if->out_ep_regs[ep->num]->
44724 + doepdma), (uint32_t) ep->dma_addr);
44725 +
44726 + }
44727 + /** Enable endpoint, clear nak */
44728 + depctl.d32 = 0;
44729 + depctl.b.epena = 1;
44730 + depctl.b.cnak = 1;
44731 +
44732 + DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44733 + }
44734 +}
44735 +
44736 +/**
44737 + * This function does the setup for a data transfer for an EP and
44738 + * starts the transfer. For an IN transfer, the packets will be
44739 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
44740 + * the packets are unloaded from the Rx FIFO in the ISR.
44741 + *
44742 + * @param core_if Programming view of DWC_otg controller.
44743 + * @param ep The EP to start the transfer on.
44744 + */
44745 +
44746 +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
44747 + dwc_ep_t * ep)
44748 +{
44749 + if (core_if->dma_enable) {
44750 + if (core_if->dma_desc_enable) {
44751 + if (ep->is_in) {
44752 + ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
44753 + } else {
44754 + ep->desc_cnt = ep->pkt_cnt;
44755 + }
44756 + dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
44757 + } else {
44758 + if (core_if->pti_enh_enable) {
44759 + dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
44760 + } else {
44761 + ep->cur_pkt_addr =
44762 + (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
44763 + xfer_buff0;
44764 + ep->cur_pkt_dma_addr =
44765 + (ep->proc_buf_num) ? ep->dma_addr1 : ep->
44766 + dma_addr0;
44767 + dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44768 + }
44769 + }
44770 + } else {
44771 + ep->cur_pkt_addr =
44772 + (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44773 + ep->cur_pkt_dma_addr =
44774 + (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44775 + dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44776 + }
44777 +}
44778 +
44779 +/**
44780 + * This function stops transfer for an EP and
44781 + * resets the ep's variables.
44782 + *
44783 + * @param core_if Programming view of DWC_otg controller.
44784 + * @param ep The EP to start the transfer on.
44785 + */
44786 +
44787 +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
44788 +{
44789 + depctl_data_t depctl = {.d32 = 0 };
44790 + volatile uint32_t *addr;
44791 +
44792 + if (ep->is_in == 1) {
44793 + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44794 + } else {
44795 + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44796 + }
44797 +
44798 + /* disable the ep */
44799 + depctl.d32 = DWC_READ_REG32(addr);
44800 +
44801 + depctl.b.epdis = 1;
44802 + depctl.b.snak = 1;
44803 +
44804 + DWC_WRITE_REG32(addr, depctl.d32);
44805 +
44806 + if (core_if->dma_desc_enable &&
44807 + ep->iso_desc_addr && ep->iso_dma_desc_addr) {
44808 + dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
44809 + ep->iso_dma_desc_addr,
44810 + ep->desc_cnt * 2);
44811 + }
44812 +
44813 + /* reset varibales */
44814 + ep->dma_addr0 = 0;
44815 + ep->dma_addr1 = 0;
44816 + ep->xfer_buff0 = 0;
44817 + ep->xfer_buff1 = 0;
44818 + ep->data_per_frame = 0;
44819 + ep->data_pattern_frame = 0;
44820 + ep->sync_frame = 0;
44821 + ep->buf_proc_intrvl = 0;
44822 + ep->bInterval = 0;
44823 + ep->proc_buf_num = 0;
44824 + ep->pkt_per_frm = 0;
44825 + ep->pkt_per_frm = 0;
44826 + ep->desc_cnt = 0;
44827 + ep->iso_desc_addr = 0;
44828 + ep->iso_dma_desc_addr = 0;
44829 +}
44830 +
44831 +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
44832 + uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
44833 + dwc_dma_t dma1, int sync_frame, int dp_frame,
44834 + int data_per_frame, int start_frame,
44835 + int buf_proc_intrvl, void *req_handle,
44836 + int atomic_alloc)
44837 +{
44838 + dwc_otg_pcd_ep_t *ep;
44839 + dwc_irqflags_t flags = 0;
44840 + dwc_ep_t *dwc_ep;
44841 + int32_t frm_data;
44842 + dsts_data_t dsts;
44843 + dwc_otg_core_if_t *core_if;
44844 +
44845 + ep = get_ep_from_handle(pcd, ep_handle);
44846 +
44847 + if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44848 + DWC_WARN("bad ep\n");
44849 + return -DWC_E_INVALID;
44850 + }
44851 +
44852 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44853 + core_if = GET_CORE_IF(pcd);
44854 + dwc_ep = &ep->dwc_ep;
44855 +
44856 + if (ep->iso_req_handle) {
44857 + DWC_WARN("ISO request in progress\n");
44858 + }
44859 +
44860 + dwc_ep->dma_addr0 = dma0;
44861 + dwc_ep->dma_addr1 = dma1;
44862 +
44863 + dwc_ep->xfer_buff0 = buf0;
44864 + dwc_ep->xfer_buff1 = buf1;
44865 +
44866 + dwc_ep->data_per_frame = data_per_frame;
44867 +
44868 + /** @todo - pattern data support is to be implemented in the future */
44869 + dwc_ep->data_pattern_frame = dp_frame;
44870 + dwc_ep->sync_frame = sync_frame;
44871 +
44872 + dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
44873 +
44874 + dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
44875 +
44876 + dwc_ep->proc_buf_num = 0;
44877 +
44878 + dwc_ep->pkt_per_frm = 0;
44879 + frm_data = ep->dwc_ep.data_per_frame;
44880 + while (frm_data > 0) {
44881 + dwc_ep->pkt_per_frm++;
44882 + frm_data -= ep->dwc_ep.maxpacket;
44883 + }
44884 +
44885 + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44886 +
44887 + if (start_frame == -1) {
44888 + dwc_ep->next_frame = dsts.b.soffn + 1;
44889 + if (dwc_ep->bInterval != 1) {
44890 + dwc_ep->next_frame =
44891 + dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
44892 + dwc_ep->next_frame %
44893 + dwc_ep->bInterval);
44894 + }
44895 + } else {
44896 + dwc_ep->next_frame = start_frame;
44897 + }
44898 +
44899 + if (!core_if->pti_enh_enable) {
44900 + dwc_ep->pkt_cnt =
44901 + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44902 + dwc_ep->bInterval;
44903 + } else {
44904 + dwc_ep->pkt_cnt =
44905 + (dwc_ep->data_per_frame *
44906 + (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
44907 + - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
44908 + }
44909 +
44910 + if (core_if->dma_desc_enable) {
44911 + dwc_ep->desc_cnt =
44912 + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44913 + dwc_ep->bInterval;
44914 + }
44915 +
44916 + if (atomic_alloc) {
44917 + dwc_ep->pkt_info =
44918 + DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44919 + } else {
44920 + dwc_ep->pkt_info =
44921 + DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44922 + }
44923 + if (!dwc_ep->pkt_info) {
44924 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44925 + return -DWC_E_NO_MEMORY;
44926 + }
44927 + if (core_if->pti_enh_enable) {
44928 + dwc_memset(dwc_ep->pkt_info, 0,
44929 + sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44930 + }
44931 +
44932 + dwc_ep->cur_pkt = 0;
44933 + ep->iso_req_handle = req_handle;
44934 +
44935 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44936 + dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
44937 + return 0;
44938 +}
44939 +
44940 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
44941 + void *req_handle)
44942 +{
44943 + dwc_irqflags_t flags = 0;
44944 + dwc_otg_pcd_ep_t *ep;
44945 + dwc_ep_t *dwc_ep;
44946 +
44947 + ep = get_ep_from_handle(pcd, ep_handle);
44948 + if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44949 + DWC_WARN("bad ep\n");
44950 + return -DWC_E_INVALID;
44951 + }
44952 + dwc_ep = &ep->dwc_ep;
44953 +
44954 + dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
44955 +
44956 + DWC_FREE(dwc_ep->pkt_info);
44957 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44958 + if (ep->iso_req_handle != req_handle) {
44959 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44960 + return -DWC_E_INVALID;
44961 + }
44962 +
44963 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44964 +
44965 + ep->iso_req_handle = 0;
44966 + return 0;
44967 +}
44968 +
44969 +/**
44970 + * This function is used for perodical data exchnage between PCD and gadget drivers.
44971 + * for Isochronous EPs
44972 + *
44973 + * - Every time a sync period completes this function is called to
44974 + * perform data exchange between PCD and gadget
44975 + */
44976 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
44977 + void *req_handle)
44978 +{
44979 + int i;
44980 + dwc_ep_t *dwc_ep;
44981 +
44982 + dwc_ep = &ep->dwc_ep;
44983 +
44984 + DWC_SPINUNLOCK(ep->pcd->lock);
44985 + pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
44986 + dwc_ep->proc_buf_num ^ 0x1);
44987 + DWC_SPINLOCK(ep->pcd->lock);
44988 +
44989 + for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
44990 + dwc_ep->pkt_info[i].status = 0;
44991 + dwc_ep->pkt_info[i].offset = 0;
44992 + dwc_ep->pkt_info[i].length = 0;
44993 + }
44994 +}
44995 +
44996 +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
44997 + void *iso_req_handle)
44998 +{
44999 + dwc_otg_pcd_ep_t *ep;
45000 + dwc_ep_t *dwc_ep;
45001 +
45002 + ep = get_ep_from_handle(pcd, ep_handle);
45003 + if (!ep->desc || ep->dwc_ep.num == 0) {
45004 + DWC_WARN("bad ep\n");
45005 + return -DWC_E_INVALID;
45006 + }
45007 + dwc_ep = &ep->dwc_ep;
45008 +
45009 + return dwc_ep->pkt_cnt;
45010 +}
45011 +
45012 +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
45013 + void *iso_req_handle, int packet,
45014 + int *status, int *actual, int *offset)
45015 +{
45016 + dwc_otg_pcd_ep_t *ep;
45017 + dwc_ep_t *dwc_ep;
45018 +
45019 + ep = get_ep_from_handle(pcd, ep_handle);
45020 + if (!ep)
45021 + DWC_WARN("bad ep\n");
45022 +
45023 + dwc_ep = &ep->dwc_ep;
45024 +
45025 + *status = dwc_ep->pkt_info[packet].status;
45026 + *actual = dwc_ep->pkt_info[packet].length;
45027 + *offset = dwc_ep->pkt_info[packet].offset;
45028 +}
45029 +
45030 +#endif /* DWC_EN_ISOC */
45031 +
45032 +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
45033 + uint32_t is_in, uint32_t ep_num)
45034 +{
45035 + /* Init EP structure */
45036 + pcd_ep->desc = 0;
45037 + pcd_ep->pcd = pcd;
45038 + pcd_ep->stopped = 1;
45039 + pcd_ep->queue_sof = 0;
45040 +
45041 + /* Init DWC ep structure */
45042 + pcd_ep->dwc_ep.is_in = is_in;
45043 + pcd_ep->dwc_ep.num = ep_num;
45044 + pcd_ep->dwc_ep.active = 0;
45045 + pcd_ep->dwc_ep.tx_fifo_num = 0;
45046 + /* Control until ep is actvated */
45047 + pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
45048 + pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
45049 + pcd_ep->dwc_ep.dma_addr = 0;
45050 + pcd_ep->dwc_ep.start_xfer_buff = 0;
45051 + pcd_ep->dwc_ep.xfer_buff = 0;
45052 + pcd_ep->dwc_ep.xfer_len = 0;
45053 + pcd_ep->dwc_ep.xfer_count = 0;
45054 + pcd_ep->dwc_ep.sent_zlp = 0;
45055 + pcd_ep->dwc_ep.total_len = 0;
45056 + pcd_ep->dwc_ep.desc_addr = 0;
45057 + pcd_ep->dwc_ep.dma_desc_addr = 0;
45058 + DWC_CIRCLEQ_INIT(&pcd_ep->queue);
45059 +}
45060 +
45061 +/**
45062 + * Initialize ep's
45063 + */
45064 +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
45065 +{
45066 + int i;
45067 + uint32_t hwcfg1;
45068 + dwc_otg_pcd_ep_t *ep;
45069 + int in_ep_cntr, out_ep_cntr;
45070 + uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
45071 + uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
45072 +
45073 + /**
45074 + * Initialize the EP0 structure.
45075 + */
45076 + ep = &pcd->ep0;
45077 + dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
45078 +
45079 + in_ep_cntr = 0;
45080 + hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
45081 + for (i = 1; in_ep_cntr < num_in_eps; i++) {
45082 + if ((hwcfg1 & 0x1) == 0) {
45083 + dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
45084 + in_ep_cntr++;
45085 + /**
45086 + * @todo NGS: Add direction to EP, based on contents
45087 + * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
45088 + * sprintf(";r
45089 + */
45090 + dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
45091 +
45092 + DWC_CIRCLEQ_INIT(&ep->queue);
45093 + }
45094 + hwcfg1 >>= 2;
45095 + }
45096 +
45097 + out_ep_cntr = 0;
45098 + hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
45099 + for (i = 1; out_ep_cntr < num_out_eps; i++) {
45100 + if ((hwcfg1 & 0x1) == 0) {
45101 + dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
45102 + out_ep_cntr++;
45103 + /**
45104 + * @todo NGS: Add direction to EP, based on contents
45105 + * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
45106 + * sprintf(";r
45107 + */
45108 + dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
45109 + DWC_CIRCLEQ_INIT(&ep->queue);
45110 + }
45111 + hwcfg1 >>= 2;
45112 + }
45113 +
45114 + pcd->ep0state = EP0_DISCONNECT;
45115 + pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
45116 + pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
45117 +}
45118 +
45119 +/**
45120 + * This function is called when the SRP timer expires. The SRP should
45121 + * complete within 6 seconds.
45122 + */
45123 +static void srp_timeout(void *ptr)
45124 +{
45125 + gotgctl_data_t gotgctl;
45126 + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
45127 + volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
45128 +
45129 + gotgctl.d32 = DWC_READ_REG32(addr);
45130 +
45131 + core_if->srp_timer_started = 0;
45132 +
45133 + if (core_if->adp_enable) {
45134 + if (gotgctl.b.bsesvld == 0) {
45135 + gpwrdn_data_t gpwrdn = {.d32 = 0 };
45136 + DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
45137 + /* Power off the core */
45138 + if (core_if->power_down == 2) {
45139 + gpwrdn.b.pwrdnswtch = 1;
45140 + DWC_MODIFY_REG32(&core_if->
45141 + core_global_regs->gpwrdn,
45142 + gpwrdn.d32, 0);
45143 + }
45144 +
45145 + gpwrdn.d32 = 0;
45146 + gpwrdn.b.pmuintsel = 1;
45147 + gpwrdn.b.pmuactv = 1;
45148 + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
45149 + gpwrdn.d32);
45150 + dwc_otg_adp_probe_start(core_if);
45151 + } else {
45152 + DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
45153 + core_if->op_state = B_PERIPHERAL;
45154 + dwc_otg_core_init(core_if);
45155 + dwc_otg_enable_global_interrupts(core_if);
45156 + cil_pcd_start(core_if);
45157 + }
45158 + }
45159 +
45160 + if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
45161 + (core_if->core_params->i2c_enable)) {
45162 + DWC_PRINTF("SRP Timeout\n");
45163 +
45164 + if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
45165 + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
45166 + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
45167 + }
45168 +
45169 + /* Clear Session Request */
45170 + gotgctl.d32 = 0;
45171 + gotgctl.b.sesreq = 1;
45172 + DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
45173 + gotgctl.d32, 0);
45174 +
45175 + core_if->srp_success = 0;
45176 + } else {
45177 + __DWC_ERROR("Device not connected/responding\n");
45178 + gotgctl.b.sesreq = 0;
45179 + DWC_WRITE_REG32(addr, gotgctl.d32);
45180 + }
45181 + } else if (gotgctl.b.sesreq) {
45182 + DWC_PRINTF("SRP Timeout\n");
45183 +
45184 + __DWC_ERROR("Device not connected/responding\n");
45185 + gotgctl.b.sesreq = 0;
45186 + DWC_WRITE_REG32(addr, gotgctl.d32);
45187 + } else {
45188 + DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
45189 + }
45190 +}
45191 +
45192 +/**
45193 + * Tasklet
45194 + *
45195 + */
45196 +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
45197 +
45198 +static void start_xfer_tasklet_func(void *data)
45199 +{
45200 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
45201 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45202 +
45203 + int i;
45204 + depctl_data_t diepctl;
45205 +
45206 + DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
45207 +
45208 + diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
45209 +
45210 + if (pcd->ep0.queue_sof) {
45211 + pcd->ep0.queue_sof = 0;
45212 + start_next_request(&pcd->ep0);
45213 + // break;
45214 + }
45215 +
45216 + for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
45217 + depctl_data_t diepctl;
45218 + diepctl.d32 =
45219 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
45220 +
45221 + if (pcd->in_ep[i].queue_sof) {
45222 + pcd->in_ep[i].queue_sof = 0;
45223 + start_next_request(&pcd->in_ep[i]);
45224 + // break;
45225 + }
45226 + }
45227 +
45228 + return;
45229 +}
45230 +
45231 +/**
45232 + * This function initialized the PCD portion of the driver.
45233 + *
45234 + */
45235 +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
45236 +{
45237 + dwc_otg_pcd_t *pcd = NULL;
45238 + dwc_otg_dev_if_t *dev_if;
45239 + int i;
45240 +
45241 + /*
45242 + * Allocate PCD structure
45243 + */
45244 + pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
45245 +
45246 + if (pcd == NULL) {
45247 + return NULL;
45248 + }
45249 +
45250 + pcd->lock = DWC_SPINLOCK_ALLOC();
45251 + DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
45252 + pcd, core_if);//GRAYG
45253 + if (!pcd->lock) {
45254 + DWC_ERROR("Could not allocate lock for pcd");
45255 + DWC_FREE(pcd);
45256 + return NULL;
45257 + }
45258 + /* Set core_if's lock pointer to hcd->lock */
45259 + core_if->lock = pcd->lock;
45260 + pcd->core_if = core_if;
45261 +
45262 + dev_if = core_if->dev_if;
45263 + dev_if->isoc_ep = NULL;
45264 +
45265 + if (core_if->hwcfg4.b.ded_fifo_en) {
45266 + DWC_PRINTF("Dedicated Tx FIFOs mode\n");
45267 + } else {
45268 + DWC_PRINTF("Shared Tx FIFO mode\n");
45269 + }
45270 +
45271 + /*
45272 + * Initialized the Core for Device mode here if there is nod ADP support.
45273 + * Otherwise it will be done later in dwc_otg_adp_start routine.
45274 + */
45275 + if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
45276 + dwc_otg_core_dev_init(core_if);
45277 + }
45278 +
45279 + /*
45280 + * Register the PCD Callbacks.
45281 + */
45282 + dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
45283 +
45284 + /*
45285 + * Initialize the DMA buffer for SETUP packets
45286 + */
45287 + if (GET_CORE_IF(pcd)->dma_enable) {
45288 + pcd->setup_pkt =
45289 + DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
45290 + &pcd->setup_pkt_dma_handle);
45291 + if (pcd->setup_pkt == NULL) {
45292 + DWC_FREE(pcd);
45293 + return NULL;
45294 + }
45295 +
45296 + pcd->status_buf =
45297 + DWC_DMA_ALLOC(sizeof(uint16_t),
45298 + &pcd->status_buf_dma_handle);
45299 + if (pcd->status_buf == NULL) {
45300 + DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45301 + pcd->setup_pkt, pcd->setup_pkt_dma_handle);
45302 + DWC_FREE(pcd);
45303 + return NULL;
45304 + }
45305 +
45306 + if (GET_CORE_IF(pcd)->dma_desc_enable) {
45307 + dev_if->setup_desc_addr[0] =
45308 + dwc_otg_ep_alloc_desc_chain
45309 + (&dev_if->dma_setup_desc_addr[0], 1);
45310 + dev_if->setup_desc_addr[1] =
45311 + dwc_otg_ep_alloc_desc_chain
45312 + (&dev_if->dma_setup_desc_addr[1], 1);
45313 + dev_if->in_desc_addr =
45314 + dwc_otg_ep_alloc_desc_chain
45315 + (&dev_if->dma_in_desc_addr, 1);
45316 + dev_if->out_desc_addr =
45317 + dwc_otg_ep_alloc_desc_chain
45318 + (&dev_if->dma_out_desc_addr, 1);
45319 + pcd->data_terminated = 0;
45320 +
45321 + if (dev_if->setup_desc_addr[0] == 0
45322 + || dev_if->setup_desc_addr[1] == 0
45323 + || dev_if->in_desc_addr == 0
45324 + || dev_if->out_desc_addr == 0) {
45325 +
45326 + if (dev_if->out_desc_addr)
45327 + dwc_otg_ep_free_desc_chain
45328 + (dev_if->out_desc_addr,
45329 + dev_if->dma_out_desc_addr, 1);
45330 + if (dev_if->in_desc_addr)
45331 + dwc_otg_ep_free_desc_chain
45332 + (dev_if->in_desc_addr,
45333 + dev_if->dma_in_desc_addr, 1);
45334 + if (dev_if->setup_desc_addr[1])
45335 + dwc_otg_ep_free_desc_chain
45336 + (dev_if->setup_desc_addr[1],
45337 + dev_if->dma_setup_desc_addr[1], 1);
45338 + if (dev_if->setup_desc_addr[0])
45339 + dwc_otg_ep_free_desc_chain
45340 + (dev_if->setup_desc_addr[0],
45341 + dev_if->dma_setup_desc_addr[0], 1);
45342 +
45343 + DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45344 + pcd->setup_pkt,
45345 + pcd->setup_pkt_dma_handle);
45346 + DWC_DMA_FREE(sizeof(*pcd->status_buf),
45347 + pcd->status_buf,
45348 + pcd->status_buf_dma_handle);
45349 +
45350 + DWC_FREE(pcd);
45351 +
45352 + return NULL;
45353 + }
45354 + }
45355 + } else {
45356 + pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
45357 + if (pcd->setup_pkt == NULL) {
45358 + DWC_FREE(pcd);
45359 + return NULL;
45360 + }
45361 +
45362 + pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
45363 + if (pcd->status_buf == NULL) {
45364 + DWC_FREE(pcd->setup_pkt);
45365 + DWC_FREE(pcd);
45366 + return NULL;
45367 + }
45368 + }
45369 +
45370 + dwc_otg_pcd_reinit(pcd);
45371 +
45372 + /* Allocate the cfi object for the PCD */
45373 +#ifdef DWC_UTE_CFI
45374 + pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
45375 + if (NULL == pcd->cfi)
45376 + goto fail;
45377 + if (init_cfi(pcd->cfi)) {
45378 + CFI_INFO("%s: Failed to init the CFI object\n", __func__);
45379 + goto fail;
45380 + }
45381 +#endif
45382 +
45383 + /* Initialize tasklets */
45384 + pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
45385 + start_xfer_tasklet_func, pcd);
45386 + pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
45387 + do_test_mode, pcd);
45388 +
45389 + /* Initialize SRP timer */
45390 + core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
45391 +
45392 + if (core_if->core_params->dev_out_nak) {
45393 + /**
45394 + * Initialize xfer timeout timer. Implemented for
45395 + * 2.93a feature "Device DDMA OUT NAK Enhancement"
45396 + */
45397 + for(i = 0; i < MAX_EPS_CHANNELS; i++) {
45398 + pcd->core_if->ep_xfer_timer[i] =
45399 + DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
45400 + &pcd->core_if->ep_xfer_info[i]);
45401 + }
45402 + }
45403 +
45404 + return pcd;
45405 +#ifdef DWC_UTE_CFI
45406 +fail:
45407 +#endif
45408 + if (pcd->setup_pkt)
45409 + DWC_FREE(pcd->setup_pkt);
45410 + if (pcd->status_buf)
45411 + DWC_FREE(pcd->status_buf);
45412 +#ifdef DWC_UTE_CFI
45413 + if (pcd->cfi)
45414 + DWC_FREE(pcd->cfi);
45415 +#endif
45416 + if (pcd)
45417 + DWC_FREE(pcd);
45418 + return NULL;
45419 +
45420 +}
45421 +
45422 +/**
45423 + * Remove PCD specific data
45424 + */
45425 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
45426 +{
45427 + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
45428 + int i;
45429 + if (pcd->core_if->core_params->dev_out_nak) {
45430 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45431 + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
45432 + pcd->core_if->ep_xfer_info[i].state = 0;
45433 + }
45434 + }
45435 +
45436 + if (GET_CORE_IF(pcd)->dma_enable) {
45437 + DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
45438 + pcd->setup_pkt_dma_handle);
45439 + DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
45440 + pcd->status_buf_dma_handle);
45441 + if (GET_CORE_IF(pcd)->dma_desc_enable) {
45442 + dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
45443 + dev_if->dma_setup_desc_addr
45444 + [0], 1);
45445 + dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
45446 + dev_if->dma_setup_desc_addr
45447 + [1], 1);
45448 + dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
45449 + dev_if->dma_in_desc_addr, 1);
45450 + dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
45451 + dev_if->dma_out_desc_addr,
45452 + 1);
45453 + }
45454 + } else {
45455 + DWC_FREE(pcd->setup_pkt);
45456 + DWC_FREE(pcd->status_buf);
45457 + }
45458 + DWC_SPINLOCK_FREE(pcd->lock);
45459 + /* Set core_if's lock pointer to NULL */
45460 + pcd->core_if->lock = NULL;
45461 +
45462 + DWC_TASK_FREE(pcd->start_xfer_tasklet);
45463 + DWC_TASK_FREE(pcd->test_mode_tasklet);
45464 + if (pcd->core_if->core_params->dev_out_nak) {
45465 + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45466 + if (pcd->core_if->ep_xfer_timer[i]) {
45467 + DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
45468 + }
45469 + }
45470 + }
45471 +
45472 +/* Release the CFI object's dynamic memory */
45473 +#ifdef DWC_UTE_CFI
45474 + if (pcd->cfi->ops.release) {
45475 + pcd->cfi->ops.release(pcd->cfi);
45476 + }
45477 +#endif
45478 +
45479 + DWC_FREE(pcd);
45480 +}
45481 +
45482 +/**
45483 + * Returns whether registered pcd is dual speed or not
45484 + */
45485 +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
45486 +{
45487 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45488 +
45489 + if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
45490 + ((core_if->hwcfg2.b.hs_phy_type == 2) &&
45491 + (core_if->hwcfg2.b.fs_phy_type == 1) &&
45492 + (core_if->core_params->ulpi_fs_ls))) {
45493 + return 0;
45494 + }
45495 +
45496 + return 1;
45497 +}
45498 +
45499 +/**
45500 + * Returns whether registered pcd is OTG capable or not
45501 + */
45502 +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
45503 +{
45504 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45505 + gusbcfg_data_t usbcfg = {.d32 = 0 };
45506 +
45507 + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
45508 + if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
45509 + return 0;
45510 + }
45511 +
45512 + return 1;
45513 +}
45514 +
45515 +/**
45516 + * This function assigns periodic Tx FIFO to an periodic EP
45517 + * in shared Tx FIFO mode
45518 + */
45519 +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
45520 +{
45521 + uint32_t TxMsk = 1;
45522 + int i;
45523 +
45524 + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
45525 + if ((TxMsk & core_if->tx_msk) == 0) {
45526 + core_if->tx_msk |= TxMsk;
45527 + return i + 1;
45528 + }
45529 + TxMsk <<= 1;
45530 + }
45531 + return 0;
45532 +}
45533 +
45534 +/**
45535 + * This function assigns periodic Tx FIFO to an periodic EP
45536 + * in shared Tx FIFO mode
45537 + */
45538 +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
45539 +{
45540 + uint32_t PerTxMsk = 1;
45541 + int i;
45542 + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
45543 + if ((PerTxMsk & core_if->p_tx_msk) == 0) {
45544 + core_if->p_tx_msk |= PerTxMsk;
45545 + return i + 1;
45546 + }
45547 + PerTxMsk <<= 1;
45548 + }
45549 + return 0;
45550 +}
45551 +
45552 +/**
45553 + * This function releases periodic Tx FIFO
45554 + * in shared Tx FIFO mode
45555 + */
45556 +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
45557 + uint32_t fifo_num)
45558 +{
45559 + core_if->p_tx_msk =
45560 + (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
45561 +}
45562 +
45563 +/**
45564 + * This function releases periodic Tx FIFO
45565 + * in shared Tx FIFO mode
45566 + */
45567 +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
45568 +{
45569 + core_if->tx_msk =
45570 + (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
45571 +}
45572 +
45573 +/**
45574 + * This function is being called from gadget
45575 + * to enable PCD endpoint.
45576 + */
45577 +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
45578 + const uint8_t * ep_desc, void *usb_ep)
45579 +{
45580 + int num, dir;
45581 + dwc_otg_pcd_ep_t *ep = NULL;
45582 + const usb_endpoint_descriptor_t *desc;
45583 + dwc_irqflags_t flags;
45584 + fifosize_data_t dptxfsiz = {.d32 = 0 };
45585 + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45586 + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45587 + int retval = 0;
45588 + int i, epcount;
45589 +
45590 + desc = (const usb_endpoint_descriptor_t *)ep_desc;
45591 +
45592 + if (!desc) {
45593 + pcd->ep0.priv = usb_ep;
45594 + ep = &pcd->ep0;
45595 + retval = -DWC_E_INVALID;
45596 + goto out;
45597 + }
45598 +
45599 + num = UE_GET_ADDR(desc->bEndpointAddress);
45600 + dir = UE_GET_DIR(desc->bEndpointAddress);
45601 +
45602 + if (!desc->wMaxPacketSize) {
45603 + DWC_WARN("bad maxpacketsize\n");
45604 + retval = -DWC_E_INVALID;
45605 + goto out;
45606 + }
45607 +
45608 + if (dir == UE_DIR_IN) {
45609 + epcount = pcd->core_if->dev_if->num_in_eps;
45610 + for (i = 0; i < epcount; i++) {
45611 + if (num == pcd->in_ep[i].dwc_ep.num) {
45612 + ep = &pcd->in_ep[i];
45613 + break;
45614 + }
45615 + }
45616 + } else {
45617 + epcount = pcd->core_if->dev_if->num_out_eps;
45618 + for (i = 0; i < epcount; i++) {
45619 + if (num == pcd->out_ep[i].dwc_ep.num) {
45620 + ep = &pcd->out_ep[i];
45621 + break;
45622 + }
45623 + }
45624 + }
45625 +
45626 + if (!ep) {
45627 + DWC_WARN("bad address\n");
45628 + retval = -DWC_E_INVALID;
45629 + goto out;
45630 + }
45631 +
45632 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45633 +
45634 + ep->desc = desc;
45635 + ep->priv = usb_ep;
45636 +
45637 + /*
45638 + * Activate the EP
45639 + */
45640 + ep->stopped = 0;
45641 +
45642 + ep->dwc_ep.is_in = (dir == UE_DIR_IN);
45643 + ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
45644 +
45645 + ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
45646 +
45647 + if (ep->dwc_ep.is_in) {
45648 + if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45649 + ep->dwc_ep.tx_fifo_num = 0;
45650 +
45651 + if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
45652 + /*
45653 + * if ISOC EP then assign a Periodic Tx FIFO.
45654 + */
45655 + ep->dwc_ep.tx_fifo_num =
45656 + assign_perio_tx_fifo(GET_CORE_IF(pcd));
45657 + }
45658 + } else {
45659 + /*
45660 + * if Dedicated FIFOs mode is on then assign a Tx FIFO.
45661 + */
45662 + ep->dwc_ep.tx_fifo_num =
45663 + assign_tx_fifo(GET_CORE_IF(pcd));
45664 + }
45665 +
45666 + /* Calculating EP info controller base address */
45667 + if (ep->dwc_ep.tx_fifo_num
45668 + && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45669 + gdfifocfg.d32 =
45670 + DWC_READ_REG32(&GET_CORE_IF(pcd)->
45671 + core_global_regs->gdfifocfg);
45672 + gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45673 + dptxfsiz.d32 =
45674 + (DWC_READ_REG32
45675 + (&GET_CORE_IF(pcd)->core_global_regs->
45676 + dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);
45677 + gdfifocfg.b.epinfobase =
45678 + gdfifocfgbase.d32 + dptxfsiz.d32;
45679 + if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45680 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45681 + core_global_regs->gdfifocfg,
45682 + gdfifocfg.d32);
45683 + }
45684 + }
45685 + }
45686 + /* Set initial data PID. */
45687 + if (ep->dwc_ep.type == UE_BULK) {
45688 + ep->dwc_ep.data_pid_start = 0;
45689 + }
45690 +
45691 + /* Alloc DMA Descriptors */
45692 + if (GET_CORE_IF(pcd)->dma_desc_enable) {
45693 +#ifndef DWC_UTE_PER_IO
45694 + if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45695 +#endif
45696 + ep->dwc_ep.desc_addr =
45697 + dwc_otg_ep_alloc_desc_chain(&ep->
45698 + dwc_ep.dma_desc_addr,
45699 + MAX_DMA_DESC_CNT);
45700 + if (!ep->dwc_ep.desc_addr) {
45701 + DWC_WARN("%s, can't allocate DMA descriptor\n",
45702 + __func__);
45703 + retval = -DWC_E_SHUTDOWN;
45704 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45705 + goto out;
45706 + }
45707 +#ifndef DWC_UTE_PER_IO
45708 + }
45709 +#endif
45710 + }
45711 +
45712 + DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
45713 + (ep->dwc_ep.is_in ? "IN" : "OUT"),
45714 + ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
45715 +#ifdef DWC_UTE_PER_IO
45716 + ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
45717 +#endif
45718 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45719 + ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
45720 + ep->dwc_ep.frame_num = 0xFFFFFFFF;
45721 + }
45722 +
45723 + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
45724 +
45725 +#ifdef DWC_UTE_CFI
45726 + if (pcd->cfi->ops.ep_enable) {
45727 + pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
45728 + }
45729 +#endif
45730 +
45731 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45732 +
45733 +out:
45734 + return retval;
45735 +}
45736 +
45737 +/**
45738 + * This function is being called from gadget
45739 + * to disable PCD endpoint.
45740 + */
45741 +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
45742 +{
45743 + dwc_otg_pcd_ep_t *ep;
45744 + dwc_irqflags_t flags;
45745 + dwc_otg_dev_dma_desc_t *desc_addr;
45746 + dwc_dma_t dma_desc_addr;
45747 + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45748 + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45749 + fifosize_data_t dptxfsiz = {.d32 = 0 };
45750 +
45751 + ep = get_ep_from_handle(pcd, ep_handle);
45752 +
45753 + if (!ep || !ep->desc) {
45754 + DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
45755 + return -DWC_E_INVALID;
45756 + }
45757 +
45758 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45759 +
45760 + dwc_otg_request_nuke(ep);
45761 +
45762 + dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
45763 + if (pcd->core_if->core_params->dev_out_nak) {
45764 + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
45765 + pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
45766 + }
45767 + ep->desc = NULL;
45768 + ep->stopped = 1;
45769 +
45770 + gdfifocfg.d32 =
45771 + DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
45772 + gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45773 +
45774 + if (ep->dwc_ep.is_in) {
45775 + if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45776 + /* Flush the Tx FIFO */
45777 + dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),
45778 + ep->dwc_ep.tx_fifo_num);
45779 + }
45780 + release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45781 + release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45782 + if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45783 + /* Decreasing EPinfo Base Addr */
45784 + dptxfsiz.d32 =
45785 + (DWC_READ_REG32
45786 + (&GET_CORE_IF(pcd)->
45787 + core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
45788 + gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
45789 + if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45790 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
45791 + gdfifocfg.d32);
45792 + }
45793 + }
45794 + }
45795 +
45796 + /* Free DMA Descriptors */
45797 + if (GET_CORE_IF(pcd)->dma_desc_enable) {
45798 + if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45799 + desc_addr = ep->dwc_ep.desc_addr;
45800 + dma_desc_addr = ep->dwc_ep.dma_desc_addr;
45801 +
45802 + /* Cannot call dma_free_coherent() with IRQs disabled */
45803 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45804 + dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
45805 + MAX_DMA_DESC_CNT);
45806 +
45807 + goto out_unlocked;
45808 + }
45809 + }
45810 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45811 +
45812 +out_unlocked:
45813 + DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
45814 + ep->dwc_ep.is_in ? "IN" : "OUT");
45815 + return 0;
45816 +
45817 +}
45818 +
45819 +/******************************************************************************/
45820 +#ifdef DWC_UTE_PER_IO
45821 +
45822 +/**
45823 + * Free the request and its extended parts
45824 + *
45825 + */
45826 +void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
45827 +{
45828 + DWC_FREE(req->ext_req.per_io_frame_descs);
45829 + DWC_FREE(req);
45830 +}
45831 +
45832 +/**
45833 + * Start the next request in the endpoint's queue.
45834 + *
45835 + */
45836 +int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
45837 + dwc_otg_pcd_ep_t * ep)
45838 +{
45839 + int i;
45840 + dwc_otg_pcd_request_t *req = NULL;
45841 + dwc_ep_t *dwcep = NULL;
45842 + struct dwc_iso_xreq_port *ereq = NULL;
45843 + struct dwc_iso_pkt_desc_port *ddesc_iso;
45844 + uint16_t nat;
45845 + depctl_data_t diepctl;
45846 +
45847 + dwcep = &ep->dwc_ep;
45848 +
45849 + if (dwcep->xiso_active_xfers > 0) {
45850 +#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers
45851 + DWC_WARN("There are currently active transfers for EP%d \
45852 + (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers,
45853 + dwcep->xiso_queued_xfers);
45854 +#endif
45855 + return 0;
45856 + }
45857 +
45858 + nat = UGETW(ep->desc->wMaxPacketSize);
45859 + nat = (nat >> 11) & 0x03;
45860 +
45861 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45862 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
45863 + ereq = &req->ext_req;
45864 + ep->stopped = 0;
45865 +
45866 + /* Get the frame number */
45867 + dwcep->xiso_frame_num =
45868 + dwc_otg_get_frame_number(GET_CORE_IF(pcd));
45869 + DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
45870 +
45871 + ddesc_iso = ereq->per_io_frame_descs;
45872 +
45873 + if (dwcep->is_in) {
45874 + /* Setup DMA Descriptor chain for IN Isoc request */
45875 + for (i = 0; i < ereq->pio_pkt_count; i++) {
45876 + //if ((i % (nat + 1)) == 0)
45877 + if ( i > 0 )
45878 + dwcep->xiso_frame_num =
45879 + (dwcep->xiso_bInterval +
45880 + dwcep->xiso_frame_num) & 0x3FFF;
45881 + dwcep->desc_addr[i].buf =
45882 + req->dma + ddesc_iso[i].offset;
45883 + dwcep->desc_addr[i].status.b_iso_in.txbytes =
45884 + ddesc_iso[i].length;
45885 + dwcep->desc_addr[i].status.b_iso_in.framenum =
45886 + dwcep->xiso_frame_num;
45887 + dwcep->desc_addr[i].status.b_iso_in.bs =
45888 + BS_HOST_READY;
45889 + dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
45890 + dwcep->desc_addr[i].status.b_iso_in.sp =
45891 + (ddesc_iso[i].length %
45892 + dwcep->maxpacket) ? 1 : 0;
45893 + dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
45894 + dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
45895 + dwcep->desc_addr[i].status.b_iso_in.l = 0;
45896 +
45897 + /* Process the last descriptor */
45898 + if (i == ereq->pio_pkt_count - 1) {
45899 + dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
45900 + dwcep->desc_addr[i].status.b_iso_in.l = 1;
45901 + }
45902 + }
45903 +
45904 + /* Setup and start the transfer for this endpoint */
45905 + dwcep->xiso_active_xfers++;
45906 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
45907 + in_ep_regs[dwcep->num]->diepdma,
45908 + dwcep->dma_desc_addr);
45909 + diepctl.d32 = 0;
45910 + diepctl.b.epena = 1;
45911 + diepctl.b.cnak = 1;
45912 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
45913 + in_ep_regs[dwcep->num]->diepctl, 0,
45914 + diepctl.d32);
45915 + } else {
45916 + /* Setup DMA Descriptor chain for OUT Isoc request */
45917 + for (i = 0; i < ereq->pio_pkt_count; i++) {
45918 + //if ((i % (nat + 1)) == 0)
45919 + dwcep->xiso_frame_num = (dwcep->xiso_bInterval +
45920 + dwcep->xiso_frame_num) & 0x3FFF;
45921 + dwcep->desc_addr[i].buf =
45922 + req->dma + ddesc_iso[i].offset;
45923 + dwcep->desc_addr[i].status.b_iso_out.rxbytes =
45924 + ddesc_iso[i].length;
45925 + dwcep->desc_addr[i].status.b_iso_out.framenum =
45926 + dwcep->xiso_frame_num;
45927 + dwcep->desc_addr[i].status.b_iso_out.bs =
45928 + BS_HOST_READY;
45929 + dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
45930 + dwcep->desc_addr[i].status.b_iso_out.sp =
45931 + (ddesc_iso[i].length %
45932 + dwcep->maxpacket) ? 1 : 0;
45933 + dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
45934 + dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
45935 + dwcep->desc_addr[i].status.b_iso_out.l = 0;
45936 +
45937 + /* Process the last descriptor */
45938 + if (i == ereq->pio_pkt_count - 1) {
45939 + dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
45940 + dwcep->desc_addr[i].status.b_iso_out.l = 1;
45941 + }
45942 + }
45943 +
45944 + /* Setup and start the transfer for this endpoint */
45945 + dwcep->xiso_active_xfers++;
45946 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45947 + dev_if->out_ep_regs[dwcep->num]->
45948 + doepdma, dwcep->dma_desc_addr);
45949 + diepctl.d32 = 0;
45950 + diepctl.b.epena = 1;
45951 + diepctl.b.cnak = 1;
45952 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
45953 + dev_if->out_ep_regs[dwcep->num]->
45954 + doepctl, 0, diepctl.d32);
45955 + }
45956 +
45957 + } else {
45958 + ep->stopped = 1;
45959 + }
45960 +
45961 + return 0;
45962 +}
45963 +
45964 +/**
45965 + * - Remove the request from the queue
45966 + */
45967 +void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
45968 +{
45969 + dwc_otg_pcd_request_t *req = NULL;
45970 + struct dwc_iso_xreq_port *ereq = NULL;
45971 + struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
45972 + dwc_ep_t *dwcep = NULL;
45973 + int i;
45974 +
45975 + //DWC_DEBUG();
45976 + dwcep = &ep->dwc_ep;
45977 +
45978 + /* Get the first pending request from the queue */
45979 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45980 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
45981 + if (!req) {
45982 + DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
45983 + return;
45984 + }
45985 + dwcep->xiso_active_xfers--;
45986 + dwcep->xiso_queued_xfers--;
45987 + /* Remove this request from the queue */
45988 + DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
45989 + } else {
45990 + DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
45991 + return;
45992 + }
45993 +
45994 + ep->stopped = 1;
45995 + ereq = &req->ext_req;
45996 + ddesc_iso = ereq->per_io_frame_descs;
45997 +
45998 + if (dwcep->xiso_active_xfers < 0) {
45999 + DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
46000 + dwcep->xiso_active_xfers);
46001 + }
46002 +
46003 + /* Fill the Isoc descs of portable extended req from dma descriptors */
46004 + for (i = 0; i < ereq->pio_pkt_count; i++) {
46005 + if (dwcep->is_in) { /* IN endpoints */
46006 + ddesc_iso[i].actual_length = ddesc_iso[i].length -
46007 + dwcep->desc_addr[i].status.b_iso_in.txbytes;
46008 + ddesc_iso[i].status =
46009 + dwcep->desc_addr[i].status.b_iso_in.txsts;
46010 + } else { /* OUT endpoints */
46011 + ddesc_iso[i].actual_length = ddesc_iso[i].length -
46012 + dwcep->desc_addr[i].status.b_iso_out.rxbytes;
46013 + ddesc_iso[i].status =
46014 + dwcep->desc_addr[i].status.b_iso_out.rxsts;
46015 + }
46016 + }
46017 +
46018 + DWC_SPINUNLOCK(ep->pcd->lock);
46019 +
46020 + /* Call the completion function in the non-portable logic */
46021 + ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
46022 + &req->ext_req);
46023 +
46024 + DWC_SPINLOCK(ep->pcd->lock);
46025 +
46026 + /* Free the request - specific freeing needed for extended request object */
46027 + dwc_pcd_xiso_ereq_free(ep, req);
46028 +
46029 + /* Start the next request */
46030 + dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
46031 +
46032 + return;
46033 +}
46034 +
46035 +/**
46036 + * Create and initialize the Isoc pkt descriptors of the extended request.
46037 + *
46038 + */
46039 +static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
46040 + void *ereq_nonport,
46041 + int atomic_alloc)
46042 +{
46043 + struct dwc_iso_xreq_port *ereq = NULL;
46044 + struct dwc_iso_xreq_port *req_mapped = NULL;
46045 + struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */
46046 + uint32_t pkt_count;
46047 + int i;
46048 +
46049 + ereq = &req->ext_req;
46050 + req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
46051 + pkt_count = req_mapped->pio_pkt_count;
46052 +
46053 + /* Create the isoc descs */
46054 + if (atomic_alloc) {
46055 + ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
46056 + } else {
46057 + ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
46058 + }
46059 +
46060 + if (!ipds) {
46061 + DWC_ERROR("Failed to allocate isoc descriptors");
46062 + return -DWC_E_NO_MEMORY;
46063 + }
46064 +
46065 + /* Initialize the extended request fields */
46066 + ereq->per_io_frame_descs = ipds;
46067 + ereq->error_count = 0;
46068 + ereq->pio_alloc_pkt_count = pkt_count;
46069 + ereq->pio_pkt_count = pkt_count;
46070 + ereq->tr_sub_flags = req_mapped->tr_sub_flags;
46071 +
46072 + /* Init the Isoc descriptors */
46073 + for (i = 0; i < pkt_count; i++) {
46074 + ipds[i].length = req_mapped->per_io_frame_descs[i].length;
46075 + ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
46076 + ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */
46077 + ipds[i].actual_length =
46078 + req_mapped->per_io_frame_descs[i].actual_length;
46079 + }
46080 +
46081 + return 0;
46082 +}
46083 +
46084 +static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
46085 +{
46086 + struct dwc_iso_pkt_desc_port *xfd = NULL;
46087 + int i;
46088 +
46089 + DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
46090 + DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
46091 + DWC_DEBUG("error_count=%d", ereq->error_count);
46092 + DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
46093 + DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
46094 + DWC_DEBUG("res=%d", ereq->res);
46095 +
46096 + for (i = 0; i < ereq->pio_pkt_count; i++) {
46097 + xfd = &ereq->per_io_frame_descs[0];
46098 + DWC_DEBUG("FD #%d", i);
46099 +
46100 + DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
46101 + DWC_DEBUG("xfd->length=%d", xfd->length);
46102 + DWC_DEBUG("xfd->offset=%d", xfd->offset);
46103 + DWC_DEBUG("xfd->status=%d", xfd->status);
46104 + }
46105 +}
46106 +
46107 +/**
46108 + *
46109 + */
46110 +int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46111 + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
46112 + int zero, void *req_handle, int atomic_alloc,
46113 + void *ereq_nonport)
46114 +{
46115 + dwc_otg_pcd_request_t *req = NULL;
46116 + dwc_otg_pcd_ep_t *ep;
46117 + dwc_irqflags_t flags;
46118 + int res;
46119 +
46120 + ep = get_ep_from_handle(pcd, ep_handle);
46121 + if (!ep) {
46122 + DWC_WARN("bad ep\n");
46123 + return -DWC_E_INVALID;
46124 + }
46125 +
46126 + /* We support this extension only for DDMA mode */
46127 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
46128 + if (!GET_CORE_IF(pcd)->dma_desc_enable)
46129 + return -DWC_E_INVALID;
46130 +
46131 + /* Create a dwc_otg_pcd_request_t object */
46132 + if (atomic_alloc) {
46133 + req = DWC_ALLOC_ATOMIC(sizeof(*req));
46134 + } else {
46135 + req = DWC_ALLOC(sizeof(*req));
46136 + }
46137 +
46138 + if (!req) {
46139 + return -DWC_E_NO_MEMORY;
46140 + }
46141 +
46142 + /* Create the Isoc descs for this request which shall be the exact match
46143 + * of the structure sent to us from the non-portable logic */
46144 + res =
46145 + dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
46146 + if (res) {
46147 + DWC_WARN("Failed to init the Isoc descriptors");
46148 + DWC_FREE(req);
46149 + return res;
46150 + }
46151 +
46152 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46153 +
46154 + DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
46155 + req->buf = buf;
46156 + req->dma = dma_buf;
46157 + req->length = buflen;
46158 + req->sent_zlp = zero;
46159 + req->priv = req_handle;
46160 +
46161 + //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46162 + ep->dwc_ep.dma_addr = dma_buf;
46163 + ep->dwc_ep.start_xfer_buff = buf;
46164 + ep->dwc_ep.xfer_buff = buf;
46165 + ep->dwc_ep.xfer_len = 0;
46166 + ep->dwc_ep.xfer_count = 0;
46167 + ep->dwc_ep.sent_zlp = 0;
46168 + ep->dwc_ep.total_len = buflen;
46169 +
46170 + /* Add this request to the tail */
46171 + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46172 + ep->dwc_ep.xiso_queued_xfers++;
46173 +
46174 +//DWC_DEBUG("CP_0");
46175 +//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
46176 +//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
46177 +//prn_ext_request(&req->ext_req);
46178 +
46179 + //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46180 +
46181 + /* If the req->status == ASAP then check if there is any active transfer
46182 + * for this endpoint. If no active transfers, then get the first entry
46183 + * from the queue and start that transfer
46184 + */
46185 + if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
46186 + res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
46187 + if (res) {
46188 + DWC_WARN("Failed to start the next Isoc transfer");
46189 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46190 + DWC_FREE(req);
46191 + return res;
46192 + }
46193 + }
46194 +
46195 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46196 + return 0;
46197 +}
46198 +
46199 +#endif
46200 +/* END ifdef DWC_UTE_PER_IO ***************************************************/
46201 +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46202 + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
46203 + int zero, void *req_handle, int atomic_alloc)
46204 +{
46205 + dwc_irqflags_t flags;
46206 + dwc_otg_pcd_request_t *req;
46207 + dwc_otg_pcd_ep_t *ep;
46208 + uint32_t max_transfer;
46209 +
46210 + ep = get_ep_from_handle(pcd, ep_handle);
46211 + if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46212 + DWC_WARN("bad ep\n");
46213 + return -DWC_E_INVALID;
46214 + }
46215 +
46216 + if (atomic_alloc) {
46217 + req = DWC_ALLOC_ATOMIC(sizeof(*req));
46218 + } else {
46219 + req = DWC_ALLOC(sizeof(*req));
46220 + }
46221 +
46222 + if (!req) {
46223 + return -DWC_E_NO_MEMORY;
46224 + }
46225 + DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
46226 + if (!GET_CORE_IF(pcd)->core_params->opt) {
46227 + if (ep->dwc_ep.num != 0) {
46228 + DWC_ERROR("queue req %p, len %d buf %p\n",
46229 + req_handle, buflen, buf);
46230 + }
46231 + }
46232 +
46233 + req->buf = buf;
46234 + req->dma = dma_buf;
46235 + req->length = buflen;
46236 + req->sent_zlp = zero;
46237 + req->priv = req_handle;
46238 + req->dw_align_buf = NULL;
46239 + if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
46240 + && !GET_CORE_IF(pcd)->dma_desc_enable)
46241 + req->dw_align_buf = DWC_DMA_ALLOC(buflen,
46242 + &req->dw_align_buf_dma);
46243 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46244 +
46245 + /*
46246 + * After adding request to the queue for IN ISOC wait for In Token Received
46247 + * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token
46248 + * Received when EP is disabled interrupt to obtain starting microframe
46249 + * (odd/even) start transfer
46250 + */
46251 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
46252 + if (req != 0) {
46253 + depctl_data_t depctl = {.d32 =
46254 + DWC_READ_REG32(&pcd->core_if->dev_if->
46255 + in_ep_regs[ep->dwc_ep.num]->
46256 + diepctl) };
46257 + ++pcd->request_pending;
46258 +
46259 + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46260 + if (ep->dwc_ep.is_in) {
46261 + depctl.b.cnak = 1;
46262 + DWC_WRITE_REG32(&pcd->core_if->dev_if->
46263 + in_ep_regs[ep->dwc_ep.num]->
46264 + diepctl, depctl.d32);
46265 + }
46266 +
46267 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46268 + }
46269 + return 0;
46270 + }
46271 +
46272 + /*
46273 + * For EP0 IN without premature status, zlp is required?
46274 + */
46275 + if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
46276 + DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
46277 + //_req->zero = 1;
46278 + }
46279 +
46280 + /* Start the transfer */
46281 + if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
46282 + /* EP0 Transfer? */
46283 + if (ep->dwc_ep.num == 0) {
46284 + switch (pcd->ep0state) {
46285 + case EP0_IN_DATA_PHASE:
46286 + DWC_DEBUGPL(DBG_PCD,
46287 + "%s ep0: EP0_IN_DATA_PHASE\n",
46288 + __func__);
46289 + break;
46290 +
46291 + case EP0_OUT_DATA_PHASE:
46292 + DWC_DEBUGPL(DBG_PCD,
46293 + "%s ep0: EP0_OUT_DATA_PHASE\n",
46294 + __func__);
46295 + if (pcd->request_config) {
46296 + /* Complete STATUS PHASE */
46297 + ep->dwc_ep.is_in = 1;
46298 + pcd->ep0state = EP0_IN_STATUS_PHASE;
46299 + }
46300 + break;
46301 +
46302 + case EP0_IN_STATUS_PHASE:
46303 + DWC_DEBUGPL(DBG_PCD,
46304 + "%s ep0: EP0_IN_STATUS_PHASE\n",
46305 + __func__);
46306 + break;
46307 +
46308 + default:
46309 + DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
46310 + pcd->ep0state);
46311 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46312 + return -DWC_E_SHUTDOWN;
46313 + }
46314 +
46315 + ep->dwc_ep.dma_addr = dma_buf;
46316 + ep->dwc_ep.start_xfer_buff = buf;
46317 + ep->dwc_ep.xfer_buff = buf;
46318 + ep->dwc_ep.xfer_len = buflen;
46319 + ep->dwc_ep.xfer_count = 0;
46320 + ep->dwc_ep.sent_zlp = 0;
46321 + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
46322 +
46323 + if (zero) {
46324 + if ((ep->dwc_ep.xfer_len %
46325 + ep->dwc_ep.maxpacket == 0)
46326 + && (ep->dwc_ep.xfer_len != 0)) {
46327 + ep->dwc_ep.sent_zlp = 1;
46328 + }
46329 +
46330 + }
46331 +
46332 + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
46333 + &ep->dwc_ep);
46334 + } // non-ep0 endpoints
46335 + else {
46336 +#ifdef DWC_UTE_CFI
46337 + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
46338 + /* store the request length */
46339 + ep->dwc_ep.cfi_req_len = buflen;
46340 + pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
46341 + ep, req);
46342 + } else {
46343 +#endif
46344 + max_transfer =
46345 + GET_CORE_IF(ep->pcd)->core_params->
46346 + max_transfer_size;
46347 +
46348 + /* Setup and start the Transfer */
46349 + if (req->dw_align_buf){
46350 + if (ep->dwc_ep.is_in)
46351 + dwc_memcpy(req->dw_align_buf,
46352 + buf, buflen);
46353 + ep->dwc_ep.dma_addr =
46354 + req->dw_align_buf_dma;
46355 + ep->dwc_ep.start_xfer_buff =
46356 + req->dw_align_buf;
46357 + ep->dwc_ep.xfer_buff =
46358 + req->dw_align_buf;
46359 + } else {
46360 + ep->dwc_ep.dma_addr = dma_buf;
46361 + ep->dwc_ep.start_xfer_buff = buf;
46362 + ep->dwc_ep.xfer_buff = buf;
46363 + }
46364 + ep->dwc_ep.xfer_len = 0;
46365 + ep->dwc_ep.xfer_count = 0;
46366 + ep->dwc_ep.sent_zlp = 0;
46367 + ep->dwc_ep.total_len = buflen;
46368 +
46369 + ep->dwc_ep.maxxfer = max_transfer;
46370 + if (GET_CORE_IF(pcd)->dma_desc_enable) {
46371 + uint32_t out_max_xfer =
46372 + DDMA_MAX_TRANSFER_SIZE -
46373 + (DDMA_MAX_TRANSFER_SIZE % 4);
46374 + if (ep->dwc_ep.is_in) {
46375 + if (ep->dwc_ep.maxxfer >
46376 + DDMA_MAX_TRANSFER_SIZE) {
46377 + ep->dwc_ep.maxxfer =
46378 + DDMA_MAX_TRANSFER_SIZE;
46379 + }
46380 + } else {
46381 + if (ep->dwc_ep.maxxfer >
46382 + out_max_xfer) {
46383 + ep->dwc_ep.maxxfer =
46384 + out_max_xfer;
46385 + }
46386 + }
46387 + }
46388 + if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
46389 + ep->dwc_ep.maxxfer -=
46390 + (ep->dwc_ep.maxxfer %
46391 + ep->dwc_ep.maxpacket);
46392 + }
46393 +
46394 + if (zero) {
46395 + if ((ep->dwc_ep.total_len %
46396 + ep->dwc_ep.maxpacket == 0)
46397 + && (ep->dwc_ep.total_len != 0)) {
46398 + ep->dwc_ep.sent_zlp = 1;
46399 + }
46400 + }
46401 +#ifdef DWC_UTE_CFI
46402 + }
46403 +#endif
46404 + dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
46405 + &ep->dwc_ep);
46406 + }
46407 + }
46408 +
46409 + if (req != 0) {
46410 + ++pcd->request_pending;
46411 + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46412 + if (ep->dwc_ep.is_in && ep->stopped
46413 + && !(GET_CORE_IF(pcd)->dma_enable)) {
46414 + /** @todo NGS Create a function for this. */
46415 + diepmsk_data_t diepmsk = {.d32 = 0 };
46416 + diepmsk.b.intktxfemp = 1;
46417 + if (GET_CORE_IF(pcd)->multiproc_int_enable) {
46418 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46419 + dev_if->dev_global_regs->diepeachintmsk
46420 + [ep->dwc_ep.num], 0,
46421 + diepmsk.d32);
46422 + } else {
46423 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46424 + dev_if->dev_global_regs->
46425 + diepmsk, 0, diepmsk.d32);
46426 + }
46427 +
46428 + }
46429 + }
46430 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46431 +
46432 + return 0;
46433 +}
46434 +
46435 +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
46436 + void *req_handle)
46437 +{
46438 + dwc_irqflags_t flags;
46439 + dwc_otg_pcd_request_t *req;
46440 + dwc_otg_pcd_ep_t *ep;
46441 +
46442 + ep = get_ep_from_handle(pcd, ep_handle);
46443 + if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46444 + DWC_WARN("bad argument\n");
46445 + return -DWC_E_INVALID;
46446 + }
46447 +
46448 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46449 +
46450 + /* make sure it's actually queued on this endpoint */
46451 + DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
46452 + if (req->priv == (void *)req_handle) {
46453 + break;
46454 + }
46455 + }
46456 +
46457 + if (req->priv != (void *)req_handle) {
46458 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46459 + return -DWC_E_INVALID;
46460 + }
46461 +
46462 + if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
46463 + dwc_otg_request_done(ep, req, -DWC_E_RESTART);
46464 + } else {
46465 + req = NULL;
46466 + }
46467 +
46468 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46469 +
46470 + return req ? 0 : -DWC_E_SHUTDOWN;
46471 +
46472 +}
46473 +
46474 +/**
46475 + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
46476 + *
46477 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
46478 + * requests. If the gadget driver clears the halt status, it will
46479 + * automatically unwedge the endpoint.
46480 + *
46481 + * Returns zero on success, else negative DWC error code.
46482 + */
46483 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
46484 +{
46485 + dwc_otg_pcd_ep_t *ep;
46486 + dwc_irqflags_t flags;
46487 + int retval = 0;
46488 +
46489 + ep = get_ep_from_handle(pcd, ep_handle);
46490 +
46491 + if ((!ep->desc && ep != &pcd->ep0) ||
46492 + (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46493 + DWC_WARN("%s, bad ep\n", __func__);
46494 + return -DWC_E_INVALID;
46495 + }
46496 +
46497 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46498 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46499 + DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46500 + ep->dwc_ep.is_in ? "IN" : "OUT");
46501 + retval = -DWC_E_AGAIN;
46502 + } else {
46503 + /* This code needs to be reviewed */
46504 + if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46505 + dtxfsts_data_t txstatus;
46506 + fifosize_data_t txfifosize;
46507 +
46508 + txfifosize.d32 =
46509 + DWC_READ_REG32(&GET_CORE_IF(pcd)->
46510 + core_global_regs->dtxfsiz[ep->dwc_ep.
46511 + tx_fifo_num]);
46512 + txstatus.d32 =
46513 + DWC_READ_REG32(&GET_CORE_IF(pcd)->
46514 + dev_if->in_ep_regs[ep->dwc_ep.num]->
46515 + dtxfsts);
46516 +
46517 + if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46518 + DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46519 + retval = -DWC_E_AGAIN;
46520 + } else {
46521 + if (ep->dwc_ep.num == 0) {
46522 + pcd->ep0state = EP0_STALL;
46523 + }
46524 +
46525 + ep->stopped = 1;
46526 + dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46527 + &ep->dwc_ep);
46528 + }
46529 + } else {
46530 + if (ep->dwc_ep.num == 0) {
46531 + pcd->ep0state = EP0_STALL;
46532 + }
46533 +
46534 + ep->stopped = 1;
46535 + dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46536 + }
46537 + }
46538 +
46539 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46540 +
46541 + return retval;
46542 +}
46543 +
46544 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
46545 +{
46546 + dwc_otg_pcd_ep_t *ep;
46547 + dwc_irqflags_t flags;
46548 + int retval = 0;
46549 +
46550 + ep = get_ep_from_handle(pcd, ep_handle);
46551 +
46552 + if (!ep || (!ep->desc && ep != &pcd->ep0) ||
46553 + (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46554 + DWC_WARN("%s, bad ep\n", __func__);
46555 + return -DWC_E_INVALID;
46556 + }
46557 +
46558 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46559 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46560 + DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46561 + ep->dwc_ep.is_in ? "IN" : "OUT");
46562 + retval = -DWC_E_AGAIN;
46563 + } else if (value == 0) {
46564 + dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46565 + } else if (value == 1) {
46566 + if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46567 + dtxfsts_data_t txstatus;
46568 + fifosize_data_t txfifosize;
46569 +
46570 + txfifosize.d32 =
46571 + DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
46572 + dtxfsiz[ep->dwc_ep.tx_fifo_num]);
46573 + txstatus.d32 =
46574 + DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
46575 + in_ep_regs[ep->dwc_ep.num]->dtxfsts);
46576 +
46577 + if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46578 + DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46579 + retval = -DWC_E_AGAIN;
46580 + } else {
46581 + if (ep->dwc_ep.num == 0) {
46582 + pcd->ep0state = EP0_STALL;
46583 + }
46584 +
46585 + ep->stopped = 1;
46586 + dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46587 + &ep->dwc_ep);
46588 + }
46589 + } else {
46590 + if (ep->dwc_ep.num == 0) {
46591 + pcd->ep0state = EP0_STALL;
46592 + }
46593 +
46594 + ep->stopped = 1;
46595 + dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46596 + }
46597 + } else if (value == 2) {
46598 + ep->dwc_ep.stall_clear_flag = 0;
46599 + } else if (value == 3) {
46600 + ep->dwc_ep.stall_clear_flag = 1;
46601 + }
46602 +
46603 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46604 +
46605 + return retval;
46606 +}
46607 +
46608 +/**
46609 + * This function initiates remote wakeup of the host from suspend state.
46610 + */
46611 +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
46612 +{
46613 + dctl_data_t dctl = { 0 };
46614 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46615 + dsts_data_t dsts;
46616 +
46617 + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
46618 + if (!dsts.b.suspsts) {
46619 + DWC_WARN("Remote wakeup while is not in suspend state\n");
46620 + }
46621 + /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
46622 + if (pcd->remote_wakeup_enable) {
46623 + if (set) {
46624 +
46625 + if (core_if->adp_enable) {
46626 + gpwrdn_data_t gpwrdn;
46627 +
46628 + dwc_otg_adp_probe_stop(core_if);
46629 +
46630 + /* Mask SRP detected interrupt from Power Down Logic */
46631 + gpwrdn.d32 = 0;
46632 + gpwrdn.b.srp_det_msk = 1;
46633 + DWC_MODIFY_REG32(&core_if->
46634 + core_global_regs->gpwrdn,
46635 + gpwrdn.d32, 0);
46636 +
46637 + /* Disable Power Down Logic */
46638 + gpwrdn.d32 = 0;
46639 + gpwrdn.b.pmuactv = 1;
46640 + DWC_MODIFY_REG32(&core_if->
46641 + core_global_regs->gpwrdn,
46642 + gpwrdn.d32, 0);
46643 +
46644 + /*
46645 + * Initialize the Core for Device mode.
46646 + */
46647 + core_if->op_state = B_PERIPHERAL;
46648 + dwc_otg_core_init(core_if);
46649 + dwc_otg_enable_global_interrupts(core_if);
46650 + cil_pcd_start(core_if);
46651 +
46652 + dwc_otg_initiate_srp(core_if);
46653 + }
46654 +
46655 + dctl.b.rmtwkupsig = 1;
46656 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46657 + dctl, 0, dctl.d32);
46658 + DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46659 +
46660 + dwc_mdelay(2);
46661 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46662 + dctl, dctl.d32, 0);
46663 + DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
46664 + }
46665 + } else {
46666 + DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
46667 + }
46668 +}
46669 +
46670 +#ifdef CONFIG_USB_DWC_OTG_LPM
46671 +/**
46672 + * This function initiates remote wakeup of the host from L1 sleep state.
46673 + */
46674 +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
46675 +{
46676 + glpmcfg_data_t lpmcfg;
46677 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46678 +
46679 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46680 +
46681 + /* Check if we are in L1 state */
46682 + if (!lpmcfg.b.prt_sleep_sts) {
46683 + DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
46684 + return;
46685 + }
46686 +
46687 + /* Check if host allows remote wakeup */
46688 + if (!lpmcfg.b.rem_wkup_en) {
46689 + DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
46690 + return;
46691 + }
46692 +
46693 + /* Check if Resume OK */
46694 + if (!lpmcfg.b.sleep_state_resumeok) {
46695 + DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
46696 + return;
46697 + }
46698 +
46699 + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46700 + lpmcfg.b.en_utmi_sleep = 0;
46701 + lpmcfg.b.hird_thres &= (~(1 << 4));
46702 + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
46703 +
46704 + if (set) {
46705 + dctl_data_t dctl = {.d32 = 0 };
46706 + dctl.b.rmtwkupsig = 1;
46707 + /* Set RmtWkUpSig bit to start remote wakup signaling.
46708 + * Hardware will automatically clear this bit.
46709 + */
46710 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
46711 + 0, dctl.d32);
46712 + DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46713 + }
46714 +
46715 +}
46716 +#endif
46717 +
46718 +/**
46719 + * Performs remote wakeup.
46720 + */
46721 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
46722 +{
46723 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46724 + dwc_irqflags_t flags;
46725 + if (dwc_otg_is_device_mode(core_if)) {
46726 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46727 +#ifdef CONFIG_USB_DWC_OTG_LPM
46728 + if (core_if->lx_state == DWC_OTG_L1) {
46729 + dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
46730 + } else {
46731 +#endif
46732 + dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
46733 +#ifdef CONFIG_USB_DWC_OTG_LPM
46734 + }
46735 +#endif
46736 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46737 + }
46738 + return;
46739 +}
46740 +
46741 +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
46742 +{
46743 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46744 + dctl_data_t dctl = { 0 };
46745 +
46746 + if (dwc_otg_is_device_mode(core_if)) {
46747 + dctl.b.sftdiscon = 1;
46748 + DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
46749 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
46750 + dwc_udelay(no_of_usecs);
46751 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
46752 +
46753 + } else{
46754 + DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
46755 + }
46756 + return;
46757 +
46758 +}
46759 +
46760 +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
46761 +{
46762 + dsts_data_t dsts;
46763 + gotgctl_data_t gotgctl;
46764 +
46765 + /*
46766 + * This function starts the Protocol if no session is in progress. If
46767 + * a session is already in progress, but the device is suspended,
46768 + * remote wakeup signaling is started.
46769 + */
46770 +
46771 + /* Check if valid session */
46772 + gotgctl.d32 =
46773 + DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
46774 + if (gotgctl.b.bsesvld) {
46775 + /* Check if suspend state */
46776 + dsts.d32 =
46777 + DWC_READ_REG32(&
46778 + (GET_CORE_IF(pcd)->dev_if->
46779 + dev_global_regs->dsts));
46780 + if (dsts.b.suspsts) {
46781 + dwc_otg_pcd_remote_wakeup(pcd, 1);
46782 + }
46783 + } else {
46784 + dwc_otg_pcd_initiate_srp(pcd);
46785 + }
46786 +
46787 + return 0;
46788 +
46789 +}
46790 +
46791 +/**
46792 + * Start the SRP timer to detect when the SRP does not complete within
46793 + * 6 seconds.
46794 + *
46795 + * @param pcd the pcd structure.
46796 + */
46797 +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
46798 +{
46799 + dwc_irqflags_t flags;
46800 + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46801 + dwc_otg_initiate_srp(GET_CORE_IF(pcd));
46802 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46803 +}
46804 +
46805 +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
46806 +{
46807 + return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
46808 +}
46809 +
46810 +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
46811 +{
46812 + return GET_CORE_IF(pcd)->core_params->lpm_enable;
46813 +}
46814 +
46815 +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
46816 +{
46817 + return pcd->b_hnp_enable;
46818 +}
46819 +
46820 +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
46821 +{
46822 + return pcd->a_hnp_support;
46823 +}
46824 +
46825 +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
46826 +{
46827 + return pcd->a_alt_hnp_support;
46828 +}
46829 +
46830 +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
46831 +{
46832 + return pcd->remote_wakeup_enable;
46833 +}
46834 +
46835 +#endif /* DWC_HOST_ONLY */
46836 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46837 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100
46838 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2013-07-06 15:25:50.000000000 +0100
46839 @@ -0,0 +1,266 @@
46840 +/* ==========================================================================
46841 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
46842 + * $Revision: #48 $
46843 + * $Date: 2012/08/10 $
46844 + * $Change: 2047372 $
46845 + *
46846 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46847 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46848 + * otherwise expressly agreed to in writing between Synopsys and you.
46849 + *
46850 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46851 + * any End User Software License Agreement or Agreement for Licensed Product
46852 + * with Synopsys or any supplement thereto. You are permitted to use and
46853 + * redistribute this Software in source and binary forms, with or without
46854 + * modification, provided that redistributions of source code must retain this
46855 + * notice. You may not view, use, disclose, copy or distribute this file or
46856 + * any information contained herein except pursuant to this license grant from
46857 + * Synopsys. If you do not agree with this notice, including the disclaimer
46858 + * below, then you are not authorized to use the Software.
46859 + *
46860 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46861 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46862 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46863 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46864 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46865 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46866 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46867 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46868 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46869 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46870 + * DAMAGE.
46871 + * ========================================================================== */
46872 +#ifndef DWC_HOST_ONLY
46873 +#if !defined(__DWC_PCD_H__)
46874 +#define __DWC_PCD_H__
46875 +
46876 +#include "dwc_otg_os_dep.h"
46877 +#include "usb.h"
46878 +#include "dwc_otg_cil.h"
46879 +#include "dwc_otg_pcd_if.h"
46880 +struct cfiobject;
46881 +
46882 +/**
46883 + * @file
46884 + *
46885 + * This file contains the structures, constants, and interfaces for
46886 + * the Perpherial Contoller Driver (PCD).
46887 + *
46888 + * The Peripheral Controller Driver (PCD) for Linux will implement the
46889 + * Gadget API, so that the existing Gadget drivers can be used. For
46890 + * the Mass Storage Function driver the File-backed USB Storage Gadget
46891 + * (FBS) driver will be used. The FBS driver supports the
46892 + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
46893 + * transports.
46894 + *
46895 + */
46896 +
46897 +/** Invalid DMA Address */
46898 +#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0)
46899 +
46900 +/** Max Transfer size for any EP */
46901 +#define DDMA_MAX_TRANSFER_SIZE 65535
46902 +
46903 +/**
46904 + * Get the pointer to the core_if from the pcd pointer.
46905 + */
46906 +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
46907 +
46908 +/**
46909 + * States of EP0.
46910 + */
46911 +typedef enum ep0_state {
46912 + EP0_DISCONNECT, /* no host */
46913 + EP0_IDLE,
46914 + EP0_IN_DATA_PHASE,
46915 + EP0_OUT_DATA_PHASE,
46916 + EP0_IN_STATUS_PHASE,
46917 + EP0_OUT_STATUS_PHASE,
46918 + EP0_STALL,
46919 +} ep0state_e;
46920 +
46921 +/** Fordward declaration.*/
46922 +struct dwc_otg_pcd;
46923 +
46924 +/** DWC_otg iso request structure.
46925 + *
46926 + */
46927 +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
46928 +
46929 +#ifdef DWC_UTE_PER_IO
46930 +
46931 +/**
46932 + * This shall be the exact analogy of the same type structure defined in the
46933 + * usb_gadget.h. Each descriptor contains
46934 + */
46935 +struct dwc_iso_pkt_desc_port {
46936 + uint32_t offset;
46937 + uint32_t length; /* expected length */
46938 + uint32_t actual_length;
46939 + uint32_t status;
46940 +};
46941 +
46942 +struct dwc_iso_xreq_port {
46943 + /** transfer/submission flag */
46944 + uint32_t tr_sub_flags;
46945 + /** Start the request ASAP */
46946 +#define DWC_EREQ_TF_ASAP 0x00000002
46947 + /** Just enqueue the request w/o initiating a transfer */
46948 +#define DWC_EREQ_TF_ENQUEUE 0x00000004
46949 +
46950 + /**
46951 + * count of ISO packets attached to this request - shall
46952 + * not exceed the pio_alloc_pkt_count
46953 + */
46954 + uint32_t pio_pkt_count;
46955 + /** count of ISO packets allocated for this request */
46956 + uint32_t pio_alloc_pkt_count;
46957 + /** number of ISO packet errors */
46958 + uint32_t error_count;
46959 + /** reserved for future extension */
46960 + uint32_t res;
46961 + /** Will be allocated and freed in the UTE gadget and based on the CFC value */
46962 + struct dwc_iso_pkt_desc_port *per_io_frame_descs;
46963 +};
46964 +#endif
46965 +/** DWC_otg request structure.
46966 + * This structure is a list of requests.
46967 + */
46968 +typedef struct dwc_otg_pcd_request {
46969 + void *priv;
46970 + void *buf;
46971 + dwc_dma_t dma;
46972 + uint32_t length;
46973 + uint32_t actual;
46974 + unsigned sent_zlp:1;
46975 + /**
46976 + * Used instead of original buffer if
46977 + * it(physical address) is not dword-aligned.
46978 + **/
46979 + uint8_t *dw_align_buf;
46980 + dwc_dma_t dw_align_buf_dma;
46981 +
46982 + DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
46983 +#ifdef DWC_UTE_PER_IO
46984 + struct dwc_iso_xreq_port ext_req;
46985 + //void *priv_ereq_nport; /* */
46986 +#endif
46987 +} dwc_otg_pcd_request_t;
46988 +
46989 +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
46990 +
46991 +/** PCD EP structure.
46992 + * This structure describes an EP, there is an array of EPs in the PCD
46993 + * structure.
46994 + */
46995 +typedef struct dwc_otg_pcd_ep {
46996 + /** USB EP Descriptor */
46997 + const usb_endpoint_descriptor_t *desc;
46998 +
46999 + /** queue of dwc_otg_pcd_requests. */
47000 + struct req_list queue;
47001 + unsigned stopped:1;
47002 + unsigned disabling:1;
47003 + unsigned dma:1;
47004 + unsigned queue_sof:1;
47005 +
47006 +#ifdef DWC_EN_ISOC
47007 + /** ISOC req handle passed */
47008 + void *iso_req_handle;
47009 +#endif //_EN_ISOC_
47010 +
47011 + /** DWC_otg ep data. */
47012 + dwc_ep_t dwc_ep;
47013 +
47014 + /** Pointer to PCD */
47015 + struct dwc_otg_pcd *pcd;
47016 +
47017 + void *priv;
47018 +} dwc_otg_pcd_ep_t;
47019 +
47020 +/** DWC_otg PCD Structure.
47021 + * This structure encapsulates the data for the dwc_otg PCD.
47022 + */
47023 +struct dwc_otg_pcd {
47024 + const struct dwc_otg_pcd_function_ops *fops;
47025 + /** The DWC otg device pointer */
47026 + struct dwc_otg_device *otg_dev;
47027 + /** Core Interface */
47028 + dwc_otg_core_if_t *core_if;
47029 + /** State of EP0 */
47030 + ep0state_e ep0state;
47031 + /** EP0 Request is pending */
47032 + unsigned ep0_pending:1;
47033 + /** Indicates when SET CONFIGURATION Request is in process */
47034 + unsigned request_config:1;
47035 + /** The state of the Remote Wakeup Enable. */
47036 + unsigned remote_wakeup_enable:1;
47037 + /** The state of the B-Device HNP Enable. */
47038 + unsigned b_hnp_enable:1;
47039 + /** The state of A-Device HNP Support. */
47040 + unsigned a_hnp_support:1;
47041 + /** The state of the A-Device Alt HNP support. */
47042 + unsigned a_alt_hnp_support:1;
47043 + /** Count of pending Requests */
47044 + unsigned request_pending;
47045 +
47046 + /** SETUP packet for EP0
47047 + * This structure is allocated as a DMA buffer on PCD initialization
47048 + * with enough space for up to 3 setup packets.
47049 + */
47050 + union {
47051 + usb_device_request_t req;
47052 + uint32_t d32[2];
47053 + } *setup_pkt;
47054 +
47055 + dwc_dma_t setup_pkt_dma_handle;
47056 +
47057 + /* Additional buffer and flag for CTRL_WR premature case */
47058 + uint8_t *backup_buf;
47059 + unsigned data_terminated;
47060 +
47061 + /** 2-byte dma buffer used to return status from GET_STATUS */
47062 + uint16_t *status_buf;
47063 + dwc_dma_t status_buf_dma_handle;
47064 +
47065 + /** EP0 */
47066 + dwc_otg_pcd_ep_t ep0;
47067 +
47068 + /** Array of IN EPs. */
47069 + dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
47070 + /** Array of OUT EPs. */
47071 + dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
47072 + /** number of valid EPs in the above array. */
47073 +// unsigned num_eps : 4;
47074 + dwc_spinlock_t *lock;
47075 +
47076 + /** Tasklet to defer starting of TEST mode transmissions until
47077 + * Status Phase has been completed.
47078 + */
47079 + dwc_tasklet_t *test_mode_tasklet;
47080 +
47081 + /** Tasklet to delay starting of xfer in DMA mode */
47082 + dwc_tasklet_t *start_xfer_tasklet;
47083 +
47084 + /** The test mode to enter when the tasklet is executed. */
47085 + unsigned test_mode;
47086 + /** The cfi_api structure that implements most of the CFI API
47087 + * and OTG specific core configuration functionality
47088 + */
47089 +#ifdef DWC_UTE_CFI
47090 + struct cfiobject *cfi;
47091 +#endif
47092 +
47093 +};
47094 +
47095 +//FIXME this functions should be static, and this prototypes should be removed
47096 +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
47097 +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
47098 + dwc_otg_pcd_request_t * req, int32_t status);
47099 +
47100 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
47101 + void *req_handle);
47102 +
47103 +extern void do_test_mode(void *data);
47104 +#endif
47105 +#endif /* DWC_HOST_ONLY */
47106 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
47107 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100
47108 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2013-07-06 15:25:50.000000000 +0100
47109 @@ -0,0 +1,360 @@
47110 +/* ==========================================================================
47111 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
47112 + * $Revision: #11 $
47113 + * $Date: 2011/10/26 $
47114 + * $Change: 1873028 $
47115 + *
47116 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
47117 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
47118 + * otherwise expressly agreed to in writing between Synopsys and you.
47119 + *
47120 + * The Software IS NOT an item of Licensed Software or Licensed Product under
47121 + * any End User Software License Agreement or Agreement for Licensed Product
47122 + * with Synopsys or any supplement thereto. You are permitted to use and
47123 + * redistribute this Software in source and binary forms, with or without
47124 + * modification, provided that redistributions of source code must retain this
47125 + * notice. You may not view, use, disclose, copy or distribute this file or
47126 + * any information contained herein except pursuant to this license grant from
47127 + * Synopsys. If you do not agree with this notice, including the disclaimer
47128 + * below, then you are not authorized to use the Software.
47129 + *
47130 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
47131 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47132 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47133 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
47134 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47135 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47136 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47137 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47138 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47139 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
47140 + * DAMAGE.
47141 + * ========================================================================== */
47142 +#ifndef DWC_HOST_ONLY
47143 +
47144 +#if !defined(__DWC_PCD_IF_H__)
47145 +#define __DWC_PCD_IF_H__
47146 +
47147 +//#include "dwc_os.h"
47148 +#include "dwc_otg_core_if.h"
47149 +
47150 +/** @file
47151 + * This file defines DWC_OTG PCD Core API.
47152 + */
47153 +
47154 +struct dwc_otg_pcd;
47155 +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
47156 +
47157 +/** Maxpacket size for EP0 */
47158 +#define MAX_EP0_SIZE 64
47159 +/** Maxpacket size for any EP */
47160 +#define MAX_PACKET_SIZE 1024
47161 +
47162 +/** @name Function Driver Callbacks */
47163 +/** @{ */
47164 +
47165 +/** This function will be called whenever a previously queued request has
47166 + * completed. The status value will be set to -DWC_E_SHUTDOWN to indicated a
47167 + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
47168 + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
47169 + * parameters. */
47170 +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47171 + void *req_handle, int32_t status,
47172 + uint32_t actual);
47173 +/**
47174 + * This function will be called whenever a previousle queued ISOC request has
47175 + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
47176 + * function.
47177 + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
47178 + * functions.
47179 + */
47180 +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47181 + void *req_handle, int proc_buf_num);
47182 +/** This function should handle any SETUP request that cannot be handled by the
47183 + * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
47184 + * class-specific requests, etc. The function must non-blocking.
47185 + *
47186 + * Returns 0 on success.
47187 + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
47188 + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
47189 + * Returns -DWC_E_SHUTDOWN on any other error. */
47190 +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
47191 +/** This is called whenever the device has been disconnected. The function
47192 + * driver should take appropriate action to clean up all pending requests in the
47193 + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
47194 + * state. */
47195 +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
47196 +/** This function is called when device has been connected. */
47197 +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
47198 +/** This function is called when device has been suspended */
47199 +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
47200 +/** This function is called when device has received LPM tokens, i.e.
47201 + * device has been sent to sleep state. */
47202 +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
47203 +/** This function is called when device has been resumed
47204 + * from suspend(L2) or L1 sleep state. */
47205 +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
47206 +/** This function is called whenever hnp params has been changed.
47207 + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
47208 + * to get hnp parameters. */
47209 +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
47210 +/** This function is called whenever USB RESET is detected. */
47211 +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
47212 +
47213 +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
47214 +
47215 +/**
47216 + *
47217 + * @param ep_handle Void pointer to the usb_ep structure
47218 + * @param ereq_port Pointer to the extended request structure created in the
47219 + * portable part.
47220 + */
47221 +typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47222 + void *req_handle, int32_t status,
47223 + void *ereq_port);
47224 +/** Function Driver Ops Data Structure */
47225 +struct dwc_otg_pcd_function_ops {
47226 + dwc_connect_cb_t connect;
47227 + dwc_disconnect_cb_t disconnect;
47228 + dwc_setup_cb_t setup;
47229 + dwc_completion_cb_t complete;
47230 + dwc_isoc_completion_cb_t isoc_complete;
47231 + dwc_suspend_cb_t suspend;
47232 + dwc_sleep_cb_t sleep;
47233 + dwc_resume_cb_t resume;
47234 + dwc_reset_cb_t reset;
47235 + dwc_hnp_params_changed_cb_t hnp_changed;
47236 + cfi_setup_cb_t cfi_setup;
47237 +#ifdef DWC_UTE_PER_IO
47238 + xiso_completion_cb_t xisoc_complete;
47239 +#endif
47240 +};
47241 +/** @} */
47242 +
47243 +/** @name Function Driver Functions */
47244 +/** @{ */
47245 +
47246 +/** Call this function to get pointer on dwc_otg_pcd_t,
47247 + * this pointer will be used for all PCD API functions.
47248 + *
47249 + * @param core_if The DWC_OTG Core
47250 + */
47251 +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
47252 +
47253 +/** Frees PCD allocated by dwc_otg_pcd_init
47254 + *
47255 + * @param pcd The PCD
47256 + */
47257 +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
47258 +
47259 +/** Call this to bind the function driver to the PCD Core.
47260 + *
47261 + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
47262 + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
47263 + */
47264 +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
47265 + const struct dwc_otg_pcd_function_ops *fops);
47266 +
47267 +/** Enables an endpoint for use. This function enables an endpoint in
47268 + * the PCD. The endpoint is described by the ep_desc which has the
47269 + * same format as a USB ep descriptor. The ep_handle parameter is used to refer
47270 + * to the endpoint from other API functions and in callbacks. Normally this
47271 + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
47272 + * core for that interface.
47273 + *
47274 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47275 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47276 + * Returns 0 on success.
47277 + *
47278 + * @param pcd The PCD
47279 + * @param ep_desc Endpoint descriptor
47280 + * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
47281 + */
47282 +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
47283 + const uint8_t * ep_desc, void *usb_ep);
47284 +
47285 +/** Disable the endpoint referenced by ep_handle.
47286 + *
47287 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47288 + * Returns -DWC_E_SHUTDOWN if any other error occurred.
47289 + * Returns 0 on success. */
47290 +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
47291 +
47292 +/** Queue a data transfer request on the endpoint referenced by ep_handle.
47293 + * After the transfer is completes, the complete callback will be called with
47294 + * the request status.
47295 + *
47296 + * @param pcd The PCD
47297 + * @param ep_handle The handle of the endpoint
47298 + * @param buf The buffer for the data
47299 + * @param dma_buf The DMA buffer for the data
47300 + * @param buflen The length of the data transfer
47301 + * @param zero Specifies whether to send zero length last packet.
47302 + * @param req_handle Set this handle to any value to use to reference this
47303 + * request in the ep_dequeue function or from the complete callback
47304 + * @param atomic_alloc If driver need to perform atomic allocations
47305 + * for internal data structures.
47306 + *
47307 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47308 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47309 + * Returns 0 on success. */
47310 +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
47311 + uint8_t * buf, dwc_dma_t dma_buf,
47312 + uint32_t buflen, int zero, void *req_handle,
47313 + int atomic_alloc);
47314 +#ifdef DWC_UTE_PER_IO
47315 +/**
47316 + *
47317 + * @param ereq_nonport Pointer to the extended request part of the
47318 + * usb_request structure defined in usb_gadget.h file.
47319 + */
47320 +extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
47321 + uint8_t * buf, dwc_dma_t dma_buf,
47322 + uint32_t buflen, int zero,
47323 + void *req_handle, int atomic_alloc,
47324 + void *ereq_nonport);
47325 +
47326 +#endif
47327 +
47328 +/** De-queue the specified data transfer that has not yet completed.
47329 + *
47330 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47331 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47332 + * Returns 0 on success. */
47333 +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
47334 + void *req_handle);
47335 +
47336 +/** Halt (STALL) an endpoint or clear it.
47337 + *
47338 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47339 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47340 + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
47341 + * Returns 0 on success. */
47342 +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
47343 +
47344 +/** This function */
47345 +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
47346 +
47347 +/** This function should be called on every hardware interrupt */
47348 +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
47349 +
47350 +/** This function returns current frame number */
47351 +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
47352 +
47353 +/**
47354 + * Start isochronous transfers on the endpoint referenced by ep_handle.
47355 + * For isochronous transfers duble buffering is used.
47356 + * After processing each of buffers comlete callback will be called with
47357 + * status for each transaction.
47358 + *
47359 + * @param pcd The PCD
47360 + * @param ep_handle The handle of the endpoint
47361 + * @param buf0 The virtual address of first data buffer
47362 + * @param buf1 The virtual address of second data buffer
47363 + * @param dma0 The DMA address of first data buffer
47364 + * @param dma1 The DMA address of second data buffer
47365 + * @param sync_frame Data pattern frame number
47366 + * @param dp_frame Data size for pattern frame
47367 + * @param data_per_frame Data size for regular frame
47368 + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
47369 + * @param buf_proc_intrvl Interval of ISOC Buffer processing
47370 + * @param req_handle Handle of ISOC request
47371 + * @param atomic_alloc Specefies whether to perform atomic allocation for
47372 + * internal data structures.
47373 + *
47374 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
47375 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
47376 + * Returns -DW_E_SHUTDOWN for any other error.
47377 + * Returns 0 on success
47378 + */
47379 +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
47380 + uint8_t * buf0, uint8_t * buf1,
47381 + dwc_dma_t dma0, dwc_dma_t dma1,
47382 + int sync_frame, int dp_frame,
47383 + int data_per_frame, int start_frame,
47384 + int buf_proc_intrvl, void *req_handle,
47385 + int atomic_alloc);
47386 +
47387 +/** Stop ISOC transfers on endpoint referenced by ep_handle.
47388 + *
47389 + * @param pcd The PCD
47390 + * @param ep_handle The handle of the endpoint
47391 + * @param req_handle Handle of ISOC request
47392 + *
47393 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
47394 + * Returns 0 on success
47395 + */
47396 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
47397 + void *req_handle);
47398 +
47399 +/** Get ISOC packet status.
47400 + *
47401 + * @param pcd The PCD
47402 + * @param ep_handle The handle of the endpoint
47403 + * @param iso_req_handle Isochronoush request handle
47404 + * @param packet Number of packet
47405 + * @param status Out parameter for returning status
47406 + * @param actual Out parameter for returning actual length
47407 + * @param offset Out parameter for returning offset
47408 + *
47409 + */
47410 +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
47411 + void *ep_handle,
47412 + void *iso_req_handle, int packet,
47413 + int *status, int *actual,
47414 + int *offset);
47415 +
47416 +/** Get ISOC packet count.
47417 + *
47418 + * @param pcd The PCD
47419 + * @param ep_handle The handle of the endpoint
47420 + * @param iso_req_handle
47421 + */
47422 +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
47423 + void *ep_handle,
47424 + void *iso_req_handle);
47425 +
47426 +/** This function starts the SRP Protocol if no session is in progress. If
47427 + * a session is already in progress, but the device is suspended,
47428 + * remote wakeup signaling is started.
47429 + */
47430 +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
47431 +
47432 +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
47433 +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
47434 +
47435 +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
47436 +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
47437 +
47438 +/** Initiate SRP */
47439 +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
47440 +
47441 +/** Starts remote wakeup signaling. */
47442 +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
47443 +
47444 +/** Starts micorsecond soft disconnect. */
47445 +extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);
47446 +/** This function returns whether device is dualspeed.*/
47447 +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
47448 +
47449 +/** This function returns whether device is otg. */
47450 +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
47451 +
47452 +/** These functions allow to get hnp parameters */
47453 +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
47454 +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
47455 +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
47456 +
47457 +/** CFI specific Interface functions */
47458 +/** Allocate a cfi buffer */
47459 +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
47460 + dwc_dma_t * addr, size_t buflen,
47461 + int flags);
47462 +
47463 +/******************************************************************************/
47464 +
47465 +/** @} */
47466 +
47467 +#endif /* __DWC_PCD_IF_H__ */
47468 +
47469 +#endif /* DWC_HOST_ONLY */
47470 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47471 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100
47472 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2013-07-06 15:25:50.000000000 +0100
47473 @@ -0,0 +1,5147 @@
47474 +/* ==========================================================================
47475 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
47476 + * $Revision: #116 $
47477 + * $Date: 2012/08/10 $
47478 + * $Change: 2047372 $
47479 + *
47480 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
47481 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
47482 + * otherwise expressly agreed to in writing between Synopsys and you.
47483 + *
47484 + * The Software IS NOT an item of Licensed Software or Licensed Product under
47485 + * any End User Software License Agreement or Agreement for Licensed Product
47486 + * with Synopsys or any supplement thereto. You are permitted to use and
47487 + * redistribute this Software in source and binary forms, with or without
47488 + * modification, provided that redistributions of source code must retain this
47489 + * notice. You may not view, use, disclose, copy or distribute this file or
47490 + * any information contained herein except pursuant to this license grant from
47491 + * Synopsys. If you do not agree with this notice, including the disclaimer
47492 + * below, then you are not authorized to use the Software.
47493 + *
47494 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
47495 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47496 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47497 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
47498 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47499 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47500 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47501 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47502 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47503 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
47504 + * DAMAGE.
47505 + * ========================================================================== */
47506 +#ifndef DWC_HOST_ONLY
47507 +
47508 +#include "dwc_otg_pcd.h"
47509 +
47510 +#ifdef DWC_UTE_CFI
47511 +#include "dwc_otg_cfi.h"
47512 +#endif
47513 +
47514 +#ifdef DWC_UTE_PER_IO
47515 +extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
47516 +#endif
47517 +//#define PRINT_CFI_DMA_DESCS
47518 +
47519 +#define DEBUG_EP0
47520 +
47521 +/**
47522 + * This function updates OTG.
47523 + */
47524 +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
47525 +{
47526 +
47527 + if (reset) {
47528 + pcd->b_hnp_enable = 0;
47529 + pcd->a_hnp_support = 0;
47530 + pcd->a_alt_hnp_support = 0;
47531 + }
47532 +
47533 + if (pcd->fops->hnp_changed) {
47534 + pcd->fops->hnp_changed(pcd);
47535 + }
47536 +}
47537 +
47538 +/** @file
47539 + * This file contains the implementation of the PCD Interrupt handlers.
47540 + *
47541 + * The PCD handles the device interrupts. Many conditions can cause a
47542 + * device interrupt. When an interrupt occurs, the device interrupt
47543 + * service routine determines the cause of the interrupt and
47544 + * dispatches handling to the appropriate function. These interrupt
47545 + * handling functions are described below.
47546 + * All interrupt registers are processed from LSB to MSB.
47547 + */
47548 +
47549 +/**
47550 + * This function prints the ep0 state for debug purposes.
47551 + */
47552 +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
47553 +{
47554 +#ifdef DEBUG
47555 + char str[40];
47556 +
47557 + switch (pcd->ep0state) {
47558 + case EP0_DISCONNECT:
47559 + dwc_strcpy(str, "EP0_DISCONNECT");
47560 + break;
47561 + case EP0_IDLE:
47562 + dwc_strcpy(str, "EP0_IDLE");
47563 + break;
47564 + case EP0_IN_DATA_PHASE:
47565 + dwc_strcpy(str, "EP0_IN_DATA_PHASE");
47566 + break;
47567 + case EP0_OUT_DATA_PHASE:
47568 + dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
47569 + break;
47570 + case EP0_IN_STATUS_PHASE:
47571 + dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
47572 + break;
47573 + case EP0_OUT_STATUS_PHASE:
47574 + dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
47575 + break;
47576 + case EP0_STALL:
47577 + dwc_strcpy(str, "EP0_STALL");
47578 + break;
47579 + default:
47580 + dwc_strcpy(str, "EP0_INVALID");
47581 + }
47582 +
47583 + DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
47584 +#endif
47585 +}
47586 +
47587 +/**
47588 + * This function calculate the size of the payload in the memory
47589 + * for out endpoints and prints size for debug purposes(used in
47590 + * 2.93a DevOutNak feature).
47591 + */
47592 +static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep)
47593 +{
47594 +#ifdef DEBUG
47595 + deptsiz_data_t deptsiz_init = {.d32 = 0 };
47596 + deptsiz_data_t deptsiz_updt = {.d32 = 0 };
47597 + int pack_num;
47598 + unsigned payload;
47599 +
47600 + deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
47601 + deptsiz_updt.d32 =
47602 + DWC_READ_REG32(&pcd->core_if->dev_if->
47603 + out_ep_regs[ep->num]->doeptsiz);
47604 + /* Payload will be */
47605 + payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
47606 + /* Packet count is decremented every time a packet
47607 + * is written to the RxFIFO not in to the external memory
47608 + * So, if payload == 0, then it means no packet was sent to ext memory*/
47609 + pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
47610 + DWC_DEBUGPL(DBG_PCDV,
47611 + "Payload for EP%d-%s\n",
47612 + ep->num, (ep->is_in ? "IN" : "OUT"));
47613 + DWC_DEBUGPL(DBG_PCDV,
47614 + "Number of transfered bytes = 0x%08x\n", payload);
47615 + DWC_DEBUGPL(DBG_PCDV,
47616 + "Number of transfered packets = %d\n", pack_num);
47617 +#endif
47618 +}
47619 +
47620 +
47621 +#ifdef DWC_UTE_CFI
47622 +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
47623 + const uint8_t * epname, int descnum)
47624 +{
47625 + CFI_INFO
47626 + ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
47627 + epname, descnum, ddesc->buf, ddesc->status.b.bytes,
47628 + ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
47629 + ddesc->status.b.bs);
47630 +}
47631 +#endif
47632 +
47633 +/**
47634 + * This function returns pointer to in ep struct with number ep_num
47635 + */
47636 +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47637 +{
47638 + int i;
47639 + int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47640 + if (ep_num == 0) {
47641 + return &pcd->ep0;
47642 + } else {
47643 + for (i = 0; i < num_in_eps; ++i) {
47644 + if (pcd->in_ep[i].dwc_ep.num == ep_num)
47645 + return &pcd->in_ep[i];
47646 + }
47647 + return 0;
47648 + }
47649 +}
47650 +
47651 +/**
47652 + * This function returns pointer to out ep struct with number ep_num
47653 + */
47654 +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47655 +{
47656 + int i;
47657 + int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47658 + if (ep_num == 0) {
47659 + return &pcd->ep0;
47660 + } else {
47661 + for (i = 0; i < num_out_eps; ++i) {
47662 + if (pcd->out_ep[i].dwc_ep.num == ep_num)
47663 + return &pcd->out_ep[i];
47664 + }
47665 + return 0;
47666 + }
47667 +}
47668 +
47669 +/**
47670 + * This functions gets a pointer to an EP from the wIndex address
47671 + * value of the control request.
47672 + */
47673 +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
47674 +{
47675 + dwc_otg_pcd_ep_t *ep;
47676 + uint32_t ep_num = UE_GET_ADDR(wIndex);
47677 +
47678 + if (ep_num == 0) {
47679 + ep = &pcd->ep0;
47680 + } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */
47681 + ep = &pcd->in_ep[ep_num - 1];
47682 + } else {
47683 + ep = &pcd->out_ep[ep_num - 1];
47684 + }
47685 +
47686 + return ep;
47687 +}
47688 +
47689 +/**
47690 + * This function checks the EP request queue, if the queue is not
47691 + * empty the next request is started.
47692 + */
47693 +void start_next_request(dwc_otg_pcd_ep_t * ep)
47694 +{
47695 + dwc_otg_pcd_request_t *req = 0;
47696 + uint32_t max_transfer =
47697 + GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
47698 +
47699 +#ifdef DWC_UTE_CFI
47700 + struct dwc_otg_pcd *pcd;
47701 + pcd = ep->pcd;
47702 +#endif
47703 +
47704 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
47705 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
47706 +
47707 +#ifdef DWC_UTE_CFI
47708 + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
47709 + ep->dwc_ep.cfi_req_len = req->length;
47710 + pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
47711 + } else {
47712 +#endif
47713 + /* Setup and start the Transfer */
47714 + if (req->dw_align_buf) {
47715 + ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
47716 + ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
47717 + ep->dwc_ep.xfer_buff = req->dw_align_buf;
47718 + } else {
47719 + ep->dwc_ep.dma_addr = req->dma;
47720 + ep->dwc_ep.start_xfer_buff = req->buf;
47721 + ep->dwc_ep.xfer_buff = req->buf;
47722 + }
47723 + ep->dwc_ep.sent_zlp = 0;
47724 + ep->dwc_ep.total_len = req->length;
47725 + ep->dwc_ep.xfer_len = 0;
47726 + ep->dwc_ep.xfer_count = 0;
47727 +
47728 + ep->dwc_ep.maxxfer = max_transfer;
47729 + if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
47730 + uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
47731 + - (DDMA_MAX_TRANSFER_SIZE % 4);
47732 + if (ep->dwc_ep.is_in) {
47733 + if (ep->dwc_ep.maxxfer >
47734 + DDMA_MAX_TRANSFER_SIZE) {
47735 + ep->dwc_ep.maxxfer =
47736 + DDMA_MAX_TRANSFER_SIZE;
47737 + }
47738 + } else {
47739 + if (ep->dwc_ep.maxxfer > out_max_xfer) {
47740 + ep->dwc_ep.maxxfer =
47741 + out_max_xfer;
47742 + }
47743 + }
47744 + }
47745 + if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
47746 + ep->dwc_ep.maxxfer -=
47747 + (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
47748 + }
47749 + if (req->sent_zlp) {
47750 + if ((ep->dwc_ep.total_len %
47751 + ep->dwc_ep.maxpacket == 0)
47752 + && (ep->dwc_ep.total_len != 0)) {
47753 + ep->dwc_ep.sent_zlp = 1;
47754 + }
47755 +
47756 + }
47757 +#ifdef DWC_UTE_CFI
47758 + }
47759 +#endif
47760 + dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
47761 + } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
47762 + DWC_PRINTF("There are no more ISOC requests \n");
47763 + ep->dwc_ep.frame_num = 0xFFFFFFFF;
47764 + }
47765 +}
47766 +
47767 +/**
47768 + * This function handles the SOF Interrupts. At this time the SOF
47769 + * Interrupt is disabled.
47770 + */
47771 +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
47772 +{
47773 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47774 +
47775 + gintsts_data_t gintsts;
47776 +
47777 + DWC_DEBUGPL(DBG_PCD, "SOF\n");
47778 +
47779 + /* Clear interrupt */
47780 + gintsts.d32 = 0;
47781 + gintsts.b.sofintr = 1;
47782 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
47783 +
47784 + return 1;
47785 +}
47786 +
47787 +/**
47788 + * This function handles the Rx Status Queue Level Interrupt, which
47789 + * indicates that there is a least one packet in the Rx FIFO. The
47790 + * packets are moved from the FIFO to memory, where they will be
47791 + * processed when the Endpoint Interrupt Register indicates Transfer
47792 + * Complete or SETUP Phase Done.
47793 + *
47794 + * Repeat the following until the Rx Status Queue is empty:
47795 + * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
47796 + * info
47797 + * -# If Receive FIFO is empty then skip to step Clear the interrupt
47798 + * and exit
47799 + * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
47800 + * SETUP data to the buffer
47801 + * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
47802 + * to the destination buffer
47803 + */
47804 +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
47805 +{
47806 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47807 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47808 + gintmsk_data_t gintmask = {.d32 = 0 };
47809 + device_grxsts_data_t status;
47810 + dwc_otg_pcd_ep_t *ep;
47811 + gintsts_data_t gintsts;
47812 +#ifdef DEBUG
47813 + static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
47814 +#endif
47815 +
47816 + //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
47817 + /* Disable the Rx Status Queue Level interrupt */
47818 + gintmask.b.rxstsqlvl = 1;
47819 + DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
47820 +
47821 + /* Get the Status from the top of the FIFO */
47822 + status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
47823 +
47824 + DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
47825 + "pktsts:%x Frame:%d(0x%0x)\n",
47826 + status.b.epnum, status.b.bcnt,
47827 + dpid_str[status.b.dpid],
47828 + status.b.pktsts, status.b.fn, status.b.fn);
47829 + /* Get pointer to EP structure */
47830 + ep = get_out_ep(pcd, status.b.epnum);
47831 +
47832 + switch (status.b.pktsts) {
47833 + case DWC_DSTS_GOUT_NAK:
47834 + DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
47835 + break;
47836 + case DWC_STS_DATA_UPDT:
47837 + DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
47838 + if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
47839 + /** @todo NGS Check for buffer overflow? */
47840 + dwc_otg_read_packet(core_if,
47841 + ep->dwc_ep.xfer_buff,
47842 + status.b.bcnt);
47843 + ep->dwc_ep.xfer_count += status.b.bcnt;
47844 + ep->dwc_ep.xfer_buff += status.b.bcnt;
47845 + }
47846 + break;
47847 + case DWC_STS_XFER_COMP:
47848 + DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
47849 + break;
47850 + case DWC_DSTS_SETUP_COMP:
47851 +#ifdef DEBUG_EP0
47852 + DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
47853 +#endif
47854 + break;
47855 + case DWC_DSTS_SETUP_UPDT:
47856 + dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
47857 +#ifdef DEBUG_EP0
47858 + DWC_DEBUGPL(DBG_PCD,
47859 + "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
47860 + pcd->setup_pkt->req.bmRequestType,
47861 + pcd->setup_pkt->req.bRequest,
47862 + UGETW(pcd->setup_pkt->req.wValue),
47863 + UGETW(pcd->setup_pkt->req.wIndex),
47864 + UGETW(pcd->setup_pkt->req.wLength));
47865 +#endif
47866 + ep->dwc_ep.xfer_count += status.b.bcnt;
47867 + break;
47868 + default:
47869 + DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
47870 + status.b.pktsts);
47871 + break;
47872 + }
47873 +
47874 + /* Enable the Rx Status Queue Level interrupt */
47875 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
47876 + /* Clear interrupt */
47877 + gintsts.d32 = 0;
47878 + gintsts.b.rxstsqlvl = 1;
47879 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47880 +
47881 + //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
47882 + return 1;
47883 +}
47884 +
47885 +/**
47886 + * This function examines the Device IN Token Learning Queue to
47887 + * determine the EP number of the last IN token received. This
47888 + * implementation is for the Mass Storage device where there are only
47889 + * 2 IN EPs (Control-IN and BULK-IN).
47890 + *
47891 + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
47892 + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
47893 + *
47894 + * @param core_if Programming view of DWC_otg controller.
47895 + *
47896 + */
47897 +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
47898 +{
47899 + dwc_otg_device_global_regs_t *dev_global_regs =
47900 + core_if->dev_if->dev_global_regs;
47901 + const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
47902 + /* Number of Token Queue Registers */
47903 + const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
47904 + dtknq1_data_t dtknqr1;
47905 + uint32_t in_tkn_epnums[4];
47906 + int ndx = 0;
47907 + int i = 0;
47908 + volatile uint32_t *addr = &dev_global_regs->dtknqr1;
47909 + int epnum = 0;
47910 +
47911 + //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
47912 +
47913 + /* Read the DTKNQ Registers */
47914 + for (i = 0; i < DTKNQ_REG_CNT; i++) {
47915 + in_tkn_epnums[i] = DWC_READ_REG32(addr);
47916 + DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
47917 + in_tkn_epnums[i]);
47918 + if (addr == &dev_global_regs->dvbusdis) {
47919 + addr = &dev_global_regs->dtknqr3_dthrctl;
47920 + } else {
47921 + ++addr;
47922 + }
47923 +
47924 + }
47925 +
47926 + /* Copy the DTKNQR1 data to the bit field. */
47927 + dtknqr1.d32 = in_tkn_epnums[0];
47928 + /* Get the EP numbers */
47929 + in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
47930 + ndx = dtknqr1.b.intknwptr - 1;
47931 +
47932 + //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
47933 + if (ndx == -1) {
47934 + /** @todo Find a simpler way to calculate the max
47935 + * queue position.*/
47936 + int cnt = TOKEN_Q_DEPTH;
47937 + if (TOKEN_Q_DEPTH <= 6) {
47938 + cnt = TOKEN_Q_DEPTH - 1;
47939 + } else if (TOKEN_Q_DEPTH <= 14) {
47940 + cnt = TOKEN_Q_DEPTH - 7;
47941 + } else if (TOKEN_Q_DEPTH <= 22) {
47942 + cnt = TOKEN_Q_DEPTH - 15;
47943 + } else {
47944 + cnt = TOKEN_Q_DEPTH - 23;
47945 + }
47946 + epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
47947 + } else {
47948 + if (ndx <= 5) {
47949 + epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
47950 + } else if (ndx <= 13) {
47951 + ndx -= 6;
47952 + epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
47953 + } else if (ndx <= 21) {
47954 + ndx -= 14;
47955 + epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
47956 + } else if (ndx <= 29) {
47957 + ndx -= 22;
47958 + epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
47959 + }
47960 + }
47961 + //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
47962 + return epnum;
47963 +}
47964 +
47965 +/**
47966 + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
47967 + * The active request is checked for the next packet to be loaded into
47968 + * the non-periodic Tx FIFO.
47969 + */
47970 +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
47971 +{
47972 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47973 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47974 + dwc_otg_dev_in_ep_regs_t *ep_regs;
47975 + gnptxsts_data_t txstatus = {.d32 = 0 };
47976 + gintsts_data_t gintsts;
47977 +
47978 + int epnum = 0;
47979 + dwc_otg_pcd_ep_t *ep = 0;
47980 + uint32_t len = 0;
47981 + int dwords;
47982 +
47983 + /* Get the epnum from the IN Token Learning Queue. */
47984 + epnum = get_ep_of_last_in_token(core_if);
47985 + ep = get_in_ep(pcd, epnum);
47986 +
47987 + DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
47988 +
47989 + ep_regs = core_if->dev_if->in_ep_regs[epnum];
47990 +
47991 + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47992 + if (len > ep->dwc_ep.maxpacket) {
47993 + len = ep->dwc_ep.maxpacket;
47994 + }
47995 + dwords = (len + 3) / 4;
47996 +
47997 + /* While there is space in the queue and space in the FIFO and
47998 + * More data to tranfer, Write packets to the Tx FIFO */
47999 + txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
48000 + DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
48001 +
48002 + while (txstatus.b.nptxqspcavail > 0 &&
48003 + txstatus.b.nptxfspcavail > dwords &&
48004 + ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
48005 + /* Write the FIFO */
48006 + dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
48007 + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
48008 +
48009 + if (len > ep->dwc_ep.maxpacket) {
48010 + len = ep->dwc_ep.maxpacket;
48011 + }
48012 +
48013 + dwords = (len + 3) / 4;
48014 + txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
48015 + DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
48016 + }
48017 +
48018 + DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
48019 + DWC_READ_REG32(&global_regs->gnptxsts));
48020 +
48021 + /* Clear interrupt */
48022 + gintsts.d32 = 0;
48023 + gintsts.b.nptxfempty = 1;
48024 + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
48025 +
48026 + return 1;
48027 +}
48028 +
48029 +/**
48030 + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
48031 + * The active request is checked for the next packet to be loaded into
48032 + * apropriate Tx FIFO.
48033 + */
48034 +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
48035 +{
48036 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48037 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48038 + dwc_otg_dev_in_ep_regs_t *ep_regs;
48039 + dtxfsts_data_t txstatus = {.d32 = 0 };
48040 + dwc_otg_pcd_ep_t *ep = 0;
48041 + uint32_t len = 0;
48042 + int dwords;
48043 +
48044 + ep = get_in_ep(pcd, epnum);
48045 +
48046 + DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
48047 +
48048 + ep_regs = core_if->dev_if->in_ep_regs[epnum];
48049 +
48050 + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
48051 +
48052 + if (len > ep->dwc_ep.maxpacket) {
48053 + len = ep->dwc_ep.maxpacket;
48054 + }
48055 +
48056 + dwords = (len + 3) / 4;
48057 +
48058 + /* While there is space in the queue and space in the FIFO and
48059 + * More data to tranfer, Write packets to the Tx FIFO */
48060 + txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
48061 + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
48062 +
48063 + while (txstatus.b.txfspcavail > dwords &&
48064 + ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
48065 + ep->dwc_ep.xfer_len != 0) {
48066 + /* Write the FIFO */
48067 + dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
48068 +
48069 + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
48070 + if (len > ep->dwc_ep.maxpacket) {
48071 + len = ep->dwc_ep.maxpacket;
48072 + }
48073 +
48074 + dwords = (len + 3) / 4;
48075 + txstatus.d32 =
48076 + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
48077 + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
48078 + txstatus.d32);
48079 + }
48080 +
48081 + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
48082 + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
48083 +
48084 + return 1;
48085 +}
48086 +
48087 +/**
48088 + * This function is called when the Device is disconnected. It stops
48089 + * any active requests and informs the Gadget driver of the
48090 + * disconnect.
48091 + */
48092 +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
48093 +{
48094 + int i, num_in_eps, num_out_eps;
48095 + dwc_otg_pcd_ep_t *ep;
48096 +
48097 + gintmsk_data_t intr_mask = {.d32 = 0 };
48098 +
48099 + DWC_SPINLOCK(pcd->lock);
48100 +
48101 + num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
48102 + num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
48103 +
48104 + DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
48105 + /* don't disconnect drivers more than once */
48106 + if (pcd->ep0state == EP0_DISCONNECT) {
48107 + DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
48108 + DWC_SPINUNLOCK(pcd->lock);
48109 + return;
48110 + }
48111 + pcd->ep0state = EP0_DISCONNECT;
48112 +
48113 + /* Reset the OTG state. */
48114 + dwc_otg_pcd_update_otg(pcd, 1);
48115 +
48116 + /* Disable the NP Tx Fifo Empty Interrupt. */
48117 + intr_mask.b.nptxfempty = 1;
48118 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48119 + intr_mask.d32, 0);
48120 +
48121 + /* Flush the FIFOs */
48122 + /**@todo NGS Flush Periodic FIFOs */
48123 + dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
48124 + dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
48125 +
48126 + /* prevent new request submissions, kill any outstanding requests */
48127 + ep = &pcd->ep0;
48128 + dwc_otg_request_nuke(ep);
48129 + /* prevent new request submissions, kill any outstanding requests */
48130 + for (i = 0; i < num_in_eps; i++) {
48131 + dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
48132 + dwc_otg_request_nuke(ep);
48133 + }
48134 + /* prevent new request submissions, kill any outstanding requests */
48135 + for (i = 0; i < num_out_eps; i++) {
48136 + dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
48137 + dwc_otg_request_nuke(ep);
48138 + }
48139 +
48140 + /* report disconnect; the driver is already quiesced */
48141 + if (pcd->fops->disconnect) {
48142 + DWC_SPINUNLOCK(pcd->lock);
48143 + pcd->fops->disconnect(pcd);
48144 + DWC_SPINLOCK(pcd->lock);
48145 + }
48146 + DWC_SPINUNLOCK(pcd->lock);
48147 +}
48148 +
48149 +/**
48150 + * This interrupt indicates that ...
48151 + */
48152 +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
48153 +{
48154 + gintmsk_data_t intr_mask = {.d32 = 0 };
48155 + gintsts_data_t gintsts;
48156 +
48157 + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
48158 + intr_mask.b.i2cintr = 1;
48159 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48160 + intr_mask.d32, 0);
48161 +
48162 + /* Clear interrupt */
48163 + gintsts.d32 = 0;
48164 + gintsts.b.i2cintr = 1;
48165 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48166 + gintsts.d32);
48167 + return 1;
48168 +}
48169 +
48170 +/**
48171 + * This interrupt indicates that ...
48172 + */
48173 +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
48174 +{
48175 + gintsts_data_t gintsts;
48176 +#if defined(VERBOSE)
48177 + DWC_PRINTF("Early Suspend Detected\n");
48178 +#endif
48179 +
48180 + /* Clear interrupt */
48181 + gintsts.d32 = 0;
48182 + gintsts.b.erlysuspend = 1;
48183 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48184 + gintsts.d32);
48185 + return 1;
48186 +}
48187 +
48188 +/**
48189 + * This function configures EPO to receive SETUP packets.
48190 + *
48191 + * @todo NGS: Update the comments from the HW FS.
48192 + *
48193 + * -# Program the following fields in the endpoint specific registers
48194 + * for Control OUT EP 0, in order to receive a setup packet
48195 + * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
48196 + * setup packets)
48197 + * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
48198 + * to back setup packets)
48199 + * - In DMA mode, DOEPDMA0 Register with a memory address to
48200 + * store any setup packets received
48201 + *
48202 + * @param core_if Programming view of DWC_otg controller.
48203 + * @param pcd Programming view of the PCD.
48204 + */
48205 +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
48206 + dwc_otg_pcd_t * pcd)
48207 +{
48208 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48209 + deptsiz0_data_t doeptsize0 = {.d32 = 0 };
48210 + dwc_otg_dev_dma_desc_t *dma_desc;
48211 + depctl_data_t doepctl = {.d32 = 0 };
48212 +
48213 +#ifdef VERBOSE
48214 + DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
48215 + DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
48216 +#endif
48217 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
48218 + doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
48219 + if (doepctl.b.epena) {
48220 + return;
48221 + }
48222 + }
48223 +
48224 + doeptsize0.b.supcnt = 3;
48225 + doeptsize0.b.pktcnt = 1;
48226 + doeptsize0.b.xfersize = 8 * 3;
48227 +
48228 + if (core_if->dma_enable) {
48229 + if (!core_if->dma_desc_enable) {
48230 + /** put here as for Hermes mode deptisz register should not be written */
48231 + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
48232 + doeptsize0.d32);
48233 +
48234 + /** @todo dma needs to handle multiple setup packets (up to 3) */
48235 + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
48236 + pcd->setup_pkt_dma_handle);
48237 + } else {
48238 + dev_if->setup_desc_index =
48239 + (dev_if->setup_desc_index + 1) & 1;
48240 + dma_desc =
48241 + dev_if->setup_desc_addr[dev_if->setup_desc_index];
48242 +
48243 + /** DMA Descriptor Setup */
48244 + dma_desc->status.b.bs = BS_HOST_BUSY;
48245 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
48246 + dma_desc->status.b.sr = 0;
48247 + dma_desc->status.b.mtrf = 0;
48248 + }
48249 + dma_desc->status.b.l = 1;
48250 + dma_desc->status.b.ioc = 1;
48251 + dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
48252 + dma_desc->buf = pcd->setup_pkt_dma_handle;
48253 + dma_desc->status.b.sts = 0;
48254 + dma_desc->status.b.bs = BS_HOST_READY;
48255 +
48256 + /** DOEPDMA0 Register write */
48257 + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
48258 + dev_if->dma_setup_desc_addr
48259 + [dev_if->setup_desc_index]);
48260 + }
48261 +
48262 + } else {
48263 + /** put here as for Hermes mode deptisz register should not be written */
48264 + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
48265 + doeptsize0.d32);
48266 + }
48267 +
48268 + /** DOEPCTL0 Register write cnak will be set after setup interrupt */
48269 + doepctl.d32 = 0;
48270 + doepctl.b.epena = 1;
48271 + if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
48272 + doepctl.b.cnak = 1;
48273 + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
48274 + } else {
48275 + DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
48276 + }
48277 +
48278 +#ifdef VERBOSE
48279 + DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
48280 + DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
48281 + DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
48282 + DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
48283 +#endif
48284 +}
48285 +
48286 +/**
48287 + * This interrupt occurs when a USB Reset is detected. When the USB
48288 + * Reset Interrupt occurs the device state is set to DEFAULT and the
48289 + * EP0 state is set to IDLE.
48290 + * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
48291 + * -# Unmask the following interrupt bits
48292 + * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
48293 + * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
48294 + * - DOEPMSK.SETUP = 1
48295 + * - DOEPMSK.XferCompl = 1
48296 + * - DIEPMSK.XferCompl = 1
48297 + * - DIEPMSK.TimeOut = 1
48298 + * -# Program the following fields in the endpoint specific registers
48299 + * for Control OUT EP 0, in order to receive a setup packet
48300 + * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
48301 + * setup packets)
48302 + * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
48303 + * to back setup packets)
48304 + * - In DMA mode, DOEPDMA0 Register with a memory address to
48305 + * store any setup packets received
48306 + * At this point, all the required initialization, except for enabling
48307 + * the control 0 OUT endpoint is done, for receiving SETUP packets.
48308 + */
48309 +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
48310 +{
48311 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48312 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48313 + depctl_data_t doepctl = {.d32 = 0 };
48314 + depctl_data_t diepctl = {.d32 = 0 };
48315 + daint_data_t daintmsk = {.d32 = 0 };
48316 + doepmsk_data_t doepmsk = {.d32 = 0 };
48317 + diepmsk_data_t diepmsk = {.d32 = 0 };
48318 + dcfg_data_t dcfg = {.d32 = 0 };
48319 + grstctl_t resetctl = {.d32 = 0 };
48320 + dctl_data_t dctl = {.d32 = 0 };
48321 + int i = 0;
48322 + gintsts_data_t gintsts;
48323 + pcgcctl_data_t power = {.d32 = 0 };
48324 +
48325 + power.d32 = DWC_READ_REG32(core_if->pcgcctl);
48326 + if (power.b.stoppclk) {
48327 + power.d32 = 0;
48328 + power.b.stoppclk = 1;
48329 + DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48330 +
48331 + power.b.pwrclmp = 1;
48332 + DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48333 +
48334 + power.b.rstpdwnmodule = 1;
48335 + DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48336 + }
48337 +
48338 + core_if->lx_state = DWC_OTG_L0;
48339 +
48340 + DWC_PRINTF("USB RESET\n");
48341 +#ifdef DWC_EN_ISOC
48342 + for (i = 1; i < 16; ++i) {
48343 + dwc_otg_pcd_ep_t *ep;
48344 + dwc_ep_t *dwc_ep;
48345 + ep = get_in_ep(pcd, i);
48346 + if (ep != 0) {
48347 + dwc_ep = &ep->dwc_ep;
48348 + dwc_ep->next_frame = 0xffffffff;
48349 + }
48350 + }
48351 +#endif /* DWC_EN_ISOC */
48352 +
48353 + /* reset the HNP settings */
48354 + dwc_otg_pcd_update_otg(pcd, 1);
48355 +
48356 + /* Clear the Remote Wakeup Signalling */
48357 + dctl.b.rmtwkupsig = 1;
48358 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
48359 +
48360 + /* Set NAK for all OUT EPs */
48361 + doepctl.b.snak = 1;
48362 + for (i = 0; i <= dev_if->num_out_eps; i++) {
48363 + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
48364 + }
48365 +
48366 + /* Flush the NP Tx FIFO */
48367 + dwc_otg_flush_tx_fifo(core_if, 0x10);
48368 + /* Flush the Learning Queue */
48369 + resetctl.b.intknqflsh = 1;
48370 + DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
48371 +
48372 + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
48373 + core_if->start_predict = 0;
48374 + for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
48375 + core_if->nextep_seq[i] = 0xff; // 0xff - EP not active
48376 + }
48377 + core_if->nextep_seq[0] = 0;
48378 + core_if->first_in_nextep_seq = 0;
48379 + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
48380 + diepctl.b.nextep = 0;
48381 + DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
48382 +
48383 + /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
48384 + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48385 + dcfg.b.epmscnt = 2;
48386 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48387 +
48388 + DWC_DEBUGPL(DBG_PCDV,
48389 + "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
48390 + __func__, core_if->first_in_nextep_seq);
48391 + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
48392 + DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
48393 + }
48394 + }
48395 +
48396 + if (core_if->multiproc_int_enable) {
48397 + daintmsk.b.inep0 = 1;
48398 + daintmsk.b.outep0 = 1;
48399 + DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
48400 + daintmsk.d32);
48401 +
48402 + doepmsk.b.setup = 1;
48403 + doepmsk.b.xfercompl = 1;
48404 + doepmsk.b.ahberr = 1;
48405 + doepmsk.b.epdisabled = 1;
48406 +
48407 + if ((core_if->dma_desc_enable) ||
48408 + (core_if->dma_enable
48409 + && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48410 + doepmsk.b.stsphsercvd = 1;
48411 + }
48412 + if (core_if->dma_desc_enable)
48413 + doepmsk.b.bna = 1;
48414 +/*
48415 + doepmsk.b.babble = 1;
48416 + doepmsk.b.nyet = 1;
48417 +
48418 + if (core_if->dma_enable) {
48419 + doepmsk.b.nak = 1;
48420 + }
48421 +*/
48422 + DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
48423 + doepmsk.d32);
48424 +
48425 + diepmsk.b.xfercompl = 1;
48426 + diepmsk.b.timeout = 1;
48427 + diepmsk.b.epdisabled = 1;
48428 + diepmsk.b.ahberr = 1;
48429 + diepmsk.b.intknepmis = 1;
48430 + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48431 + diepmsk.b.intknepmis = 0;
48432 +
48433 +/* if (core_if->dma_desc_enable) {
48434 + diepmsk.b.bna = 1;
48435 + }
48436 +*/
48437 +/*
48438 + if (core_if->dma_enable) {
48439 + diepmsk.b.nak = 1;
48440 + }
48441 +*/
48442 + DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
48443 + diepmsk.d32);
48444 + } else {
48445 + daintmsk.b.inep0 = 1;
48446 + daintmsk.b.outep0 = 1;
48447 + DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
48448 + daintmsk.d32);
48449 +
48450 + doepmsk.b.setup = 1;
48451 + doepmsk.b.xfercompl = 1;
48452 + doepmsk.b.ahberr = 1;
48453 + doepmsk.b.epdisabled = 1;
48454 +
48455 + if ((core_if->dma_desc_enable) ||
48456 + (core_if->dma_enable
48457 + && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48458 + doepmsk.b.stsphsercvd = 1;
48459 + }
48460 + if (core_if->dma_desc_enable)
48461 + doepmsk.b.bna = 1;
48462 + DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
48463 +
48464 + diepmsk.b.xfercompl = 1;
48465 + diepmsk.b.timeout = 1;
48466 + diepmsk.b.epdisabled = 1;
48467 + diepmsk.b.ahberr = 1;
48468 + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48469 + diepmsk.b.intknepmis = 0;
48470 +/*
48471 + if (core_if->dma_desc_enable) {
48472 + diepmsk.b.bna = 1;
48473 + }
48474 +*/
48475 +
48476 + DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
48477 + }
48478 +
48479 + /* Reset Device Address */
48480 + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48481 + dcfg.b.devaddr = 0;
48482 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48483 +
48484 + /* setup EP0 to receive SETUP packets */
48485 + if (core_if->snpsid <= OTG_CORE_REV_2_94a)
48486 + ep0_out_start(core_if, pcd);
48487 +
48488 + /* Clear interrupt */
48489 + gintsts.d32 = 0;
48490 + gintsts.b.usbreset = 1;
48491 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48492 +
48493 + return 1;
48494 +}
48495 +
48496 +/**
48497 + * Get the device speed from the device status register and convert it
48498 + * to USB speed constant.
48499 + *
48500 + * @param core_if Programming view of DWC_otg controller.
48501 + */
48502 +static int get_device_speed(dwc_otg_core_if_t * core_if)
48503 +{
48504 + dsts_data_t dsts;
48505 + int speed = 0;
48506 + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
48507 +
48508 + switch (dsts.b.enumspd) {
48509 + case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
48510 + speed = USB_SPEED_HIGH;
48511 + break;
48512 + case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
48513 + case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
48514 + speed = USB_SPEED_FULL;
48515 + break;
48516 +
48517 + case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
48518 + speed = USB_SPEED_LOW;
48519 + break;
48520 + }
48521 +
48522 + return speed;
48523 +}
48524 +
48525 +/**
48526 + * Read the device status register and set the device speed in the
48527 + * data structure.
48528 + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
48529 + */
48530 +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
48531 +{
48532 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48533 + gintsts_data_t gintsts;
48534 + gusbcfg_data_t gusbcfg;
48535 + dwc_otg_core_global_regs_t *global_regs =
48536 + GET_CORE_IF(pcd)->core_global_regs;
48537 + uint8_t utmi16b, utmi8b;
48538 + int speed;
48539 + DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
48540 +
48541 + if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
48542 + utmi16b = 6; //vahrama old value was 6;
48543 + utmi8b = 9;
48544 + } else {
48545 + utmi16b = 4;
48546 + utmi8b = 8;
48547 + }
48548 + dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
48549 + if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
48550 + ep0_out_start(GET_CORE_IF(pcd), pcd);
48551 + }
48552 +
48553 +#ifdef DEBUG_EP0
48554 + print_ep0_state(pcd);
48555 +#endif
48556 +
48557 + if (pcd->ep0state == EP0_DISCONNECT) {
48558 + pcd->ep0state = EP0_IDLE;
48559 + } else if (pcd->ep0state == EP0_STALL) {
48560 + pcd->ep0state = EP0_IDLE;
48561 + }
48562 +
48563 + pcd->ep0state = EP0_IDLE;
48564 +
48565 + ep0->stopped = 0;
48566 +
48567 + speed = get_device_speed(GET_CORE_IF(pcd));
48568 + pcd->fops->connect(pcd, speed);
48569 +
48570 + /* Set USB turnaround time based on device speed and PHY interface. */
48571 + gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
48572 + if (speed == USB_SPEED_HIGH) {
48573 + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48574 + DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
48575 + /* ULPI interface */
48576 + gusbcfg.b.usbtrdtim = 9;
48577 + }
48578 + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48579 + DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
48580 + /* UTMI+ interface */
48581 + if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
48582 + gusbcfg.b.usbtrdtim = utmi8b;
48583 + } else if (GET_CORE_IF(pcd)->hwcfg4.
48584 + b.utmi_phy_data_width == 1) {
48585 + gusbcfg.b.usbtrdtim = utmi16b;
48586 + } else if (GET_CORE_IF(pcd)->
48587 + core_params->phy_utmi_width == 8) {
48588 + gusbcfg.b.usbtrdtim = utmi8b;
48589 + } else {
48590 + gusbcfg.b.usbtrdtim = utmi16b;
48591 + }
48592 + }
48593 + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48594 + DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
48595 + /* UTMI+ OR ULPI interface */
48596 + if (gusbcfg.b.ulpi_utmi_sel == 1) {
48597 + /* ULPI interface */
48598 + gusbcfg.b.usbtrdtim = 9;
48599 + } else {
48600 + /* UTMI+ interface */
48601 + if (GET_CORE_IF(pcd)->
48602 + core_params->phy_utmi_width == 16) {
48603 + gusbcfg.b.usbtrdtim = utmi16b;
48604 + } else {
48605 + gusbcfg.b.usbtrdtim = utmi8b;
48606 + }
48607 + }
48608 + }
48609 + } else {
48610 + /* Full or low speed */
48611 + gusbcfg.b.usbtrdtim = 9;
48612 + }
48613 + DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
48614 +
48615 + /* Clear interrupt */
48616 + gintsts.d32 = 0;
48617 + gintsts.b.enumdone = 1;
48618 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48619 + gintsts.d32);
48620 + return 1;
48621 +}
48622 +
48623 +/**
48624 + * This interrupt indicates that the ISO OUT Packet was dropped due to
48625 + * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs
48626 + * read all the data from the Rx FIFO.
48627 + */
48628 +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
48629 +{
48630 + gintmsk_data_t intr_mask = {.d32 = 0 };
48631 + gintsts_data_t gintsts;
48632 +
48633 + DWC_WARN("INTERRUPT Handler not implemented for %s\n",
48634 + "ISOC Out Dropped");
48635 +
48636 + intr_mask.b.isooutdrop = 1;
48637 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48638 + intr_mask.d32, 0);
48639 +
48640 + /* Clear interrupt */
48641 + gintsts.d32 = 0;
48642 + gintsts.b.isooutdrop = 1;
48643 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48644 + gintsts.d32);
48645 +
48646 + return 1;
48647 +}
48648 +
48649 +/**
48650 + * This interrupt indicates the end of the portion of the micro-frame
48651 + * for periodic transactions. If there is a periodic transaction for
48652 + * the next frame, load the packets into the EP periodic Tx FIFO.
48653 + */
48654 +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
48655 +{
48656 + gintmsk_data_t intr_mask = {.d32 = 0 };
48657 + gintsts_data_t gintsts;
48658 + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
48659 +
48660 + intr_mask.b.eopframe = 1;
48661 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48662 + intr_mask.d32, 0);
48663 +
48664 + /* Clear interrupt */
48665 + gintsts.d32 = 0;
48666 + gintsts.b.eopframe = 1;
48667 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48668 + gintsts.d32);
48669 +
48670 + return 1;
48671 +}
48672 +
48673 +/**
48674 + * This interrupt indicates that EP of the packet on the top of the
48675 + * non-periodic Tx FIFO does not match EP of the IN Token received.
48676 + *
48677 + * The "Device IN Token Queue" Registers are read to determine the
48678 + * order the IN Tokens have been received. The non-periodic Tx FIFO
48679 + * is flushed, so it can be reloaded in the order seen in the IN Token
48680 + * Queue.
48681 + */
48682 +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
48683 +{
48684 + gintsts_data_t gintsts;
48685 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48686 + dctl_data_t dctl;
48687 + gintmsk_data_t intr_mask = {.d32 = 0 };
48688 +
48689 + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
48690 + core_if->start_predict = 1;
48691 +
48692 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48693 +
48694 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
48695 + if (!gintsts.b.ginnakeff) {
48696 + /* Disable EP Mismatch interrupt */
48697 + intr_mask.d32 = 0;
48698 + intr_mask.b.epmismatch = 1;
48699 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
48700 + /* Enable the Global IN NAK Effective Interrupt */
48701 + intr_mask.d32 = 0;
48702 + intr_mask.b.ginnakeff = 1;
48703 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
48704 + /* Set the global non-periodic IN NAK handshake */
48705 + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48706 + dctl.b.sgnpinnak = 1;
48707 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48708 + } else {
48709 + DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
48710 + }
48711 + /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
48712 + * handler after Global IN NAK Effective interrupt will be asserted */
48713 + }
48714 + /* Clear interrupt */
48715 + gintsts.d32 = 0;
48716 + gintsts.b.epmismatch = 1;
48717 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48718 +
48719 + return 1;
48720 +}
48721 +
48722 +/**
48723 + * This interrupt is valid only in DMA mode. This interrupt indicates that the
48724 + * core has stopped fetching data for IN endpoints due to the unavailability of
48725 + * TxFIFO space or Request Queue space. This interrupt is used by the
48726 + * application for an endpoint mismatch algorithm.
48727 + *
48728 + * @param pcd The PCD
48729 + */
48730 +int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
48731 +{
48732 + gintsts_data_t gintsts;
48733 + gintmsk_data_t gintmsk_data;
48734 + dctl_data_t dctl;
48735 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48736 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48737 +
48738 + /* Clear the global non-periodic IN NAK handshake */
48739 + dctl.d32 = 0;
48740 + dctl.b.cgnpinnak = 1;
48741 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
48742 +
48743 + /* Mask GINTSTS.FETSUSP interrupt */
48744 + gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
48745 + gintmsk_data.b.fetsusp = 0;
48746 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
48747 +
48748 + /* Clear interrupt */
48749 + gintsts.d32 = 0;
48750 + gintsts.b.fetsusp = 1;
48751 + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48752 +
48753 + return 1;
48754 +}
48755 +/**
48756 + * This funcion stalls EP0.
48757 + */
48758 +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
48759 +{
48760 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48761 + usb_device_request_t *ctrl = &pcd->setup_pkt->req;
48762 + DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
48763 + ctrl->bmRequestType, ctrl->bRequest, err_val);
48764 +
48765 + ep0->dwc_ep.is_in = 1;
48766 + dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
48767 + pcd->ep0.stopped = 1;
48768 + pcd->ep0state = EP0_IDLE;
48769 + ep0_out_start(GET_CORE_IF(pcd), pcd);
48770 +}
48771 +
48772 +/**
48773 + * This functions delegates the setup command to the gadget driver.
48774 + */
48775 +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
48776 + usb_device_request_t * ctrl)
48777 +{
48778 + int ret = 0;
48779 + DWC_SPINUNLOCK(pcd->lock);
48780 + ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
48781 + DWC_SPINLOCK(pcd->lock);
48782 + if (ret < 0) {
48783 + ep0_do_stall(pcd, ret);
48784 + }
48785 +
48786 + /** @todo This is a g_file_storage gadget driver specific
48787 + * workaround: a DELAYED_STATUS result from the fsg_setup
48788 + * routine will result in the gadget queueing a EP0 IN status
48789 + * phase for a two-stage control transfer. Exactly the same as
48790 + * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
48791 + * specific request. Need a generic way to know when the gadget
48792 + * driver will queue the status phase. Can we assume when we
48793 + * call the gadget driver setup() function that it will always
48794 + * queue and require the following flag? Need to look into
48795 + * this.
48796 + */
48797 +
48798 + if (ret == 256 + 999) {
48799 + pcd->request_config = 1;
48800 + }
48801 +}
48802 +
48803 +#ifdef DWC_UTE_CFI
48804 +/**
48805 + * This functions delegates the CFI setup commands to the gadget driver.
48806 + * This function will return a negative value to indicate a failure.
48807 + */
48808 +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
48809 + struct cfi_usb_ctrlrequest *ctrl_req)
48810 +{
48811 + int ret = 0;
48812 +
48813 + if (pcd->fops && pcd->fops->cfi_setup) {
48814 + DWC_SPINUNLOCK(pcd->lock);
48815 + ret = pcd->fops->cfi_setup(pcd, ctrl_req);
48816 + DWC_SPINLOCK(pcd->lock);
48817 + if (ret < 0) {
48818 + ep0_do_stall(pcd, ret);
48819 + return ret;
48820 + }
48821 + }
48822 +
48823 + return ret;
48824 +}
48825 +#endif
48826 +
48827 +/**
48828 + * This function starts the Zero-Length Packet for the IN status phase
48829 + * of a 2 stage control transfer.
48830 + */
48831 +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
48832 +{
48833 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48834 + if (pcd->ep0state == EP0_STALL) {
48835 + return;
48836 + }
48837 +
48838 + pcd->ep0state = EP0_IN_STATUS_PHASE;
48839 +
48840 + /* Prepare for more SETUP Packets */
48841 + DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
48842 + if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
48843 + && (pcd->core_if->dma_desc_enable)
48844 + && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
48845 + DWC_DEBUGPL(DBG_PCDV,
48846 + "Data terminated wait next packet in out_desc_addr\n");
48847 + pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
48848 + pcd->data_terminated = 1;
48849 + }
48850 + ep0->dwc_ep.xfer_len = 0;
48851 + ep0->dwc_ep.xfer_count = 0;
48852 + ep0->dwc_ep.is_in = 1;
48853 + ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48854 + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48855 +
48856 + /* Prepare for more SETUP Packets */
48857 + //ep0_out_start(GET_CORE_IF(pcd), pcd);
48858 +}
48859 +
48860 +/**
48861 + * This function starts the Zero-Length Packet for the OUT status phase
48862 + * of a 2 stage control transfer.
48863 + */
48864 +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
48865 +{
48866 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48867 + if (pcd->ep0state == EP0_STALL) {
48868 + DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
48869 + return;
48870 + }
48871 + pcd->ep0state = EP0_OUT_STATUS_PHASE;
48872 +
48873 + DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
48874 + ep0->dwc_ep.xfer_len = 0;
48875 + ep0->dwc_ep.xfer_count = 0;
48876 + ep0->dwc_ep.is_in = 0;
48877 + ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48878 + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48879 +
48880 + /* Prepare for more SETUP Packets */
48881 + if (GET_CORE_IF(pcd)->dma_enable == 0) {
48882 + ep0_out_start(GET_CORE_IF(pcd), pcd);
48883 + }
48884 +}
48885 +
48886 +/**
48887 + * Clear the EP halt (STALL) and if pending requests start the
48888 + * transfer.
48889 + */
48890 +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
48891 +{
48892 + if (ep->dwc_ep.stall_clear_flag == 0)
48893 + dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
48894 +
48895 + /* Reactive the EP */
48896 + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
48897 + if (ep->stopped) {
48898 + ep->stopped = 0;
48899 + /* If there is a request in the EP queue start it */
48900 +
48901 + /** @todo FIXME: this causes an EP mismatch in DMA mode.
48902 + * epmismatch not yet implemented. */
48903 +
48904 + /*
48905 + * Above fixme is solved by implmenting a tasklet to call the
48906 + * start_next_request(), outside of interrupt context at some
48907 + * time after the current time, after a clear-halt setup packet.
48908 + * Still need to implement ep mismatch in the future if a gadget
48909 + * ever uses more than one endpoint at once
48910 + */
48911 + ep->queue_sof = 1;
48912 + DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
48913 + }
48914 + /* Start Control Status Phase */
48915 + do_setup_in_status_phase(pcd);
48916 +}
48917 +
48918 +/**
48919 + * This function is called when the SET_FEATURE TEST_MODE Setup packet
48920 + * is sent from the host. The Device Control register is written with
48921 + * the Test Mode bits set to the specified Test Mode. This is done as
48922 + * a tasklet so that the "Status" phase of the control transfer
48923 + * completes before transmitting the TEST packets.
48924 + *
48925 + * @todo This has not been tested since the tasklet struct was put
48926 + * into the PCD struct!
48927 + *
48928 + */
48929 +void do_test_mode(void *data)
48930 +{
48931 + dctl_data_t dctl;
48932 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
48933 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48934 + int test_mode = pcd->test_mode;
48935 +
48936 +// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
48937 +
48938 + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48939 + switch (test_mode) {
48940 + case 1: // TEST_J
48941 + dctl.b.tstctl = 1;
48942 + break;
48943 +
48944 + case 2: // TEST_K
48945 + dctl.b.tstctl = 2;
48946 + break;
48947 +
48948 + case 3: // TEST_SE0_NAK
48949 + dctl.b.tstctl = 3;
48950 + break;
48951 +
48952 + case 4: // TEST_PACKET
48953 + dctl.b.tstctl = 4;
48954 + break;
48955 +
48956 + case 5: // TEST_FORCE_ENABLE
48957 + dctl.b.tstctl = 5;
48958 + break;
48959 + }
48960 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48961 +}
48962 +
48963 +/**
48964 + * This function process the GET_STATUS Setup Commands.
48965 + */
48966 +static inline void do_get_status(dwc_otg_pcd_t * pcd)
48967 +{
48968 + usb_device_request_t ctrl = pcd->setup_pkt->req;
48969 + dwc_otg_pcd_ep_t *ep;
48970 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48971 + uint16_t *status = pcd->status_buf;
48972 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48973 +
48974 +#ifdef DEBUG_EP0
48975 + DWC_DEBUGPL(DBG_PCD,
48976 + "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
48977 + ctrl.bmRequestType, ctrl.bRequest,
48978 + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48979 + UGETW(ctrl.wLength));
48980 +#endif
48981 +
48982 + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48983 + case UT_DEVICE:
48984 + if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
48985 + DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
48986 + DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
48987 + DWC_PRINTF("OTG CAP - %d, %d\n",
48988 + core_if->core_params->otg_cap,
48989 + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
48990 + if (core_if->otg_ver == 1
48991 + && core_if->core_params->otg_cap ==
48992 + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48993 + uint8_t *otgsts = (uint8_t*)pcd->status_buf;
48994 + *otgsts = (core_if->otg_sts & 0x1);
48995 + pcd->ep0_pending = 1;
48996 + ep0->dwc_ep.start_xfer_buff =
48997 + (uint8_t *) otgsts;
48998 + ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
48999 + ep0->dwc_ep.dma_addr =
49000 + pcd->status_buf_dma_handle;
49001 + ep0->dwc_ep.xfer_len = 1;
49002 + ep0->dwc_ep.xfer_count = 0;
49003 + ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
49004 + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
49005 + &ep0->dwc_ep);
49006 + return;
49007 + } else {
49008 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49009 + return;
49010 + }
49011 + break;
49012 + } else {
49013 + *status = 0x1; /* Self powered */
49014 + *status |= pcd->remote_wakeup_enable << 1;
49015 + break;
49016 + }
49017 + case UT_INTERFACE:
49018 + *status = 0;
49019 + break;
49020 +
49021 + case UT_ENDPOINT:
49022 + ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
49023 + if (ep == 0 || UGETW(ctrl.wLength) > 2) {
49024 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49025 + return;
49026 + }
49027 + /** @todo check for EP stall */
49028 + *status = ep->stopped;
49029 + break;
49030 + }
49031 + pcd->ep0_pending = 1;
49032 + ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
49033 + ep0->dwc_ep.xfer_buff = (uint8_t *) status;
49034 + ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
49035 + ep0->dwc_ep.xfer_len = 2;
49036 + ep0->dwc_ep.xfer_count = 0;
49037 + ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
49038 + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
49039 +}
49040 +
49041 +/**
49042 + * This function process the SET_FEATURE Setup Commands.
49043 + */
49044 +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
49045 +{
49046 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
49047 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
49048 + usb_device_request_t ctrl = pcd->setup_pkt->req;
49049 + dwc_otg_pcd_ep_t *ep = 0;
49050 + int32_t otg_cap_param = core_if->core_params->otg_cap;
49051 + gotgctl_data_t gotgctl = {.d32 = 0 };
49052 +
49053 + DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
49054 + ctrl.bmRequestType, ctrl.bRequest,
49055 + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
49056 + UGETW(ctrl.wLength));
49057 + DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
49058 +
49059 + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
49060 + case UT_DEVICE:
49061 + switch (UGETW(ctrl.wValue)) {
49062 + case UF_DEVICE_REMOTE_WAKEUP:
49063 + pcd->remote_wakeup_enable = 1;
49064 + break;
49065 +
49066 + case UF_TEST_MODE:
49067 + /* Setup the Test Mode tasklet to do the Test
49068 + * Packet generation after the SETUP Status
49069 + * phase has completed. */
49070 +
49071 + /** @todo This has not been tested since the
49072 + * tasklet struct was put into the PCD
49073 + * struct! */
49074 + pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
49075 + DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
49076 + break;
49077 +
49078 + case UF_DEVICE_B_HNP_ENABLE:
49079 + DWC_DEBUGPL(DBG_PCDV,
49080 + "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
49081 +
49082 + /* dev may initiate HNP */
49083 + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
49084 + pcd->b_hnp_enable = 1;
49085 + dwc_otg_pcd_update_otg(pcd, 0);
49086 + DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
49087 + /**@todo Is the gotgctl.devhnpen cleared
49088 + * by a USB Reset? */
49089 + gotgctl.b.devhnpen = 1;
49090 + gotgctl.b.hnpreq = 1;
49091 + DWC_WRITE_REG32(&global_regs->gotgctl,
49092 + gotgctl.d32);
49093 + } else {
49094 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49095 + return;
49096 + }
49097 + break;
49098 +
49099 + case UF_DEVICE_A_HNP_SUPPORT:
49100 + /* RH port supports HNP */
49101 + DWC_DEBUGPL(DBG_PCDV,
49102 + "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
49103 + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
49104 + pcd->a_hnp_support = 1;
49105 + dwc_otg_pcd_update_otg(pcd, 0);
49106 + } else {
49107 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49108 + return;
49109 + }
49110 + break;
49111 +
49112 + case UF_DEVICE_A_ALT_HNP_SUPPORT:
49113 + /* other RH port does */
49114 + DWC_DEBUGPL(DBG_PCDV,
49115 + "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
49116 + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
49117 + pcd->a_alt_hnp_support = 1;
49118 + dwc_otg_pcd_update_otg(pcd, 0);
49119 + } else {
49120 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49121 + return;
49122 + }
49123 + break;
49124 +
49125 + default:
49126 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49127 + return;
49128 +
49129 + }
49130 + do_setup_in_status_phase(pcd);
49131 + break;
49132 +
49133 + case UT_INTERFACE:
49134 + do_gadget_setup(pcd, &ctrl);
49135 + break;
49136 +
49137 + case UT_ENDPOINT:
49138 + if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
49139 + ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
49140 + if (ep == 0) {
49141 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49142 + return;
49143 + }
49144 + ep->stopped = 1;
49145 + dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
49146 + }
49147 + do_setup_in_status_phase(pcd);
49148 + break;
49149 + }
49150 +}
49151 +
49152 +/**
49153 + * This function process the CLEAR_FEATURE Setup Commands.
49154 + */
49155 +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
49156 +{
49157 + usb_device_request_t ctrl = pcd->setup_pkt->req;
49158 + dwc_otg_pcd_ep_t *ep = 0;
49159 +
49160 + DWC_DEBUGPL(DBG_PCD,
49161 + "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
49162 + ctrl.bmRequestType, ctrl.bRequest,
49163 + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
49164 + UGETW(ctrl.wLength));
49165 +
49166 + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
49167 + case UT_DEVICE:
49168 + switch (UGETW(ctrl.wValue)) {
49169 + case UF_DEVICE_REMOTE_WAKEUP:
49170 + pcd->remote_wakeup_enable = 0;
49171 + break;
49172 +
49173 + case UF_TEST_MODE:
49174 + /** @todo Add CLEAR_FEATURE for TEST modes. */
49175 + break;
49176 +
49177 + default:
49178 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49179 + return;
49180 + }
49181 + do_setup_in_status_phase(pcd);
49182 + break;
49183 +
49184 + case UT_ENDPOINT:
49185 + ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
49186 + if (ep == 0) {
49187 + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49188 + return;
49189 + }
49190 +
49191 + pcd_clear_halt(pcd, ep);
49192 +
49193 + break;
49194 + }
49195 +}
49196 +
49197 +/**
49198 + * This function process the SET_ADDRESS Setup Commands.
49199 + */
49200 +static inline void do_set_address(dwc_otg_pcd_t * pcd)
49201 +{
49202 + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
49203 + usb_device_request_t ctrl = pcd->setup_pkt->req;
49204 +
49205 + if (ctrl.bmRequestType == UT_DEVICE) {
49206 + dcfg_data_t dcfg = {.d32 = 0 };
49207 +
49208 +#ifdef DEBUG_EP0
49209 +// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
49210 +#endif
49211 + dcfg.b.devaddr = UGETW(ctrl.wValue);
49212 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
49213 + do_setup_in_status_phase(pcd);
49214 + }
49215 +}
49216 +
49217 +/**
49218 + * This function processes SETUP commands. In Linux, the USB Command
49219 + * processing is done in two places - the first being the PCD and the
49220 + * second in the Gadget Driver (for example, the File-Backed Storage
49221 + * Gadget Driver).
49222 + *
49223 + * <table>
49224 + * <tr><td>Command </td><td>Driver </td><td>Description</td></tr>
49225 + *
49226 + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
49227 + * defined in chapter 9 of the USB 2.0 Specification chapter 9
49228 + * </td></tr>
49229 + *
49230 + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
49231 + * requests are the ENDPOINT_HALT feature is procesed, all others the
49232 + * interface requests are ignored.</td></tr>
49233 + *
49234 + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
49235 + * requests are processed by the PCD. Interface requests are passed
49236 + * to the Gadget Driver.</td></tr>
49237 + *
49238 + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
49239 + * with device address received </td></tr>
49240 + *
49241 + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
49242 + * requested descriptor</td></tr>
49243 + *
49244 + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
49245 + * not implemented by any of the existing Gadget Drivers.</td></tr>
49246 + *
49247 + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
49248 + * all EPs and enable EPs for new configuration.</td></tr>
49249 + *
49250 + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
49251 + * the current configuration</td></tr>
49252 + *
49253 + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
49254 + * EPs and enable EPs for new configuration.</td></tr>
49255 + *
49256 + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
49257 + * current interface.</td></tr>
49258 + *
49259 + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
49260 + * message.</td></tr>
49261 + * </table>
49262 + *
49263 + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
49264 + * processed by pcd_setup. Calling the Function Driver's setup function from
49265 + * pcd_setup processes the gadget SETUP commands.
49266 + */
49267 +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
49268 +{
49269 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
49270 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49271 + usb_device_request_t ctrl = pcd->setup_pkt->req;
49272 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
49273 +
49274 + deptsiz0_data_t doeptsize0 = {.d32 = 0 };
49275 +
49276 +#ifdef DWC_UTE_CFI
49277 + int retval = 0;
49278 + struct cfi_usb_ctrlrequest cfi_req;
49279 +#endif
49280 +
49281 + doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
49282 +
49283 + /** In BDMA more then 1 setup packet is not supported till 3.00a */
49284 + if (core_if->dma_enable && core_if->dma_desc_enable == 0
49285 + && (doeptsize0.b.supcnt < 2)
49286 + && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
49287 + DWC_ERROR
49288 + ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n");
49289 + }
49290 + if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
49291 + && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
49292 + ctrl =
49293 + (pcd->setup_pkt +
49294 + (3 - doeptsize0.b.supcnt - 1 +
49295 + ep0->dwc_ep.stp_rollover))->req;
49296 + }
49297 +#ifdef DEBUG_EP0
49298 + DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
49299 + ctrl.bmRequestType, ctrl.bRequest,
49300 + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
49301 + UGETW(ctrl.wLength));
49302 +#endif
49303 +
49304 + /* Clean up the request queue */
49305 + dwc_otg_request_nuke(ep0);
49306 + ep0->stopped = 0;
49307 +
49308 + if (ctrl.bmRequestType & UE_DIR_IN) {
49309 + ep0->dwc_ep.is_in = 1;
49310 + pcd->ep0state = EP0_IN_DATA_PHASE;
49311 + } else {
49312 + ep0->dwc_ep.is_in = 0;
49313 + pcd->ep0state = EP0_OUT_DATA_PHASE;
49314 + }
49315 +
49316 + if (UGETW(ctrl.wLength) == 0) {
49317 + ep0->dwc_ep.is_in = 1;
49318 + pcd->ep0state = EP0_IN_STATUS_PHASE;
49319 + }
49320 +
49321 + if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
49322 +
49323 +#ifdef DWC_UTE_CFI
49324 + DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
49325 +
49326 + //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",
49327 + ctrl.bRequestType, ctrl.bRequest);
49328 + if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
49329 + if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
49330 + retval = cfi_setup(pcd, &cfi_req);
49331 + if (retval < 0) {
49332 + ep0_do_stall(pcd, retval);
49333 + pcd->ep0_pending = 0;
49334 + return;
49335 + }
49336 +
49337 + /* if need gadget setup then call it and check the retval */
49338 + if (pcd->cfi->need_gadget_att) {
49339 + retval =
49340 + cfi_gadget_setup(pcd,
49341 + &pcd->
49342 + cfi->ctrl_req);
49343 + if (retval < 0) {
49344 + pcd->ep0_pending = 0;
49345 + return;
49346 + }
49347 + }
49348 +
49349 + if (pcd->cfi->need_status_in_complete) {
49350 + do_setup_in_status_phase(pcd);
49351 + }
49352 + return;
49353 + }
49354 + }
49355 +#endif
49356 +
49357 + /* handle non-standard (class/vendor) requests in the gadget driver */
49358 + do_gadget_setup(pcd, &ctrl);
49359 + return;
49360 + }
49361 +
49362 + /** @todo NGS: Handle bad setup packet? */
49363 +
49364 +///////////////////////////////////////////
49365 +//// --- Standard Request handling --- ////
49366 +
49367 + switch (ctrl.bRequest) {
49368 + case UR_GET_STATUS:
49369 + do_get_status(pcd);
49370 + break;
49371 +
49372 + case UR_CLEAR_FEATURE:
49373 + do_clear_feature(pcd);
49374 + break;
49375 +
49376 + case UR_SET_FEATURE:
49377 + do_set_feature(pcd);
49378 + break;
49379 +
49380 + case UR_SET_ADDRESS:
49381 + do_set_address(pcd);
49382 + break;
49383 +
49384 + case UR_SET_INTERFACE:
49385 + case UR_SET_CONFIG:
49386 +// _pcd->request_config = 1; /* Configuration changed */
49387 + do_gadget_setup(pcd, &ctrl);
49388 + break;
49389 +
49390 + case UR_SYNCH_FRAME:
49391 + do_gadget_setup(pcd, &ctrl);
49392 + break;
49393 +
49394 + default:
49395 + /* Call the Gadget Driver's setup functions */
49396 + do_gadget_setup(pcd, &ctrl);
49397 + break;
49398 + }
49399 +}
49400 +
49401 +/**
49402 + * This function completes the ep0 control transfer.
49403 + */
49404 +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
49405 +{
49406 + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49407 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49408 + dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49409 + dev_if->in_ep_regs[ep->dwc_ep.num];
49410 +#ifdef DEBUG_EP0
49411 + dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49412 + dev_if->out_ep_regs[ep->dwc_ep.num];
49413 +#endif
49414 + deptsiz0_data_t deptsiz;
49415 + dev_dma_desc_sts_t desc_sts;
49416 + dwc_otg_pcd_request_t *req;
49417 + int is_last = 0;
49418 + dwc_otg_pcd_t *pcd = ep->pcd;
49419 +
49420 +#ifdef DWC_UTE_CFI
49421 + struct cfi_usb_ctrlrequest *ctrlreq;
49422 + int retval = -DWC_E_NOT_SUPPORTED;
49423 +#endif
49424 +
49425 + desc_sts.b.bytes = 0;
49426 +
49427 + if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49428 + if (ep->dwc_ep.is_in) {
49429 +#ifdef DEBUG_EP0
49430 + DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
49431 +#endif
49432 + do_setup_out_status_phase(pcd);
49433 + } else {
49434 +#ifdef DEBUG_EP0
49435 + DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
49436 +#endif
49437 +
49438 +#ifdef DWC_UTE_CFI
49439 + ctrlreq = &pcd->cfi->ctrl_req;
49440 +
49441 + if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
49442 + if (ctrlreq->bRequest > 0xB0
49443 + && ctrlreq->bRequest < 0xBF) {
49444 +
49445 + /* Return if the PCD failed to handle the request */
49446 + if ((retval =
49447 + pcd->cfi->ops.
49448 + ctrl_write_complete(pcd->cfi,
49449 + pcd)) < 0) {
49450 + CFI_INFO
49451 + ("ERROR setting a new value in the PCD(%d)\n",
49452 + retval);
49453 + ep0_do_stall(pcd, retval);
49454 + pcd->ep0_pending = 0;
49455 + return 0;
49456 + }
49457 +
49458 + /* If the gadget needs to be notified on the request */
49459 + if (pcd->cfi->need_gadget_att == 1) {
49460 + //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
49461 + retval =
49462 + cfi_gadget_setup(pcd,
49463 + &pcd->cfi->
49464 + ctrl_req);
49465 +
49466 + /* Return from the function if the gadget failed to process
49467 + * the request properly - this should never happen !!!
49468 + */
49469 + if (retval < 0) {
49470 + CFI_INFO
49471 + ("ERROR setting a new value in the gadget(%d)\n",
49472 + retval);
49473 + pcd->ep0_pending = 0;
49474 + return 0;
49475 + }
49476 + }
49477 +
49478 + CFI_INFO("%s: RETVAL=%d\n", __func__,
49479 + retval);
49480 + /* If we hit here then the PCD and the gadget has properly
49481 + * handled the request - so send the ZLP IN to the host.
49482 + */
49483 + /* @todo: MAS - decide whether we need to start the setup
49484 + * stage based on the need_setup value of the cfi object
49485 + */
49486 + do_setup_in_status_phase(pcd);
49487 + pcd->ep0_pending = 0;
49488 + return 1;
49489 + }
49490 + }
49491 +#endif
49492 +
49493 + do_setup_in_status_phase(pcd);
49494 + }
49495 + pcd->ep0_pending = 0;
49496 + return 1;
49497 + }
49498 +
49499 + if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49500 + return 0;
49501 + }
49502 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
49503 +
49504 + if (pcd->ep0state == EP0_OUT_STATUS_PHASE
49505 + || pcd->ep0state == EP0_IN_STATUS_PHASE) {
49506 + is_last = 1;
49507 + } else if (ep->dwc_ep.is_in) {
49508 + deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49509 + if (core_if->dma_desc_enable != 0)
49510 + desc_sts = dev_if->in_desc_addr->status;
49511 +#ifdef DEBUG_EP0
49512 + DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n",
49513 + ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49514 + deptsiz.b.xfersize, deptsiz.b.pktcnt);
49515 +#endif
49516 +
49517 + if (((core_if->dma_desc_enable == 0)
49518 + && (deptsiz.b.xfersize == 0))
49519 + || ((core_if->dma_desc_enable != 0)
49520 + && (desc_sts.b.bytes == 0))) {
49521 + req->actual = ep->dwc_ep.xfer_count;
49522 + /* Is a Zero Len Packet needed? */
49523 + if (req->sent_zlp) {
49524 +#ifdef DEBUG_EP0
49525 + DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
49526 +#endif
49527 + req->sent_zlp = 0;
49528 + }
49529 + do_setup_out_status_phase(pcd);
49530 + }
49531 + } else {
49532 + /* ep0-OUT */
49533 +#ifdef DEBUG_EP0
49534 + deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
49535 + DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
49536 + ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49537 + deptsiz.b.xfersize, deptsiz.b.pktcnt);
49538 +#endif
49539 + req->actual = ep->dwc_ep.xfer_count;
49540 +
49541 + /* Is a Zero Len Packet needed? */
49542 + if (req->sent_zlp) {
49543 +#ifdef DEBUG_EP0
49544 + DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
49545 +#endif
49546 + req->sent_zlp = 0;
49547 + }
49548 + /* For older cores do setup in status phase in Slave/BDMA modes,
49549 + * starting from 3.00 do that only in slave, and for DMA modes
49550 + * just re-enable ep 0 OUT here*/
49551 + if (core_if->dma_enable == 0
49552 + || (core_if->dma_desc_enable == 0
49553 + && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
49554 + do_setup_in_status_phase(pcd);
49555 + } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
49556 + DWC_DEBUGPL(DBG_PCDV,
49557 + "Enable out ep before in status phase\n");
49558 + ep0_out_start(core_if, pcd);
49559 + }
49560 + }
49561 +
49562 + /* Complete the request */
49563 + if (is_last) {
49564 + dwc_otg_request_done(ep, req, 0);
49565 + ep->dwc_ep.start_xfer_buff = 0;
49566 + ep->dwc_ep.xfer_buff = 0;
49567 + ep->dwc_ep.xfer_len = 0;
49568 + return 1;
49569 + }
49570 + return 0;
49571 +}
49572 +
49573 +#ifdef DWC_UTE_CFI
49574 +/**
49575 + * This function calculates traverses all the CFI DMA descriptors and
49576 + * and accumulates the bytes that are left to be transfered.
49577 + *
49578 + * @return The total bytes left to transfered, or a negative value as failure
49579 + */
49580 +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
49581 +{
49582 + int32_t ret = 0;
49583 + int i;
49584 + struct dwc_otg_dma_desc *ddesc = NULL;
49585 + struct cfi_ep *cfiep;
49586 +
49587 + /* See if the pcd_ep has its respective cfi_ep mapped */
49588 + cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
49589 + if (!cfiep) {
49590 + CFI_INFO("%s: Failed to find ep\n", __func__);
49591 + return -1;
49592 + }
49593 +
49594 + ddesc = ep->dwc_ep.descs;
49595 +
49596 + for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
49597 +
49598 +#if defined(PRINT_CFI_DMA_DESCS)
49599 + print_desc(ddesc, ep->ep.name, i);
49600 +#endif
49601 + ret += ddesc->status.b.bytes;
49602 + ddesc++;
49603 + }
49604 +
49605 + if (ret)
49606 + CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
49607 + ret);
49608 +
49609 + return ret;
49610 +}
49611 +#endif
49612 +
49613 +/**
49614 + * This function completes the request for the EP. If there are
49615 + * additional requests for the EP in the queue they will be started.
49616 + */
49617 +static void complete_ep(dwc_otg_pcd_ep_t * ep)
49618 +{
49619 + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49620 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49621 + dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49622 + dev_if->in_ep_regs[ep->dwc_ep.num];
49623 + deptsiz_data_t deptsiz;
49624 + dev_dma_desc_sts_t desc_sts;
49625 + dwc_otg_pcd_request_t *req = 0;
49626 + dwc_otg_dev_dma_desc_t *dma_desc;
49627 + uint32_t byte_count = 0;
49628 + int is_last = 0;
49629 + int i;
49630 +
49631 + DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
49632 + (ep->dwc_ep.is_in ? "IN" : "OUT"));
49633 +
49634 + /* Get any pending requests */
49635 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49636 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
49637 + if (!req) {
49638 + DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
49639 + return;
49640 + }
49641 + } else {
49642 + DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
49643 + return;
49644 + }
49645 +
49646 + DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
49647 +
49648 + if (ep->dwc_ep.is_in) {
49649 + deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49650 +
49651 + if (core_if->dma_enable) {
49652 + if (core_if->dma_desc_enable == 0) {
49653 + if (deptsiz.b.xfersize == 0
49654 + && deptsiz.b.pktcnt == 0) {
49655 + byte_count =
49656 + ep->dwc_ep.xfer_len -
49657 + ep->dwc_ep.xfer_count;
49658 +
49659 + ep->dwc_ep.xfer_buff += byte_count;
49660 + ep->dwc_ep.dma_addr += byte_count;
49661 + ep->dwc_ep.xfer_count += byte_count;
49662 +
49663 + DWC_DEBUGPL(DBG_PCDV,
49664 + "%d-%s len=%d xfersize=%d pktcnt=%d\n",
49665 + ep->dwc_ep.num,
49666 + (ep->dwc_ep.
49667 + is_in ? "IN" : "OUT"),
49668 + ep->dwc_ep.xfer_len,
49669 + deptsiz.b.xfersize,
49670 + deptsiz.b.pktcnt);
49671 +
49672 + if (ep->dwc_ep.xfer_len <
49673 + ep->dwc_ep.total_len) {
49674 + dwc_otg_ep_start_transfer
49675 + (core_if, &ep->dwc_ep);
49676 + } else if (ep->dwc_ep.sent_zlp) {
49677 + /*
49678 + * This fragment of code should initiate 0
49679 + * length transfer in case if it is queued
49680 + * a transfer with size divisible to EPs max
49681 + * packet size and with usb_request zero field
49682 + * is set, which means that after data is transfered,
49683 + * it is also should be transfered
49684 + * a 0 length packet at the end. For Slave and
49685 + * Buffer DMA modes in this case SW has
49686 + * to initiate 2 transfers one with transfer size,
49687 + * and the second with 0 size. For Descriptor
49688 + * DMA mode SW is able to initiate a transfer,
49689 + * which will handle all the packets including
49690 + * the last 0 length.
49691 + */
49692 + ep->dwc_ep.sent_zlp = 0;
49693 + dwc_otg_ep_start_zl_transfer
49694 + (core_if, &ep->dwc_ep);
49695 + } else {
49696 + is_last = 1;
49697 + }
49698 + } else {
49699 + if (ep->dwc_ep.type ==
49700 + DWC_OTG_EP_TYPE_ISOC) {
49701 + req->actual = 0;
49702 + dwc_otg_request_done(ep, req, 0);
49703 +
49704 + ep->dwc_ep.start_xfer_buff = 0;
49705 + ep->dwc_ep.xfer_buff = 0;
49706 + ep->dwc_ep.xfer_len = 0;
49707 +
49708 + /* If there is a request in the queue start it. */
49709 + start_next_request(ep);
49710 + } else
49711 + DWC_WARN
49712 + ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
49713 + ep->dwc_ep.num,
49714 + (ep->dwc_ep.is_in ? "IN" : "OUT"),
49715 + deptsiz.b.xfersize,
49716 + deptsiz.b.pktcnt);
49717 + }
49718 + } else {
49719 + dma_desc = ep->dwc_ep.desc_addr;
49720 + byte_count = 0;
49721 + ep->dwc_ep.sent_zlp = 0;
49722 +
49723 +#ifdef DWC_UTE_CFI
49724 + CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49725 + ep->dwc_ep.buff_mode);
49726 + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49727 + int residue;
49728 +
49729 + residue = cfi_calc_desc_residue(ep);
49730 + if (residue < 0)
49731 + return;
49732 +
49733 + byte_count = residue;
49734 + } else {
49735 +#endif
49736 + for (i = 0; i < ep->dwc_ep.desc_cnt;
49737 + ++i) {
49738 + desc_sts = dma_desc->status;
49739 + byte_count += desc_sts.b.bytes;
49740 + dma_desc++;
49741 + }
49742 +#ifdef DWC_UTE_CFI
49743 + }
49744 +#endif
49745 + if (byte_count == 0) {
49746 + ep->dwc_ep.xfer_count =
49747 + ep->dwc_ep.total_len;
49748 + is_last = 1;
49749 + } else {
49750 + DWC_WARN("Incomplete transfer\n");
49751 + }
49752 + }
49753 + } else {
49754 + if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
49755 + DWC_DEBUGPL(DBG_PCDV,
49756 + "%d-%s len=%d xfersize=%d pktcnt=%d\n",
49757 + ep->dwc_ep.num,
49758 + ep->dwc_ep.is_in ? "IN" : "OUT",
49759 + ep->dwc_ep.xfer_len,
49760 + deptsiz.b.xfersize,
49761 + deptsiz.b.pktcnt);
49762 +
49763 + /* Check if the whole transfer was completed,
49764 + * if no, setup transfer for next portion of data
49765 + */
49766 + if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49767 + dwc_otg_ep_start_transfer(core_if,
49768 + &ep->dwc_ep);
49769 + } else if (ep->dwc_ep.sent_zlp) {
49770 + /*
49771 + * This fragment of code should initiate 0
49772 + * length trasfer in case if it is queued
49773 + * a trasfer with size divisible to EPs max
49774 + * packet size and with usb_request zero field
49775 + * is set, which means that after data is transfered,
49776 + * it is also should be transfered
49777 + * a 0 length packet at the end. For Slave and
49778 + * Buffer DMA modes in this case SW has
49779 + * to initiate 2 transfers one with transfer size,
49780 + * and the second with 0 size. For Desriptor
49781 + * DMA mode SW is able to initiate a transfer,
49782 + * which will handle all the packets including
49783 + * the last 0 legth.
49784 + */
49785 + ep->dwc_ep.sent_zlp = 0;
49786 + dwc_otg_ep_start_zl_transfer(core_if,
49787 + &ep->dwc_ep);
49788 + } else {
49789 + is_last = 1;
49790 + }
49791 + } else {
49792 + DWC_WARN
49793 + ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
49794 + ep->dwc_ep.num,
49795 + (ep->dwc_ep.is_in ? "IN" : "OUT"),
49796 + deptsiz.b.xfersize, deptsiz.b.pktcnt);
49797 + }
49798 + }
49799 + } else {
49800 + dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49801 + dev_if->out_ep_regs[ep->dwc_ep.num];
49802 + desc_sts.d32 = 0;
49803 + if (core_if->dma_enable) {
49804 + if (core_if->dma_desc_enable) {
49805 + dma_desc = ep->dwc_ep.desc_addr;
49806 + byte_count = 0;
49807 + ep->dwc_ep.sent_zlp = 0;
49808 +
49809 +#ifdef DWC_UTE_CFI
49810 + CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49811 + ep->dwc_ep.buff_mode);
49812 + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49813 + int residue;
49814 + residue = cfi_calc_desc_residue(ep);
49815 + if (residue < 0)
49816 + return;
49817 + byte_count = residue;
49818 + } else {
49819 +#endif
49820 +
49821 + for (i = 0; i < ep->dwc_ep.desc_cnt;
49822 + ++i) {
49823 + desc_sts = dma_desc->status;
49824 + byte_count += desc_sts.b.bytes;
49825 + dma_desc++;
49826 + }
49827 +
49828 +#ifdef DWC_UTE_CFI
49829 + }
49830 +#endif
49831 + /* Checking for interrupt Out transfers with not
49832 + * dword aligned mps sizes
49833 + */
49834 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
49835 + (ep->dwc_ep.maxpacket%4)) {
49836 + ep->dwc_ep.xfer_count =
49837 + ep->dwc_ep.total_len - byte_count;
49838 + if ((ep->dwc_ep.xfer_len %
49839 + ep->dwc_ep.maxpacket)
49840 + && (ep->dwc_ep.xfer_len /
49841 + ep->dwc_ep.maxpacket <
49842 + MAX_DMA_DESC_CNT))
49843 + ep->dwc_ep.xfer_len -=
49844 + (ep->dwc_ep.desc_cnt -
49845 + 1) * ep->dwc_ep.maxpacket +
49846 + ep->dwc_ep.xfer_len %
49847 + ep->dwc_ep.maxpacket;
49848 + else
49849 + ep->dwc_ep.xfer_len -=
49850 + ep->dwc_ep.desc_cnt *
49851 + ep->dwc_ep.maxpacket;
49852 + if (ep->dwc_ep.xfer_len > 0) {
49853 + dwc_otg_ep_start_transfer
49854 + (core_if, &ep->dwc_ep);
49855 + } else {
49856 + is_last = 1;
49857 + }
49858 + } else {
49859 + ep->dwc_ep.xfer_count =
49860 + ep->dwc_ep.total_len - byte_count +
49861 + ((4 -
49862 + (ep->dwc_ep.
49863 + total_len & 0x3)) & 0x3);
49864 + is_last = 1;
49865 + }
49866 + } else {
49867 + deptsiz.d32 = 0;
49868 + deptsiz.d32 =
49869 + DWC_READ_REG32(&out_ep_regs->doeptsiz);
49870 +
49871 + byte_count = (ep->dwc_ep.xfer_len -
49872 + ep->dwc_ep.xfer_count -
49873 + deptsiz.b.xfersize);
49874 + ep->dwc_ep.xfer_buff += byte_count;
49875 + ep->dwc_ep.dma_addr += byte_count;
49876 + ep->dwc_ep.xfer_count += byte_count;
49877 +
49878 + /* Check if the whole transfer was completed,
49879 + * if no, setup transfer for next portion of data
49880 + */
49881 + if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49882 + dwc_otg_ep_start_transfer(core_if,
49883 + &ep->dwc_ep);
49884 + } else if (ep->dwc_ep.sent_zlp) {
49885 + /*
49886 + * This fragment of code should initiate 0
49887 + * length trasfer in case if it is queued
49888 + * a trasfer with size divisible to EPs max
49889 + * packet size and with usb_request zero field
49890 + * is set, which means that after data is transfered,
49891 + * it is also should be transfered
49892 + * a 0 length packet at the end. For Slave and
49893 + * Buffer DMA modes in this case SW has
49894 + * to initiate 2 transfers one with transfer size,
49895 + * and the second with 0 size. For Desriptor
49896 + * DMA mode SW is able to initiate a transfer,
49897 + * which will handle all the packets including
49898 + * the last 0 legth.
49899 + */
49900 + ep->dwc_ep.sent_zlp = 0;
49901 + dwc_otg_ep_start_zl_transfer(core_if,
49902 + &ep->dwc_ep);
49903 + } else {
49904 + is_last = 1;
49905 + }
49906 + }
49907 + } else {
49908 + /* Check if the whole transfer was completed,
49909 + * if no, setup transfer for next portion of data
49910 + */
49911 + if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49912 + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
49913 + } else if (ep->dwc_ep.sent_zlp) {
49914 + /*
49915 + * This fragment of code should initiate 0
49916 + * length transfer in case if it is queued
49917 + * a transfer with size divisible to EPs max
49918 + * packet size and with usb_request zero field
49919 + * is set, which means that after data is transfered,
49920 + * it is also should be transfered
49921 + * a 0 length packet at the end. For Slave and
49922 + * Buffer DMA modes in this case SW has
49923 + * to initiate 2 transfers one with transfer size,
49924 + * and the second with 0 size. For Descriptor
49925 + * DMA mode SW is able to initiate a transfer,
49926 + * which will handle all the packets including
49927 + * the last 0 length.
49928 + */
49929 + ep->dwc_ep.sent_zlp = 0;
49930 + dwc_otg_ep_start_zl_transfer(core_if,
49931 + &ep->dwc_ep);
49932 + } else {
49933 + is_last = 1;
49934 + }
49935 + }
49936 +
49937 + DWC_DEBUGPL(DBG_PCDV,
49938 + "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
49939 + &out_ep_regs->doeptsiz, ep->dwc_ep.num,
49940 + ep->dwc_ep.is_in ? "IN" : "OUT",
49941 + ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
49942 + deptsiz.b.xfersize, deptsiz.b.pktcnt);
49943 + }
49944 +
49945 + /* Complete the request */
49946 + if (is_last) {
49947 +#ifdef DWC_UTE_CFI
49948 + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49949 + req->actual = ep->dwc_ep.cfi_req_len - byte_count;
49950 + } else {
49951 +#endif
49952 + req->actual = ep->dwc_ep.xfer_count;
49953 +#ifdef DWC_UTE_CFI
49954 + }
49955 +#endif
49956 + if (req->dw_align_buf) {
49957 + if (!ep->dwc_ep.is_in) {
49958 + dwc_memcpy(req->buf, req->dw_align_buf, req->length);
49959 + }
49960 + DWC_DMA_FREE(req->length, req->dw_align_buf,
49961 + req->dw_align_buf_dma);
49962 + }
49963 +
49964 + dwc_otg_request_done(ep, req, 0);
49965 +
49966 + ep->dwc_ep.start_xfer_buff = 0;
49967 + ep->dwc_ep.xfer_buff = 0;
49968 + ep->dwc_ep.xfer_len = 0;
49969 +
49970 + /* If there is a request in the queue start it. */
49971 + start_next_request(ep);
49972 + }
49973 +}
49974 +
49975 +#ifdef DWC_EN_ISOC
49976 +
49977 +/**
49978 + * This function BNA interrupt for Isochronous EPs
49979 + *
49980 + */
49981 +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
49982 +{
49983 + dwc_ep_t *dwc_ep = &ep->dwc_ep;
49984 + volatile uint32_t *addr;
49985 + depctl_data_t depctl = {.d32 = 0 };
49986 + dwc_otg_pcd_t *pcd = ep->pcd;
49987 + dwc_otg_dev_dma_desc_t *dma_desc;
49988 + int i;
49989 +
49990 + dma_desc =
49991 + dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
49992 +
49993 + if (dwc_ep->is_in) {
49994 + dev_dma_desc_sts_t sts = {.d32 = 0 };
49995 + for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49996 + sts.d32 = dma_desc->status.d32;
49997 + sts.b_iso_in.bs = BS_HOST_READY;
49998 + dma_desc->status.d32 = sts.d32;
49999 + }
50000 + } else {
50001 + dev_dma_desc_sts_t sts = {.d32 = 0 };
50002 + for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
50003 + sts.d32 = dma_desc->status.d32;
50004 + sts.b_iso_out.bs = BS_HOST_READY;
50005 + dma_desc->status.d32 = sts.d32;
50006 + }
50007 + }
50008 +
50009 + if (dwc_ep->is_in == 0) {
50010 + addr =
50011 + &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
50012 + num]->doepctl;
50013 + } else {
50014 + addr =
50015 + &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50016 + }
50017 + depctl.b.epena = 1;
50018 + DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
50019 +}
50020 +
50021 +/**
50022 + * This function sets latest iso packet information(non-PTI mode)
50023 + *
50024 + * @param core_if Programming view of DWC_otg controller.
50025 + * @param ep The EP to start the transfer on.
50026 + *
50027 + */
50028 +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
50029 +{
50030 + deptsiz_data_t deptsiz = {.d32 = 0 };
50031 + dma_addr_t dma_addr;
50032 + uint32_t offset;
50033 +
50034 + if (ep->proc_buf_num)
50035 + dma_addr = ep->dma_addr1;
50036 + else
50037 + dma_addr = ep->dma_addr0;
50038 +
50039 + if (ep->is_in) {
50040 + deptsiz.d32 =
50041 + DWC_READ_REG32(&core_if->dev_if->
50042 + in_ep_regs[ep->num]->dieptsiz);
50043 + offset = ep->data_per_frame;
50044 + } else {
50045 + deptsiz.d32 =
50046 + DWC_READ_REG32(&core_if->dev_if->
50047 + out_ep_regs[ep->num]->doeptsiz);
50048 + offset =
50049 + ep->data_per_frame +
50050 + (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
50051 + }
50052 +
50053 + if (!deptsiz.b.xfersize) {
50054 + ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
50055 + ep->pkt_info[ep->cur_pkt].offset =
50056 + ep->cur_pkt_dma_addr - dma_addr;
50057 + ep->pkt_info[ep->cur_pkt].status = 0;
50058 + } else {
50059 + ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
50060 + ep->pkt_info[ep->cur_pkt].offset =
50061 + ep->cur_pkt_dma_addr - dma_addr;
50062 + ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
50063 + }
50064 + ep->cur_pkt_addr += offset;
50065 + ep->cur_pkt_dma_addr += offset;
50066 + ep->cur_pkt++;
50067 +}
50068 +
50069 +/**
50070 + * This function sets latest iso packet information(DDMA mode)
50071 + *
50072 + * @param core_if Programming view of DWC_otg controller.
50073 + * @param dwc_ep The EP to start the transfer on.
50074 + *
50075 + */
50076 +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
50077 + dwc_ep_t * dwc_ep)
50078 +{
50079 + dwc_otg_dev_dma_desc_t *dma_desc;
50080 + dev_dma_desc_sts_t sts = {.d32 = 0 };
50081 + iso_pkt_info_t *iso_packet;
50082 + uint32_t data_per_desc;
50083 + uint32_t offset;
50084 + int i, j;
50085 +
50086 + iso_packet = dwc_ep->pkt_info;
50087 +
50088 + /** Reinit closed DMA Descriptors*/
50089 + /** ISO OUT EP */
50090 + if (dwc_ep->is_in == 0) {
50091 + dma_desc =
50092 + dwc_ep->iso_desc_addr +
50093 + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50094 + offset = 0;
50095 +
50096 + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
50097 + i += dwc_ep->pkt_per_frm) {
50098 + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
50099 + data_per_desc =
50100 + ((j + 1) * dwc_ep->maxpacket >
50101 + dwc_ep->
50102 + data_per_frame) ? dwc_ep->data_per_frame -
50103 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50104 + data_per_desc +=
50105 + (data_per_desc % 4) ? (4 -
50106 + data_per_desc %
50107 + 4) : 0;
50108 +
50109 + sts.d32 = dma_desc->status.d32;
50110 +
50111 + /* Write status in iso_packet_decsriptor */
50112 + iso_packet->status =
50113 + sts.b_iso_out.rxsts +
50114 + (sts.b_iso_out.bs ^ BS_DMA_DONE);
50115 + if (iso_packet->status) {
50116 + iso_packet->status = -DWC_E_NO_DATA;
50117 + }
50118 +
50119 + /* Received data length */
50120 + if (!sts.b_iso_out.rxbytes) {
50121 + iso_packet->length =
50122 + data_per_desc -
50123 + sts.b_iso_out.rxbytes;
50124 + } else {
50125 + iso_packet->length =
50126 + data_per_desc -
50127 + sts.b_iso_out.rxbytes + (4 -
50128 + dwc_ep->data_per_frame
50129 + % 4);
50130 + }
50131 +
50132 + iso_packet->offset = offset;
50133 +
50134 + offset += data_per_desc;
50135 + dma_desc++;
50136 + iso_packet++;
50137 + }
50138 + }
50139 +
50140 + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
50141 + data_per_desc =
50142 + ((j + 1) * dwc_ep->maxpacket >
50143 + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50144 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50145 + data_per_desc +=
50146 + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50147 +
50148 + sts.d32 = dma_desc->status.d32;
50149 +
50150 + /* Write status in iso_packet_decsriptor */
50151 + iso_packet->status =
50152 + sts.b_iso_out.rxsts +
50153 + (sts.b_iso_out.bs ^ BS_DMA_DONE);
50154 + if (iso_packet->status) {
50155 + iso_packet->status = -DWC_E_NO_DATA;
50156 + }
50157 +
50158 + /* Received data length */
50159 + iso_packet->length =
50160 + dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
50161 +
50162 + iso_packet->offset = offset;
50163 +
50164 + offset += data_per_desc;
50165 + iso_packet++;
50166 + dma_desc++;
50167 + }
50168 +
50169 + sts.d32 = dma_desc->status.d32;
50170 +
50171 + /* Write status in iso_packet_decsriptor */
50172 + iso_packet->status =
50173 + sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
50174 + if (iso_packet->status) {
50175 + iso_packet->status = -DWC_E_NO_DATA;
50176 + }
50177 + /* Received data length */
50178 + if (!sts.b_iso_out.rxbytes) {
50179 + iso_packet->length =
50180 + dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
50181 + } else {
50182 + iso_packet->length =
50183 + dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
50184 + (4 - dwc_ep->data_per_frame % 4);
50185 + }
50186 +
50187 + iso_packet->offset = offset;
50188 + } else {
50189 +/** ISO IN EP */
50190 +
50191 + dma_desc =
50192 + dwc_ep->iso_desc_addr +
50193 + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50194 +
50195 + for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50196 + sts.d32 = dma_desc->status.d32;
50197 +
50198 + /* Write status in iso packet descriptor */
50199 + iso_packet->status =
50200 + sts.b_iso_in.txsts +
50201 + (sts.b_iso_in.bs ^ BS_DMA_DONE);
50202 + if (iso_packet->status != 0) {
50203 + iso_packet->status = -DWC_E_NO_DATA;
50204 +
50205 + }
50206 + /* Bytes has been transfered */
50207 + iso_packet->length =
50208 + dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
50209 +
50210 + dma_desc++;
50211 + iso_packet++;
50212 + }
50213 +
50214 + sts.d32 = dma_desc->status.d32;
50215 + while (sts.b_iso_in.bs == BS_DMA_BUSY) {
50216 + sts.d32 = dma_desc->status.d32;
50217 + }
50218 +
50219 + /* Write status in iso packet descriptor ??? do be done with ERROR codes */
50220 + iso_packet->status =
50221 + sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
50222 + if (iso_packet->status != 0) {
50223 + iso_packet->status = -DWC_E_NO_DATA;
50224 + }
50225 +
50226 + /* Bytes has been transfered */
50227 + iso_packet->length =
50228 + dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
50229 + }
50230 +}
50231 +
50232 +/**
50233 + * This function reinitialize DMA Descriptors for Isochronous transfer
50234 + *
50235 + * @param core_if Programming view of DWC_otg controller.
50236 + * @param dwc_ep The EP to start the transfer on.
50237 + *
50238 + */
50239 +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
50240 +{
50241 + int i, j;
50242 + dwc_otg_dev_dma_desc_t *dma_desc;
50243 + dma_addr_t dma_ad;
50244 + volatile uint32_t *addr;
50245 + dev_dma_desc_sts_t sts = {.d32 = 0 };
50246 + uint32_t data_per_desc;
50247 +
50248 + if (dwc_ep->is_in == 0) {
50249 + addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
50250 + } else {
50251 + addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50252 + }
50253 +
50254 + if (dwc_ep->proc_buf_num == 0) {
50255 + /** Buffer 0 descriptors setup */
50256 + dma_ad = dwc_ep->dma_addr0;
50257 + } else {
50258 + /** Buffer 1 descriptors setup */
50259 + dma_ad = dwc_ep->dma_addr1;
50260 + }
50261 +
50262 + /** Reinit closed DMA Descriptors*/
50263 + /** ISO OUT EP */
50264 + if (dwc_ep->is_in == 0) {
50265 + dma_desc =
50266 + dwc_ep->iso_desc_addr +
50267 + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50268 +
50269 + sts.b_iso_out.bs = BS_HOST_READY;
50270 + sts.b_iso_out.rxsts = 0;
50271 + sts.b_iso_out.l = 0;
50272 + sts.b_iso_out.sp = 0;
50273 + sts.b_iso_out.ioc = 0;
50274 + sts.b_iso_out.pid = 0;
50275 + sts.b_iso_out.framenum = 0;
50276 +
50277 + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
50278 + i += dwc_ep->pkt_per_frm) {
50279 + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
50280 + data_per_desc =
50281 + ((j + 1) * dwc_ep->maxpacket >
50282 + dwc_ep->
50283 + data_per_frame) ? dwc_ep->data_per_frame -
50284 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50285 + data_per_desc +=
50286 + (data_per_desc % 4) ? (4 -
50287 + data_per_desc %
50288 + 4) : 0;
50289 + sts.b_iso_out.rxbytes = data_per_desc;
50290 + dma_desc->buf = dma_ad;
50291 + dma_desc->status.d32 = sts.d32;
50292 +
50293 + dma_ad += data_per_desc;
50294 + dma_desc++;
50295 + }
50296 + }
50297 +
50298 + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
50299 +
50300 + data_per_desc =
50301 + ((j + 1) * dwc_ep->maxpacket >
50302 + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50303 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50304 + data_per_desc +=
50305 + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50306 + sts.b_iso_out.rxbytes = data_per_desc;
50307 +
50308 + dma_desc->buf = dma_ad;
50309 + dma_desc->status.d32 = sts.d32;
50310 +
50311 + dma_desc++;
50312 + dma_ad += data_per_desc;
50313 + }
50314 +
50315 + sts.b_iso_out.ioc = 1;
50316 + sts.b_iso_out.l = dwc_ep->proc_buf_num;
50317 +
50318 + data_per_desc =
50319 + ((j + 1) * dwc_ep->maxpacket >
50320 + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50321 + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50322 + data_per_desc +=
50323 + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50324 + sts.b_iso_out.rxbytes = data_per_desc;
50325 +
50326 + dma_desc->buf = dma_ad;
50327 + dma_desc->status.d32 = sts.d32;
50328 + } else {
50329 +/** ISO IN EP */
50330 +
50331 + dma_desc =
50332 + dwc_ep->iso_desc_addr +
50333 + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50334 +
50335 + sts.b_iso_in.bs = BS_HOST_READY;
50336 + sts.b_iso_in.txsts = 0;
50337 + sts.b_iso_in.sp = 0;
50338 + sts.b_iso_in.ioc = 0;
50339 + sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
50340 + sts.b_iso_in.framenum = dwc_ep->next_frame;
50341 + sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
50342 + sts.b_iso_in.l = 0;
50343 +
50344 + for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50345 + dma_desc->buf = dma_ad;
50346 + dma_desc->status.d32 = sts.d32;
50347 +
50348 + sts.b_iso_in.framenum += dwc_ep->bInterval;
50349 + dma_ad += dwc_ep->data_per_frame;
50350 + dma_desc++;
50351 + }
50352 +
50353 + sts.b_iso_in.ioc = 1;
50354 + sts.b_iso_in.l = dwc_ep->proc_buf_num;
50355 +
50356 + dma_desc->buf = dma_ad;
50357 + dma_desc->status.d32 = sts.d32;
50358 +
50359 + dwc_ep->next_frame =
50360 + sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
50361 + }
50362 + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50363 +}
50364 +
50365 +/**
50366 + * This function is to handle Iso EP transfer complete interrupt
50367 + * in case Iso out packet was dropped
50368 + *
50369 + * @param core_if Programming view of DWC_otg controller.
50370 + * @param dwc_ep The EP for wihich transfer complete was asserted
50371 + *
50372 + */
50373 +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
50374 + dwc_ep_t * dwc_ep)
50375 +{
50376 + uint32_t dma_addr;
50377 + uint32_t drp_pkt;
50378 + uint32_t drp_pkt_cnt;
50379 + deptsiz_data_t deptsiz = {.d32 = 0 };
50380 + depctl_data_t depctl = {.d32 = 0 };
50381 + int i;
50382 +
50383 + deptsiz.d32 =
50384 + DWC_READ_REG32(&core_if->dev_if->
50385 + out_ep_regs[dwc_ep->num]->doeptsiz);
50386 +
50387 + drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
50388 + drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
50389 +
50390 + /* Setting dropped packets status */
50391 + for (i = 0; i < drp_pkt_cnt; ++i) {
50392 + dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
50393 + drp_pkt++;
50394 + deptsiz.b.pktcnt--;
50395 + }
50396 +
50397 + if (deptsiz.b.pktcnt > 0) {
50398 + deptsiz.b.xfersize =
50399 + dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
50400 + deptsiz.b.pktcnt) * dwc_ep->maxpacket;
50401 + } else {
50402 + deptsiz.b.xfersize = 0;
50403 + deptsiz.b.pktcnt = 0;
50404 + }
50405 +
50406 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
50407 + deptsiz.d32);
50408 +
50409 + if (deptsiz.b.pktcnt > 0) {
50410 + if (dwc_ep->proc_buf_num) {
50411 + dma_addr =
50412 + dwc_ep->dma_addr1 + dwc_ep->xfer_len -
50413 + deptsiz.b.xfersize;
50414 + } else {
50415 + dma_addr =
50416 + dwc_ep->dma_addr0 + dwc_ep->xfer_len -
50417 + deptsiz.b.xfersize;;
50418 + }
50419 +
50420 + DWC_WRITE_REG32(&core_if->dev_if->
50421 + out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
50422 +
50423 + /** Re-enable endpoint, clear nak */
50424 + depctl.d32 = 0;
50425 + depctl.b.epena = 1;
50426 + depctl.b.cnak = 1;
50427 +
50428 + DWC_MODIFY_REG32(&core_if->dev_if->
50429 + out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
50430 + depctl.d32);
50431 + return 0;
50432 + } else {
50433 + return 1;
50434 + }
50435 +}
50436 +
50437 +/**
50438 + * This function sets iso packets information(PTI mode)
50439 + *
50440 + * @param core_if Programming view of DWC_otg controller.
50441 + * @param ep The EP to start the transfer on.
50442 + *
50443 + */
50444 +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
50445 +{
50446 + int i, j;
50447 + dma_addr_t dma_ad;
50448 + iso_pkt_info_t *packet_info = ep->pkt_info;
50449 + uint32_t offset;
50450 + uint32_t frame_data;
50451 + deptsiz_data_t deptsiz;
50452 +
50453 + if (ep->proc_buf_num == 0) {
50454 + /** Buffer 0 descriptors setup */
50455 + dma_ad = ep->dma_addr0;
50456 + } else {
50457 + /** Buffer 1 descriptors setup */
50458 + dma_ad = ep->dma_addr1;
50459 + }
50460 +
50461 + if (ep->is_in) {
50462 + deptsiz.d32 =
50463 + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
50464 + dieptsiz);
50465 + } else {
50466 + deptsiz.d32 =
50467 + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
50468 + doeptsiz);
50469 + }
50470 +
50471 + if (!deptsiz.b.xfersize) {
50472 + offset = 0;
50473 + for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
50474 + frame_data = ep->data_per_frame;
50475 + for (j = 0; j < ep->pkt_per_frm; ++j) {
50476 +
50477 + /* Packet status - is not set as initially
50478 + * it is set to 0 and if packet was sent
50479 + successfully, status field will remain 0*/
50480 +
50481 + /* Bytes has been transfered */
50482 + packet_info->length =
50483 + (ep->maxpacket <
50484 + frame_data) ? ep->maxpacket : frame_data;
50485 +
50486 + /* Received packet offset */
50487 + packet_info->offset = offset;
50488 + offset += packet_info->length;
50489 + frame_data -= packet_info->length;
50490 +
50491 + packet_info++;
50492 + }
50493 + }
50494 + return 1;
50495 + } else {
50496 + /* This is a workaround for in case of Transfer Complete with
50497 + * PktDrpSts interrupts merging - in this case Transfer complete
50498 + * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
50499 + * set and with DOEPTSIZ register non zero. Investigations showed,
50500 + * that this happens when Out packet is dropped, but because of
50501 + * interrupts merging during first interrupt handling PktDrpSts
50502 + * bit is cleared and for next merged interrupts it is not reset.
50503 + * In this case SW hadles the interrupt as if PktDrpSts bit is set.
50504 + */
50505 + if (ep->is_in) {
50506 + return 1;
50507 + } else {
50508 + return handle_iso_out_pkt_dropped(core_if, ep);
50509 + }
50510 + }
50511 +}
50512 +
50513 +/**
50514 + * This function is to handle Iso EP transfer complete interrupt
50515 + *
50516 + * @param pcd The PCD
50517 + * @param ep The EP for which transfer complete was asserted
50518 + *
50519 + */
50520 +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
50521 +{
50522 + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
50523 + dwc_ep_t *dwc_ep = &ep->dwc_ep;
50524 + uint8_t is_last = 0;
50525 +
50526 + if (ep->dwc_ep.next_frame == 0xffffffff) {
50527 + DWC_WARN("Next frame is not set!\n");
50528 + return;
50529 + }
50530 +
50531 + if (core_if->dma_enable) {
50532 + if (core_if->dma_desc_enable) {
50533 + set_ddma_iso_pkts_info(core_if, dwc_ep);
50534 + reinit_ddma_iso_xfer(core_if, dwc_ep);
50535 + is_last = 1;
50536 + } else {
50537 + if (core_if->pti_enh_enable) {
50538 + if (set_iso_pkts_info(core_if, dwc_ep)) {
50539 + dwc_ep->proc_buf_num =
50540 + (dwc_ep->proc_buf_num ^ 1) & 0x1;
50541 + dwc_otg_iso_ep_start_buf_transfer
50542 + (core_if, dwc_ep);
50543 + is_last = 1;
50544 + }
50545 + } else {
50546 + set_current_pkt_info(core_if, dwc_ep);
50547 + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50548 + is_last = 1;
50549 + dwc_ep->cur_pkt = 0;
50550 + dwc_ep->proc_buf_num =
50551 + (dwc_ep->proc_buf_num ^ 1) & 0x1;
50552 + if (dwc_ep->proc_buf_num) {
50553 + dwc_ep->cur_pkt_addr =
50554 + dwc_ep->xfer_buff1;
50555 + dwc_ep->cur_pkt_dma_addr =
50556 + dwc_ep->dma_addr1;
50557 + } else {
50558 + dwc_ep->cur_pkt_addr =
50559 + dwc_ep->xfer_buff0;
50560 + dwc_ep->cur_pkt_dma_addr =
50561 + dwc_ep->dma_addr0;
50562 + }
50563 +
50564 + }
50565 + dwc_otg_iso_ep_start_frm_transfer(core_if,
50566 + dwc_ep);
50567 + }
50568 + }
50569 + } else {
50570 + set_current_pkt_info(core_if, dwc_ep);
50571 + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50572 + is_last = 1;
50573 + dwc_ep->cur_pkt = 0;
50574 + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50575 + if (dwc_ep->proc_buf_num) {
50576 + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
50577 + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
50578 + } else {
50579 + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
50580 + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
50581 + }
50582 +
50583 + }
50584 + dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
50585 + }
50586 + if (is_last)
50587 + dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
50588 +}
50589 +#endif /* DWC_EN_ISOC */
50590 +
50591 +/**
50592 + * This function handle BNA interrupt for Non Isochronous EPs
50593 + *
50594 + */
50595 +static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
50596 +{
50597 + dwc_ep_t *dwc_ep = &ep->dwc_ep;
50598 + volatile uint32_t *addr;
50599 + depctl_data_t depctl = {.d32 = 0 };
50600 + dwc_otg_pcd_t *pcd = ep->pcd;
50601 + dwc_otg_dev_dma_desc_t *dma_desc;
50602 + dev_dma_desc_sts_t sts = {.d32 = 0 };
50603 + dwc_otg_core_if_t *core_if = ep->pcd->core_if;
50604 + int i, start;
50605 +
50606 + if (!dwc_ep->desc_cnt)
50607 + DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
50608 + (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
50609 +
50610 + if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
50611 + && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
50612 + uint32_t doepdma;
50613 + dwc_otg_dev_out_ep_regs_t *out_regs =
50614 + core_if->dev_if->out_ep_regs[dwc_ep->num];
50615 + doepdma = DWC_READ_REG32(&(out_regs->doepdma));
50616 + start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
50617 + dma_desc = &(dwc_ep->desc_addr[start]);
50618 + } else {
50619 + start = 0;
50620 + dma_desc = dwc_ep->desc_addr;
50621 + }
50622 +
50623 +
50624 + for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
50625 + sts.d32 = dma_desc->status.d32;
50626 + sts.b.bs = BS_HOST_READY;
50627 + dma_desc->status.d32 = sts.d32;
50628 + }
50629 +
50630 + if (dwc_ep->is_in == 0) {
50631 + addr =
50632 + &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
50633 + doepctl;
50634 + } else {
50635 + addr =
50636 + &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50637 + }
50638 + depctl.b.epena = 1;
50639 + depctl.b.cnak = 1;
50640 + DWC_MODIFY_REG32(addr, 0, depctl.d32);
50641 +}
50642 +
50643 +/**
50644 + * This function handles EP0 Control transfers.
50645 + *
50646 + * The state of the control transfers are tracked in
50647 + * <code>ep0state</code>.
50648 + */
50649 +static void handle_ep0(dwc_otg_pcd_t * pcd)
50650 +{
50651 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50652 + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
50653 + dev_dma_desc_sts_t desc_sts;
50654 + deptsiz0_data_t deptsiz;
50655 + uint32_t byte_count;
50656 +
50657 +#ifdef DEBUG_EP0
50658 + DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
50659 + print_ep0_state(pcd);
50660 +#endif
50661 +
50662 +// DWC_PRINTF("HANDLE EP0\n");
50663 +
50664 + switch (pcd->ep0state) {
50665 + case EP0_DISCONNECT:
50666 + break;
50667 +
50668 + case EP0_IDLE:
50669 + pcd->request_config = 0;
50670 +
50671 + pcd_setup(pcd);
50672 + break;
50673 +
50674 + case EP0_IN_DATA_PHASE:
50675 +#ifdef DEBUG_EP0
50676 + DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
50677 + ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50678 + ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50679 +#endif
50680 +
50681 + if (core_if->dma_enable != 0) {
50682 + /*
50683 + * For EP0 we can only program 1 packet at a time so we
50684 + * need to do the make calculations after each complete.
50685 + * Call write_packet to make the calculations, as in
50686 + * slave mode, and use those values to determine if we
50687 + * can complete.
50688 + */
50689 + if (core_if->dma_desc_enable == 0) {
50690 + deptsiz.d32 =
50691 + DWC_READ_REG32(&core_if->
50692 + dev_if->in_ep_regs[0]->
50693 + dieptsiz);
50694 + byte_count =
50695 + ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
50696 + } else {
50697 + desc_sts =
50698 + core_if->dev_if->in_desc_addr->status;
50699 + byte_count =
50700 + ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
50701 + }
50702 + ep0->dwc_ep.xfer_count += byte_count;
50703 + ep0->dwc_ep.xfer_buff += byte_count;
50704 + ep0->dwc_ep.dma_addr += byte_count;
50705 + }
50706 + if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50707 + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50708 + &ep0->dwc_ep);
50709 + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50710 + } else if (ep0->dwc_ep.sent_zlp) {
50711 + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50712 + &ep0->dwc_ep);
50713 + ep0->dwc_ep.sent_zlp = 0;
50714 + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50715 + } else {
50716 + ep0_complete_request(ep0);
50717 + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50718 + }
50719 + break;
50720 + case EP0_OUT_DATA_PHASE:
50721 +#ifdef DEBUG_EP0
50722 + DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
50723 + ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50724 + ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50725 +#endif
50726 + if (core_if->dma_enable != 0) {
50727 + if (core_if->dma_desc_enable == 0) {
50728 + deptsiz.d32 =
50729 + DWC_READ_REG32(&core_if->
50730 + dev_if->out_ep_regs[0]->
50731 + doeptsiz);
50732 + byte_count =
50733 + ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
50734 + } else {
50735 + desc_sts =
50736 + core_if->dev_if->out_desc_addr->status;
50737 + byte_count =
50738 + ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
50739 + }
50740 + ep0->dwc_ep.xfer_count += byte_count;
50741 + ep0->dwc_ep.xfer_buff += byte_count;
50742 + ep0->dwc_ep.dma_addr += byte_count;
50743 + }
50744 + if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50745 + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50746 + &ep0->dwc_ep);
50747 + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50748 + } else if (ep0->dwc_ep.sent_zlp) {
50749 + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50750 + &ep0->dwc_ep);
50751 + ep0->dwc_ep.sent_zlp = 0;
50752 + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50753 + } else {
50754 + ep0_complete_request(ep0);
50755 + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50756 + }
50757 + break;
50758 +
50759 + case EP0_IN_STATUS_PHASE:
50760 + case EP0_OUT_STATUS_PHASE:
50761 + DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
50762 + ep0_complete_request(ep0);
50763 + pcd->ep0state = EP0_IDLE;
50764 + ep0->stopped = 1;
50765 + ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */
50766 +
50767 + /* Prepare for more SETUP Packets */
50768 + if (core_if->dma_enable) {
50769 + ep0_out_start(core_if, pcd);
50770 + }
50771 + break;
50772 +
50773 + case EP0_STALL:
50774 + DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
50775 + break;
50776 + }
50777 +#ifdef DEBUG_EP0
50778 + print_ep0_state(pcd);
50779 +#endif
50780 +}
50781 +
50782 +/**
50783 + * Restart transfer
50784 + */
50785 +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
50786 +{
50787 + dwc_otg_core_if_t *core_if;
50788 + dwc_otg_dev_if_t *dev_if;
50789 + deptsiz_data_t dieptsiz = {.d32 = 0 };
50790 + dwc_otg_pcd_ep_t *ep;
50791 +
50792 + ep = get_in_ep(pcd, epnum);
50793 +
50794 +#ifdef DWC_EN_ISOC
50795 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
50796 + return;
50797 + }
50798 +#endif /* DWC_EN_ISOC */
50799 +
50800 + core_if = GET_CORE_IF(pcd);
50801 + dev_if = core_if->dev_if;
50802 +
50803 + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50804 +
50805 + DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
50806 + " stopped=%d\n", ep->dwc_ep.xfer_buff,
50807 + ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
50808 + /*
50809 + * If xfersize is 0 and pktcnt in not 0, resend the last packet.
50810 + */
50811 + if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
50812 + ep->dwc_ep.start_xfer_buff != 0) {
50813 + if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
50814 + ep->dwc_ep.xfer_count = 0;
50815 + ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
50816 + ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50817 + } else {
50818 + ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
50819 + /* convert packet size to dwords. */
50820 + ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
50821 + ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50822 + }
50823 + ep->stopped = 0;
50824 + DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
50825 + "xfer_len=%0x stopped=%d\n",
50826 + ep->dwc_ep.xfer_buff,
50827 + ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
50828 + ep->stopped);
50829 + if (epnum == 0) {
50830 + dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
50831 + } else {
50832 + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
50833 + }
50834 + }
50835 +}
50836 +
50837 +/*
50838 + * This function create new nextep sequnce based on Learn Queue.
50839 + *
50840 + * @param core_if Programming view of DWC_otg controller
50841 + */
50842 +void predict_nextep_seq( dwc_otg_core_if_t * core_if)
50843 +{
50844 + dwc_otg_device_global_regs_t *dev_global_regs =
50845 + core_if->dev_if->dev_global_regs;
50846 + const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
50847 + /* Number of Token Queue Registers */
50848 + const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
50849 + dtknq1_data_t dtknqr1;
50850 + uint32_t in_tkn_epnums[4];
50851 + uint8_t seqnum[MAX_EPS_CHANNELS];
50852 + uint8_t intkn_seq[TOKEN_Q_DEPTH];
50853 + grstctl_t resetctl = {.d32 = 0 };
50854 + uint8_t temp;
50855 + int ndx = 0;
50856 + int start = 0;
50857 + int end = 0;
50858 + int sort_done = 0;
50859 + int i = 0;
50860 + volatile uint32_t *addr = &dev_global_regs->dtknqr1;
50861 +
50862 +
50863 + DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
50864 +
50865 + /* Read the DTKNQ Registers */
50866 + for (i = 0; i < DTKNQ_REG_CNT; i++) {
50867 + in_tkn_epnums[i] = DWC_READ_REG32(addr);
50868 + DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
50869 + in_tkn_epnums[i]);
50870 + if (addr == &dev_global_regs->dvbusdis) {
50871 + addr = &dev_global_regs->dtknqr3_dthrctl;
50872 + } else {
50873 + ++addr;
50874 + }
50875 +
50876 + }
50877 +
50878 + /* Copy the DTKNQR1 data to the bit field. */
50879 + dtknqr1.d32 = in_tkn_epnums[0];
50880 + if (dtknqr1.b.wrap_bit) {
50881 + ndx = dtknqr1.b.intknwptr;
50882 + end = ndx -1;
50883 + if (end < 0)
50884 + end = TOKEN_Q_DEPTH -1;
50885 + } else {
50886 + ndx = 0;
50887 + end = dtknqr1.b.intknwptr -1;
50888 + if (end < 0)
50889 + end = 0;
50890 + }
50891 + start = ndx;
50892 +
50893 + /* Fill seqnum[] by initial values: EP number + 31 */
50894 + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50895 + seqnum[i] = i +31;
50896 + }
50897 +
50898 + /* Fill intkn_seq[] from in_tkn_epnums[0] */
50899 + for (i=0; i < 6; i++)
50900 + intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
50901 +
50902 + if (TOKEN_Q_DEPTH > 6) {
50903 + /* Fill intkn_seq[] from in_tkn_epnums[1] */
50904 + for (i=6; i < 14; i++)
50905 + intkn_seq[i] =
50906 + (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
50907 + }
50908 +
50909 + if (TOKEN_Q_DEPTH > 14) {
50910 + /* Fill intkn_seq[] from in_tkn_epnums[1] */
50911 + for (i=14; i < 22; i++)
50912 + intkn_seq[i] =
50913 + (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
50914 + }
50915 +
50916 + if (TOKEN_Q_DEPTH > 22) {
50917 + /* Fill intkn_seq[] from in_tkn_epnums[1] */
50918 + for (i=22; i < 30; i++)
50919 + intkn_seq[i] =
50920 + (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
50921 + }
50922 +
50923 + DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
50924 + start, end);
50925 + for (i=0; i<TOKEN_Q_DEPTH; i++)
50926 + DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
50927 +
50928 + /* Update seqnum based on intkn_seq[] */
50929 + i = 0;
50930 + do {
50931 + seqnum[intkn_seq[ndx]] = i;
50932 + ndx++;
50933 + i++;
50934 + if (ndx == TOKEN_Q_DEPTH)
50935 + ndx = 0;
50936 + } while ( i < TOKEN_Q_DEPTH );
50937 +
50938 + /* Mark non active EP's in seqnum[] by 0xff */
50939 + for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50940 + if (core_if->nextep_seq[i] == 0xff )
50941 + seqnum[i] = 0xff;
50942 + }
50943 +
50944 + /* Sort seqnum[] */
50945 + sort_done = 0;
50946 + while (!sort_done) {
50947 + sort_done = 1;
50948 + for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50949 + if (seqnum[i] > seqnum[i+1]) {
50950 + temp = seqnum[i];
50951 + seqnum[i] = seqnum[i+1];
50952 + seqnum[i+1] = temp;
50953 + sort_done = 0;
50954 + }
50955 + }
50956 + }
50957 +
50958 + ndx = start + seqnum[0];
50959 + if (ndx >= TOKEN_Q_DEPTH)
50960 + ndx = ndx % TOKEN_Q_DEPTH;
50961 + core_if->first_in_nextep_seq = intkn_seq[ndx];
50962 +
50963 + /* Update seqnum[] by EP numbers */
50964 + for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50965 + ndx = start + i;
50966 + if (seqnum[i] < 31) {
50967 + ndx = start + seqnum[i];
50968 + if (ndx >= TOKEN_Q_DEPTH)
50969 + ndx = ndx % TOKEN_Q_DEPTH;
50970 + seqnum[i] = intkn_seq[ndx];
50971 + } else {
50972 + if (seqnum[i] < 0xff) {
50973 + seqnum[i] = seqnum[i] - 31;
50974 + } else {
50975 + break;
50976 + }
50977 + }
50978 + }
50979 +
50980 + /* Update nextep_seq[] based on seqnum[] */
50981 + for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50982 + if (seqnum[i] != 0xff) {
50983 + if (seqnum[i+1] != 0xff) {
50984 + core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
50985 + } else {
50986 + core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
50987 + break;
50988 + }
50989 + } else {
50990 + break;
50991 + }
50992 + }
50993 +
50994 + DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
50995 + __func__, core_if->first_in_nextep_seq);
50996 + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50997 + DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
50998 + }
50999 +
51000 + /* Flush the Learning Queue */
51001 + resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
51002 + resetctl.b.intknqflsh = 1;
51003 + DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
51004 +
51005 +
51006 +}
51007 +
51008 +/**
51009 + * handle the IN EP disable interrupt.
51010 + */
51011 +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
51012 + const uint32_t epnum)
51013 +{
51014 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51015 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
51016 + deptsiz_data_t dieptsiz = {.d32 = 0 };
51017 + dctl_data_t dctl = {.d32 = 0 };
51018 + dwc_otg_pcd_ep_t *ep;
51019 + dwc_ep_t *dwc_ep;
51020 + gintmsk_data_t gintmsk_data;
51021 + depctl_data_t depctl;
51022 + uint32_t diepdma;
51023 + uint32_t remain_to_transfer = 0;
51024 + uint8_t i;
51025 + uint32_t xfer_size;
51026 +
51027 + ep = get_in_ep(pcd, epnum);
51028 + dwc_ep = &ep->dwc_ep;
51029 +
51030 + if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51031 + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
51032 + complete_ep(ep);
51033 + return;
51034 + }
51035 +
51036 + DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
51037 + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
51038 + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
51039 + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51040 +
51041 + DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
51042 + dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
51043 +
51044 + if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {
51045 + if (ep->stopped) {
51046 + if (core_if->en_multiple_tx_fifo)
51047 + /* Flush the Tx FIFO */
51048 + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
51049 + /* Clear the Global IN NP NAK */
51050 + dctl.d32 = 0;
51051 + dctl.b.cgnpinnak = 1;
51052 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
51053 + /* Restart the transaction */
51054 + if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
51055 + restart_transfer(pcd, epnum);
51056 + }
51057 + } else {
51058 + /* Restart the transaction */
51059 + if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
51060 + restart_transfer(pcd, epnum);
51061 + }
51062 + DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
51063 + }
51064 + return;
51065 + }
51066 +
51067 + if (core_if->start_predict > 2) { // NP IN EP
51068 + core_if->start_predict--;
51069 + return;
51070 + }
51071 +
51072 + core_if->start_predict--;
51073 +
51074 + if (core_if->start_predict == 1) { // All NP IN Ep's disabled now
51075 +
51076 + predict_nextep_seq(core_if);
51077 +
51078 + /* Update all active IN EP's NextEP field based of nextep_seq[] */
51079 + for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
51080 + depctl.d32 =
51081 + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51082 + if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP
51083 + depctl.b.nextep = core_if->nextep_seq[i];
51084 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
51085 + }
51086 + }
51087 + /* Flush Shared NP TxFIFO */
51088 + dwc_otg_flush_tx_fifo(core_if, 0);
51089 + /* Rewind buffers */
51090 + if (!core_if->dma_desc_enable) {
51091 + i = core_if->first_in_nextep_seq;
51092 + do {
51093 + ep = get_in_ep(pcd, i);
51094 + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
51095 + xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
51096 + if (xfer_size > ep->dwc_ep.maxxfer)
51097 + xfer_size = ep->dwc_ep.maxxfer;
51098 + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51099 + if (dieptsiz.b.pktcnt != 0) {
51100 + if (xfer_size == 0) {
51101 + remain_to_transfer = 0;
51102 + } else {
51103 + if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
51104 + remain_to_transfer =
51105 + dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
51106 + } else {
51107 + remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)
51108 + + (xfer_size % ep->dwc_ep.maxpacket);
51109 + }
51110 + }
51111 + diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
51112 + dieptsiz.b.xfersize = remain_to_transfer;
51113 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
51114 + diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
51115 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
51116 + }
51117 + i = core_if->nextep_seq[i];
51118 + } while (i != core_if->first_in_nextep_seq);
51119 + } else { // dma_desc_enable
51120 + DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
51121 + }
51122 +
51123 + /* Restart transfers in predicted sequences */
51124 + i = core_if->first_in_nextep_seq;
51125 + do {
51126 + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
51127 + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51128 + if (dieptsiz.b.pktcnt != 0) {
51129 + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51130 + depctl.b.epena = 1;
51131 + depctl.b.cnak = 1;
51132 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
51133 + }
51134 + i = core_if->nextep_seq[i];
51135 + } while (i != core_if->first_in_nextep_seq);
51136 +
51137 + /* Clear the global non-periodic IN NAK handshake */
51138 + dctl.d32 = 0;
51139 + dctl.b.cgnpinnak = 1;
51140 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
51141 +
51142 + /* Unmask EP Mismatch interrupt */
51143 + gintmsk_data.d32 = 0;
51144 + gintmsk_data.b.epmismatch = 1;
51145 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
51146 +
51147 + core_if->start_predict = 0;
51148 +
51149 + }
51150 +}
51151 +
51152 +/**
51153 + * Handler for the IN EP timeout handshake interrupt.
51154 + */
51155 +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
51156 + const uint32_t epnum)
51157 +{
51158 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51159 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
51160 +
51161 +#ifdef DEBUG
51162 + deptsiz_data_t dieptsiz = {.d32 = 0 };
51163 + uint32_t num = 0;
51164 +#endif
51165 + dctl_data_t dctl = {.d32 = 0 };
51166 + dwc_otg_pcd_ep_t *ep;
51167 +
51168 + gintmsk_data_t intr_mask = {.d32 = 0 };
51169 +
51170 + ep = get_in_ep(pcd, epnum);
51171 +
51172 + /* Disable the NP Tx Fifo Empty Interrrupt */
51173 + if (!core_if->dma_enable) {
51174 + intr_mask.b.nptxfempty = 1;
51175 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51176 + intr_mask.d32, 0);
51177 + }
51178 + /** @todo NGS Check EP type.
51179 + * Implement for Periodic EPs */
51180 + /*
51181 + * Non-periodic EP
51182 + */
51183 + /* Enable the Global IN NAK Effective Interrupt */
51184 + intr_mask.b.ginnakeff = 1;
51185 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
51186 +
51187 + /* Set Global IN NAK */
51188 + dctl.b.sgnpinnak = 1;
51189 + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
51190 +
51191 + ep->stopped = 1;
51192 +
51193 +#ifdef DEBUG
51194 + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
51195 + DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
51196 + dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
51197 +#endif
51198 +
51199 +#ifdef DISABLE_PERIODIC_EP
51200 + /*
51201 + * Set the NAK bit for this EP to
51202 + * start the disable process.
51203 + */
51204 + diepctl.d32 = 0;
51205 + diepctl.b.snak = 1;
51206 + DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
51207 + diepctl.d32);
51208 + ep->disabling = 1;
51209 + ep->stopped = 1;
51210 +#endif
51211 +}
51212 +
51213 +/**
51214 + * Handler for the IN EP NAK interrupt.
51215 + */
51216 +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
51217 + const uint32_t epnum)
51218 +{
51219 + /** @todo implement ISR */
51220 + dwc_otg_core_if_t *core_if;
51221 + diepmsk_data_t intr_mask = {.d32 = 0 };
51222 +
51223 + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
51224 + core_if = GET_CORE_IF(pcd);
51225 + intr_mask.b.nak = 1;
51226 +
51227 + if (core_if->multiproc_int_enable) {
51228 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51229 + diepeachintmsk[epnum], intr_mask.d32, 0);
51230 + } else {
51231 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
51232 + intr_mask.d32, 0);
51233 + }
51234 +
51235 + return 1;
51236 +}
51237 +
51238 +/**
51239 + * Handler for the OUT EP Babble interrupt.
51240 + */
51241 +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
51242 + const uint32_t epnum)
51243 +{
51244 + /** @todo implement ISR */
51245 + dwc_otg_core_if_t *core_if;
51246 + doepmsk_data_t intr_mask = {.d32 = 0 };
51247 +
51248 + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
51249 + "OUT EP Babble");
51250 + core_if = GET_CORE_IF(pcd);
51251 + intr_mask.b.babble = 1;
51252 +
51253 + if (core_if->multiproc_int_enable) {
51254 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51255 + doepeachintmsk[epnum], intr_mask.d32, 0);
51256 + } else {
51257 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51258 + intr_mask.d32, 0);
51259 + }
51260 +
51261 + return 1;
51262 +}
51263 +
51264 +/**
51265 + * Handler for the OUT EP NAK interrupt.
51266 + */
51267 +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
51268 + const uint32_t epnum)
51269 +{
51270 + /** @todo implement ISR */
51271 + dwc_otg_core_if_t *core_if;
51272 + doepmsk_data_t intr_mask = {.d32 = 0 };
51273 +
51274 + DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
51275 + core_if = GET_CORE_IF(pcd);
51276 + intr_mask.b.nak = 1;
51277 +
51278 + if (core_if->multiproc_int_enable) {
51279 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51280 + doepeachintmsk[epnum], intr_mask.d32, 0);
51281 + } else {
51282 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51283 + intr_mask.d32, 0);
51284 + }
51285 +
51286 + return 1;
51287 +}
51288 +
51289 +/**
51290 + * Handler for the OUT EP NYET interrupt.
51291 + */
51292 +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
51293 + const uint32_t epnum)
51294 +{
51295 + /** @todo implement ISR */
51296 + dwc_otg_core_if_t *core_if;
51297 + doepmsk_data_t intr_mask = {.d32 = 0 };
51298 +
51299 + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
51300 + core_if = GET_CORE_IF(pcd);
51301 + intr_mask.b.nyet = 1;
51302 +
51303 + if (core_if->multiproc_int_enable) {
51304 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51305 + doepeachintmsk[epnum], intr_mask.d32, 0);
51306 + } else {
51307 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51308 + intr_mask.d32, 0);
51309 + }
51310 +
51311 + return 1;
51312 +}
51313 +
51314 +/**
51315 + * This interrupt indicates that an IN EP has a pending Interrupt.
51316 + * The sequence for handling the IN EP interrupt is shown below:
51317 + * -# Read the Device All Endpoint Interrupt register
51318 + * -# Repeat the following for each IN EP interrupt bit set (from
51319 + * LSB to MSB).
51320 + * -# Read the Device Endpoint Interrupt (DIEPINTn) register
51321 + * -# If "Transfer Complete" call the request complete function
51322 + * -# If "Endpoint Disabled" complete the EP disable procedure.
51323 + * -# If "AHB Error Interrupt" log error
51324 + * -# If "Time-out Handshake" log error
51325 + * -# If "IN Token Received when TxFIFO Empty" write packet to Tx
51326 + * FIFO.
51327 + * -# If "IN Token EP Mismatch" (disable, this is handled by EP
51328 + * Mismatch Interrupt)
51329 + */
51330 +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
51331 +{
51332 +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
51333 +do { \
51334 + diepint_data_t diepint = {.d32=0}; \
51335 + diepint.b.__intr = 1; \
51336 + DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
51337 + diepint.d32); \
51338 +} while (0)
51339 +
51340 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51341 + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
51342 + diepint_data_t diepint = {.d32 = 0 };
51343 + depctl_data_t depctl = {.d32 = 0 };
51344 + uint32_t ep_intr;
51345 + uint32_t epnum = 0;
51346 + dwc_otg_pcd_ep_t *ep;
51347 + dwc_ep_t *dwc_ep;
51348 + gintmsk_data_t intr_mask = {.d32 = 0 };
51349 +
51350 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
51351 +
51352 + /* Read in the device interrupt bits */
51353 + ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
51354 +
51355 + /* Service the Device IN interrupts for each endpoint */
51356 + while (ep_intr) {
51357 + if (ep_intr & 0x1) {
51358 + uint32_t empty_msk;
51359 + /* Get EP pointer */
51360 + ep = get_in_ep(pcd, epnum);
51361 + dwc_ep = &ep->dwc_ep;
51362 +
51363 + depctl.d32 =
51364 + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51365 + empty_msk =
51366 + DWC_READ_REG32(&dev_if->
51367 + dev_global_regs->dtknqr4_fifoemptymsk);
51368 +
51369 + DWC_DEBUGPL(DBG_PCDV,
51370 + "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n",
51371 + epnum, empty_msk, depctl.d32);
51372 +
51373 + DWC_DEBUGPL(DBG_PCD,
51374 + "EP%d-%s: type=%d, mps=%d\n",
51375 + dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51376 + dwc_ep->type, dwc_ep->maxpacket);
51377 +
51378 + diepint.d32 =
51379 + dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
51380 +
51381 + DWC_DEBUGPL(DBG_PCDV,
51382 + "EP %d Interrupt Register - 0x%x\n", epnum,
51383 + diepint.d32);
51384 + /* Transfer complete */
51385 + if (diepint.b.xfercompl) {
51386 + /* Disable the NP Tx FIFO Empty
51387 + * Interrupt */
51388 + if (core_if->en_multiple_tx_fifo == 0) {
51389 + intr_mask.b.nptxfempty = 1;
51390 + DWC_MODIFY_REG32
51391 + (&core_if->core_global_regs->gintmsk,
51392 + intr_mask.d32, 0);
51393 + } else {
51394 + /* Disable the Tx FIFO Empty Interrupt for this EP */
51395 + uint32_t fifoemptymsk =
51396 + 0x1 << dwc_ep->num;
51397 + DWC_MODIFY_REG32(&core_if->
51398 + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
51399 + fifoemptymsk, 0);
51400 + }
51401 + /* Clear the bit in DIEPINTn for this interrupt */
51402 + CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
51403 +
51404 + /* Complete the transfer */
51405 + if (epnum == 0) {
51406 + handle_ep0(pcd);
51407 + }
51408 +#ifdef DWC_EN_ISOC
51409 + else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51410 + if (!ep->stopped)
51411 + complete_iso_ep(pcd, ep);
51412 + }
51413 +#endif /* DWC_EN_ISOC */
51414 +#ifdef DWC_UTE_PER_IO
51415 + else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51416 + if (!ep->stopped)
51417 + complete_xiso_ep(ep);
51418 + }
51419 +#endif /* DWC_UTE_PER_IO */
51420 + else {
51421 + if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&
51422 + dwc_ep->bInterval > 1) {
51423 + dwc_ep->frame_num += dwc_ep->bInterval;
51424 + if (dwc_ep->frame_num > 0x3FFF)
51425 + {
51426 + dwc_ep->frm_overrun = 1;
51427 + dwc_ep->frame_num &= 0x3FFF;
51428 + } else
51429 + dwc_ep->frm_overrun = 0;
51430 + }
51431 + complete_ep(ep);
51432 + if(diepint.b.nak)
51433 + CLEAR_IN_EP_INTR(core_if, epnum, nak);
51434 + }
51435 + }
51436 + /* Endpoint disable */
51437 + if (diepint.b.epdisabled) {
51438 + DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
51439 + epnum);
51440 + handle_in_ep_disable_intr(pcd, epnum);
51441 +
51442 + /* Clear the bit in DIEPINTn for this interrupt */
51443 + CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
51444 + }
51445 + /* AHB Error */
51446 + if (diepint.b.ahberr) {
51447 + DWC_ERROR("EP%d IN AHB Error\n", epnum);
51448 + /* Clear the bit in DIEPINTn for this interrupt */
51449 + CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
51450 + }
51451 + /* TimeOUT Handshake (non-ISOC IN EPs) */
51452 + if (diepint.b.timeout) {
51453 + DWC_ERROR("EP%d IN Time-out\n", epnum);
51454 + handle_in_ep_timeout_intr(pcd, epnum);
51455 +
51456 + CLEAR_IN_EP_INTR(core_if, epnum, timeout);
51457 + }
51458 + /** IN Token received with TxF Empty */
51459 + if (diepint.b.intktxfemp) {
51460 + DWC_DEBUGPL(DBG_ANY,
51461 + "EP%d IN TKN TxFifo Empty\n",
51462 + epnum);
51463 + if (!ep->stopped && epnum != 0) {
51464 +
51465 + diepmsk_data_t diepmsk = {.d32 = 0 };
51466 + diepmsk.b.intktxfemp = 1;
51467 +
51468 + if (core_if->multiproc_int_enable) {
51469 + DWC_MODIFY_REG32
51470 + (&dev_if->dev_global_regs->diepeachintmsk
51471 + [epnum], diepmsk.d32, 0);
51472 + } else {
51473 + DWC_MODIFY_REG32
51474 + (&dev_if->dev_global_regs->diepmsk,
51475 + diepmsk.d32, 0);
51476 + }
51477 + } else if (core_if->dma_desc_enable
51478 + && epnum == 0
51479 + && pcd->ep0state ==
51480 + EP0_OUT_STATUS_PHASE) {
51481 + // EP0 IN set STALL
51482 + depctl.d32 =
51483 + DWC_READ_REG32(&dev_if->in_ep_regs
51484 + [epnum]->diepctl);
51485 +
51486 + /* set the disable and stall bits */
51487 + if (depctl.b.epena) {
51488 + depctl.b.epdis = 1;
51489 + }
51490 + depctl.b.stall = 1;
51491 + DWC_WRITE_REG32(&dev_if->in_ep_regs
51492 + [epnum]->diepctl,
51493 + depctl.d32);
51494 + }
51495 + CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
51496 + }
51497 + /** IN Token Received with EP mismatch */
51498 + if (diepint.b.intknepmis) {
51499 + DWC_DEBUGPL(DBG_ANY,
51500 + "EP%d IN TKN EP Mismatch\n", epnum);
51501 + CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
51502 + }
51503 + /** IN Endpoint NAK Effective */
51504 + if (diepint.b.inepnakeff) {
51505 + DWC_DEBUGPL(DBG_ANY,
51506 + "EP%d IN EP NAK Effective\n",
51507 + epnum);
51508 + /* Periodic EP */
51509 + if (ep->disabling) {
51510 + depctl.d32 = 0;
51511 + depctl.b.snak = 1;
51512 + depctl.b.epdis = 1;
51513 + DWC_MODIFY_REG32(&dev_if->in_ep_regs
51514 + [epnum]->diepctl,
51515 + depctl.d32,
51516 + depctl.d32);
51517 + }
51518 + CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
51519 +
51520 + }
51521 +
51522 + /** IN EP Tx FIFO Empty Intr */
51523 + if (diepint.b.emptyintr) {
51524 + DWC_DEBUGPL(DBG_ANY,
51525 + "EP%d Tx FIFO Empty Intr \n",
51526 + epnum);
51527 + write_empty_tx_fifo(pcd, epnum);
51528 +
51529 + CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
51530 +
51531 + }
51532 +
51533 + /** IN EP BNA Intr */
51534 + if (diepint.b.bna) {
51535 + CLEAR_IN_EP_INTR(core_if, epnum, bna);
51536 + if (core_if->dma_desc_enable) {
51537 +#ifdef DWC_EN_ISOC
51538 + if (dwc_ep->type ==
51539 + DWC_OTG_EP_TYPE_ISOC) {
51540 + /*
51541 + * This checking is performed to prevent first "false" BNA
51542 + * handling occuring right after reconnect
51543 + */
51544 + if (dwc_ep->next_frame !=
51545 + 0xffffffff)
51546 + dwc_otg_pcd_handle_iso_bna(ep);
51547 + } else
51548 +#endif /* DWC_EN_ISOC */
51549 + {
51550 + dwc_otg_pcd_handle_noniso_bna(ep);
51551 + }
51552 + }
51553 + }
51554 + /* NAK Interrutp */
51555 + if (diepint.b.nak) {
51556 + DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
51557 + epnum);
51558 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51559 + depctl_data_t depctl;
51560 + if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
51561 + ep->dwc_ep.frame_num = core_if->frame_num;
51562 + if (ep->dwc_ep.bInterval > 1) {
51563 + depctl.d32 = 0;
51564 + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51565 + if (ep->dwc_ep.frame_num & 0x1) {
51566 + depctl.b.setd1pid = 1;
51567 + depctl.b.setd0pid = 0;
51568 + } else {
51569 + depctl.b.setd0pid = 1;
51570 + depctl.b.setd1pid = 0;
51571 + }
51572 + DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
51573 + }
51574 + start_next_request(ep);
51575 + }
51576 + ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
51577 + if (dwc_ep->frame_num > 0x3FFF) {
51578 + dwc_ep->frm_overrun = 1;
51579 + dwc_ep->frame_num &= 0x3FFF;
51580 + } else
51581 + dwc_ep->frm_overrun = 0;
51582 + }
51583 +
51584 + CLEAR_IN_EP_INTR(core_if, epnum, nak);
51585 + }
51586 + }
51587 + epnum++;
51588 + ep_intr >>= 1;
51589 + }
51590 +
51591 + return 1;
51592 +#undef CLEAR_IN_EP_INTR
51593 +}
51594 +
51595 +/**
51596 + * This interrupt indicates that an OUT EP has a pending Interrupt.
51597 + * The sequence for handling the OUT EP interrupt is shown below:
51598 + * -# Read the Device All Endpoint Interrupt register
51599 + * -# Repeat the following for each OUT EP interrupt bit set (from
51600 + * LSB to MSB).
51601 + * -# Read the Device Endpoint Interrupt (DOEPINTn) register
51602 + * -# If "Transfer Complete" call the request complete function
51603 + * -# If "Endpoint Disabled" complete the EP disable procedure.
51604 + * -# If "AHB Error Interrupt" log error
51605 + * -# If "Setup Phase Done" process Setup Packet (See Standard USB
51606 + * Command Processing)
51607 + */
51608 +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
51609 +{
51610 +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
51611 +do { \
51612 + doepint_data_t doepint = {.d32=0}; \
51613 + doepint.b.__intr = 1; \
51614 + DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
51615 + doepint.d32); \
51616 +} while (0)
51617 +
51618 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51619 + uint32_t ep_intr;
51620 + doepint_data_t doepint = {.d32 = 0 };
51621 + uint32_t epnum = 0;
51622 + dwc_otg_pcd_ep_t *ep;
51623 + dwc_ep_t *dwc_ep;
51624 + dctl_data_t dctl = {.d32 = 0 };
51625 + gintmsk_data_t gintmsk = {.d32 = 0 };
51626 +
51627 +
51628 + DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
51629 +
51630 + /* Read in the device interrupt bits */
51631 + ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
51632 +
51633 + while (ep_intr) {
51634 + if (ep_intr & 0x1) {
51635 + /* Get EP pointer */
51636 + ep = get_out_ep(pcd, epnum);
51637 + dwc_ep = &ep->dwc_ep;
51638 +
51639 +#ifdef VERBOSE
51640 + DWC_DEBUGPL(DBG_PCDV,
51641 + "EP%d-%s: type=%d, mps=%d\n",
51642 + dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51643 + dwc_ep->type, dwc_ep->maxpacket);
51644 +#endif
51645 + doepint.d32 =
51646 + dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
51647 + /* Moved this interrupt upper due to core deffect of asserting
51648 + * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
51649 + if (doepint.b.stsphsercvd) {
51650 + deptsiz0_data_t deptsiz;
51651 + CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
51652 + deptsiz.d32 =
51653 + DWC_READ_REG32(&core_if->dev_if->
51654 + out_ep_regs[0]->doeptsiz);
51655 + if (core_if->snpsid >= OTG_CORE_REV_3_00a
51656 + && core_if->dma_enable
51657 + && core_if->dma_desc_enable == 0
51658 + && doepint.b.xfercompl
51659 + && deptsiz.b.xfersize == 24) {
51660 + CLEAR_OUT_EP_INTR(core_if, epnum,
51661 + xfercompl);
51662 + doepint.b.xfercompl = 0;
51663 + ep0_out_start(core_if, pcd);
51664 + }
51665 + if ((core_if->dma_desc_enable) ||
51666 + (core_if->dma_enable
51667 + && core_if->snpsid >=
51668 + OTG_CORE_REV_3_00a)) {
51669 + do_setup_in_status_phase(pcd);
51670 + }
51671 + }
51672 + /* Transfer complete */
51673 + if (doepint.b.xfercompl) {
51674 +
51675 + if (epnum == 0) {
51676 + /* Clear the bit in DOEPINTn for this interrupt */
51677 + CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51678 + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
51679 + DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51680 + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
51681 + doepint.d32);
51682 + DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
51683 + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
51684 +
51685 + if (core_if->snpsid >= OTG_CORE_REV_3_00a
51686 + && core_if->dma_enable == 0) {
51687 + doepint_data_t doepint;
51688 + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51689 + out_ep_regs[0]->doepint);
51690 + if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
51691 + CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51692 + goto exit_xfercompl;
51693 + }
51694 + }
51695 + /* In case of DDMA look at SR bit to go to the Data Stage */
51696 + if (core_if->dma_desc_enable) {
51697 + dev_dma_desc_sts_t status = {.d32 = 0};
51698 + if (pcd->ep0state == EP0_IDLE) {
51699 + status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51700 + dev_if->setup_desc_index]->status.d32;
51701 + if(pcd->data_terminated) {
51702 + pcd->data_terminated = 0;
51703 + status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51704 + dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
51705 + }
51706 + if (status.b.sr) {
51707 + if (doepint.b.setup) {
51708 + DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
51709 + /* Already started data stage, clear setup */
51710 + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51711 + doepint.b.setup = 0;
51712 + handle_ep0(pcd);
51713 + /* Prepare for more setup packets */
51714 + if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51715 + pcd->ep0state == EP0_IN_DATA_PHASE) {
51716 + ep0_out_start(core_if, pcd);
51717 + }
51718 +
51719 + goto exit_xfercompl;
51720 + } else {
51721 + /* Prepare for more setup packets */
51722 + DWC_DEBUGPL(DBG_PCDV,
51723 + "EP0_IDLE SR=1 setup=0 new setup comes\n");
51724 + ep0_out_start(core_if, pcd);
51725 + }
51726 + }
51727 + } else {
51728 + dwc_otg_pcd_request_t *req;
51729 + dev_dma_desc_sts_t status = {.d32 = 0};
51730 + diepint_data_t diepint0;
51731 + diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51732 + in_ep_regs[0]->diepint);
51733 +
51734 + if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
51735 + DWC_ERROR("EP0 is stalled/disconnected\n");
51736 + }
51737 +
51738 + /* Clear IN xfercompl if set */
51739 + if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
51740 + || pcd->ep0state == EP0_IN_DATA_PHASE)) {
51741 + DWC_WRITE_REG32(&core_if->dev_if->
51742 + in_ep_regs[0]->diepint, diepint0.d32);
51743 + }
51744 +
51745 + status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51746 + dev_if->setup_desc_index]->status.d32;
51747 +
51748 + if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
51749 + && (pcd->ep0state == EP0_OUT_DATA_PHASE))
51750 + status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51751 + if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
51752 + status.d32 = status.d32 = core_if->dev_if->
51753 + out_desc_addr->status.d32;
51754 +
51755 + if (status.b.sr) {
51756 + if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51757 + DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51758 + } else {
51759 + DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51760 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
51761 + if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51762 + pcd->ep0state == EP0_OUT_DATA_PHASE) {
51763 + /* Read arrived setup packet from req->buf */
51764 + dwc_memcpy(&pcd->setup_pkt->req,
51765 + req->buf + ep->dwc_ep.xfer_count, 8);
51766 + }
51767 + req->actual = ep->dwc_ep.xfer_count;
51768 + dwc_otg_request_done(ep, req, -ECONNRESET);
51769 + ep->dwc_ep.start_xfer_buff = 0;
51770 + ep->dwc_ep.xfer_buff = 0;
51771 + ep->dwc_ep.xfer_len = 0;
51772 + }
51773 + pcd->ep0state = EP0_IDLE;
51774 + if (doepint.b.setup) {
51775 + DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51776 + /* Data stage started, clear setup */
51777 + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51778 + doepint.b.setup = 0;
51779 + handle_ep0(pcd);
51780 + /* Prepare for setup packets if ep0in was enabled*/
51781 + if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51782 + ep0_out_start(core_if, pcd);
51783 + }
51784 +
51785 + goto exit_xfercompl;
51786 + } else {
51787 + /* Prepare for more setup packets */
51788 + DWC_DEBUGPL(DBG_PCDV,
51789 + "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51790 + ep0_out_start(core_if, pcd);
51791 + }
51792 + }
51793 + }
51794 + }
51795 + if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
51796 + && core_if->dma_desc_enable == 0) {
51797 + doepint_data_t doepint_temp = {.d32 = 0};
51798 + deptsiz0_data_t doeptsize0 = {.d32 = 0 };
51799 + doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51800 + out_ep_regs[ep->dwc_ep.num]->doepint);
51801 + doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
51802 + out_ep_regs[ep->dwc_ep.num]->doeptsiz);
51803 + if (pcd->ep0state == EP0_IDLE) {
51804 + if (doepint_temp.b.sr) {
51805 + CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51806 + }
51807 + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51808 + out_ep_regs[0]->doepint);
51809 + if (doeptsize0.b.supcnt == 3) {
51810 + DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
51811 + ep->dwc_ep.stp_rollover = 1;
51812 + }
51813 + if (doepint.b.setup) {
51814 +retry:
51815 + /* Already started data stage, clear setup */
51816 + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51817 + doepint.b.setup = 0;
51818 + handle_ep0(pcd);
51819 + ep->dwc_ep.stp_rollover = 0;
51820 + /* Prepare for more setup packets */
51821 + if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51822 + pcd->ep0state == EP0_IN_DATA_PHASE) {
51823 + ep0_out_start(core_if, pcd);
51824 + }
51825 + goto exit_xfercompl;
51826 + } else {
51827 + /* Prepare for more setup packets */
51828 + DWC_DEBUGPL(DBG_ANY,
51829 + "EP0_IDLE SR=1 setup=0 new setup comes\n");
51830 + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51831 + out_ep_regs[0]->doepint);
51832 + if(doepint.b.setup)
51833 + goto retry;
51834 + ep0_out_start(core_if, pcd);
51835 + }
51836 + } else {
51837 + dwc_otg_pcd_request_t *req;
51838 + diepint_data_t diepint0 = {.d32 = 0};
51839 + doepint_data_t doepint_temp = {.d32 = 0};
51840 + depctl_data_t diepctl0;
51841 + diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51842 + in_ep_regs[0]->diepint);
51843 + diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
51844 + in_ep_regs[0]->diepctl);
51845 +
51846 + if (pcd->ep0state == EP0_IN_DATA_PHASE
51847 + || pcd->ep0state == EP0_IN_STATUS_PHASE) {
51848 + if (diepint0.b.xfercompl) {
51849 + DWC_WRITE_REG32(&core_if->dev_if->
51850 + in_ep_regs[0]->diepint, diepint0.d32);
51851 + }
51852 + if (diepctl0.b.epena) {
51853 + diepint_data_t diepint = {.d32 = 0};
51854 + diepctl0.b.snak = 1;
51855 + DWC_WRITE_REG32(&core_if->dev_if->
51856 + in_ep_regs[0]->diepctl, diepctl0.d32);
51857 + do {
51858 + dwc_udelay(10);
51859 + diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51860 + in_ep_regs[0]->diepint);
51861 + } while (!diepint.b.inepnakeff);
51862 + diepint.b.inepnakeff = 1;
51863 + DWC_WRITE_REG32(&core_if->dev_if->
51864 + in_ep_regs[0]->diepint, diepint.d32);
51865 + diepctl0.d32 = 0;
51866 + diepctl0.b.epdis = 1;
51867 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
51868 + diepctl0.d32);
51869 + do {
51870 + dwc_udelay(10);
51871 + diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51872 + in_ep_regs[0]->diepint);
51873 + } while (!diepint.b.epdisabled);
51874 + diepint.b.epdisabled = 1;
51875 + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
51876 + diepint.d32);
51877 + }
51878 + }
51879 + doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51880 + out_ep_regs[ep->dwc_ep.num]->doepint);
51881 + if (doepint_temp.b.sr) {
51882 + CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51883 + if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51884 + DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51885 + } else {
51886 + DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51887 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
51888 + if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51889 + pcd->ep0state == EP0_OUT_DATA_PHASE) {
51890 + /* Read arrived setup packet from req->buf */
51891 + dwc_memcpy(&pcd->setup_pkt->req,
51892 + req->buf + ep->dwc_ep.xfer_count, 8);
51893 + }
51894 + req->actual = ep->dwc_ep.xfer_count;
51895 + dwc_otg_request_done(ep, req, -ECONNRESET);
51896 + ep->dwc_ep.start_xfer_buff = 0;
51897 + ep->dwc_ep.xfer_buff = 0;
51898 + ep->dwc_ep.xfer_len = 0;
51899 + }
51900 + pcd->ep0state = EP0_IDLE;
51901 + if (doepint.b.setup) {
51902 + DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51903 + /* Data stage started, clear setup */
51904 + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51905 + doepint.b.setup = 0;
51906 + handle_ep0(pcd);
51907 + /* Prepare for setup packets if ep0in was enabled*/
51908 + if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51909 + ep0_out_start(core_if, pcd);
51910 + }
51911 + goto exit_xfercompl;
51912 + } else {
51913 + /* Prepare for more setup packets */
51914 + DWC_DEBUGPL(DBG_PCDV,
51915 + "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51916 + ep0_out_start(core_if, pcd);
51917 + }
51918 + }
51919 + }
51920 + }
51921 + if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
51922 + handle_ep0(pcd);
51923 +exit_xfercompl:
51924 + DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51925 + dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
51926 + } else {
51927 + if (core_if->dma_desc_enable == 0
51928 + || pcd->ep0state != EP0_IDLE)
51929 + handle_ep0(pcd);
51930 + }
51931 +#ifdef DWC_EN_ISOC
51932 + } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51933 + if (doepint.b.pktdrpsts == 0) {
51934 + /* Clear the bit in DOEPINTn for this interrupt */
51935 + CLEAR_OUT_EP_INTR(core_if,
51936 + epnum,
51937 + xfercompl);
51938 + complete_iso_ep(pcd, ep);
51939 + } else {
51940 +
51941 + doepint_data_t doepint = {.d32 = 0 };
51942 + doepint.b.xfercompl = 1;
51943 + doepint.b.pktdrpsts = 1;
51944 + DWC_WRITE_REG32
51945 + (&core_if->dev_if->out_ep_regs
51946 + [epnum]->doepint,
51947 + doepint.d32);
51948 + if (handle_iso_out_pkt_dropped
51949 + (core_if, dwc_ep)) {
51950 + complete_iso_ep(pcd,
51951 + ep);
51952 + }
51953 + }
51954 +#endif /* DWC_EN_ISOC */
51955 +#ifdef DWC_UTE_PER_IO
51956 + } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51957 + CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51958 + if (!ep->stopped)
51959 + complete_xiso_ep(ep);
51960 +#endif /* DWC_UTE_PER_IO */
51961 + } else {
51962 + /* Clear the bit in DOEPINTn for this interrupt */
51963 + CLEAR_OUT_EP_INTR(core_if, epnum,
51964 + xfercompl);
51965 +
51966 + if (core_if->core_params->dev_out_nak) {
51967 + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
51968 + pcd->core_if->ep_xfer_info[epnum].state = 0;
51969 +#ifdef DEBUG
51970 + print_memory_payload(pcd, dwc_ep);
51971 +#endif
51972 + }
51973 + complete_ep(ep);
51974 + }
51975 +
51976 + }
51977 +
51978 + /* Endpoint disable */
51979 + if (doepint.b.epdisabled) {
51980 +
51981 + /* Clear the bit in DOEPINTn for this interrupt */
51982 + CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
51983 + if (core_if->core_params->dev_out_nak) {
51984 +#ifdef DEBUG
51985 + print_memory_payload(pcd, dwc_ep);
51986 +#endif
51987 + /* In case of timeout condition */
51988 + if (core_if->ep_xfer_info[epnum].state == 2) {
51989 + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51990 + dev_global_regs->dctl);
51991 + dctl.b.cgoutnak = 1;
51992 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51993 + dctl.d32);
51994 + /* Unmask goutnakeff interrupt which was masked
51995 + * during handle nak out interrupt */
51996 + gintmsk.b.goutnakeff = 1;
51997 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51998 + 0, gintmsk.d32);
51999 +
52000 + complete_ep(ep);
52001 + }
52002 + }
52003 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
52004 + {
52005 + dctl_data_t dctl;
52006 + gintmsk_data_t intr_mask = {.d32 = 0};
52007 + dwc_otg_pcd_request_t *req = 0;
52008 +
52009 + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
52010 + dev_global_regs->dctl);
52011 + dctl.b.cgoutnak = 1;
52012 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
52013 + dctl.d32);
52014 +
52015 + intr_mask.d32 = 0;
52016 + intr_mask.b.incomplisoout = 1;
52017 +
52018 + /* Get any pending requests */
52019 + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
52020 + req = DWC_CIRCLEQ_FIRST(&ep->queue);
52021 + if (!req) {
52022 + DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
52023 + } else {
52024 + dwc_otg_request_done(ep, req, 0);
52025 + start_next_request(ep);
52026 + }
52027 + } else {
52028 + DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
52029 + }
52030 + }
52031 + }
52032 + /* AHB Error */
52033 + if (doepint.b.ahberr) {
52034 + DWC_ERROR("EP%d OUT AHB Error\n", epnum);
52035 + DWC_ERROR("EP%d DEPDMA=0x%08x \n",
52036 + epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
52037 + CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
52038 + }
52039 + /* Setup Phase Done (contorl EPs) */
52040 + if (doepint.b.setup) {
52041 +#ifdef DEBUG_EP0
52042 + DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
52043 +#endif
52044 + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
52045 +
52046 + handle_ep0(pcd);
52047 + }
52048 +
52049 + /** OUT EP BNA Intr */
52050 + if (doepint.b.bna) {
52051 + CLEAR_OUT_EP_INTR(core_if, epnum, bna);
52052 + if (core_if->dma_desc_enable) {
52053 +#ifdef DWC_EN_ISOC
52054 + if (dwc_ep->type ==
52055 + DWC_OTG_EP_TYPE_ISOC) {
52056 + /*
52057 + * This checking is performed to prevent first "false" BNA
52058 + * handling occuring right after reconnect
52059 + */
52060 + if (dwc_ep->next_frame !=
52061 + 0xffffffff)
52062 + dwc_otg_pcd_handle_iso_bna(ep);
52063 + } else
52064 +#endif /* DWC_EN_ISOC */
52065 + {
52066 + dwc_otg_pcd_handle_noniso_bna(ep);
52067 + }
52068 + }
52069 + }
52070 + /* Babble Interrupt */
52071 + if (doepint.b.babble) {
52072 + DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
52073 + epnum);
52074 + handle_out_ep_babble_intr(pcd, epnum);
52075 +
52076 + CLEAR_OUT_EP_INTR(core_if, epnum, babble);
52077 + }
52078 + if (doepint.b.outtknepdis) {
52079 + DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
52080 + disabled\n",epnum);
52081 + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
52082 + doepmsk_data_t doepmsk = {.d32 = 0};
52083 + ep->dwc_ep.frame_num = core_if->frame_num;
52084 + if (ep->dwc_ep.bInterval > 1) {
52085 + depctl_data_t depctl;
52086 + depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
52087 + out_ep_regs[epnum]->doepctl);
52088 + if (ep->dwc_ep.frame_num & 0x1) {
52089 + depctl.b.setd1pid = 1;
52090 + depctl.b.setd0pid = 0;
52091 + } else {
52092 + depctl.b.setd0pid = 1;
52093 + depctl.b.setd1pid = 0;
52094 + }
52095 + DWC_WRITE_REG32(&core_if->dev_if->
52096 + out_ep_regs[epnum]->doepctl, depctl.d32);
52097 + }
52098 + start_next_request(ep);
52099 + doepmsk.b.outtknepdis = 1;
52100 + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
52101 + doepmsk.d32, 0);
52102 + }
52103 + CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
52104 + }
52105 +
52106 + /* NAK Interrutp */
52107 + if (doepint.b.nak) {
52108 + DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
52109 + handle_out_ep_nak_intr(pcd, epnum);
52110 +
52111 + CLEAR_OUT_EP_INTR(core_if, epnum, nak);
52112 + }
52113 + /* NYET Interrutp */
52114 + if (doepint.b.nyet) {
52115 + DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
52116 + handle_out_ep_nyet_intr(pcd, epnum);
52117 +
52118 + CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
52119 + }
52120 + }
52121 +
52122 + epnum++;
52123 + ep_intr >>= 1;
52124 + }
52125 +
52126 + return 1;
52127 +
52128 +#undef CLEAR_OUT_EP_INTR
52129 +}
52130 +static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
52131 +{
52132 + int retval = 0;
52133 + if(!frm_overrun && curr_fr >= trgt_fr)
52134 + retval = 1;
52135 + else if (frm_overrun
52136 + && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
52137 + retval = 1;
52138 + return retval;
52139 +}
52140 +/**
52141 + * Incomplete ISO IN Transfer Interrupt.
52142 + * This interrupt indicates one of the following conditions occurred
52143 + * while transmitting an ISOC transaction.
52144 + * - Corrupted IN Token for ISOC EP.
52145 + * - Packet not complete in FIFO.
52146 + * The follow actions will be taken:
52147 + * -# Determine the EP
52148 + * -# Set incomplete flag in dwc_ep structure
52149 + * -# Disable EP; when "Endpoint Disabled" interrupt is received
52150 + * Flush FIFO
52151 + */
52152 +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
52153 +{
52154 + gintsts_data_t gintsts;
52155 +
52156 +#ifdef DWC_EN_ISOC
52157 + dwc_otg_dev_if_t *dev_if;
52158 + deptsiz_data_t deptsiz = {.d32 = 0 };
52159 + depctl_data_t depctl = {.d32 = 0 };
52160 + dsts_data_t dsts = {.d32 = 0 };
52161 + dwc_ep_t *dwc_ep;
52162 + int i;
52163 +
52164 + dev_if = GET_CORE_IF(pcd)->dev_if;
52165 +
52166 + for (i = 1; i <= dev_if->num_in_eps; ++i) {
52167 + dwc_ep = &pcd->in_ep[i].dwc_ep;
52168 + if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
52169 + deptsiz.d32 =
52170 + DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
52171 + depctl.d32 =
52172 + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52173 +
52174 + if (depctl.b.epdis && deptsiz.d32) {
52175 + set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
52176 + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
52177 + dwc_ep->cur_pkt = 0;
52178 + dwc_ep->proc_buf_num =
52179 + (dwc_ep->proc_buf_num ^ 1) & 0x1;
52180 +
52181 + if (dwc_ep->proc_buf_num) {
52182 + dwc_ep->cur_pkt_addr =
52183 + dwc_ep->xfer_buff1;
52184 + dwc_ep->cur_pkt_dma_addr =
52185 + dwc_ep->dma_addr1;
52186 + } else {
52187 + dwc_ep->cur_pkt_addr =
52188 + dwc_ep->xfer_buff0;
52189 + dwc_ep->cur_pkt_dma_addr =
52190 + dwc_ep->dma_addr0;
52191 + }
52192 +
52193 + }
52194 +
52195 + dsts.d32 =
52196 + DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
52197 + dev_global_regs->dsts);
52198 + dwc_ep->next_frame = dsts.b.soffn;
52199 +
52200 + dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
52201 + (pcd),
52202 + dwc_ep);
52203 + }
52204 + }
52205 + }
52206 +
52207 +#else
52208 + depctl_data_t depctl = {.d32 = 0 };
52209 + dwc_ep_t *dwc_ep;
52210 + dwc_otg_dev_if_t *dev_if;
52211 + int i;
52212 + dev_if = GET_CORE_IF(pcd)->dev_if;
52213 +
52214 + DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
52215 +
52216 + for (i = 1; i <= dev_if->num_in_eps; ++i) {
52217 + dwc_ep = &pcd->in_ep[i-1].dwc_ep;
52218 + depctl.d32 =
52219 + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52220 + if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
52221 + if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,
52222 + dwc_ep->frm_overrun))
52223 + {
52224 + depctl.d32 =
52225 + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52226 + depctl.b.snak = 1;
52227 + depctl.b.epdis = 1;
52228 + DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
52229 + }
52230 + }
52231 + }
52232 +
52233 + /*intr_mask.b.incomplisoin = 1;
52234 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52235 + intr_mask.d32, 0); */
52236 +#endif //DWC_EN_ISOC
52237 +
52238 + /* Clear interrupt */
52239 + gintsts.d32 = 0;
52240 + gintsts.b.incomplisoin = 1;
52241 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52242 + gintsts.d32);
52243 +
52244 + return 1;
52245 +}
52246 +
52247 +/**
52248 + * Incomplete ISO OUT Transfer Interrupt.
52249 + *
52250 + * This interrupt indicates that the core has dropped an ISO OUT
52251 + * packet. The following conditions can be the cause:
52252 + * - FIFO Full, the entire packet would not fit in the FIFO.
52253 + * - CRC Error
52254 + * - Corrupted Token
52255 + * The follow actions will be taken:
52256 + * -# Determine the EP
52257 + * -# Set incomplete flag in dwc_ep structure
52258 + * -# Read any data from the FIFO
52259 + * -# Disable EP. When "Endpoint Disabled" interrupt is received
52260 + * re-enable EP.
52261 + */
52262 +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
52263 +{
52264 +
52265 + gintsts_data_t gintsts;
52266 +
52267 +#ifdef DWC_EN_ISOC
52268 + dwc_otg_dev_if_t *dev_if;
52269 + deptsiz_data_t deptsiz = {.d32 = 0 };
52270 + depctl_data_t depctl = {.d32 = 0 };
52271 + dsts_data_t dsts = {.d32 = 0 };
52272 + dwc_ep_t *dwc_ep;
52273 + int i;
52274 +
52275 + dev_if = GET_CORE_IF(pcd)->dev_if;
52276 +
52277 + for (i = 1; i <= dev_if->num_out_eps; ++i) {
52278 + dwc_ep = &pcd->in_ep[i].dwc_ep;
52279 + if (pcd->out_ep[i].dwc_ep.active &&
52280 + pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
52281 + deptsiz.d32 =
52282 + DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
52283 + depctl.d32 =
52284 + DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52285 +
52286 + if (depctl.b.epdis && deptsiz.d32) {
52287 + set_current_pkt_info(GET_CORE_IF(pcd),
52288 + &pcd->out_ep[i].dwc_ep);
52289 + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
52290 + dwc_ep->cur_pkt = 0;
52291 + dwc_ep->proc_buf_num =
52292 + (dwc_ep->proc_buf_num ^ 1) & 0x1;
52293 +
52294 + if (dwc_ep->proc_buf_num) {
52295 + dwc_ep->cur_pkt_addr =
52296 + dwc_ep->xfer_buff1;
52297 + dwc_ep->cur_pkt_dma_addr =
52298 + dwc_ep->dma_addr1;
52299 + } else {
52300 + dwc_ep->cur_pkt_addr =
52301 + dwc_ep->xfer_buff0;
52302 + dwc_ep->cur_pkt_dma_addr =
52303 + dwc_ep->dma_addr0;
52304 + }
52305 +
52306 + }
52307 +
52308 + dsts.d32 =
52309 + DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
52310 + dev_global_regs->dsts);
52311 + dwc_ep->next_frame = dsts.b.soffn;
52312 +
52313 + dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
52314 + (pcd),
52315 + dwc_ep);
52316 + }
52317 + }
52318 + }
52319 +#else
52320 + /** @todo implement ISR */
52321 + gintmsk_data_t intr_mask = {.d32 = 0 };
52322 + dwc_otg_core_if_t *core_if;
52323 + deptsiz_data_t deptsiz = {.d32 = 0 };
52324 + depctl_data_t depctl = {.d32 = 0 };
52325 + dctl_data_t dctl = {.d32 = 0 };
52326 + dwc_ep_t *dwc_ep = NULL;
52327 + int i;
52328 + core_if = GET_CORE_IF(pcd);
52329 +
52330 + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
52331 + dwc_ep = &pcd->out_ep[i].dwc_ep;
52332 + depctl.d32 =
52333 + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52334 + if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
52335 + core_if->dev_if->isoc_ep = dwc_ep;
52336 + deptsiz.d32 =
52337 + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
52338 + break;
52339 + }
52340 + }
52341 + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
52342 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
52343 + intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
52344 +
52345 + if (!intr_mask.b.goutnakeff) {
52346 + /* Unmask it */
52347 + intr_mask.b.goutnakeff = 1;
52348 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
52349 + }
52350 + if (!gintsts.b.goutnakeff) {
52351 + dctl.b.sgoutnak = 1;
52352 + }
52353 + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
52354 +
52355 + depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52356 + if (depctl.b.epena) {
52357 + depctl.b.epdis = 1;
52358 + depctl.b.snak = 1;
52359 + }
52360 + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
52361 +
52362 + intr_mask.d32 = 0;
52363 + intr_mask.b.incomplisoout = 1;
52364 +
52365 +#endif /* DWC_EN_ISOC */
52366 +
52367 + /* Clear interrupt */
52368 + gintsts.d32 = 0;
52369 + gintsts.b.incomplisoout = 1;
52370 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52371 + gintsts.d32);
52372 +
52373 + return 1;
52374 +}
52375 +
52376 +/**
52377 + * This function handles the Global IN NAK Effective interrupt.
52378 + *
52379 + */
52380 +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
52381 +{
52382 + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52383 + depctl_data_t diepctl = {.d32 = 0 };
52384 + gintmsk_data_t intr_mask = {.d32 = 0 };
52385 + gintsts_data_t gintsts;
52386 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52387 + int i;
52388 +
52389 + DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
52390 +
52391 + /* Disable all active IN EPs */
52392 + for (i = 0; i <= dev_if->num_in_eps; i++) {
52393 + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52394 + if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
52395 + if (core_if->start_predict > 0)
52396 + core_if->start_predict++;
52397 + diepctl.b.epdis = 1;
52398 + diepctl.b.snak = 1;
52399 + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
52400 + }
52401 + }
52402 +
52403 +
52404 + /* Disable the Global IN NAK Effective Interrupt */
52405 + intr_mask.b.ginnakeff = 1;
52406 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52407 + intr_mask.d32, 0);
52408 +
52409 + /* Clear interrupt */
52410 + gintsts.d32 = 0;
52411 + gintsts.b.ginnakeff = 1;
52412 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52413 + gintsts.d32);
52414 +
52415 + return 1;
52416 +}
52417 +
52418 +/**
52419 + * OUT NAK Effective.
52420 + *
52421 + */
52422 +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
52423 +{
52424 + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52425 + gintmsk_data_t intr_mask = {.d32 = 0 };
52426 + gintsts_data_t gintsts;
52427 + depctl_data_t doepctl;
52428 + int i;
52429 +
52430 + /* Disable the Global OUT NAK Effective Interrupt */
52431 + intr_mask.b.goutnakeff = 1;
52432 + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52433 + intr_mask.d32, 0);
52434 +
52435 + /* If DEV OUT NAK enabled*/
52436 + if (pcd->core_if->core_params->dev_out_nak) {
52437 + /* Run over all out endpoints to determine the ep number on
52438 + * which the timeout has happened
52439 + */
52440 + for (i = 0; i <= dev_if->num_out_eps; i++) {
52441 + if ( pcd->core_if->ep_xfer_info[i].state == 2 )
52442 + break;
52443 + }
52444 + if (i > dev_if->num_out_eps) {
52445 + dctl_data_t dctl;
52446 + dctl.d32 =
52447 + DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
52448 + dctl.b.cgoutnak = 1;
52449 + DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
52450 + dctl.d32);
52451 + goto out;
52452 + }
52453 +
52454 + /* Disable the endpoint */
52455 + doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52456 + if (doepctl.b.epena) {
52457 + doepctl.b.epdis = 1;
52458 + doepctl.b.snak = 1;
52459 + }
52460 + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
52461 + return 1;
52462 + }
52463 + /* We come here from Incomplete ISO OUT handler */
52464 + if (dev_if->isoc_ep) {
52465 + dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
52466 + uint32_t epnum = dwc_ep->num;
52467 + doepint_data_t doepint;
52468 + doepint.d32 =
52469 + DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
52470 + dev_if->isoc_ep = NULL;
52471 + doepctl.d32 =
52472 + DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
52473 + DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
52474 + if (doepctl.b.epena) {
52475 + doepctl.b.epdis = 1;
52476 + doepctl.b.snak = 1;
52477 + }
52478 + DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
52479 + doepctl.d32);
52480 + return 1;
52481 + } else
52482 + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
52483 + "Global OUT NAK Effective\n");
52484 +
52485 +out:
52486 + /* Clear interrupt */
52487 + gintsts.d32 = 0;
52488 + gintsts.b.goutnakeff = 1;
52489 + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52490 + gintsts.d32);
52491 +
52492 + return 1;
52493 +}
52494 +
52495 +/**
52496 + * PCD interrupt handler.
52497 + *
52498 + * The PCD handles the device interrupts. Many conditions can cause a
52499 + * device interrupt. When an interrupt occurs, the device interrupt
52500 + * service routine determines the cause of the interrupt and
52501 + * dispatches handling to the appropriate function. These interrupt
52502 + * handling functions are described below.
52503 + *
52504 + * All interrupt registers are processed from LSB to MSB.
52505 + *
52506 + */
52507 +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
52508 +{
52509 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52510 +#ifdef VERBOSE
52511 + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
52512 +#endif
52513 + gintsts_data_t gintr_status;
52514 + int32_t retval = 0;
52515 +
52516 + /* Exit from ISR if core is hibernated */
52517 + if (core_if->hibernation_suspend == 1) {
52518 + return retval;
52519 + }
52520 +#ifdef VERBOSE
52521 + DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n",
52522 + __func__,
52523 + DWC_READ_REG32(&global_regs->gintsts),
52524 + DWC_READ_REG32(&global_regs->gintmsk));
52525 +#endif
52526 +
52527 + if (dwc_otg_is_device_mode(core_if)) {
52528 + DWC_SPINLOCK(pcd->lock);
52529 +#ifdef VERBOSE
52530 + DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n",
52531 + __func__,
52532 + DWC_READ_REG32(&global_regs->gintsts),
52533 + DWC_READ_REG32(&global_regs->gintmsk));
52534 +#endif
52535 +
52536 + gintr_status.d32 = dwc_otg_read_core_intr(core_if);
52537 +
52538 + DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
52539 + __func__, gintr_status.d32);
52540 +
52541 + if (gintr_status.b.sofintr) {
52542 + retval |= dwc_otg_pcd_handle_sof_intr(pcd);
52543 + }
52544 + if (gintr_status.b.rxstsqlvl) {
52545 + retval |=
52546 + dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
52547 + }
52548 + if (gintr_status.b.nptxfempty) {
52549 + retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
52550 + }
52551 + if (gintr_status.b.goutnakeff) {
52552 + retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
52553 + }
52554 + if (gintr_status.b.i2cintr) {
52555 + retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
52556 + }
52557 + if (gintr_status.b.erlysuspend) {
52558 + retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
52559 + }
52560 + if (gintr_status.b.usbreset) {
52561 + retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
52562 + }
52563 + if (gintr_status.b.enumdone) {
52564 + retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
52565 + }
52566 + if (gintr_status.b.isooutdrop) {
52567 + retval |=
52568 + dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
52569 + (pcd);
52570 + }
52571 + if (gintr_status.b.eopframe) {
52572 + retval |=
52573 + dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
52574 + }
52575 + if (gintr_status.b.inepint) {
52576 + if (!core_if->multiproc_int_enable) {
52577 + retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52578 + }
52579 + }
52580 + if (gintr_status.b.outepintr) {
52581 + if (!core_if->multiproc_int_enable) {
52582 + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52583 + }
52584 + }
52585 + if (gintr_status.b.epmismatch) {
52586 + retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
52587 + }
52588 + if (gintr_status.b.fetsusp) {
52589 + retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
52590 + }
52591 + if (gintr_status.b.ginnakeff) {
52592 + retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
52593 + }
52594 + if (gintr_status.b.incomplisoin) {
52595 + retval |=
52596 + dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
52597 + }
52598 + if (gintr_status.b.incomplisoout) {
52599 + retval |=
52600 + dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
52601 + }
52602 +
52603 + /* In MPI mode Device Endpoints interrupts are asserted
52604 + * without setting outepintr and inepint bits set, so these
52605 + * Interrupt handlers are called without checking these bit-fields
52606 + */
52607 + if (core_if->multiproc_int_enable) {
52608 + retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52609 + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52610 + }
52611 +#ifdef VERBOSE
52612 + DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
52613 + DWC_READ_REG32(&global_regs->gintsts));
52614 +#endif
52615 + DWC_SPINUNLOCK(pcd->lock);
52616 + }
52617 + return retval;
52618 +}
52619 +
52620 +#endif /* DWC_HOST_ONLY */
52621 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52622 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100
52623 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2013-07-06 15:25:50.000000000 +0100
52624 @@ -0,0 +1,1358 @@
52625 + /* ==========================================================================
52626 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
52627 + * $Revision: #21 $
52628 + * $Date: 2012/08/10 $
52629 + * $Change: 2047372 $
52630 + *
52631 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
52632 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
52633 + * otherwise expressly agreed to in writing between Synopsys and you.
52634 + *
52635 + * The Software IS NOT an item of Licensed Software or Licensed Product under
52636 + * any End User Software License Agreement or Agreement for Licensed Product
52637 + * with Synopsys or any supplement thereto. You are permitted to use and
52638 + * redistribute this Software in source and binary forms, with or without
52639 + * modification, provided that redistributions of source code must retain this
52640 + * notice. You may not view, use, disclose, copy or distribute this file or
52641 + * any information contained herein except pursuant to this license grant from
52642 + * Synopsys. If you do not agree with this notice, including the disclaimer
52643 + * below, then you are not authorized to use the Software.
52644 + *
52645 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
52646 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52647 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52648 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
52649 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52650 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
52651 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52652 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52653 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52654 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52655 + * DAMAGE.
52656 + * ========================================================================== */
52657 +#ifndef DWC_HOST_ONLY
52658 +
52659 +/** @file
52660 + * This file implements the Peripheral Controller Driver.
52661 + *
52662 + * The Peripheral Controller Driver (PCD) is responsible for
52663 + * translating requests from the Function Driver into the appropriate
52664 + * actions on the DWC_otg controller. It isolates the Function Driver
52665 + * from the specifics of the controller by providing an API to the
52666 + * Function Driver.
52667 + *
52668 + * The Peripheral Controller Driver for Linux will implement the
52669 + * Gadget API, so that the existing Gadget drivers can be used.
52670 + * (Gadget Driver is the Linux terminology for a Function Driver.)
52671 + *
52672 + * The Linux Gadget API is defined in the header file
52673 + * <code><linux/usb_gadget.h></code>. The USB EP operations API is
52674 + * defined in the structure <code>usb_ep_ops</code> and the USB
52675 + * Controller API is defined in the structure
52676 + * <code>usb_gadget_ops</code>.
52677 + *
52678 + */
52679 +
52680 +#include "dwc_otg_os_dep.h"
52681 +#include "dwc_otg_pcd_if.h"
52682 +#include "dwc_otg_pcd.h"
52683 +#include "dwc_otg_driver.h"
52684 +#include "dwc_otg_dbg.h"
52685 +
52686 +static struct gadget_wrapper {
52687 + dwc_otg_pcd_t *pcd;
52688 +
52689 + struct usb_gadget gadget;
52690 + struct usb_gadget_driver *driver;
52691 +
52692 + struct usb_ep ep0;
52693 + struct usb_ep in_ep[16];
52694 + struct usb_ep out_ep[16];
52695 +
52696 +} *gadget_wrapper;
52697 +
52698 +/* Display the contents of the buffer */
52699 +extern void dump_msg(const u8 * buf, unsigned int length);
52700 +/**
52701 + * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
52702 + * if the endpoint is not found
52703 + */
52704 +static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
52705 +{
52706 + int i;
52707 + if (pcd->ep0.priv == handle) {
52708 + return &pcd->ep0;
52709 + }
52710 +
52711 + for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
52712 + if (pcd->in_ep[i].priv == handle)
52713 + return &pcd->in_ep[i];
52714 + if (pcd->out_ep[i].priv == handle)
52715 + return &pcd->out_ep[i];
52716 + }
52717 +
52718 + return NULL;
52719 +}
52720 +
52721 +/* USB Endpoint Operations */
52722 +/*
52723 + * The following sections briefly describe the behavior of the Gadget
52724 + * API endpoint operations implemented in the DWC_otg driver
52725 + * software. Detailed descriptions of the generic behavior of each of
52726 + * these functions can be found in the Linux header file
52727 + * include/linux/usb_gadget.h.
52728 + *
52729 + * The Gadget API provides wrapper functions for each of the function
52730 + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
52731 + * function, which then calls the underlying PCD function. The
52732 + * following sections are named according to the wrapper
52733 + * functions. Within each section, the corresponding DWC_otg PCD
52734 + * function name is specified.
52735 + *
52736 + */
52737 +
52738 +/**
52739 + * This function is called by the Gadget Driver for each EP to be
52740 + * configured for the current configuration (SET_CONFIGURATION).
52741 + *
52742 + * This function initializes the dwc_otg_ep_t data structure, and then
52743 + * calls dwc_otg_ep_activate.
52744 + */
52745 +static int ep_enable(struct usb_ep *usb_ep,
52746 + const struct usb_endpoint_descriptor *ep_desc)
52747 +{
52748 + int retval;
52749 +
52750 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
52751 +
52752 + if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
52753 + DWC_WARN("%s, bad ep or descriptor\n", __func__);
52754 + return -EINVAL;
52755 + }
52756 + if (usb_ep == &gadget_wrapper->ep0) {
52757 + DWC_WARN("%s, bad ep(0)\n", __func__);
52758 + return -EINVAL;
52759 + }
52760 +
52761 + /* Check FIFO size? */
52762 + if (!ep_desc->wMaxPacketSize) {
52763 + DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
52764 + return -ERANGE;
52765 + }
52766 +
52767 + if (!gadget_wrapper->driver ||
52768 + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52769 + DWC_WARN("%s, bogus device state\n", __func__);
52770 + return -ESHUTDOWN;
52771 + }
52772 +
52773 + /* Delete after check - MAS */
52774 +#if 0
52775 + nat = (uint32_t) ep_desc->wMaxPacketSize;
52776 + printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
52777 + nat = (nat >> 11) & 0x03;
52778 + printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
52779 +#endif
52780 + retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
52781 + (const uint8_t *)ep_desc,
52782 + (void *)usb_ep);
52783 + if (retval) {
52784 + DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
52785 + return -EINVAL;
52786 + }
52787 +
52788 + usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
52789 +
52790 + return 0;
52791 +}
52792 +
52793 +/**
52794 + * This function is called when an EP is disabled due to disconnect or
52795 + * change in configuration. Any pending requests will terminate with a
52796 + * status of -ESHUTDOWN.
52797 + *
52798 + * This function modifies the dwc_otg_ep_t data structure for this EP,
52799 + * and then calls dwc_otg_ep_deactivate.
52800 + */
52801 +static int ep_disable(struct usb_ep *usb_ep)
52802 +{
52803 + int retval;
52804 +
52805 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
52806 + if (!usb_ep) {
52807 + DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
52808 + usb_ep ? usb_ep->name : NULL);
52809 + return -EINVAL;
52810 + }
52811 +
52812 + retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
52813 + if (retval) {
52814 + retval = -EINVAL;
52815 + }
52816 +
52817 + return retval;
52818 +}
52819 +
52820 +/**
52821 + * This function allocates a request object to use with the specified
52822 + * endpoint.
52823 + *
52824 + * @param ep The endpoint to be used with with the request
52825 + * @param gfp_flags the GFP_* flags to use.
52826 + */
52827 +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
52828 + gfp_t gfp_flags)
52829 +{
52830 + struct usb_request *usb_req;
52831 +
52832 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
52833 + if (0 == ep) {
52834 + DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
52835 + return 0;
52836 + }
52837 + usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
52838 + if (0 == usb_req) {
52839 + DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
52840 + return 0;
52841 + }
52842 + memset(usb_req, 0, sizeof(*usb_req));
52843 + usb_req->dma = DWC_DMA_ADDR_INVALID;
52844 +
52845 + return usb_req;
52846 +}
52847 +
52848 +/**
52849 + * This function frees a request object.
52850 + *
52851 + * @param ep The endpoint associated with the request
52852 + * @param req The request being freed
52853 + */
52854 +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
52855 +{
52856 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
52857 +
52858 + if (0 == ep || 0 == req) {
52859 + DWC_WARN("%s() %s\n", __func__,
52860 + "Invalid ep or req argument!\n");
52861 + return;
52862 + }
52863 +
52864 + kfree(req);
52865 +}
52866 +
52867 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52868 +/**
52869 + * This function allocates an I/O buffer to be used for a transfer
52870 + * to/from the specified endpoint.
52871 + *
52872 + * @param usb_ep The endpoint to be used with with the request
52873 + * @param bytes The desired number of bytes for the buffer
52874 + * @param dma Pointer to the buffer's DMA address; must be valid
52875 + * @param gfp_flags the GFP_* flags to use.
52876 + * @return address of a new buffer or null is buffer could not be allocated.
52877 + */
52878 +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
52879 + dma_addr_t * dma, gfp_t gfp_flags)
52880 +{
52881 + void *buf;
52882 + dwc_otg_pcd_t *pcd = 0;
52883 +
52884 + pcd = gadget_wrapper->pcd;
52885 +
52886 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
52887 + dma, gfp_flags);
52888 +
52889 + /* Check dword alignment */
52890 + if ((bytes & 0x3UL) != 0) {
52891 + DWC_WARN("%s() Buffer size is not a multiple of"
52892 + "DWORD size (%d)", __func__, bytes);
52893 + }
52894 +
52895 + buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
52896 +
52897 + /* Check dword alignment */
52898 + if (((int)buf & 0x3UL) != 0) {
52899 + DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
52900 + __func__, buf);
52901 + }
52902 +
52903 + return buf;
52904 +}
52905 +
52906 +/**
52907 + * This function frees an I/O buffer that was allocated by alloc_buffer.
52908 + *
52909 + * @param usb_ep the endpoint associated with the buffer
52910 + * @param buf address of the buffer
52911 + * @param dma The buffer's DMA address
52912 + * @param bytes The number of bytes of the buffer
52913 + */
52914 +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
52915 + dma_addr_t dma, unsigned bytes)
52916 +{
52917 + dwc_otg_pcd_t *pcd = 0;
52918 +
52919 + pcd = gadget_wrapper->pcd;
52920 +
52921 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
52922 +
52923 + dma_free_coherent(NULL, bytes, buf, dma);
52924 +}
52925 +#endif
52926 +
52927 +/**
52928 + * This function is used to submit an I/O Request to an EP.
52929 + *
52930 + * - When the request completes the request's completion callback
52931 + * is called to return the request to the driver.
52932 + * - An EP, except control EPs, may have multiple requests
52933 + * pending.
52934 + * - Once submitted the request cannot be examined or modified.
52935 + * - Each request is turned into one or more packets.
52936 + * - A BULK EP can queue any amount of data; the transfer is
52937 + * packetized.
52938 + * - Zero length Packets are specified with the request 'zero'
52939 + * flag.
52940 + */
52941 +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
52942 + gfp_t gfp_flags)
52943 +{
52944 + dwc_otg_pcd_t *pcd;
52945 + struct dwc_otg_pcd_ep *ep = NULL;
52946 + int retval = 0, is_isoc_ep = 0;
52947 + dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
52948 +
52949 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
52950 + __func__, usb_ep, usb_req, gfp_flags);
52951 +
52952 + if (!usb_req || !usb_req->complete || !usb_req->buf) {
52953 + DWC_WARN("bad params\n");
52954 + return -EINVAL;
52955 + }
52956 +
52957 + if (!usb_ep) {
52958 + DWC_WARN("bad ep\n");
52959 + return -EINVAL;
52960 + }
52961 +
52962 + pcd = gadget_wrapper->pcd;
52963 + if (!gadget_wrapper->driver ||
52964 + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52965 + DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52966 + gadget_wrapper->gadget.speed);
52967 + DWC_WARN("bogus device state\n");
52968 + return -ESHUTDOWN;
52969 + }
52970 +
52971 + DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
52972 + usb_ep->name, usb_req, usb_req->length, usb_req->buf);
52973 +
52974 + usb_req->status = -EINPROGRESS;
52975 + usb_req->actual = 0;
52976 +
52977 + ep = ep_from_handle(pcd, usb_ep);
52978 + if (ep == NULL)
52979 + is_isoc_ep = 0;
52980 + else
52981 + is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
52982 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52983 + dma_addr = usb_req->dma;
52984 +#else
52985 + if (GET_CORE_IF(pcd)->dma_enable) {
52986 + dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
52987 + struct device *dev = NULL;
52988 +
52989 + if (otg_dev != NULL)
52990 + dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
52991 +
52992 + if (usb_req->length != 0 &&
52993 + usb_req->dma == DWC_DMA_ADDR_INVALID) {
52994 + dma_addr = dma_map_single(dev, usb_req->buf,
52995 + usb_req->length,
52996 + ep->dwc_ep.is_in ?
52997 + DMA_TO_DEVICE:
52998 + DMA_FROM_DEVICE);
52999 + }
53000 + }
53001 +#endif
53002 +
53003 +#ifdef DWC_UTE_PER_IO
53004 + if (is_isoc_ep == 1) {
53005 + retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
53006 + usb_req->length, usb_req->zero, usb_req,
53007 + gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
53008 + if (retval)
53009 + return -EINVAL;
53010 +
53011 + return 0;
53012 + }
53013 +#endif
53014 + retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
53015 + usb_req->length, usb_req->zero, usb_req,
53016 + gfp_flags == GFP_ATOMIC ? 1 : 0);
53017 + if (retval) {
53018 + return -EINVAL;
53019 + }
53020 +
53021 + return 0;
53022 +}
53023 +
53024 +/**
53025 + * This function cancels an I/O request from an EP.
53026 + */
53027 +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
53028 +{
53029 + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
53030 +
53031 + if (!usb_ep || !usb_req) {
53032 + DWC_WARN("bad argument\n");
53033 + return -EINVAL;
53034 + }
53035 + if (!gadget_wrapper->driver ||
53036 + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
53037 + DWC_WARN("bogus device state\n");
53038 + return -ESHUTDOWN;
53039 + }
53040 + if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
53041 + return -EINVAL;
53042 + }
53043 +
53044 + return 0;
53045 +}
53046 +
53047 +/**
53048 + * usb_ep_set_halt stalls an endpoint.
53049 + *
53050 + * usb_ep_clear_halt clears an endpoint halt and resets its data
53051 + * toggle.
53052 + *
53053 + * Both of these functions are implemented with the same underlying
53054 + * function. The behavior depends on the value argument.
53055 + *
53056 + * @param[in] usb_ep the Endpoint to halt or clear halt.
53057 + * @param[in] value
53058 + * - 0 means clear_halt.
53059 + * - 1 means set_halt,
53060 + * - 2 means clear stall lock flag.
53061 + * - 3 means set stall lock flag.
53062 + */
53063 +static int ep_halt(struct usb_ep *usb_ep, int value)
53064 +{
53065 + int retval = 0;
53066 +
53067 + DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
53068 +
53069 + if (!usb_ep) {
53070 + DWC_WARN("bad ep\n");
53071 + return -EINVAL;
53072 + }
53073 +
53074 + retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
53075 + if (retval == -DWC_E_AGAIN) {
53076 + return -EAGAIN;
53077 + } else if (retval) {
53078 + retval = -EINVAL;
53079 + }
53080 +
53081 + return retval;
53082 +}
53083 +
53084 +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
53085 +#if 0
53086 +/**
53087 + * ep_wedge: sets the halt feature and ignores clear requests
53088 + *
53089 + * @usb_ep: the endpoint being wedged
53090 + *
53091 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
53092 + * requests. If the gadget driver clears the halt status, it will
53093 + * automatically unwedge the endpoint.
53094 + *
53095 + * Returns zero on success, else negative errno. *
53096 + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
53097 + */
53098 +static int ep_wedge(struct usb_ep *usb_ep)
53099 +{
53100 + int retval = 0;
53101 +
53102 + DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
53103 +
53104 + if (!usb_ep) {
53105 + DWC_WARN("bad ep\n");
53106 + return -EINVAL;
53107 + }
53108 +
53109 + retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
53110 + if (retval == -DWC_E_AGAIN) {
53111 + retval = -EAGAIN;
53112 + } else if (retval) {
53113 + retval = -EINVAL;
53114 + }
53115 +
53116 + return retval;
53117 +}
53118 +#endif
53119 +
53120 +#ifdef DWC_EN_ISOC
53121 +/**
53122 + * This function is used to submit an ISOC Transfer Request to an EP.
53123 + *
53124 + * - Every time a sync period completes the request's completion callback
53125 + * is called to provide data to the gadget driver.
53126 + * - Once submitted the request cannot be modified.
53127 + * - Each request is turned into periodic data packets untill ISO
53128 + * Transfer is stopped..
53129 + */
53130 +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
53131 + gfp_t gfp_flags)
53132 +{
53133 + int retval = 0;
53134 +
53135 + if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
53136 + DWC_WARN("bad params\n");
53137 + return -EINVAL;
53138 + }
53139 +
53140 + if (!usb_ep) {
53141 + DWC_PRINTF("bad params\n");
53142 + return -EINVAL;
53143 + }
53144 +
53145 + req->status = -EINPROGRESS;
53146 +
53147 + retval =
53148 + dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
53149 + req->buf1, req->dma0, req->dma1,
53150 + req->sync_frame, req->data_pattern_frame,
53151 + req->data_per_frame,
53152 + req->
53153 + flags & USB_REQ_ISO_ASAP ? -1 :
53154 + req->start_frame, req->buf_proc_intrvl,
53155 + req, gfp_flags == GFP_ATOMIC ? 1 : 0);
53156 +
53157 + if (retval) {
53158 + return -EINVAL;
53159 + }
53160 +
53161 + return retval;
53162 +}
53163 +
53164 +/**
53165 + * This function stops ISO EP Periodic Data Transfer.
53166 + */
53167 +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
53168 +{
53169 + int retval = 0;
53170 + if (!usb_ep) {
53171 + DWC_WARN("bad ep\n");
53172 + }
53173 +
53174 + if (!gadget_wrapper->driver ||
53175 + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
53176 + DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
53177 + gadget_wrapper->gadget.speed);
53178 + DWC_WARN("bogus device state\n");
53179 + }
53180 +
53181 + dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
53182 + if (retval) {
53183 + retval = -EINVAL;
53184 + }
53185 +
53186 + return retval;
53187 +}
53188 +
53189 +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
53190 + int packets, gfp_t gfp_flags)
53191 +{
53192 + struct usb_iso_request *pReq = NULL;
53193 + uint32_t req_size;
53194 +
53195 + req_size = sizeof(struct usb_iso_request);
53196 + req_size +=
53197 + (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
53198 +
53199 + pReq = kmalloc(req_size, gfp_flags);
53200 + if (!pReq) {
53201 + DWC_WARN("Can't allocate Iso Request\n");
53202 + return 0;
53203 + }
53204 + pReq->iso_packet_desc0 = (void *)(pReq + 1);
53205 +
53206 + pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
53207 +
53208 + return pReq;
53209 +}
53210 +
53211 +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
53212 +{
53213 + kfree(req);
53214 +}
53215 +
53216 +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
53217 + .ep_ops = {
53218 + .enable = ep_enable,
53219 + .disable = ep_disable,
53220 +
53221 + .alloc_request = dwc_otg_pcd_alloc_request,
53222 + .free_request = dwc_otg_pcd_free_request,
53223 +
53224 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
53225 + .alloc_buffer = dwc_otg_pcd_alloc_buffer,
53226 + .free_buffer = dwc_otg_pcd_free_buffer,
53227 +#endif
53228 +
53229 + .queue = ep_queue,
53230 + .dequeue = ep_dequeue,
53231 +
53232 + .set_halt = ep_halt,
53233 + .fifo_status = 0,
53234 + .fifo_flush = 0,
53235 + },
53236 + .iso_ep_start = iso_ep_start,
53237 + .iso_ep_stop = iso_ep_stop,
53238 + .alloc_iso_request = alloc_iso_request,
53239 + .free_iso_request = free_iso_request,
53240 +};
53241 +
53242 +#else
53243 +
53244 + int (*enable) (struct usb_ep *ep,
53245 + const struct usb_endpoint_descriptor *desc);
53246 + int (*disable) (struct usb_ep *ep);
53247 +
53248 + struct usb_request *(*alloc_request) (struct usb_ep *ep,
53249 + gfp_t gfp_flags);
53250 + void (*free_request) (struct usb_ep *ep, struct usb_request *req);
53251 +
53252 + int (*queue) (struct usb_ep *ep, struct usb_request *req,
53253 + gfp_t gfp_flags);
53254 + int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
53255 +
53256 + int (*set_halt) (struct usb_ep *ep, int value);
53257 + int (*set_wedge) (struct usb_ep *ep);
53258 +
53259 + int (*fifo_status) (struct usb_ep *ep);
53260 + void (*fifo_flush) (struct usb_ep *ep);
53261 +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
53262 + .enable = ep_enable,
53263 + .disable = ep_disable,
53264 +
53265 + .alloc_request = dwc_otg_pcd_alloc_request,
53266 + .free_request = dwc_otg_pcd_free_request,
53267 +
53268 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
53269 + .alloc_buffer = dwc_otg_pcd_alloc_buffer,
53270 + .free_buffer = dwc_otg_pcd_free_buffer,
53271 +#else
53272 + /* .set_wedge = ep_wedge, */
53273 + .set_wedge = NULL, /* uses set_halt instead */
53274 +#endif
53275 +
53276 + .queue = ep_queue,
53277 + .dequeue = ep_dequeue,
53278 +
53279 + .set_halt = ep_halt,
53280 + .fifo_status = 0,
53281 + .fifo_flush = 0,
53282 +
53283 +};
53284 +
53285 +#endif /* _EN_ISOC_ */
53286 +/* Gadget Operations */
53287 +/**
53288 + * The following gadget operations will be implemented in the DWC_otg
53289 + * PCD. Functions in the API that are not described below are not
53290 + * implemented.
53291 + *
53292 + * The Gadget API provides wrapper functions for each of the function
53293 + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
53294 + * wrapper function, which then calls the underlying PCD function. The
53295 + * following sections are named according to the wrapper functions
53296 + * (except for ioctl, which doesn't have a wrapper function). Within
53297 + * each section, the corresponding DWC_otg PCD function name is
53298 + * specified.
53299 + *
53300 + */
53301 +
53302 +/**
53303 + *Gets the USB Frame number of the last SOF.
53304 + */
53305 +static int get_frame_number(struct usb_gadget *gadget)
53306 +{
53307 + struct gadget_wrapper *d;
53308 +
53309 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53310 +
53311 + if (gadget == 0) {
53312 + return -ENODEV;
53313 + }
53314 +
53315 + d = container_of(gadget, struct gadget_wrapper, gadget);
53316 + return dwc_otg_pcd_get_frame_number(d->pcd);
53317 +}
53318 +
53319 +#ifdef CONFIG_USB_DWC_OTG_LPM
53320 +static int test_lpm_enabled(struct usb_gadget *gadget)
53321 +{
53322 + struct gadget_wrapper *d;
53323 +
53324 + d = container_of(gadget, struct gadget_wrapper, gadget);
53325 +
53326 + return dwc_otg_pcd_is_lpm_enabled(d->pcd);
53327 +}
53328 +#endif
53329 +
53330 +/**
53331 + * Initiates Session Request Protocol (SRP) to wakeup the host if no
53332 + * session is in progress. If a session is already in progress, but
53333 + * the device is suspended, remote wakeup signaling is started.
53334 + *
53335 + */
53336 +static int wakeup(struct usb_gadget *gadget)
53337 +{
53338 + struct gadget_wrapper *d;
53339 +
53340 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53341 +
53342 + if (gadget == 0) {
53343 + return -ENODEV;
53344 + } else {
53345 + d = container_of(gadget, struct gadget_wrapper, gadget);
53346 + }
53347 + dwc_otg_pcd_wakeup(d->pcd);
53348 + return 0;
53349 +}
53350 +
53351 +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
53352 + .get_frame = get_frame_number,
53353 + .wakeup = wakeup,
53354 +#ifdef CONFIG_USB_DWC_OTG_LPM
53355 + .lpm_support = test_lpm_enabled,
53356 +#endif
53357 + // current versions must always be self-powered
53358 +};
53359 +
53360 +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
53361 +{
53362 + int retval = -DWC_E_NOT_SUPPORTED;
53363 + if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
53364 + retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
53365 + (struct usb_ctrlrequest
53366 + *)bytes);
53367 + }
53368 +
53369 + if (retval == -ENOTSUPP) {
53370 + retval = -DWC_E_NOT_SUPPORTED;
53371 + } else if (retval < 0) {
53372 + retval = -DWC_E_INVALID;
53373 + }
53374 +
53375 + return retval;
53376 +}
53377 +
53378 +#ifdef DWC_EN_ISOC
53379 +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53380 + void *req_handle, int proc_buf_num)
53381 +{
53382 + int i, packet_count;
53383 + struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
53384 + struct usb_iso_request *iso_req = req_handle;
53385 +
53386 + if (proc_buf_num) {
53387 + iso_packet = iso_req->iso_packet_desc1;
53388 + } else {
53389 + iso_packet = iso_req->iso_packet_desc0;
53390 + }
53391 + packet_count =
53392 + dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
53393 + for (i = 0; i < packet_count; ++i) {
53394 + int status;
53395 + int actual;
53396 + int offset;
53397 + dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
53398 + i, &status, &actual, &offset);
53399 + switch (status) {
53400 + case -DWC_E_NO_DATA:
53401 + status = -ENODATA;
53402 + break;
53403 + default:
53404 + if (status) {
53405 + DWC_PRINTF("unknown status in isoc packet\n");
53406 + }
53407 +
53408 + }
53409 + iso_packet[i].status = status;
53410 + iso_packet[i].offset = offset;
53411 + iso_packet[i].actual_length = actual;
53412 + }
53413 +
53414 + iso_req->status = 0;
53415 + iso_req->process_buffer(ep_handle, iso_req);
53416 +
53417 + return 0;
53418 +}
53419 +#endif /* DWC_EN_ISOC */
53420 +
53421 +#ifdef DWC_UTE_PER_IO
53422 +/**
53423 + * Copy the contents of the extended request to the Linux usb_request's
53424 + * extended part and call the gadget's completion.
53425 + *
53426 + * @param pcd Pointer to the pcd structure
53427 + * @param ep_handle Void pointer to the usb_ep structure
53428 + * @param req_handle Void pointer to the usb_request structure
53429 + * @param status Request status returned from the portable logic
53430 + * @param ereq_port Void pointer to the extended request structure
53431 + * created in the the portable part that contains the
53432 + * results of the processed iso packets.
53433 + */
53434 +static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53435 + void *req_handle, int32_t status, void *ereq_port)
53436 +{
53437 + struct dwc_ute_iso_req_ext *ereqorg = NULL;
53438 + struct dwc_iso_xreq_port *ereqport = NULL;
53439 + struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
53440 + int i;
53441 + struct usb_request *req;
53442 + //struct dwc_ute_iso_packet_descriptor *
53443 + //int status = 0;
53444 +
53445 + req = (struct usb_request *)req_handle;
53446 + ereqorg = &req->ext_req;
53447 + ereqport = (struct dwc_iso_xreq_port *)ereq_port;
53448 + desc_org = ereqorg->per_io_frame_descs;
53449 +
53450 + if (req && req->complete) {
53451 + /* Copy the request data from the portable logic to our request */
53452 + for (i = 0; i < ereqport->pio_pkt_count; i++) {
53453 + desc_org[i].actual_length =
53454 + ereqport->per_io_frame_descs[i].actual_length;
53455 + desc_org[i].status =
53456 + ereqport->per_io_frame_descs[i].status;
53457 + }
53458 +
53459 + switch (status) {
53460 + case -DWC_E_SHUTDOWN:
53461 + req->status = -ESHUTDOWN;
53462 + break;
53463 + case -DWC_E_RESTART:
53464 + req->status = -ECONNRESET;
53465 + break;
53466 + case -DWC_E_INVALID:
53467 + req->status = -EINVAL;
53468 + break;
53469 + case -DWC_E_TIMEOUT:
53470 + req->status = -ETIMEDOUT;
53471 + break;
53472 + default:
53473 + req->status = status;
53474 + }
53475 +
53476 + /* And call the gadget's completion */
53477 + req->complete(ep_handle, req);
53478 + }
53479 +
53480 + return 0;
53481 +}
53482 +#endif /* DWC_UTE_PER_IO */
53483 +
53484 +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53485 + void *req_handle, int32_t status, uint32_t actual)
53486 +{
53487 + struct usb_request *req = (struct usb_request *)req_handle;
53488 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53489 + struct dwc_otg_pcd_ep *ep = NULL;
53490 +#endif
53491 +
53492 + if (req && req->complete) {
53493 + switch (status) {
53494 + case -DWC_E_SHUTDOWN:
53495 + req->status = -ESHUTDOWN;
53496 + break;
53497 + case -DWC_E_RESTART:
53498 + req->status = -ECONNRESET;
53499 + break;
53500 + case -DWC_E_INVALID:
53501 + req->status = -EINVAL;
53502 + break;
53503 + case -DWC_E_TIMEOUT:
53504 + req->status = -ETIMEDOUT;
53505 + break;
53506 + default:
53507 + req->status = status;
53508 +
53509 + }
53510 +
53511 + req->actual = actual;
53512 + DWC_SPINUNLOCK(pcd->lock);
53513 + req->complete(ep_handle, req);
53514 + DWC_SPINLOCK(pcd->lock);
53515 + }
53516 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53517 + ep = ep_from_handle(pcd, ep_handle);
53518 + if (GET_CORE_IF(pcd)->dma_enable) {
53519 + if (req->length != 0) {
53520 + dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
53521 + struct device *dev = NULL;
53522 +
53523 + if (otg_dev != NULL)
53524 + dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
53525 +
53526 + dma_unmap_single(dev, req->dma, req->length,
53527 + ep->dwc_ep.is_in ?
53528 + DMA_TO_DEVICE: DMA_FROM_DEVICE);
53529 + }
53530 + }
53531 +#endif
53532 +
53533 + return 0;
53534 +}
53535 +
53536 +static int _connect(dwc_otg_pcd_t * pcd, int speed)
53537 +{
53538 + gadget_wrapper->gadget.speed = speed;
53539 + return 0;
53540 +}
53541 +
53542 +static int _disconnect(dwc_otg_pcd_t * pcd)
53543 +{
53544 + if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
53545 + gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
53546 + }
53547 + return 0;
53548 +}
53549 +
53550 +static int _resume(dwc_otg_pcd_t * pcd)
53551 +{
53552 + if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
53553 + gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
53554 + }
53555 +
53556 + return 0;
53557 +}
53558 +
53559 +static int _suspend(dwc_otg_pcd_t * pcd)
53560 +{
53561 + if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
53562 + gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
53563 + }
53564 + return 0;
53565 +}
53566 +
53567 +/**
53568 + * This function updates the otg values in the gadget structure.
53569 + */
53570 +static int _hnp_changed(dwc_otg_pcd_t * pcd)
53571 +{
53572 +
53573 + if (!gadget_wrapper->gadget.is_otg)
53574 + return 0;
53575 +
53576 + gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
53577 + gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
53578 + gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
53579 + return 0;
53580 +}
53581 +
53582 +static int _reset(dwc_otg_pcd_t * pcd)
53583 +{
53584 + return 0;
53585 +}
53586 +
53587 +#ifdef DWC_UTE_CFI
53588 +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
53589 +{
53590 + int retval = -DWC_E_INVALID;
53591 + if (gadget_wrapper->driver->cfi_feature_setup) {
53592 + retval =
53593 + gadget_wrapper->driver->
53594 + cfi_feature_setup(&gadget_wrapper->gadget,
53595 + (struct cfi_usb_ctrlrequest *)cfi_req);
53596 + }
53597 +
53598 + return retval;
53599 +}
53600 +#endif
53601 +
53602 +static const struct dwc_otg_pcd_function_ops fops = {
53603 + .complete = _complete,
53604 +#ifdef DWC_EN_ISOC
53605 + .isoc_complete = _isoc_complete,
53606 +#endif
53607 + .setup = _setup,
53608 + .disconnect = _disconnect,
53609 + .connect = _connect,
53610 + .resume = _resume,
53611 + .suspend = _suspend,
53612 + .hnp_changed = _hnp_changed,
53613 + .reset = _reset,
53614 +#ifdef DWC_UTE_CFI
53615 + .cfi_setup = _cfi_setup,
53616 +#endif
53617 +#ifdef DWC_UTE_PER_IO
53618 + .xisoc_complete = _xisoc_complete,
53619 +#endif
53620 +};
53621 +
53622 +/**
53623 + * This function is the top level PCD interrupt handler.
53624 + */
53625 +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
53626 +{
53627 + dwc_otg_pcd_t *pcd = dev;
53628 + int32_t retval = IRQ_NONE;
53629 +
53630 + retval = dwc_otg_pcd_handle_intr(pcd);
53631 + if (retval != 0) {
53632 + S3C2410X_CLEAR_EINTPEND();
53633 + }
53634 + return IRQ_RETVAL(retval);
53635 +}
53636 +
53637 +/**
53638 + * This function initialized the usb_ep structures to there default
53639 + * state.
53640 + *
53641 + * @param d Pointer on gadget_wrapper.
53642 + */
53643 +void gadget_add_eps(struct gadget_wrapper *d)
53644 +{
53645 + static const char *names[] = {
53646 +
53647 + "ep0",
53648 + "ep1in",
53649 + "ep2in",
53650 + "ep3in",
53651 + "ep4in",
53652 + "ep5in",
53653 + "ep6in",
53654 + "ep7in",
53655 + "ep8in",
53656 + "ep9in",
53657 + "ep10in",
53658 + "ep11in",
53659 + "ep12in",
53660 + "ep13in",
53661 + "ep14in",
53662 + "ep15in",
53663 + "ep1out",
53664 + "ep2out",
53665 + "ep3out",
53666 + "ep4out",
53667 + "ep5out",
53668 + "ep6out",
53669 + "ep7out",
53670 + "ep8out",
53671 + "ep9out",
53672 + "ep10out",
53673 + "ep11out",
53674 + "ep12out",
53675 + "ep13out",
53676 + "ep14out",
53677 + "ep15out"
53678 + };
53679 +
53680 + int i;
53681 + struct usb_ep *ep;
53682 + int8_t dev_endpoints;
53683 +
53684 + DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
53685 +
53686 + INIT_LIST_HEAD(&d->gadget.ep_list);
53687 + d->gadget.ep0 = &d->ep0;
53688 + d->gadget.speed = USB_SPEED_UNKNOWN;
53689 +
53690 + INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
53691 +
53692 + /**
53693 + * Initialize the EP0 structure.
53694 + */
53695 + ep = &d->ep0;
53696 +
53697 + /* Init the usb_ep structure. */
53698 + ep->name = names[0];
53699 + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53700 +
53701 + /**
53702 + * @todo NGS: What should the max packet size be set to
53703 + * here? Before EP type is set?
53704 + */
53705 + ep->maxpacket = MAX_PACKET_SIZE;
53706 + dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
53707 +
53708 + list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53709 +
53710 + /**
53711 + * Initialize the EP structures.
53712 + */
53713 + dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
53714 +
53715 + for (i = 0; i < dev_endpoints; i++) {
53716 + ep = &d->in_ep[i];
53717 +
53718 + /* Init the usb_ep structure. */
53719 + ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
53720 + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53721 +
53722 + /**
53723 + * @todo NGS: What should the max packet size be set to
53724 + * here? Before EP type is set?
53725 + */
53726 + ep->maxpacket = MAX_PACKET_SIZE;
53727 + list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53728 + }
53729 +
53730 + dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
53731 +
53732 + for (i = 0; i < dev_endpoints; i++) {
53733 + ep = &d->out_ep[i];
53734 +
53735 + /* Init the usb_ep structure. */
53736 + ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
53737 + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53738 +
53739 + /**
53740 + * @todo NGS: What should the max packet size be set to
53741 + * here? Before EP type is set?
53742 + */
53743 + ep->maxpacket = MAX_PACKET_SIZE;
53744 +
53745 + list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53746 + }
53747 +
53748 + /* remove ep0 from the list. There is a ep0 pointer. */
53749 + list_del_init(&d->ep0.ep_list);
53750 +
53751 + d->ep0.maxpacket = MAX_EP0_SIZE;
53752 +}
53753 +
53754 +/**
53755 + * This function releases the Gadget device.
53756 + * required by device_unregister().
53757 + *
53758 + * @todo Should this do something? Should it free the PCD?
53759 + */
53760 +static void dwc_otg_pcd_gadget_release(struct device *dev)
53761 +{
53762 + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
53763 +}
53764 +
53765 +static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)
53766 +{
53767 + static char pcd_name[] = "dwc_otg_pcd";
53768 + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53769 + struct gadget_wrapper *d;
53770 + int retval;
53771 +
53772 + d = DWC_ALLOC(sizeof(*d));
53773 + if (d == NULL) {
53774 + return NULL;
53775 + }
53776 +
53777 + memset(d, 0, sizeof(*d));
53778 +
53779 + d->gadget.name = pcd_name;
53780 + d->pcd = otg_dev->pcd;
53781 +
53782 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
53783 + strcpy(d->gadget.dev.bus_id, "gadget");
53784 +#else
53785 + dev_set_name(&d->gadget.dev, "%s", "gadget");
53786 +#endif
53787 +
53788 + d->gadget.dev.parent = &_dev->dev;
53789 + d->gadget.dev.release = dwc_otg_pcd_gadget_release;
53790 + d->gadget.ops = &dwc_otg_pcd_ops;
53791 + d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;
53792 + d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
53793 +
53794 + d->driver = 0;
53795 + /* Register the gadget device */
53796 + retval = device_register(&d->gadget.dev);
53797 + if (retval != 0) {
53798 + DWC_ERROR("device_register failed\n");
53799 + DWC_FREE(d);
53800 + return NULL;
53801 + }
53802 +
53803 + return d;
53804 +}
53805 +
53806 +static void free_wrapper(struct gadget_wrapper *d)
53807 +{
53808 + if (d->driver) {
53809 + /* should have been done already by driver model core */
53810 + DWC_WARN("driver '%s' is still registered\n",
53811 + d->driver->driver.name);
53812 + usb_gadget_unregister_driver(d->driver);
53813 + }
53814 +
53815 + device_unregister(&d->gadget.dev);
53816 + DWC_FREE(d);
53817 +}
53818 +
53819 +/**
53820 + * This function initialized the PCD portion of the driver.
53821 + *
53822 + */
53823 +int pcd_init(dwc_bus_dev_t *_dev)
53824 +{
53825 + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53826 + int retval = 0;
53827 +
53828 + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
53829 +
53830 + otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
53831 +
53832 + if (!otg_dev->pcd) {
53833 + DWC_ERROR("dwc_otg_pcd_init failed\n");
53834 + return -ENOMEM;
53835 + }
53836 +
53837 + otg_dev->pcd->otg_dev = otg_dev;
53838 + gadget_wrapper = alloc_wrapper(_dev);
53839 +
53840 + /*
53841 + * Initialize EP structures
53842 + */
53843 + gadget_add_eps(gadget_wrapper);
53844 + /*
53845 + * Setup interupt handler
53846 + */
53847 +#ifdef PLATFORM_INTERFACE
53848 + DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53849 + platform_get_irq(_dev, 0));
53850 + retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
53851 + IRQF_SHARED, gadget_wrapper->gadget.name,
53852 + otg_dev->pcd);
53853 + if (retval != 0) {
53854 + DWC_ERROR("request of irq%d failed\n",
53855 + platform_get_irq(_dev, 0));
53856 + free_wrapper(gadget_wrapper);
53857 + return -EBUSY;
53858 + }
53859 +#else
53860 + DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53861 + _dev->irq);
53862 + retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
53863 + IRQF_SHARED | IRQF_DISABLED,
53864 + gadget_wrapper->gadget.name, otg_dev->pcd);
53865 + if (retval != 0) {
53866 + DWC_ERROR("request of irq%d failed\n", _dev->irq);
53867 + free_wrapper(gadget_wrapper);
53868 + return -EBUSY;
53869 + }
53870 +#endif
53871 +
53872 + dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
53873 +
53874 + return retval;
53875 +}
53876 +
53877 +/**
53878 + * Cleanup the PCD.
53879 + */
53880 +void pcd_remove(dwc_bus_dev_t *_dev)
53881 +{
53882 + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53883 + dwc_otg_pcd_t *pcd = otg_dev->pcd;
53884 +
53885 + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
53886 +
53887 + /*
53888 + * Free the IRQ
53889 + */
53890 +#ifdef PLATFORM_INTERFACE
53891 + free_irq(platform_get_irq(_dev, 0), pcd);
53892 +#else
53893 + free_irq(_dev->irq, pcd);
53894 +#endif
53895 + dwc_otg_pcd_remove(otg_dev->pcd);
53896 + free_wrapper(gadget_wrapper);
53897 + otg_dev->pcd = 0;
53898 +}
53899 +
53900 +/**
53901 + * This function registers a gadget driver with the PCD.
53902 + *
53903 + * When a driver is successfully registered, it will receive control
53904 + * requests including set_configuration(), which enables non-control
53905 + * requests. then usb traffic follows until a disconnect is reported.
53906 + * then a host may connect again, or the driver might get unbound.
53907 + *
53908 + * @param driver The driver being registered
53909 + * @param bind The bind function of gadget driver
53910 + */
53911 +
53912 +int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
53913 +{
53914 + int retval;
53915 +
53916 + DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
53917 + driver->driver.name);
53918 +
53919 + if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
53920 + !driver->bind ||
53921 + !driver->unbind || !driver->disconnect || !driver->setup) {
53922 + DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
53923 + return -EINVAL;
53924 + }
53925 + if (gadget_wrapper == 0) {
53926 + DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
53927 + return -ENODEV;
53928 + }
53929 + if (gadget_wrapper->driver != 0) {
53930 + DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
53931 + return -EBUSY;
53932 + }
53933 +
53934 + /* hook up the driver */
53935 + gadget_wrapper->driver = driver;
53936 + gadget_wrapper->gadget.dev.driver = &driver->driver;
53937 +
53938 + DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
53939 + retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);
53940 + if (retval) {
53941 + DWC_ERROR("bind to driver %s --> error %d\n",
53942 + driver->driver.name, retval);
53943 + gadget_wrapper->driver = 0;
53944 + gadget_wrapper->gadget.dev.driver = 0;
53945 + return retval;
53946 + }
53947 + DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
53948 + driver->driver.name);
53949 + return 0;
53950 +}
53951 +EXPORT_SYMBOL(usb_gadget_probe_driver);
53952 +
53953 +/**
53954 + * This function unregisters a gadget driver
53955 + *
53956 + * @param driver The driver being unregistered
53957 + */
53958 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
53959 +{
53960 + //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
53961 +
53962 + if (gadget_wrapper == 0) {
53963 + DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
53964 + -ENODEV);
53965 + return -ENODEV;
53966 + }
53967 + if (driver == 0 || driver != gadget_wrapper->driver) {
53968 + DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
53969 + -EINVAL);
53970 + return -EINVAL;
53971 + }
53972 +
53973 + driver->unbind(&gadget_wrapper->gadget);
53974 + gadget_wrapper->driver = 0;
53975 +
53976 + DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
53977 + return 0;
53978 +}
53979 +
53980 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
53981 +
53982 +#endif /* DWC_HOST_ONLY */
53983 diff -urN linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53984 --- linux-3.10/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100
53985 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2013-07-06 15:25:50.000000000 +0100
53986 @@ -0,0 +1,2550 @@
53987 +/* ==========================================================================
53988 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
53989 + * $Revision: #98 $
53990 + * $Date: 2012/08/10 $
53991 + * $Change: 2047372 $
53992 + *
53993 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
53994 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
53995 + * otherwise expressly agreed to in writing between Synopsys and you.
53996 + *
53997 + * The Software IS NOT an item of Licensed Software or Licensed Product under
53998 + * any End User Software License Agreement or Agreement for Licensed Product
53999 + * with Synopsys or any supplement thereto. You are permitted to use and
54000 + * redistribute this Software in source and binary forms, with or without
54001 + * modification, provided that redistributions of source code must retain this
54002 + * notice. You may not view, use, disclose, copy or distribute this file or
54003 + * any information contained herein except pursuant to this license grant from
54004 + * Synopsys. If you do not agree with this notice, including the disclaimer
54005 + * below, then you are not authorized to use the Software.
54006 + *
54007 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
54008 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54009 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54010 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
54011 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54012 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
54013 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54014 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54015 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54016 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
54017 + * DAMAGE.
54018 + * ========================================================================== */
54019 +
54020 +#ifndef __DWC_OTG_REGS_H__
54021 +#define __DWC_OTG_REGS_H__
54022 +
54023 +#include "dwc_otg_core_if.h"
54024 +
54025 +/**
54026 + * @file
54027 + *
54028 + * This file contains the data structures for accessing the DWC_otg core registers.
54029 + *
54030 + * The application interfaces with the HS OTG core by reading from and
54031 + * writing to the Control and Status Register (CSR) space through the
54032 + * AHB Slave interface. These registers are 32 bits wide, and the
54033 + * addresses are 32-bit-block aligned.
54034 + * CSRs are classified as follows:
54035 + * - Core Global Registers
54036 + * - Device Mode Registers
54037 + * - Device Global Registers
54038 + * - Device Endpoint Specific Registers
54039 + * - Host Mode Registers
54040 + * - Host Global Registers
54041 + * - Host Port CSRs
54042 + * - Host Channel Specific Registers
54043 + *
54044 + * Only the Core Global registers can be accessed in both Device and
54045 + * Host modes. When the HS OTG core is operating in one mode, either
54046 + * Device or Host, the application must not access registers from the
54047 + * other mode. When the core switches from one mode to another, the
54048 + * registers in the new mode of operation must be reprogrammed as they
54049 + * would be after a power-on reset.
54050 + */
54051 +
54052 +/****************************************************************************/
54053 +/** DWC_otg Core registers .
54054 + * The dwc_otg_core_global_regs structure defines the size
54055 + * and relative field offsets for the Core Global registers.
54056 + */
54057 +typedef struct dwc_otg_core_global_regs {
54058 + /** OTG Control and Status Register. <i>Offset: 000h</i> */
54059 + volatile uint32_t gotgctl;
54060 + /** OTG Interrupt Register. <i>Offset: 004h</i> */
54061 + volatile uint32_t gotgint;
54062 + /**Core AHB Configuration Register. <i>Offset: 008h</i> */
54063 + volatile uint32_t gahbcfg;
54064 +
54065 +#define DWC_GLBINTRMASK 0x0001
54066 +#define DWC_DMAENABLE 0x0020
54067 +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
54068 +#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000
54069 +#define DWC_PTXEMPTYLVL_EMPTY 0x0100
54070 +#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000
54071 +
54072 + /**Core USB Configuration Register. <i>Offset: 00Ch</i> */
54073 + volatile uint32_t gusbcfg;
54074 + /**Core Reset Register. <i>Offset: 010h</i> */
54075 + volatile uint32_t grstctl;
54076 + /**Core Interrupt Register. <i>Offset: 014h</i> */
54077 + volatile uint32_t gintsts;
54078 + /**Core Interrupt Mask Register. <i>Offset: 018h</i> */
54079 + volatile uint32_t gintmsk;
54080 + /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */
54081 + volatile uint32_t grxstsr;
54082 + /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/
54083 + volatile uint32_t grxstsp;
54084 + /**Receive FIFO Size Register. <i>Offset: 024h</i> */
54085 + volatile uint32_t grxfsiz;
54086 + /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */
54087 + volatile uint32_t gnptxfsiz;
54088 + /**Non Periodic Transmit FIFO/Queue Status Register (Read
54089 + * Only). <i>Offset: 02Ch</i> */
54090 + volatile uint32_t gnptxsts;
54091 + /**I2C Access Register. <i>Offset: 030h</i> */
54092 + volatile uint32_t gi2cctl;
54093 + /**PHY Vendor Control Register. <i>Offset: 034h</i> */
54094 + volatile uint32_t gpvndctl;
54095 + /**General Purpose Input/Output Register. <i>Offset: 038h</i> */
54096 + volatile uint32_t ggpio;
54097 + /**User ID Register. <i>Offset: 03Ch</i> */
54098 + volatile uint32_t guid;
54099 + /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */
54100 + volatile uint32_t gsnpsid;
54101 + /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */
54102 + volatile uint32_t ghwcfg1;
54103 + /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */
54104 + volatile uint32_t ghwcfg2;
54105 +#define DWC_SLAVE_ONLY_ARCH 0
54106 +#define DWC_EXT_DMA_ARCH 1
54107 +#define DWC_INT_DMA_ARCH 2
54108 +
54109 +#define DWC_MODE_HNP_SRP_CAPABLE 0
54110 +#define DWC_MODE_SRP_ONLY_CAPABLE 1
54111 +#define DWC_MODE_NO_HNP_SRP_CAPABLE 2
54112 +#define DWC_MODE_SRP_CAPABLE_DEVICE 3
54113 +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
54114 +#define DWC_MODE_SRP_CAPABLE_HOST 5
54115 +#define DWC_MODE_NO_SRP_CAPABLE_HOST 6
54116 +
54117 + /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */
54118 + volatile uint32_t ghwcfg3;
54119 + /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/
54120 + volatile uint32_t ghwcfg4;
54121 + /** Core LPM Configuration register <i>Offset: 054h</i>*/
54122 + volatile uint32_t glpmcfg;
54123 + /** Global PowerDn Register <i>Offset: 058h</i> */
54124 + volatile uint32_t gpwrdn;
54125 + /** Global DFIFO SW Config Register <i>Offset: 05Ch</i> */
54126 + volatile uint32_t gdfifocfg;
54127 + /** ADP Control Register <i>Offset: 060h</i> */
54128 + volatile uint32_t adpctl;
54129 + /** Reserved <i>Offset: 064h-0FFh</i> */
54130 + volatile uint32_t reserved39[39];
54131 + /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
54132 + volatile uint32_t hptxfsiz;
54133 + /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
54134 + otherwise Device Transmit FIFO#n Register.
54135 + * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
54136 + volatile uint32_t dtxfsiz[15];
54137 +} dwc_otg_core_global_regs_t;
54138 +
54139 +/**
54140 + * This union represents the bit fields of the Core OTG Control
54141 + * and Status Register (GOTGCTL). Set the bits using the bit
54142 + * fields then write the <i>d32</i> value to the register.
54143 + */
54144 +typedef union gotgctl_data {
54145 + /** raw register data */
54146 + uint32_t d32;
54147 + /** register bits */
54148 + struct {
54149 + unsigned sesreqscs:1;
54150 + unsigned sesreq:1;
54151 + unsigned vbvalidoven:1;
54152 + unsigned vbvalidovval:1;
54153 + unsigned avalidoven:1;
54154 + unsigned avalidovval:1;
54155 + unsigned bvalidoven:1;
54156 + unsigned bvalidovval:1;
54157 + unsigned hstnegscs:1;
54158 + unsigned hnpreq:1;
54159 + unsigned hstsethnpen:1;
54160 + unsigned devhnpen:1;
54161 + unsigned reserved12_15:4;
54162 + unsigned conidsts:1;
54163 + unsigned dbnctime:1;
54164 + unsigned asesvld:1;
54165 + unsigned bsesvld:1;
54166 + unsigned otgver:1;
54167 + unsigned reserved1:1;
54168 + unsigned multvalidbc:5;
54169 + unsigned chirpen:1;
54170 + unsigned reserved28_31:4;
54171 + } b;
54172 +} gotgctl_data_t;
54173 +
54174 +/**
54175 + * This union represents the bit fields of the Core OTG Interrupt Register
54176 + * (GOTGINT). Set/clear the bits using the bit fields then write the <i>d32</i>
54177 + * value to the register.
54178 + */
54179 +typedef union gotgint_data {
54180 + /** raw register data */
54181 + uint32_t d32;
54182 + /** register bits */
54183 + struct {
54184 + /** Current Mode */
54185 + unsigned reserved0_1:2;
54186 +
54187 + /** Session End Detected */
54188 + unsigned sesenddet:1;
54189 +
54190 + unsigned reserved3_7:5;
54191 +
54192 + /** Session Request Success Status Change */
54193 + unsigned sesreqsucstschng:1;
54194 + /** Host Negotiation Success Status Change */
54195 + unsigned hstnegsucstschng:1;
54196 +
54197 + unsigned reserved10_16:7;
54198 +
54199 + /** Host Negotiation Detected */
54200 + unsigned hstnegdet:1;
54201 + /** A-Device Timeout Change */
54202 + unsigned adevtoutchng:1;
54203 + /** Debounce Done */
54204 + unsigned debdone:1;
54205 + /** Multi-Valued input changed */
54206 + unsigned mvic:1;
54207 +
54208 + unsigned reserved31_21:11;
54209 +
54210 + } b;
54211 +} gotgint_data_t;
54212 +
54213 +/**
54214 + * This union represents the bit fields of the Core AHB Configuration
54215 + * Register (GAHBCFG). Set/clear the bits using the bit fields then
54216 + * write the <i>d32</i> value to the register.
54217 + */
54218 +typedef union gahbcfg_data {
54219 + /** raw register data */
54220 + uint32_t d32;
54221 + /** register bits */
54222 + struct {
54223 + unsigned glblintrmsk:1;
54224 +#define DWC_GAHBCFG_GLBINT_ENABLE 1
54225 +
54226 + unsigned hburstlen:4;
54227 +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0
54228 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1
54229 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3
54230 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5
54231 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7
54232 +
54233 + unsigned dmaenable:1;
54234 +#define DWC_GAHBCFG_DMAENABLE 1
54235 + unsigned reserved:1;
54236 + unsigned nptxfemplvl_txfemplvl:1;
54237 + unsigned ptxfemplvl:1;
54238 +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1
54239 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
54240 + unsigned reserved9_20:12;
54241 + unsigned remmemsupp:1;
54242 + unsigned notialldmawrit:1;
54243 + unsigned ahbsingle:1;
54244 + unsigned reserved24_31:8;
54245 + } b;
54246 +} gahbcfg_data_t;
54247 +
54248 +/**
54249 + * This union represents the bit fields of the Core USB Configuration
54250 + * Register (GUSBCFG). Set the bits using the bit fields then write
54251 + * the <i>d32</i> value to the register.
54252 + */
54253 +typedef union gusbcfg_data {
54254 + /** raw register data */
54255 + uint32_t d32;
54256 + /** register bits */
54257 + struct {
54258 + unsigned toutcal:3;
54259 + unsigned phyif:1;
54260 + unsigned ulpi_utmi_sel:1;
54261 + unsigned fsintf:1;
54262 + unsigned physel:1;
54263 + unsigned ddrsel:1;
54264 + unsigned srpcap:1;
54265 + unsigned hnpcap:1;
54266 + unsigned usbtrdtim:4;
54267 + unsigned reserved1:1;
54268 + unsigned phylpwrclksel:1;
54269 + unsigned otgutmifssel:1;
54270 + unsigned ulpi_fsls:1;
54271 + unsigned ulpi_auto_res:1;
54272 + unsigned ulpi_clk_sus_m:1;
54273 + unsigned ulpi_ext_vbus_drv:1;
54274 + unsigned ulpi_int_vbus_indicator:1;
54275 + unsigned term_sel_dl_pulse:1;
54276 + unsigned indicator_complement:1;
54277 + unsigned indicator_pass_through:1;
54278 + unsigned ulpi_int_prot_dis:1;
54279 + unsigned ic_usb_cap:1;
54280 + unsigned ic_traffic_pull_remove:1;
54281 + unsigned tx_end_delay:1;
54282 + unsigned force_host_mode:1;
54283 + unsigned force_dev_mode:1;
54284 + unsigned reserved31:1;
54285 + } b;
54286 +} gusbcfg_data_t;
54287 +
54288 +/**
54289 + * This union represents the bit fields of the Core Reset Register
54290 + * (GRSTCTL). Set/clear the bits using the bit fields then write the
54291 + * <i>d32</i> value to the register.
54292 + */
54293 +typedef union grstctl_data {
54294 + /** raw register data */
54295 + uint32_t d32;
54296 + /** register bits */
54297 + struct {
54298 + /** Core Soft Reset (CSftRst) (Device and Host)
54299 + *
54300 + * The application can flush the control logic in the
54301 + * entire core using this bit. This bit resets the
54302 + * pipelines in the AHB Clock domain as well as the
54303 + * PHY Clock domain.
54304 + *
54305 + * The state machines are reset to an IDLE state, the
54306 + * control bits in the CSRs are cleared, all the
54307 + * transmit FIFOs and the receive FIFO are flushed.
54308 + *
54309 + * The status mask bits that control the generation of
54310 + * the interrupt, are cleared, to clear the
54311 + * interrupt. The interrupt status bits are not
54312 + * cleared, so the application can get the status of
54313 + * any events that occurred in the core after it has
54314 + * set this bit.
54315 + *
54316 + * Any transactions on the AHB are terminated as soon
54317 + * as possible following the protocol. Any
54318 + * transactions on the USB are terminated immediately.
54319 + *
54320 + * The configuration settings in the CSRs are
54321 + * unchanged, so the software doesn't have to
54322 + * reprogram these registers (Device
54323 + * Configuration/Host Configuration/Core System
54324 + * Configuration/Core PHY Configuration).
54325 + *
54326 + * The application can write to this bit, any time it
54327 + * wants to reset the core. This is a self clearing
54328 + * bit and the core clears this bit after all the
54329 + * necessary logic is reset in the core, which may
54330 + * take several clocks, depending on the current state
54331 + * of the core.
54332 + */
54333 + unsigned csftrst:1;
54334 + /** Hclk Soft Reset
54335 + *
54336 + * The application uses this bit to reset the control logic in
54337 + * the AHB clock domain. Only AHB clock domain pipelines are
54338 + * reset.
54339 + */
54340 + unsigned hsftrst:1;
54341 + /** Host Frame Counter Reset (Host Only)<br>
54342 + *
54343 + * The application can reset the (micro)frame number
54344 + * counter inside the core, using this bit. When the
54345 + * (micro)frame counter is reset, the subsequent SOF
54346 + * sent out by the core, will have a (micro)frame
54347 + * number of 0.
54348 + */
54349 + unsigned hstfrm:1;
54350 + /** In Token Sequence Learning Queue Flush
54351 + * (INTknQFlsh) (Device Only)
54352 + */
54353 + unsigned intknqflsh:1;
54354 + /** RxFIFO Flush (RxFFlsh) (Device and Host)
54355 + *
54356 + * The application can flush the entire Receive FIFO
54357 + * using this bit. The application must first
54358 + * ensure that the core is not in the middle of a
54359 + * transaction. The application should write into
54360 + * this bit, only after making sure that neither the
54361 + * DMA engine is reading from the RxFIFO nor the MAC
54362 + * is writing the data in to the FIFO. The
54363 + * application should wait until the bit is cleared
54364 + * before performing any other operations. This bit
54365 + * will takes 8 clocks (slowest of PHY or AHB clock)
54366 + * to clear.
54367 + */
54368 + unsigned rxfflsh:1;
54369 + /** TxFIFO Flush (TxFFlsh) (Device and Host).
54370 + *
54371 + * This bit is used to selectively flush a single or
54372 + * all transmit FIFOs. The application must first
54373 + * ensure that the core is not in the middle of a
54374 + * transaction. The application should write into
54375 + * this bit, only after making sure that neither the
54376 + * DMA engine is writing into the TxFIFO nor the MAC
54377 + * is reading the data out of the FIFO. The
54378 + * application should wait until the core clears this
54379 + * bit, before performing any operations. This bit
54380 + * will takes 8 clocks (slowest of PHY or AHB clock)
54381 + * to clear.
54382 + */
54383 + unsigned txfflsh:1;
54384 +
54385 + /** TxFIFO Number (TxFNum) (Device and Host).
54386 + *
54387 + * This is the FIFO number which needs to be flushed,
54388 + * using the TxFIFO Flush bit. This field should not
54389 + * be changed until the TxFIFO Flush bit is cleared by
54390 + * the core.
54391 + * - 0x0 : Non Periodic TxFIFO Flush
54392 + * - 0x1 : Periodic TxFIFO #1 Flush in device mode
54393 + * or Periodic TxFIFO in host mode
54394 + * - 0x2 : Periodic TxFIFO #2 Flush in device mode.
54395 + * - ...
54396 + * - 0xF : Periodic TxFIFO #15 Flush in device mode
54397 + * - 0x10: Flush all the Transmit NonPeriodic and
54398 + * Transmit Periodic FIFOs in the core
54399 + */
54400 + unsigned txfnum:5;
54401 + /** Reserved */
54402 + unsigned reserved11_29:19;
54403 + /** DMA Request Signal. Indicated DMA request is in
54404 + * probress. Used for debug purpose. */
54405 + unsigned dmareq:1;
54406 + /** AHB Master Idle. Indicates the AHB Master State
54407 + * Machine is in IDLE condition. */
54408 + unsigned ahbidle:1;
54409 + } b;
54410 +} grstctl_t;
54411 +
54412 +/**
54413 + * This union represents the bit fields of the Core Interrupt Mask
54414 + * Register (GINTMSK). Set/clear the bits using the bit fields then
54415 + * write the <i>d32</i> value to the register.
54416 + */
54417 +typedef union gintmsk_data {
54418 + /** raw register data */
54419 + uint32_t d32;
54420 + /** register bits */
54421 + struct {
54422 + unsigned reserved0:1;
54423 + unsigned modemismatch:1;
54424 + unsigned otgintr:1;
54425 + unsigned sofintr:1;
54426 + unsigned rxstsqlvl:1;
54427 + unsigned nptxfempty:1;
54428 + unsigned ginnakeff:1;
54429 + unsigned goutnakeff:1;
54430 + unsigned ulpickint:1;
54431 + unsigned i2cintr:1;
54432 + unsigned erlysuspend:1;
54433 + unsigned usbsuspend:1;
54434 + unsigned usbreset:1;
54435 + unsigned enumdone:1;
54436 + unsigned isooutdrop:1;
54437 + unsigned eopframe:1;
54438 + unsigned restoredone:1;
54439 + unsigned epmismatch:1;
54440 + unsigned inepintr:1;
54441 + unsigned outepintr:1;
54442 + unsigned incomplisoin:1;
54443 + unsigned incomplisoout:1;
54444 + unsigned fetsusp:1;
54445 + unsigned resetdet:1;
54446 + unsigned portintr:1;
54447 + unsigned hcintr:1;
54448 + unsigned ptxfempty:1;
54449 + unsigned lpmtranrcvd:1;
54450 + unsigned conidstschng:1;
54451 + unsigned disconnect:1;
54452 + unsigned sessreqintr:1;
54453 + unsigned wkupintr:1;
54454 + } b;
54455 +} gintmsk_data_t;
54456 +/**
54457 + * This union represents the bit fields of the Core Interrupt Register
54458 + * (GINTSTS). Set/clear the bits using the bit fields then write the
54459 + * <i>d32</i> value to the register.
54460 + */
54461 +typedef union gintsts_data {
54462 + /** raw register data */
54463 + uint32_t d32;
54464 +#define DWC_SOF_INTR_MASK 0x0008
54465 + /** register bits */
54466 + struct {
54467 +#define DWC_HOST_MODE 1
54468 + unsigned curmode:1;
54469 + unsigned modemismatch:1;
54470 + unsigned otgintr:1;
54471 + unsigned sofintr:1;
54472 + unsigned rxstsqlvl:1;
54473 + unsigned nptxfempty:1;
54474 + unsigned ginnakeff:1;
54475 + unsigned goutnakeff:1;
54476 + unsigned ulpickint:1;
54477 + unsigned i2cintr:1;
54478 + unsigned erlysuspend:1;
54479 + unsigned usbsuspend:1;
54480 + unsigned usbreset:1;
54481 + unsigned enumdone:1;
54482 + unsigned isooutdrop:1;
54483 + unsigned eopframe:1;
54484 + unsigned restoredone:1;
54485 + unsigned epmismatch:1;
54486 + unsigned inepint:1;
54487 + unsigned outepintr:1;
54488 + unsigned incomplisoin:1;
54489 + unsigned incomplisoout:1;
54490 + unsigned fetsusp:1;
54491 + unsigned resetdet:1;
54492 + unsigned portintr:1;
54493 + unsigned hcintr:1;
54494 + unsigned ptxfempty:1;
54495 + unsigned lpmtranrcvd:1;
54496 + unsigned conidstschng:1;
54497 + unsigned disconnect:1;
54498 + unsigned sessreqintr:1;
54499 + unsigned wkupintr:1;
54500 + } b;
54501 +} gintsts_data_t;
54502 +
54503 +/**
54504 + * This union represents the bit fields in the Device Receive Status Read and
54505 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54506 + * element then read out the bits using the <i>b</i>it elements.
54507 + */
54508 +typedef union device_grxsts_data {
54509 + /** raw register data */
54510 + uint32_t d32;
54511 + /** register bits */
54512 + struct {
54513 + unsigned epnum:4;
54514 + unsigned bcnt:11;
54515 + unsigned dpid:2;
54516 +
54517 +#define DWC_STS_DATA_UPDT 0x2 // OUT Data Packet
54518 +#define DWC_STS_XFER_COMP 0x3 // OUT Data Transfer Complete
54519 +
54520 +#define DWC_DSTS_GOUT_NAK 0x1 // Global OUT NAK
54521 +#define DWC_DSTS_SETUP_COMP 0x4 // Setup Phase Complete
54522 +#define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet
54523 + unsigned pktsts:4;
54524 + unsigned fn:4;
54525 + unsigned reserved25_31:7;
54526 + } b;
54527 +} device_grxsts_data_t;
54528 +
54529 +/**
54530 + * This union represents the bit fields in the Host Receive Status Read and
54531 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54532 + * element then read out the bits using the <i>b</i>it elements.
54533 + */
54534 +typedef union host_grxsts_data {
54535 + /** raw register data */
54536 + uint32_t d32;
54537 + /** register bits */
54538 + struct {
54539 + unsigned chnum:4;
54540 + unsigned bcnt:11;
54541 + unsigned dpid:2;
54542 +
54543 + unsigned pktsts:4;
54544 +#define DWC_GRXSTS_PKTSTS_IN 0x2
54545 +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3
54546 +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
54547 +#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7
54548 +
54549 + unsigned reserved21_31:11;
54550 + } b;
54551 +} host_grxsts_data_t;
54552 +
54553 +/**
54554 + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
54555 + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element
54556 + * then read out the bits using the <i>b</i>it elements.
54557 + */
54558 +typedef union fifosize_data {
54559 + /** raw register data */
54560 + uint32_t d32;
54561 + /** register bits */
54562 + struct {
54563 + unsigned startaddr:16;
54564 + unsigned depth:16;
54565 + } b;
54566 +} fifosize_data_t;
54567 +
54568 +/**
54569 + * This union represents the bit fields in the Non-Periodic Transmit
54570 + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
54571 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54572 + * elements.
54573 + */
54574 +typedef union gnptxsts_data {
54575 + /** raw register data */
54576 + uint32_t d32;
54577 + /** register bits */
54578 + struct {
54579 + unsigned nptxfspcavail:16;
54580 + unsigned nptxqspcavail:8;
54581 + /** Top of the Non-Periodic Transmit Request Queue
54582 + * - bit 24 - Terminate (Last entry for the selected
54583 + * channel/EP)
54584 + * - bits 26:25 - Token Type
54585 + * - 2'b00 - IN/OUT
54586 + * - 2'b01 - Zero Length OUT
54587 + * - 2'b10 - PING/Complete Split
54588 + * - 2'b11 - Channel Halt
54589 + * - bits 30:27 - Channel/EP Number
54590 + */
54591 + unsigned nptxqtop_terminate:1;
54592 + unsigned nptxqtop_token:2;
54593 + unsigned nptxqtop_chnep:4;
54594 + unsigned reserved:1;
54595 + } b;
54596 +} gnptxsts_data_t;
54597 +
54598 +/**
54599 + * This union represents the bit fields in the Transmit
54600 + * FIFO Status Register (DTXFSTS). Read the register into the
54601 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54602 + * elements.
54603 + */
54604 +typedef union dtxfsts_data {
54605 + /** raw register data */
54606 + uint32_t d32;
54607 + /** register bits */
54608 + struct {
54609 + unsigned txfspcavail:16;
54610 + unsigned reserved:16;
54611 + } b;
54612 +} dtxfsts_data_t;
54613 +
54614 +/**
54615 + * This union represents the bit fields in the I2C Control Register
54616 + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
54617 + * bits using the <i>b</i>it elements.
54618 + */
54619 +typedef union gi2cctl_data {
54620 + /** raw register data */
54621 + uint32_t d32;
54622 + /** register bits */
54623 + struct {
54624 + unsigned rwdata:8;
54625 + unsigned regaddr:8;
54626 + unsigned addr:7;
54627 + unsigned i2cen:1;
54628 + unsigned ack:1;
54629 + unsigned i2csuspctl:1;
54630 + unsigned i2cdevaddr:2;
54631 + unsigned i2cdatse0:1;
54632 + unsigned reserved:1;
54633 + unsigned rw:1;
54634 + unsigned bsydne:1;
54635 + } b;
54636 +} gi2cctl_data_t;
54637 +
54638 +/**
54639 + * This union represents the bit fields in the PHY Vendor Control Register
54640 + * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the
54641 + * bits using the <i>b</i>it elements.
54642 + */
54643 +typedef union gpvndctl_data {
54644 + /** raw register data */
54645 + uint32_t d32;
54646 + /** register bits */
54647 + struct {
54648 + unsigned regdata:8;
54649 + unsigned vctrl:8;
54650 + unsigned regaddr16_21:6;
54651 + unsigned regwr:1;
54652 + unsigned reserved23_24:2;
54653 + unsigned newregreq:1;
54654 + unsigned vstsbsy:1;
54655 + unsigned vstsdone:1;
54656 + unsigned reserved28_30:3;
54657 + unsigned disulpidrvr:1;
54658 + } b;
54659 +} gpvndctl_data_t;
54660 +
54661 +/**
54662 + * This union represents the bit fields in the General Purpose
54663 + * Input/Output Register (GGPIO).
54664 + * Read the register into the <i>d32</i> element then read out the
54665 + * bits using the <i>b</i>it elements.
54666 + */
54667 +typedef union ggpio_data {
54668 + /** raw register data */
54669 + uint32_t d32;
54670 + /** register bits */
54671 + struct {
54672 + unsigned gpi:16;
54673 + unsigned gpo:16;
54674 + } b;
54675 +} ggpio_data_t;
54676 +
54677 +/**
54678 + * This union represents the bit fields in the User ID Register
54679 + * (GUID). Read the register into the <i>d32</i> element then read out the
54680 + * bits using the <i>b</i>it elements.
54681 + */
54682 +typedef union guid_data {
54683 + /** raw register data */
54684 + uint32_t d32;
54685 + /** register bits */
54686 + struct {
54687 + unsigned rwdata:32;
54688 + } b;
54689 +} guid_data_t;
54690 +
54691 +/**
54692 + * This union represents the bit fields in the Synopsys ID Register
54693 + * (GSNPSID). Read the register into the <i>d32</i> element then read out the
54694 + * bits using the <i>b</i>it elements.
54695 + */
54696 +typedef union gsnpsid_data {
54697 + /** raw register data */
54698 + uint32_t d32;
54699 + /** register bits */
54700 + struct {
54701 + unsigned rwdata:32;
54702 + } b;
54703 +} gsnpsid_data_t;
54704 +
54705 +/**
54706 + * This union represents the bit fields in the User HW Config1
54707 + * Register. Read the register into the <i>d32</i> element then read
54708 + * out the bits using the <i>b</i>it elements.
54709 + */
54710 +typedef union hwcfg1_data {
54711 + /** raw register data */
54712 + uint32_t d32;
54713 + /** register bits */
54714 + struct {
54715 + unsigned ep_dir0:2;
54716 + unsigned ep_dir1:2;
54717 + unsigned ep_dir2:2;
54718 + unsigned ep_dir3:2;
54719 + unsigned ep_dir4:2;
54720 + unsigned ep_dir5:2;
54721 + unsigned ep_dir6:2;
54722 + unsigned ep_dir7:2;
54723 + unsigned ep_dir8:2;
54724 + unsigned ep_dir9:2;
54725 + unsigned ep_dir10:2;
54726 + unsigned ep_dir11:2;
54727 + unsigned ep_dir12:2;
54728 + unsigned ep_dir13:2;
54729 + unsigned ep_dir14:2;
54730 + unsigned ep_dir15:2;
54731 + } b;
54732 +} hwcfg1_data_t;
54733 +
54734 +/**
54735 + * This union represents the bit fields in the User HW Config2
54736 + * Register. Read the register into the <i>d32</i> element then read
54737 + * out the bits using the <i>b</i>it elements.
54738 + */
54739 +typedef union hwcfg2_data {
54740 + /** raw register data */
54741 + uint32_t d32;
54742 + /** register bits */
54743 + struct {
54744 + /* GHWCFG2 */
54745 + unsigned op_mode:3;
54746 +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
54747 +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
54748 +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
54749 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
54750 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
54751 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
54752 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
54753 +
54754 + unsigned architecture:2;
54755 + unsigned point2point:1;
54756 + unsigned hs_phy_type:2;
54757 +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
54758 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
54759 +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
54760 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
54761 +
54762 + unsigned fs_phy_type:2;
54763 + unsigned num_dev_ep:4;
54764 + unsigned num_host_chan:4;
54765 + unsigned perio_ep_supported:1;
54766 + unsigned dynamic_fifo:1;
54767 + unsigned multi_proc_int:1;
54768 + unsigned reserved21:1;
54769 + unsigned nonperio_tx_q_depth:2;
54770 + unsigned host_perio_tx_q_depth:2;
54771 + unsigned dev_token_q_depth:5;
54772 + unsigned otg_enable_ic_usb:1;
54773 + } b;
54774 +} hwcfg2_data_t;
54775 +
54776 +/**
54777 + * This union represents the bit fields in the User HW Config3
54778 + * Register. Read the register into the <i>d32</i> element then read
54779 + * out the bits using the <i>b</i>it elements.
54780 + */
54781 +typedef union hwcfg3_data {
54782 + /** raw register data */
54783 + uint32_t d32;
54784 + /** register bits */
54785 + struct {
54786 + /* GHWCFG3 */
54787 + unsigned xfer_size_cntr_width:4;
54788 + unsigned packet_size_cntr_width:3;
54789 + unsigned otg_func:1;
54790 + unsigned i2c:1;
54791 + unsigned vendor_ctrl_if:1;
54792 + unsigned optional_features:1;
54793 + unsigned synch_reset_type:1;
54794 + unsigned adp_supp:1;
54795 + unsigned otg_enable_hsic:1;
54796 + unsigned bc_support:1;
54797 + unsigned otg_lpm_en:1;
54798 + unsigned dfifo_depth:16;
54799 + } b;
54800 +} hwcfg3_data_t;
54801 +
54802 +/**
54803 + * This union represents the bit fields in the User HW Config4
54804 + * Register. Read the register into the <i>d32</i> element then read
54805 + * out the bits using the <i>b</i>it elements.
54806 + */
54807 +typedef union hwcfg4_data {
54808 + /** raw register data */
54809 + uint32_t d32;
54810 + /** register bits */
54811 + struct {
54812 + unsigned num_dev_perio_in_ep:4;
54813 + unsigned power_optimiz:1;
54814 + unsigned min_ahb_freq:1;
54815 + unsigned hiber:1;
54816 + unsigned xhiber:1;
54817 + unsigned reserved:6;
54818 + unsigned utmi_phy_data_width:2;
54819 + unsigned num_dev_mode_ctrl_ep:4;
54820 + unsigned iddig_filt_en:1;
54821 + unsigned vbus_valid_filt_en:1;
54822 + unsigned a_valid_filt_en:1;
54823 + unsigned b_valid_filt_en:1;
54824 + unsigned session_end_filt_en:1;
54825 + unsigned ded_fifo_en:1;
54826 + unsigned num_in_eps:4;
54827 + unsigned desc_dma:1;
54828 + unsigned desc_dma_dyn:1;
54829 + } b;
54830 +} hwcfg4_data_t;
54831 +
54832 +/**
54833 + * This union represents the bit fields of the Core LPM Configuration
54834 + * Register (GLPMCFG). Set the bits using bit fields then write
54835 + * the <i>d32</i> value to the register.
54836 + */
54837 +typedef union glpmctl_data {
54838 + /** raw register data */
54839 + uint32_t d32;
54840 + /** register bits */
54841 + struct {
54842 + /** LPM-Capable (LPMCap) (Device and Host)
54843 + * The application uses this bit to control
54844 + * the DWC_otg core LPM capabilities.
54845 + */
54846 + unsigned lpm_cap_en:1;
54847 + /** LPM response programmed by application (AppL1Res) (Device)
54848 + * Handshake response to LPM token pre-programmed
54849 + * by device application software.
54850 + */
54851 + unsigned appl_resp:1;
54852 + /** Host Initiated Resume Duration (HIRD) (Device and Host)
54853 + * In Host mode this field indicates the value of HIRD
54854 + * to be sent in an LPM transaction.
54855 + * In Device mode this field is updated with the
54856 + * Received LPM Token HIRD bmAttribute
54857 + * when an ACK/NYET/STALL response is sent
54858 + * to an LPM transaction.
54859 + */
54860 + unsigned hird:4;
54861 + /** RemoteWakeEnable (bRemoteWake) (Device and Host)
54862 + * In Host mode this bit indicates the value of remote
54863 + * wake up to be sent in wIndex field of LPM transaction.
54864 + * In Device mode this field is updated with the
54865 + * Received LPM Token bRemoteWake bmAttribute
54866 + * when an ACK/NYET/STALL response is sent
54867 + * to an LPM transaction.
54868 + */
54869 + unsigned rem_wkup_en:1;
54870 + /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
54871 + * The application uses this bit to control
54872 + * the utmi_sleep_n assertion to the PHY when in L1 state.
54873 + */
54874 + unsigned en_utmi_sleep:1;
54875 + /** HIRD Threshold (HIRD_Thres) (Device and Host)
54876 + */
54877 + unsigned hird_thres:5;
54878 + /** LPM Response (CoreL1Res) (Device and Host)
54879 + * In Host mode this bit contains handsake response to
54880 + * LPM transaction.
54881 + * In Device mode the response of the core to
54882 + * LPM transaction received is reflected in these two bits.
54883 + - 0x0 : ERROR (No handshake response)
54884 + - 0x1 : STALL
54885 + - 0x2 : NYET
54886 + - 0x3 : ACK
54887 + */
54888 + unsigned lpm_resp:2;
54889 + /** Port Sleep Status (SlpSts) (Device and Host)
54890 + * This bit is set as long as a Sleep condition
54891 + * is present on the USB bus.
54892 + */
54893 + unsigned prt_sleep_sts:1;
54894 + /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
54895 + * Indicates that the application or host
54896 + * can start resume from Sleep state.
54897 + */
54898 + unsigned sleep_state_resumeok:1;
54899 + /** LPM channel Index (LPM_Chnl_Indx) (Host)
54900 + * The channel number on which the LPM transaction
54901 + * has to be applied while sending
54902 + * an LPM transaction to the local device.
54903 + */
54904 + unsigned lpm_chan_index:4;
54905 + /** LPM Retry Count (LPM_Retry_Cnt) (Host)
54906 + * Number host retries that would be performed
54907 + * if the device response was not valid response.
54908 + */
54909 + unsigned retry_count:3;
54910 + /** Send LPM Transaction (SndLPM) (Host)
54911 + * When set by application software,
54912 + * an LPM transaction containing two tokens
54913 + * is sent.
54914 + */
54915 + unsigned send_lpm:1;
54916 + /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
54917 + * Number of LPM Host Retries still remaining
54918 + * to be transmitted for the current LPM sequence
54919 + */
54920 + unsigned retry_count_sts:3;
54921 + unsigned reserved28_29:2;
54922 + /** In host mode once this bit is set, the host
54923 + * configures to drive the HSIC Idle state on the bus.
54924 + * It then waits for the device to initiate the Connect sequence.
54925 + * In device mode once this bit is set, the device waits for
54926 + * the HSIC Idle line state on the bus. Upon receving the Idle
54927 + * line state, it initiates the HSIC Connect sequence.
54928 + */
54929 + unsigned hsic_connect:1;
54930 + /** This bit overrides and functionally inverts
54931 + * the if_select_hsic input port signal.
54932 + */
54933 + unsigned inv_sel_hsic:1;
54934 + } b;
54935 +} glpmcfg_data_t;
54936 +
54937 +/**
54938 + * This union represents the bit fields of the Core ADP Timer, Control and
54939 + * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write
54940 + * the <i>d32</i> value to the register.
54941 + */
54942 +typedef union adpctl_data {
54943 + /** raw register data */
54944 + uint32_t d32;
54945 + /** register bits */
54946 + struct {
54947 + /** Probe Discharge (PRB_DSCHG)
54948 + * These bits set the times for TADP_DSCHG.
54949 + * These bits are defined as follows:
54950 + * 2'b00 - 4 msec
54951 + * 2'b01 - 8 msec
54952 + * 2'b10 - 16 msec
54953 + * 2'b11 - 32 msec
54954 + */
54955 + unsigned prb_dschg:2;
54956 + /** Probe Delta (PRB_DELTA)
54957 + * These bits set the resolution for RTIM value.
54958 + * The bits are defined in units of 32 kHz clock cycles as follows:
54959 + * 2'b00 - 1 cycles
54960 + * 2'b01 - 2 cycles
54961 + * 2'b10 - 3 cycles
54962 + * 2'b11 - 4 cycles
54963 + * For example if this value is chosen to 2'b01, it means that RTIM
54964 + * increments for every 3(three) 32Khz clock cycles.
54965 + */
54966 + unsigned prb_delta:2;
54967 + /** Probe Period (PRB_PER)
54968 + * These bits sets the TADP_PRD as shown in Figure 4 as follows:
54969 + * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec)
54970 + * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec)
54971 + * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec)
54972 + * 2'b11 - Reserved
54973 + */
54974 + unsigned prb_per:2;
54975 + /** These bits capture the latest time it took for VBUS to ramp from
54976 + * VADP_SINK to VADP_PRB.
54977 + * 0x000 - 1 cycles
54978 + * 0x001 - 2 cycles
54979 + * 0x002 - 3 cycles
54980 + * etc
54981 + * 0x7FF - 2048 cycles
54982 + * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.
54983 + */
54984 + unsigned rtim:11;
54985 + /** Enable Probe (EnaPrb)
54986 + * When programmed to 1'b1, the core performs a probe operation.
54987 + * This bit is valid only if OTG_Ver = 1'b1.
54988 + */
54989 + unsigned enaprb:1;
54990 + /** Enable Sense (EnaSns)
54991 + * When programmed to 1'b1, the core performs a Sense operation.
54992 + * This bit is valid only if OTG_Ver = 1'b1.
54993 + */
54994 + unsigned enasns:1;
54995 + /** ADP Reset (ADPRes)
54996 + * When set, ADP controller is reset.
54997 + * This bit is valid only if OTG_Ver = 1'b1.
54998 + */
54999 + unsigned adpres:1;
55000 + /** ADP Enable (ADPEn)
55001 + * When set, the core performs either ADP probing or sensing
55002 + * based on EnaPrb or EnaSns.
55003 + * This bit is valid only if OTG_Ver = 1'b1.
55004 + */
55005 + unsigned adpen:1;
55006 + /** ADP Probe Interrupt (ADP_PRB_INT)
55007 + * When this bit is set, it means that the VBUS
55008 + * voltage is greater than VADP_PRB or VADP_PRB is reached.
55009 + * This bit is valid only if OTG_Ver = 1'b1.
55010 + */
55011 + unsigned adp_prb_int:1;
55012 + /**
55013 + * ADP Sense Interrupt (ADP_SNS_INT)
55014 + * When this bit is set, it means that the VBUS voltage is greater than
55015 + * VADP_SNS value or VADP_SNS is reached.
55016 + * This bit is valid only if OTG_Ver = 1'b1.
55017 + */
55018 + unsigned adp_sns_int:1;
55019 + /** ADP Tomeout Interrupt (ADP_TMOUT_INT)
55020 + * This bit is relevant only for an ADP probe.
55021 + * When this bit is set, it means that the ramp time has
55022 + * completed ie ADPCTL.RTIM has reached its terminal value
55023 + * of 0x7FF. This is a debug feature that allows software
55024 + * to read the ramp time after each cycle.
55025 + * This bit is valid only if OTG_Ver = 1'b1.
55026 + */
55027 + unsigned adp_tmout_int:1;
55028 + /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)
55029 + * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.
55030 + * This bit is valid only if OTG_Ver = 1'b1.
55031 + */
55032 + unsigned adp_prb_int_msk:1;
55033 + /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)
55034 + * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.
55035 + * This bit is valid only if OTG_Ver = 1'b1.
55036 + */
55037 + unsigned adp_sns_int_msk:1;
55038 + /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)
55039 + * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.
55040 + * This bit is valid only if OTG_Ver = 1'b1.
55041 + */
55042 + unsigned adp_tmout_int_msk:1;
55043 + /** Access Request
55044 + * 2'b00 - Read/Write Valid (updated by the core)
55045 + * 2'b01 - Read
55046 + * 2'b00 - Write
55047 + * 2'b00 - Reserved
55048 + */
55049 + unsigned ar:2;
55050 + /** Reserved */
55051 + unsigned reserved29_31:3;
55052 + } b;
55053 +} adpctl_data_t;
55054 +
55055 +////////////////////////////////////////////
55056 +// Device Registers
55057 +/**
55058 + * Device Global Registers. <i>Offsets 800h-BFFh</i>
55059 + *
55060 + * The following structures define the size and relative field offsets
55061 + * for the Device Mode Registers.
55062 + *
55063 + * <i>These registers are visible only in Device mode and must not be
55064 + * accessed in Host mode, as the results are unknown.</i>
55065 + */
55066 +typedef struct dwc_otg_dev_global_regs {
55067 + /** Device Configuration Register. <i>Offset 800h</i> */
55068 + volatile uint32_t dcfg;
55069 + /** Device Control Register. <i>Offset: 804h</i> */
55070 + volatile uint32_t dctl;
55071 + /** Device Status Register (Read Only). <i>Offset: 808h</i> */
55072 + volatile uint32_t dsts;
55073 + /** Reserved. <i>Offset: 80Ch</i> */
55074 + uint32_t unused;
55075 + /** Device IN Endpoint Common Interrupt Mask
55076 + * Register. <i>Offset: 810h</i> */
55077 + volatile uint32_t diepmsk;
55078 + /** Device OUT Endpoint Common Interrupt Mask
55079 + * Register. <i>Offset: 814h</i> */
55080 + volatile uint32_t doepmsk;
55081 + /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */
55082 + volatile uint32_t daint;
55083 + /** Device All Endpoints Interrupt Mask Register. <i>Offset:
55084 + * 81Ch</i> */
55085 + volatile uint32_t daintmsk;
55086 + /** Device IN Token Queue Read Register-1 (Read Only).
55087 + * <i>Offset: 820h</i> */
55088 + volatile uint32_t dtknqr1;
55089 + /** Device IN Token Queue Read Register-2 (Read Only).
55090 + * <i>Offset: 824h</i> */
55091 + volatile uint32_t dtknqr2;
55092 + /** Device VBUS discharge Register. <i>Offset: 828h</i> */
55093 + volatile uint32_t dvbusdis;
55094 + /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */
55095 + volatile uint32_t dvbuspulse;
55096 + /** Device IN Token Queue Read Register-3 (Read Only). /
55097 + * Device Thresholding control register (Read/Write)
55098 + * <i>Offset: 830h</i> */
55099 + volatile uint32_t dtknqr3_dthrctl;
55100 + /** Device IN Token Queue Read Register-4 (Read Only). /
55101 + * Device IN EPs empty Inr. Mask Register (Read/Write)
55102 + * <i>Offset: 834h</i> */
55103 + volatile uint32_t dtknqr4_fifoemptymsk;
55104 + /** Device Each Endpoint Interrupt Register (Read Only). /
55105 + * <i>Offset: 838h</i> */
55106 + volatile uint32_t deachint;
55107 + /** Device Each Endpoint Interrupt mask Register (Read/Write). /
55108 + * <i>Offset: 83Ch</i> */
55109 + volatile uint32_t deachintmsk;
55110 + /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
55111 + * <i>Offset: 840h</i> */
55112 + volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
55113 + /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
55114 + * <i>Offset: 880h</i> */
55115 + volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
55116 +} dwc_otg_device_global_regs_t;
55117 +
55118 +/**
55119 + * This union represents the bit fields in the Device Configuration
55120 + * Register. Read the register into the <i>d32</i> member then
55121 + * set/clear the bits using the <i>b</i>it elements. Write the
55122 + * <i>d32</i> member to the dcfg register.
55123 + */
55124 +typedef union dcfg_data {
55125 + /** raw register data */
55126 + uint32_t d32;
55127 + /** register bits */
55128 + struct {
55129 + /** Device Speed */
55130 + unsigned devspd:2;
55131 + /** Non Zero Length Status OUT Handshake */
55132 + unsigned nzstsouthshk:1;
55133 +#define DWC_DCFG_SEND_STALL 1
55134 +
55135 + unsigned ena32khzs:1;
55136 + /** Device Addresses */
55137 + unsigned devaddr:7;
55138 + /** Periodic Frame Interval */
55139 + unsigned perfrint:2;
55140 +#define DWC_DCFG_FRAME_INTERVAL_80 0
55141 +#define DWC_DCFG_FRAME_INTERVAL_85 1
55142 +#define DWC_DCFG_FRAME_INTERVAL_90 2
55143 +#define DWC_DCFG_FRAME_INTERVAL_95 3
55144 +
55145 + /** Enable Device OUT NAK for bulk in DDMA mode */
55146 + unsigned endevoutnak:1;
55147 +
55148 + unsigned reserved14_17:4;
55149 + /** In Endpoint Mis-match count */
55150 + unsigned epmscnt:5;
55151 + /** Enable Descriptor DMA in Device mode */
55152 + unsigned descdma:1;
55153 + unsigned perschintvl:2;
55154 + unsigned resvalid:6;
55155 + } b;
55156 +} dcfg_data_t;
55157 +
55158 +/**
55159 + * This union represents the bit fields in the Device Control
55160 + * Register. Read the register into the <i>d32</i> member then
55161 + * set/clear the bits using the <i>b</i>it elements.
55162 + */
55163 +typedef union dctl_data {
55164 + /** raw register data */
55165 + uint32_t d32;
55166 + /** register bits */
55167 + struct {
55168 + /** Remote Wakeup */
55169 + unsigned rmtwkupsig:1;
55170 + /** Soft Disconnect */
55171 + unsigned sftdiscon:1;
55172 + /** Global Non-Periodic IN NAK Status */
55173 + unsigned gnpinnaksts:1;
55174 + /** Global OUT NAK Status */
55175 + unsigned goutnaksts:1;
55176 + /** Test Control */
55177 + unsigned tstctl:3;
55178 + /** Set Global Non-Periodic IN NAK */
55179 + unsigned sgnpinnak:1;
55180 + /** Clear Global Non-Periodic IN NAK */
55181 + unsigned cgnpinnak:1;
55182 + /** Set Global OUT NAK */
55183 + unsigned sgoutnak:1;
55184 + /** Clear Global OUT NAK */
55185 + unsigned cgoutnak:1;
55186 + /** Power-On Programming Done */
55187 + unsigned pwronprgdone:1;
55188 + /** Reserved */
55189 + unsigned reserved:1;
55190 + /** Global Multi Count */
55191 + unsigned gmc:2;
55192 + /** Ignore Frame Number for ISOC EPs */
55193 + unsigned ifrmnum:1;
55194 + /** NAK on Babble */
55195 + unsigned nakonbble:1;
55196 + /** Enable Continue on BNA */
55197 + unsigned encontonbna:1;
55198 +
55199 + unsigned reserved18_31:14;
55200 + } b;
55201 +} dctl_data_t;
55202 +
55203 +/**
55204 + * This union represents the bit fields in the Device Status
55205 + * Register. Read the register into the <i>d32</i> member then
55206 + * set/clear the bits using the <i>b</i>it elements.
55207 + */
55208 +typedef union dsts_data {
55209 + /** raw register data */
55210 + uint32_t d32;
55211 + /** register bits */
55212 + struct {
55213 + /** Suspend Status */
55214 + unsigned suspsts:1;
55215 + /** Enumerated Speed */
55216 + unsigned enumspd:2;
55217 +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
55218 +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
55219 +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2
55220 +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3
55221 + /** Erratic Error */
55222 + unsigned errticerr:1;
55223 + unsigned reserved4_7:4;
55224 + /** Frame or Microframe Number of the received SOF */
55225 + unsigned soffn:14;
55226 + unsigned reserved22_31:10;
55227 + } b;
55228 +} dsts_data_t;
55229 +
55230 +/**
55231 + * This union represents the bit fields in the Device IN EP Interrupt
55232 + * Register and the Device IN EP Common Mask Register.
55233 + *
55234 + * - Read the register into the <i>d32</i> member then set/clear the
55235 + * bits using the <i>b</i>it elements.
55236 + */
55237 +typedef union diepint_data {
55238 + /** raw register data */
55239 + uint32_t d32;
55240 + /** register bits */
55241 + struct {
55242 + /** Transfer complete mask */
55243 + unsigned xfercompl:1;
55244 + /** Endpoint disable mask */
55245 + unsigned epdisabled:1;
55246 + /** AHB Error mask */
55247 + unsigned ahberr:1;
55248 + /** TimeOUT Handshake mask (non-ISOC EPs) */
55249 + unsigned timeout:1;
55250 + /** IN Token received with TxF Empty mask */
55251 + unsigned intktxfemp:1;
55252 + /** IN Token Received with EP mismatch mask */
55253 + unsigned intknepmis:1;
55254 + /** IN Endpoint NAK Effective mask */
55255 + unsigned inepnakeff:1;
55256 + /** Reserved */
55257 + unsigned emptyintr:1;
55258 +
55259 + unsigned txfifoundrn:1;
55260 +
55261 + /** BNA Interrupt mask */
55262 + unsigned bna:1;
55263 +
55264 + unsigned reserved10_12:3;
55265 + /** BNA Interrupt mask */
55266 + unsigned nak:1;
55267 +
55268 + unsigned reserved14_31:18;
55269 + } b;
55270 +} diepint_data_t;
55271 +
55272 +/**
55273 + * This union represents the bit fields in the Device IN EP
55274 + * Common/Dedicated Interrupt Mask Register.
55275 + */
55276 +typedef union diepint_data diepmsk_data_t;
55277 +
55278 +/**
55279 + * This union represents the bit fields in the Device OUT EP Interrupt
55280 + * Registerand Device OUT EP Common Interrupt Mask Register.
55281 + *
55282 + * - Read the register into the <i>d32</i> member then set/clear the
55283 + * bits using the <i>b</i>it elements.
55284 + */
55285 +typedef union doepint_data {
55286 + /** raw register data */
55287 + uint32_t d32;
55288 + /** register bits */
55289 + struct {
55290 + /** Transfer complete */
55291 + unsigned xfercompl:1;
55292 + /** Endpoint disable */
55293 + unsigned epdisabled:1;
55294 + /** AHB Error */
55295 + unsigned ahberr:1;
55296 + /** Setup Phase Done (contorl EPs) */
55297 + unsigned setup:1;
55298 + /** OUT Token Received when Endpoint Disabled */
55299 + unsigned outtknepdis:1;
55300 +
55301 + unsigned stsphsercvd:1;
55302 + /** Back-to-Back SETUP Packets Received */
55303 + unsigned back2backsetup:1;
55304 +
55305 + unsigned reserved7:1;
55306 + /** OUT packet Error */
55307 + unsigned outpkterr:1;
55308 + /** BNA Interrupt */
55309 + unsigned bna:1;
55310 +
55311 + unsigned reserved10:1;
55312 + /** Packet Drop Status */
55313 + unsigned pktdrpsts:1;
55314 + /** Babble Interrupt */
55315 + unsigned babble:1;
55316 + /** NAK Interrupt */
55317 + unsigned nak:1;
55318 + /** NYET Interrupt */
55319 + unsigned nyet:1;
55320 + /** Bit indicating setup packet received */
55321 + unsigned sr:1;
55322 +
55323 + unsigned reserved16_31:16;
55324 + } b;
55325 +} doepint_data_t;
55326 +
55327 +/**
55328 + * This union represents the bit fields in the Device OUT EP
55329 + * Common/Dedicated Interrupt Mask Register.
55330 + */
55331 +typedef union doepint_data doepmsk_data_t;
55332 +
55333 +/**
55334 + * This union represents the bit fields in the Device All EP Interrupt
55335 + * and Mask Registers.
55336 + * - Read the register into the <i>d32</i> member then set/clear the
55337 + * bits using the <i>b</i>it elements.
55338 + */
55339 +typedef union daint_data {
55340 + /** raw register data */
55341 + uint32_t d32;
55342 + /** register bits */
55343 + struct {
55344 + /** IN Endpoint bits */
55345 + unsigned in:16;
55346 + /** OUT Endpoint bits */
55347 + unsigned out:16;
55348 + } ep;
55349 + struct {
55350 + /** IN Endpoint bits */
55351 + unsigned inep0:1;
55352 + unsigned inep1:1;
55353 + unsigned inep2:1;
55354 + unsigned inep3:1;
55355 + unsigned inep4:1;
55356 + unsigned inep5:1;
55357 + unsigned inep6:1;
55358 + unsigned inep7:1;
55359 + unsigned inep8:1;
55360 + unsigned inep9:1;
55361 + unsigned inep10:1;
55362 + unsigned inep11:1;
55363 + unsigned inep12:1;
55364 + unsigned inep13:1;
55365 + unsigned inep14:1;
55366 + unsigned inep15:1;
55367 + /** OUT Endpoint bits */
55368 + unsigned outep0:1;
55369 + unsigned outep1:1;
55370 + unsigned outep2:1;
55371 + unsigned outep3:1;
55372 + unsigned outep4:1;
55373 + unsigned outep5:1;
55374 + unsigned outep6:1;
55375 + unsigned outep7:1;
55376 + unsigned outep8:1;
55377 + unsigned outep9:1;
55378 + unsigned outep10:1;
55379 + unsigned outep11:1;
55380 + unsigned outep12:1;
55381 + unsigned outep13:1;
55382 + unsigned outep14:1;
55383 + unsigned outep15:1;
55384 + } b;
55385 +} daint_data_t;
55386 +
55387 +/**
55388 + * This union represents the bit fields in the Device IN Token Queue
55389 + * Read Registers.
55390 + * - Read the register into the <i>d32</i> member.
55391 + * - READ-ONLY Register
55392 + */
55393 +typedef union dtknq1_data {
55394 + /** raw register data */
55395 + uint32_t d32;
55396 + /** register bits */
55397 + struct {
55398 + /** In Token Queue Write Pointer */
55399 + unsigned intknwptr:5;
55400 + /** Reserved */
55401 + unsigned reserved05_06:2;
55402 + /** write pointer has wrapped. */
55403 + unsigned wrap_bit:1;
55404 + /** EP Numbers of IN Tokens 0 ... 4 */
55405 + unsigned epnums0_5:24;
55406 + } b;
55407 +} dtknq1_data_t;
55408 +
55409 +/**
55410 + * This union represents Threshold control Register
55411 + * - Read and write the register into the <i>d32</i> member.
55412 + * - READ-WRITABLE Register
55413 + */
55414 +typedef union dthrctl_data {
55415 + /** raw register data */
55416 + uint32_t d32;
55417 + /** register bits */
55418 + struct {
55419 + /** non ISO Tx Thr. Enable */
55420 + unsigned non_iso_thr_en:1;
55421 + /** ISO Tx Thr. Enable */
55422 + unsigned iso_thr_en:1;
55423 + /** Tx Thr. Length */
55424 + unsigned tx_thr_len:9;
55425 + /** AHB Threshold ratio */
55426 + unsigned ahb_thr_ratio:2;
55427 + /** Reserved */
55428 + unsigned reserved13_15:3;
55429 + /** Rx Thr. Enable */
55430 + unsigned rx_thr_en:1;
55431 + /** Rx Thr. Length */
55432 + unsigned rx_thr_len:9;
55433 + unsigned reserved26:1;
55434 + /** Arbiter Parking Enable*/
55435 + unsigned arbprken:1;
55436 + /** Reserved */
55437 + unsigned reserved28_31:4;
55438 + } b;
55439 +} dthrctl_data_t;
55440 +
55441 +/**
55442 + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
55443 + * 900h-AFCh</i>
55444 + *
55445 + * There will be one set of endpoint registers per logical endpoint
55446 + * implemented.
55447 + *
55448 + * <i>These registers are visible only in Device mode and must not be
55449 + * accessed in Host mode, as the results are unknown.</i>
55450 + */
55451 +typedef struct dwc_otg_dev_in_ep_regs {
55452 + /** Device IN Endpoint Control Register. <i>Offset:900h +
55453 + * (ep_num * 20h) + 00h</i> */
55454 + volatile uint32_t diepctl;
55455 + /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
55456 + uint32_t reserved04;
55457 + /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
55458 + * (ep_num * 20h) + 08h</i> */
55459 + volatile uint32_t diepint;
55460 + /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
55461 + uint32_t reserved0C;
55462 + /** Device IN Endpoint Transfer Size
55463 + * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
55464 + volatile uint32_t dieptsiz;
55465 + /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
55466 + * (ep_num * 20h) + 14h</i> */
55467 + volatile uint32_t diepdma;
55468 + /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
55469 + * (ep_num * 20h) + 18h</i> */
55470 + volatile uint32_t dtxfsts;
55471 + /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
55472 + * (ep_num * 20h) + 1Ch</i> */
55473 + volatile uint32_t diepdmab;
55474 +} dwc_otg_dev_in_ep_regs_t;
55475 +
55476 +/**
55477 + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
55478 + * B00h-CFCh</i>
55479 + *
55480 + * There will be one set of endpoint registers per logical endpoint
55481 + * implemented.
55482 + *
55483 + * <i>These registers are visible only in Device mode and must not be
55484 + * accessed in Host mode, as the results are unknown.</i>
55485 + */
55486 +typedef struct dwc_otg_dev_out_ep_regs {
55487 + /** Device OUT Endpoint Control Register. <i>Offset:B00h +
55488 + * (ep_num * 20h) + 00h</i> */
55489 + volatile uint32_t doepctl;
55490 + /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
55491 + uint32_t reserved04;
55492 + /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
55493 + * (ep_num * 20h) + 08h</i> */
55494 + volatile uint32_t doepint;
55495 + /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
55496 + uint32_t reserved0C;
55497 + /** Device OUT Endpoint Transfer Size Register. <i>Offset:
55498 + * B00h + (ep_num * 20h) + 10h</i> */
55499 + volatile uint32_t doeptsiz;
55500 + /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
55501 + * + (ep_num * 20h) + 14h</i> */
55502 + volatile uint32_t doepdma;
55503 + /** Reserved. <i>Offset:B00h + * (ep_num * 20h) + 18h</i> */
55504 + uint32_t unused;
55505 + /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
55506 + * + (ep_num * 20h) + 1Ch</i> */
55507 + uint32_t doepdmab;
55508 +} dwc_otg_dev_out_ep_regs_t;
55509 +
55510 +/**
55511 + * This union represents the bit fields in the Device EP Control
55512 + * Register. Read the register into the <i>d32</i> member then
55513 + * set/clear the bits using the <i>b</i>it elements.
55514 + */
55515 +typedef union depctl_data {
55516 + /** raw register data */
55517 + uint32_t d32;
55518 + /** register bits */
55519 + struct {
55520 + /** Maximum Packet Size
55521 + * IN/OUT EPn
55522 + * IN/OUT EP0 - 2 bits
55523 + * 2'b00: 64 Bytes
55524 + * 2'b01: 32
55525 + * 2'b10: 16
55526 + * 2'b11: 8 */
55527 + unsigned mps:11;
55528 +#define DWC_DEP0CTL_MPS_64 0
55529 +#define DWC_DEP0CTL_MPS_32 1
55530 +#define DWC_DEP0CTL_MPS_16 2
55531 +#define DWC_DEP0CTL_MPS_8 3
55532 +
55533 + /** Next Endpoint
55534 + * IN EPn/IN EP0
55535 + * OUT EPn/OUT EP0 - reserved */
55536 + unsigned nextep:4;
55537 +
55538 + /** USB Active Endpoint */
55539 + unsigned usbactep:1;
55540 +
55541 + /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
55542 + * This field contains the PID of the packet going to
55543 + * be received or transmitted on this endpoint. The
55544 + * application should program the PID of the first
55545 + * packet going to be received or transmitted on this
55546 + * endpoint , after the endpoint is
55547 + * activated. Application use the SetD1PID and
55548 + * SetD0PID fields of this register to program either
55549 + * D0 or D1 PID.
55550 + *
55551 + * The encoding for this field is
55552 + * - 0: D0
55553 + * - 1: D1
55554 + */
55555 + unsigned dpid:1;
55556 +
55557 + /** NAK Status */
55558 + unsigned naksts:1;
55559 +
55560 + /** Endpoint Type
55561 + * 2'b00: Control
55562 + * 2'b01: Isochronous
55563 + * 2'b10: Bulk
55564 + * 2'b11: Interrupt */
55565 + unsigned eptype:2;
55566 +
55567 + /** Snoop Mode
55568 + * OUT EPn/OUT EP0
55569 + * IN EPn/IN EP0 - reserved */
55570 + unsigned snp:1;
55571 +
55572 + /** Stall Handshake */
55573 + unsigned stall:1;
55574 +
55575 + /** Tx Fifo Number
55576 + * IN EPn/IN EP0
55577 + * OUT EPn/OUT EP0 - reserved */
55578 + unsigned txfnum:4;
55579 +
55580 + /** Clear NAK */
55581 + unsigned cnak:1;
55582 + /** Set NAK */
55583 + unsigned snak:1;
55584 + /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
55585 + * Writing to this field sets the Endpoint DPID (DPID)
55586 + * field in this register to DATA0. Set Even
55587 + * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
55588 + * Writing to this field sets the Even/Odd
55589 + * (micro)frame (EO_FrNum) field to even (micro)
55590 + * frame.
55591 + */
55592 + unsigned setd0pid:1;
55593 + /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
55594 + * Writing to this field sets the Endpoint DPID (DPID)
55595 + * field in this register to DATA1 Set Odd
55596 + * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
55597 + * Writing to this field sets the Even/Odd
55598 + * (micro)frame (EO_FrNum) field to odd (micro) frame.
55599 + */
55600 + unsigned setd1pid:1;
55601 +
55602 + /** Endpoint Disable */
55603 + unsigned epdis:1;
55604 + /** Endpoint Enable */
55605 + unsigned epena:1;
55606 + } b;
55607 +} depctl_data_t;
55608 +
55609 +/**
55610 + * This union represents the bit fields in the Device EP Transfer
55611 + * Size Register. Read the register into the <i>d32</i> member then
55612 + * set/clear the bits using the <i>b</i>it elements.
55613 + */
55614 +typedef union deptsiz_data {
55615 + /** raw register data */
55616 + uint32_t d32;
55617 + /** register bits */
55618 + struct {
55619 + /** Transfer size */
55620 + unsigned xfersize:19;
55621 +/** Max packet count for EP (pow(2,10)-1) */
55622 +#define MAX_PKT_CNT 1023
55623 + /** Packet Count */
55624 + unsigned pktcnt:10;
55625 + /** Multi Count - Periodic IN endpoints */
55626 + unsigned mc:2;
55627 + unsigned reserved:1;
55628 + } b;
55629 +} deptsiz_data_t;
55630 +
55631 +/**
55632 + * This union represents the bit fields in the Device EP 0 Transfer
55633 + * Size Register. Read the register into the <i>d32</i> member then
55634 + * set/clear the bits using the <i>b</i>it elements.
55635 + */
55636 +typedef union deptsiz0_data {
55637 + /** raw register data */
55638 + uint32_t d32;
55639 + /** register bits */
55640 + struct {
55641 + /** Transfer size */
55642 + unsigned xfersize:7;
55643 + /** Reserved */
55644 + unsigned reserved7_18:12;
55645 + /** Packet Count */
55646 + unsigned pktcnt:2;
55647 + /** Reserved */
55648 + unsigned reserved21_28:8;
55649 + /**Setup Packet Count (DOEPTSIZ0 Only) */
55650 + unsigned supcnt:2;
55651 + unsigned reserved31;
55652 + } b;
55653 +} deptsiz0_data_t;
55654 +
55655 +/////////////////////////////////////////////////
55656 +// DMA Descriptor Specific Structures
55657 +//
55658 +
55659 +/** Buffer status definitions */
55660 +
55661 +#define BS_HOST_READY 0x0
55662 +#define BS_DMA_BUSY 0x1
55663 +#define BS_DMA_DONE 0x2
55664 +#define BS_HOST_BUSY 0x3
55665 +
55666 +/** Receive/Transmit status definitions */
55667 +
55668 +#define RTS_SUCCESS 0x0
55669 +#define RTS_BUFFLUSH 0x1
55670 +#define RTS_RESERVED 0x2
55671 +#define RTS_BUFERR 0x3
55672 +
55673 +/**
55674 + * This union represents the bit fields in the DMA Descriptor
55675 + * status quadlet. Read the quadlet into the <i>d32</i> member then
55676 + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
55677 + * <i>b_iso_in</i> elements.
55678 + */
55679 +typedef union dev_dma_desc_sts {
55680 + /** raw register data */
55681 + uint32_t d32;
55682 + /** quadlet bits */
55683 + struct {
55684 + /** Received number of bytes */
55685 + unsigned bytes:16;
55686 + /** NAK bit - only for OUT EPs */
55687 + unsigned nak:1;
55688 + unsigned reserved17_22:6;
55689 + /** Multiple Transfer - only for OUT EPs */
55690 + unsigned mtrf:1;
55691 + /** Setup Packet received - only for OUT EPs */
55692 + unsigned sr:1;
55693 + /** Interrupt On Complete */
55694 + unsigned ioc:1;
55695 + /** Short Packet */
55696 + unsigned sp:1;
55697 + /** Last */
55698 + unsigned l:1;
55699 + /** Receive Status */
55700 + unsigned sts:2;
55701 + /** Buffer Status */
55702 + unsigned bs:2;
55703 + } b;
55704 +
55705 +//#ifdef DWC_EN_ISOC
55706 + /** iso out quadlet bits */
55707 + struct {
55708 + /** Received number of bytes */
55709 + unsigned rxbytes:11;
55710 +
55711 + unsigned reserved11:1;
55712 + /** Frame Number */
55713 + unsigned framenum:11;
55714 + /** Received ISO Data PID */
55715 + unsigned pid:2;
55716 + /** Interrupt On Complete */
55717 + unsigned ioc:1;
55718 + /** Short Packet */
55719 + unsigned sp:1;
55720 + /** Last */
55721 + unsigned l:1;
55722 + /** Receive Status */
55723 + unsigned rxsts:2;
55724 + /** Buffer Status */
55725 + unsigned bs:2;
55726 + } b_iso_out;
55727 +
55728 + /** iso in quadlet bits */
55729 + struct {
55730 + /** Transmited number of bytes */
55731 + unsigned txbytes:12;
55732 + /** Frame Number */
55733 + unsigned framenum:11;
55734 + /** Transmited ISO Data PID */
55735 + unsigned pid:2;
55736 + /** Interrupt On Complete */
55737 + unsigned ioc:1;
55738 + /** Short Packet */
55739 + unsigned sp:1;
55740 + /** Last */
55741 + unsigned l:1;
55742 + /** Transmit Status */
55743 + unsigned txsts:2;
55744 + /** Buffer Status */
55745 + unsigned bs:2;
55746 + } b_iso_in;
55747 +//#endif /* DWC_EN_ISOC */
55748 +} dev_dma_desc_sts_t;
55749 +
55750 +/**
55751 + * DMA Descriptor structure
55752 + *
55753 + * DMA Descriptor structure contains two quadlets:
55754 + * Status quadlet and Data buffer pointer.
55755 + */
55756 +typedef struct dwc_otg_dev_dma_desc {
55757 + /** DMA Descriptor status quadlet */
55758 + dev_dma_desc_sts_t status;
55759 + /** DMA Descriptor data buffer pointer */
55760 + uint32_t buf;
55761 +} dwc_otg_dev_dma_desc_t;
55762 +
55763 +/**
55764 + * The dwc_otg_dev_if structure contains information needed to manage
55765 + * the DWC_otg controller acting in device mode. It represents the
55766 + * programming view of the device-specific aspects of the controller.
55767 + */
55768 +typedef struct dwc_otg_dev_if {
55769 + /** Pointer to device Global registers.
55770 + * Device Global Registers starting at offset 800h
55771 + */
55772 + dwc_otg_device_global_regs_t *dev_global_regs;
55773 +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
55774 +
55775 + /**
55776 + * Device Logical IN Endpoint-Specific Registers 900h-AFCh
55777 + */
55778 + dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
55779 +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
55780 +#define DWC_EP_REG_OFFSET 0x20
55781 +
55782 + /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
55783 + dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
55784 +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
55785 +
55786 + /* Device configuration information */
55787 + uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */
55788 + uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */
55789 + uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/
55790 +
55791 + /** Size of periodic FIFOs (Bytes) */
55792 + uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
55793 +
55794 + /** Size of Tx FIFOs (Bytes) */
55795 + uint16_t tx_fifo_size[MAX_TX_FIFOS];
55796 +
55797 + /** Thresholding enable flags and length varaiables **/
55798 + uint16_t rx_thr_en;
55799 + uint16_t iso_tx_thr_en;
55800 + uint16_t non_iso_tx_thr_en;
55801 +
55802 + uint16_t rx_thr_length;
55803 + uint16_t tx_thr_length;
55804 +
55805 + /**
55806 + * Pointers to the DMA Descriptors for EP0 Control
55807 + * transfers (virtual and physical)
55808 + */
55809 +
55810 + /** 2 descriptors for SETUP packets */
55811 + dwc_dma_t dma_setup_desc_addr[2];
55812 + dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
55813 +
55814 + /** Pointer to Descriptor with latest SETUP packet */
55815 + dwc_otg_dev_dma_desc_t *psetup;
55816 +
55817 + /** Index of current SETUP handler descriptor */
55818 + uint32_t setup_desc_index;
55819 +
55820 + /** Descriptor for Data In or Status In phases */
55821 + dwc_dma_t dma_in_desc_addr;
55822 + dwc_otg_dev_dma_desc_t *in_desc_addr;
55823 +
55824 + /** Descriptor for Data Out or Status Out phases */
55825 + dwc_dma_t dma_out_desc_addr;
55826 + dwc_otg_dev_dma_desc_t *out_desc_addr;
55827 +
55828 + /** Setup Packet Detected - if set clear NAK when queueing */
55829 + uint32_t spd;
55830 + /** Isoc ep pointer on which incomplete happens */
55831 + void *isoc_ep;
55832 +
55833 +} dwc_otg_dev_if_t;
55834 +
55835 +/////////////////////////////////////////////////
55836 +// Host Mode Register Structures
55837 +//
55838 +/**
55839 + * The Host Global Registers structure defines the size and relative
55840 + * field offsets for the Host Mode Global Registers. Host Global
55841 + * Registers offsets 400h-7FFh.
55842 +*/
55843 +typedef struct dwc_otg_host_global_regs {
55844 + /** Host Configuration Register. <i>Offset: 400h</i> */
55845 + volatile uint32_t hcfg;
55846 + /** Host Frame Interval Register. <i>Offset: 404h</i> */
55847 + volatile uint32_t hfir;
55848 + /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
55849 + volatile uint32_t hfnum;
55850 + /** Reserved. <i>Offset: 40Ch</i> */
55851 + uint32_t reserved40C;
55852 + /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
55853 + volatile uint32_t hptxsts;
55854 + /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
55855 + volatile uint32_t haint;
55856 + /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
55857 + volatile uint32_t haintmsk;
55858 + /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
55859 + volatile uint32_t hflbaddr;
55860 +} dwc_otg_host_global_regs_t;
55861 +
55862 +/**
55863 + * This union represents the bit fields in the Host Configuration Register.
55864 + * Read the register into the <i>d32</i> member then set/clear the bits using
55865 + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
55866 + */
55867 +typedef union hcfg_data {
55868 + /** raw register data */
55869 + uint32_t d32;
55870 +
55871 + /** register bits */
55872 + struct {
55873 + /** FS/LS Phy Clock Select */
55874 + unsigned fslspclksel:2;
55875 +#define DWC_HCFG_30_60_MHZ 0
55876 +#define DWC_HCFG_48_MHZ 1
55877 +#define DWC_HCFG_6_MHZ 2
55878 +
55879 + /** FS/LS Only Support */
55880 + unsigned fslssupp:1;
55881 + unsigned reserved3_6:4;
55882 + /** Enable 32-KHz Suspend Mode */
55883 + unsigned ena32khzs:1;
55884 + /** Resume Validation Periiod */
55885 + unsigned resvalid:8;
55886 + unsigned reserved16_22:7;
55887 + /** Enable Scatter/gather DMA in Host mode */
55888 + unsigned descdma:1;
55889 + /** Frame List Entries */
55890 + unsigned frlisten:2;
55891 + /** Enable Periodic Scheduling */
55892 + unsigned perschedena:1;
55893 + unsigned reserved27_30:4;
55894 + unsigned modechtimen:1;
55895 + } b;
55896 +} hcfg_data_t;
55897 +
55898 +/**
55899 + * This union represents the bit fields in the Host Frame Remaing/Number
55900 + * Register.
55901 + */
55902 +typedef union hfir_data {
55903 + /** raw register data */
55904 + uint32_t d32;
55905 +
55906 + /** register bits */
55907 + struct {
55908 + unsigned frint:16;
55909 + unsigned hfirrldctrl:1;
55910 + unsigned reserved:15;
55911 + } b;
55912 +} hfir_data_t;
55913 +
55914 +/**
55915 + * This union represents the bit fields in the Host Frame Remaing/Number
55916 + * Register.
55917 + */
55918 +typedef union hfnum_data {
55919 + /** raw register data */
55920 + uint32_t d32;
55921 +
55922 + /** register bits */
55923 + struct {
55924 + unsigned frnum:16;
55925 +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
55926 + unsigned frrem:16;
55927 + } b;
55928 +} hfnum_data_t;
55929 +
55930 +typedef union hptxsts_data {
55931 + /** raw register data */
55932 + uint32_t d32;
55933 +
55934 + /** register bits */
55935 + struct {
55936 + unsigned ptxfspcavail:16;
55937 + unsigned ptxqspcavail:8;
55938 + /** Top of the Periodic Transmit Request Queue
55939 + * - bit 24 - Terminate (last entry for the selected channel)
55940 + * - bits 26:25 - Token Type
55941 + * - 2'b00 - Zero length
55942 + * - 2'b01 - Ping
55943 + * - 2'b10 - Disable
55944 + * - bits 30:27 - Channel Number
55945 + * - bit 31 - Odd/even microframe
55946 + */
55947 + unsigned ptxqtop_terminate:1;
55948 + unsigned ptxqtop_token:2;
55949 + unsigned ptxqtop_chnum:4;
55950 + unsigned ptxqtop_odd:1;
55951 + } b;
55952 +} hptxsts_data_t;
55953 +
55954 +/**
55955 + * This union represents the bit fields in the Host Port Control and Status
55956 + * Register. Read the register into the <i>d32</i> member then set/clear the
55957 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55958 + * hprt0 register.
55959 + */
55960 +typedef union hprt0_data {
55961 + /** raw register data */
55962 + uint32_t d32;
55963 + /** register bits */
55964 + struct {
55965 + unsigned prtconnsts:1;
55966 + unsigned prtconndet:1;
55967 + unsigned prtena:1;
55968 + unsigned prtenchng:1;
55969 + unsigned prtovrcurract:1;
55970 + unsigned prtovrcurrchng:1;
55971 + unsigned prtres:1;
55972 + unsigned prtsusp:1;
55973 + unsigned prtrst:1;
55974 + unsigned reserved9:1;
55975 + unsigned prtlnsts:2;
55976 + unsigned prtpwr:1;
55977 + unsigned prttstctl:4;
55978 + unsigned prtspd:2;
55979 +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
55980 +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
55981 +#define DWC_HPRT0_PRTSPD_LOW_SPEED 2
55982 + unsigned reserved19_31:13;
55983 + } b;
55984 +} hprt0_data_t;
55985 +
55986 +/**
55987 + * This union represents the bit fields in the Host All Interrupt
55988 + * Register.
55989 + */
55990 +typedef union haint_data {
55991 + /** raw register data */
55992 + uint32_t d32;
55993 + /** register bits */
55994 + struct {
55995 + unsigned ch0:1;
55996 + unsigned ch1:1;
55997 + unsigned ch2:1;
55998 + unsigned ch3:1;
55999 + unsigned ch4:1;
56000 + unsigned ch5:1;
56001 + unsigned ch6:1;
56002 + unsigned ch7:1;
56003 + unsigned ch8:1;
56004 + unsigned ch9:1;
56005 + unsigned ch10:1;
56006 + unsigned ch11:1;
56007 + unsigned ch12:1;
56008 + unsigned ch13:1;
56009 + unsigned ch14:1;
56010 + unsigned ch15:1;
56011 + unsigned reserved:16;
56012 + } b;
56013 +
56014 + struct {
56015 + unsigned chint:16;
56016 + unsigned reserved:16;
56017 + } b2;
56018 +} haint_data_t;
56019 +
56020 +/**
56021 + * This union represents the bit fields in the Host All Interrupt
56022 + * Register.
56023 + */
56024 +typedef union haintmsk_data {
56025 + /** raw register data */
56026 + uint32_t d32;
56027 + /** register bits */
56028 + struct {
56029 + unsigned ch0:1;
56030 + unsigned ch1:1;
56031 + unsigned ch2:1;
56032 + unsigned ch3:1;
56033 + unsigned ch4:1;
56034 + unsigned ch5:1;
56035 + unsigned ch6:1;
56036 + unsigned ch7:1;
56037 + unsigned ch8:1;
56038 + unsigned ch9:1;
56039 + unsigned ch10:1;
56040 + unsigned ch11:1;
56041 + unsigned ch12:1;
56042 + unsigned ch13:1;
56043 + unsigned ch14:1;
56044 + unsigned ch15:1;
56045 + unsigned reserved:16;
56046 + } b;
56047 +
56048 + struct {
56049 + unsigned chint:16;
56050 + unsigned reserved:16;
56051 + } b2;
56052 +} haintmsk_data_t;
56053 +
56054 +/**
56055 + * Host Channel Specific Registers. <i>500h-5FCh</i>
56056 + */
56057 +typedef struct dwc_otg_hc_regs {
56058 + /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
56059 + volatile uint32_t hcchar;
56060 + /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
56061 + volatile uint32_t hcsplt;
56062 + /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
56063 + volatile uint32_t hcint;
56064 + /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
56065 + volatile uint32_t hcintmsk;
56066 + /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
56067 + volatile uint32_t hctsiz;
56068 + /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
56069 + volatile uint32_t hcdma;
56070 + volatile uint32_t reserved;
56071 + /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
56072 + volatile uint32_t hcdmab;
56073 +} dwc_otg_hc_regs_t;
56074 +
56075 +/**
56076 + * This union represents the bit fields in the Host Channel Characteristics
56077 + * Register. Read the register into the <i>d32</i> member then set/clear the
56078 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56079 + * hcchar register.
56080 + */
56081 +typedef union hcchar_data {
56082 + /** raw register data */
56083 + uint32_t d32;
56084 +
56085 + /** register bits */
56086 + struct {
56087 + /** Maximum packet size in bytes */
56088 + unsigned mps:11;
56089 +
56090 + /** Endpoint number */
56091 + unsigned epnum:4;
56092 +
56093 + /** 0: OUT, 1: IN */
56094 + unsigned epdir:1;
56095 +
56096 + unsigned reserved:1;
56097 +
56098 + /** 0: Full/high speed device, 1: Low speed device */
56099 + unsigned lspddev:1;
56100 +
56101 + /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
56102 + unsigned eptype:2;
56103 +
56104 + /** Packets per frame for periodic transfers. 0 is reserved. */
56105 + unsigned multicnt:2;
56106 +
56107 + /** Device address */
56108 + unsigned devaddr:7;
56109 +
56110 + /**
56111 + * Frame to transmit periodic transaction.
56112 + * 0: even, 1: odd
56113 + */
56114 + unsigned oddfrm:1;
56115 +
56116 + /** Channel disable */
56117 + unsigned chdis:1;
56118 +
56119 + /** Channel enable */
56120 + unsigned chen:1;
56121 + } b;
56122 +} hcchar_data_t;
56123 +
56124 +typedef union hcsplt_data {
56125 + /** raw register data */
56126 + uint32_t d32;
56127 +
56128 + /** register bits */
56129 + struct {
56130 + /** Port Address */
56131 + unsigned prtaddr:7;
56132 +
56133 + /** Hub Address */
56134 + unsigned hubaddr:7;
56135 +
56136 + /** Transaction Position */
56137 + unsigned xactpos:2;
56138 +#define DWC_HCSPLIT_XACTPOS_MID 0
56139 +#define DWC_HCSPLIT_XACTPOS_END 1
56140 +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
56141 +#define DWC_HCSPLIT_XACTPOS_ALL 3
56142 +
56143 + /** Do Complete Split */
56144 + unsigned compsplt:1;
56145 +
56146 + /** Reserved */
56147 + unsigned reserved:14;
56148 +
56149 + /** Split Enble */
56150 + unsigned spltena:1;
56151 + } b;
56152 +} hcsplt_data_t;
56153 +
56154 +/**
56155 + * This union represents the bit fields in the Host All Interrupt
56156 + * Register.
56157 + */
56158 +typedef union hcint_data {
56159 + /** raw register data */
56160 + uint32_t d32;
56161 + /** register bits */
56162 + struct {
56163 + /** Transfer Complete */
56164 + unsigned xfercomp:1;
56165 + /** Channel Halted */
56166 + unsigned chhltd:1;
56167 + /** AHB Error */
56168 + unsigned ahberr:1;
56169 + /** STALL Response Received */
56170 + unsigned stall:1;
56171 + /** NAK Response Received */
56172 + unsigned nak:1;
56173 + /** ACK Response Received */
56174 + unsigned ack:1;
56175 + /** NYET Response Received */
56176 + unsigned nyet:1;
56177 + /** Transaction Err */
56178 + unsigned xacterr:1;
56179 + /** Babble Error */
56180 + unsigned bblerr:1;
56181 + /** Frame Overrun */
56182 + unsigned frmovrun:1;
56183 + /** Data Toggle Error */
56184 + unsigned datatglerr:1;
56185 + /** Buffer Not Available (only for DDMA mode) */
56186 + unsigned bna:1;
56187 + /** Exessive transaction error (only for DDMA mode) */
56188 + unsigned xcs_xact:1;
56189 + /** Frame List Rollover interrupt */
56190 + unsigned frm_list_roll:1;
56191 + /** Reserved */
56192 + unsigned reserved14_31:18;
56193 + } b;
56194 +} hcint_data_t;
56195 +
56196 +/**
56197 + * This union represents the bit fields in the Host Channel Interrupt Mask
56198 + * Register. Read the register into the <i>d32</i> member then set/clear the
56199 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56200 + * hcintmsk register.
56201 + */
56202 +typedef union hcintmsk_data {
56203 + /** raw register data */
56204 + uint32_t d32;
56205 +
56206 + /** register bits */
56207 + struct {
56208 + unsigned xfercompl:1;
56209 + unsigned chhltd:1;
56210 + unsigned ahberr:1;
56211 + unsigned stall:1;
56212 + unsigned nak:1;
56213 + unsigned ack:1;
56214 + unsigned nyet:1;
56215 + unsigned xacterr:1;
56216 + unsigned bblerr:1;
56217 + unsigned frmovrun:1;
56218 + unsigned datatglerr:1;
56219 + unsigned bna:1;
56220 + unsigned xcs_xact:1;
56221 + unsigned frm_list_roll:1;
56222 + unsigned reserved14_31:18;
56223 + } b;
56224 +} hcintmsk_data_t;
56225 +
56226 +/**
56227 + * This union represents the bit fields in the Host Channel Transfer Size
56228 + * Register. Read the register into the <i>d32</i> member then set/clear the
56229 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56230 + * hcchar register.
56231 + */
56232 +
56233 +typedef union hctsiz_data {
56234 + /** raw register data */
56235 + uint32_t d32;
56236 +
56237 + /** register bits */
56238 + struct {
56239 + /** Total transfer size in bytes */
56240 + unsigned xfersize:19;
56241 +
56242 + /** Data packets to transfer */
56243 + unsigned pktcnt:10;
56244 +
56245 + /**
56246 + * Packet ID for next data packet
56247 + * 0: DATA0
56248 + * 1: DATA2
56249 + * 2: DATA1
56250 + * 3: MDATA (non-Control), SETUP (Control)
56251 + */
56252 + unsigned pid:2;
56253 +#define DWC_HCTSIZ_DATA0 0
56254 +#define DWC_HCTSIZ_DATA1 2
56255 +#define DWC_HCTSIZ_DATA2 1
56256 +#define DWC_HCTSIZ_MDATA 3
56257 +#define DWC_HCTSIZ_SETUP 3
56258 +
56259 + /** Do PING protocol when 1 */
56260 + unsigned dopng:1;
56261 + } b;
56262 +
56263 + /** register bits */
56264 + struct {
56265 + /** Scheduling information */
56266 + unsigned schinfo:8;
56267 +
56268 + /** Number of transfer descriptors.
56269 + * Max value:
56270 + * 64 in general,
56271 + * 256 only for HS isochronous endpoint.
56272 + */
56273 + unsigned ntd:8;
56274 +
56275 + /** Data packets to transfer */
56276 + unsigned reserved16_28:13;
56277 +
56278 + /**
56279 + * Packet ID for next data packet
56280 + * 0: DATA0
56281 + * 1: DATA2
56282 + * 2: DATA1
56283 + * 3: MDATA (non-Control)
56284 + */
56285 + unsigned pid:2;
56286 +
56287 + /** Do PING protocol when 1 */
56288 + unsigned dopng:1;
56289 + } b_ddma;
56290 +} hctsiz_data_t;
56291 +
56292 +/**
56293 + * This union represents the bit fields in the Host DMA Address
56294 + * Register used in Descriptor DMA mode.
56295 + */
56296 +typedef union hcdma_data {
56297 + /** raw register data */
56298 + uint32_t d32;
56299 + /** register bits */
56300 + struct {
56301 + unsigned reserved0_2:3;
56302 + /** Current Transfer Descriptor. Not used for ISOC */
56303 + unsigned ctd:8;
56304 + /** Start Address of Descriptor List */
56305 + unsigned dma_addr:21;
56306 + } b;
56307 +} hcdma_data_t;
56308 +
56309 +/**
56310 + * This union represents the bit fields in the DMA Descriptor
56311 + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
56312 + * set/clear the bits using the <i>b</i>it elements.
56313 + */
56314 +typedef union host_dma_desc_sts {
56315 + /** raw register data */
56316 + uint32_t d32;
56317 + /** quadlet bits */
56318 +
56319 + /* for non-isochronous */
56320 + struct {
56321 + /** Number of bytes */
56322 + unsigned n_bytes:17;
56323 + /** QTD offset to jump when Short Packet received - only for IN EPs */
56324 + unsigned qtd_offset:6;
56325 + /**
56326 + * Set to request the core to jump to alternate QTD if
56327 + * Short Packet received - only for IN EPs
56328 + */
56329 + unsigned a_qtd:1;
56330 + /**
56331 + * Setup Packet bit. When set indicates that buffer contains
56332 + * setup packet.
56333 + */
56334 + unsigned sup:1;
56335 + /** Interrupt On Complete */
56336 + unsigned ioc:1;
56337 + /** End of List */
56338 + unsigned eol:1;
56339 + unsigned reserved27:1;
56340 + /** Rx/Tx Status */
56341 + unsigned sts:2;
56342 +#define DMA_DESC_STS_PKTERR 1
56343 + unsigned reserved30:1;
56344 + /** Active Bit */
56345 + unsigned a:1;
56346 + } b;
56347 + /* for isochronous */
56348 + struct {
56349 + /** Number of bytes */
56350 + unsigned n_bytes:12;
56351 + unsigned reserved12_24:13;
56352 + /** Interrupt On Complete */
56353 + unsigned ioc:1;
56354 + unsigned reserved26_27:2;
56355 + /** Rx/Tx Status */
56356 + unsigned sts:2;
56357 + unsigned reserved30:1;
56358 + /** Active Bit */
56359 + unsigned a:1;
56360 + } b_isoc;
56361 +} host_dma_desc_sts_t;
56362 +
56363 +#define MAX_DMA_DESC_SIZE 131071
56364 +#define MAX_DMA_DESC_NUM_GENERIC 64
56365 +#define MAX_DMA_DESC_NUM_HS_ISOC 256
56366 +#define MAX_FRLIST_EN_NUM 64
56367 +/**
56368 + * Host-mode DMA Descriptor structure
56369 + *
56370 + * DMA Descriptor structure contains two quadlets:
56371 + * Status quadlet and Data buffer pointer.
56372 + */
56373 +typedef struct dwc_otg_host_dma_desc {
56374 + /** DMA Descriptor status quadlet */
56375 + host_dma_desc_sts_t status;
56376 + /** DMA Descriptor data buffer pointer */
56377 + uint32_t buf;
56378 +} dwc_otg_host_dma_desc_t;
56379 +
56380 +/** OTG Host Interface Structure.
56381 + *
56382 + * The OTG Host Interface Structure structure contains information
56383 + * needed to manage the DWC_otg controller acting in host mode. It
56384 + * represents the programming view of the host-specific aspects of the
56385 + * controller.
56386 + */
56387 +typedef struct dwc_otg_host_if {
56388 + /** Host Global Registers starting at offset 400h.*/
56389 + dwc_otg_host_global_regs_t *host_global_regs;
56390 +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
56391 +
56392 + /** Host Port 0 Control and Status Register */
56393 + volatile uint32_t *hprt0;
56394 +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
56395 +
56396 + /** Host Channel Specific Registers at offsets 500h-5FCh. */
56397 + dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
56398 +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
56399 +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
56400 +
56401 + /* Host configuration information */
56402 + /** Number of Host Channels (range: 1-16) */
56403 + uint8_t num_host_channels;
56404 + /** Periodic EPs supported (0: no, 1: yes) */
56405 + uint8_t perio_eps_supported;
56406 + /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
56407 + uint16_t perio_tx_fifo_size;
56408 +
56409 +} dwc_otg_host_if_t;
56410 +
56411 +/**
56412 + * This union represents the bit fields in the Power and Clock Gating Control
56413 + * Register. Read the register into the <i>d32</i> member then set/clear the
56414 + * bits using the <i>b</i>it elements.
56415 + */
56416 +typedef union pcgcctl_data {
56417 + /** raw register data */
56418 + uint32_t d32;
56419 +
56420 + /** register bits */
56421 + struct {
56422 + /** Stop Pclk */
56423 + unsigned stoppclk:1;
56424 + /** Gate Hclk */
56425 + unsigned gatehclk:1;
56426 + /** Power Clamp */
56427 + unsigned pwrclmp:1;
56428 + /** Reset Power Down Modules */
56429 + unsigned rstpdwnmodule:1;
56430 + /** Reserved */
56431 + unsigned reserved:1;
56432 + /** Enable Sleep Clock Gating (Enbl_L1Gating) */
56433 + unsigned enbl_sleep_gating:1;
56434 + /** PHY In Sleep (PhySleep) */
56435 + unsigned phy_in_sleep:1;
56436 + /** Deep Sleep*/
56437 + unsigned deep_sleep:1;
56438 + unsigned resetaftsusp:1;
56439 + unsigned restoremode:1;
56440 + unsigned enbl_extnd_hiber:1;
56441 + unsigned extnd_hiber_pwrclmp:1;
56442 + unsigned extnd_hiber_switch:1;
56443 + unsigned ess_reg_restored:1;
56444 + unsigned prt_clk_sel:2;
56445 + unsigned port_power:1;
56446 + unsigned max_xcvrselect:2;
56447 + unsigned max_termsel:1;
56448 + unsigned mac_dev_addr:7;
56449 + unsigned p2hd_dev_enum_spd:2;
56450 + unsigned p2hd_prt_spd:2;
56451 + unsigned if_dev_mode:1;
56452 + } b;
56453 +} pcgcctl_data_t;
56454 +
56455 +/**
56456 + * This union represents the bit fields in the Global Data FIFO Software
56457 + * Configuration Register. Read the register into the <i>d32</i> member then
56458 + * set/clear the bits using the <i>b</i>it elements.
56459 + */
56460 +typedef union gdfifocfg_data {
56461 + /* raw register data */
56462 + uint32_t d32;
56463 + /** register bits */
56464 + struct {
56465 + /** OTG Data FIFO depth */
56466 + unsigned gdfifocfg:16;
56467 + /** Start address of EP info controller */
56468 + unsigned epinfobase:16;
56469 + } b;
56470 +} gdfifocfg_data_t;
56471 +
56472 +/**
56473 + * This union represents the bit fields in the Global Power Down Register
56474 + * Register. Read the register into the <i>d32</i> member then set/clear the
56475 + * bits using the <i>b</i>it elements.
56476 + */
56477 +typedef union gpwrdn_data {
56478 + /* raw register data */
56479 + uint32_t d32;
56480 +
56481 + /** register bits */
56482 + struct {
56483 + /** PMU Interrupt Select */
56484 + unsigned pmuintsel:1;
56485 + /** PMU Active */
56486 + unsigned pmuactv:1;
56487 + /** Restore */
56488 + unsigned restore:1;
56489 + /** Power Down Clamp */
56490 + unsigned pwrdnclmp:1;
56491 + /** Power Down Reset */
56492 + unsigned pwrdnrstn:1;
56493 + /** Power Down Switch */
56494 + unsigned pwrdnswtch:1;
56495 + /** Disable VBUS */
56496 + unsigned dis_vbus:1;
56497 + /** Line State Change */
56498 + unsigned lnstschng:1;
56499 + /** Line state change mask */
56500 + unsigned lnstchng_msk:1;
56501 + /** Reset Detected */
56502 + unsigned rst_det:1;
56503 + /** Reset Detect mask */
56504 + unsigned rst_det_msk:1;
56505 + /** Disconnect Detected */
56506 + unsigned disconn_det:1;
56507 + /** Disconnect Detect mask */
56508 + unsigned disconn_det_msk:1;
56509 + /** Connect Detected*/
56510 + unsigned connect_det:1;
56511 + /** Connect Detected Mask*/
56512 + unsigned connect_det_msk:1;
56513 + /** SRP Detected */
56514 + unsigned srp_det:1;
56515 + /** SRP Detect mask */
56516 + unsigned srp_det_msk:1;
56517 + /** Status Change Interrupt */
56518 + unsigned sts_chngint:1;
56519 + /** Status Change Interrupt Mask */
56520 + unsigned sts_chngint_msk:1;
56521 + /** Line State */
56522 + unsigned linestate:2;
56523 + /** Indicates current mode(status of IDDIG signal) */
56524 + unsigned idsts:1;
56525 + /** B Session Valid signal status*/
56526 + unsigned bsessvld:1;
56527 + /** ADP Event Detected */
56528 + unsigned adp_int:1;
56529 + /** Multi Valued ID pin */
56530 + unsigned mult_val_id_bc:5;
56531 + /** Reserved 24_31 */
56532 + unsigned reserved29_31:3;
56533 + } b;
56534 +} gpwrdn_data_t;
56535 +
56536 +#endif
56537 diff -urN linux-3.10/drivers/usb/host/dwc_otg/Makefile linux-rpi-3.10.y/drivers/usb/host/dwc_otg/Makefile
56538 --- linux-3.10/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100
56539 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/Makefile 2013-07-06 15:25:50.000000000 +0100
56540 @@ -0,0 +1,81 @@
56541 +#
56542 +# Makefile for DWC_otg Highspeed USB controller driver
56543 +#
56544 +
56545 +ifneq ($(KERNELRELEASE),)
56546 +
56547 +# Use the BUS_INTERFACE variable to compile the software for either
56548 +# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.
56549 +ifeq ($(BUS_INTERFACE),)
56550 +# BUS_INTERFACE = -DPCI_INTERFACE
56551 +# BUS_INTERFACE = -DLM_INTERFACE
56552 + BUS_INTERFACE = -DPLATFORM_INTERFACE
56553 +endif
56554 +
56555 +#EXTRA_CFLAGS += -DDEBUG
56556 +#EXTRA_CFLAGS += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
56557 +
56558 +# Use one of the following flags to compile the software in host-only or
56559 +# device-only mode.
56560 +#EXTRA_CFLAGS += -DDWC_HOST_ONLY
56561 +#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY
56562 +
56563 +EXTRA_CFLAGS += -Dlinux -DDWC_HS_ELECT_TST
56564 +#EXTRA_CFLAGS += -DDWC_EN_ISOC
56565 +EXTRA_CFLAGS += -I$(obj)/../dwc_common_port
56566 +#EXTRA_CFLAGS += -I$(PORTLIB)
56567 +EXTRA_CFLAGS += -DDWC_LINUX
56568 +EXTRA_CFLAGS += $(CFI)
56569 +EXTRA_CFLAGS += $(BUS_INTERFACE)
56570 +#EXTRA_CFLAGS += -DDWC_DEV_SRPCAP
56571 +
56572 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
56573 +
56574 +dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o
56575 +dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o
56576 +dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
56577 +dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o
56578 +dwc_otg-objs += dwc_otg_adp.o
56579 +dwc_otg-objs += dwc_otg_mphi_fix.o
56580 +ifneq ($(CFI),)
56581 +dwc_otg-objs += dwc_otg_cfi.o
56582 +endif
56583 +
56584 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
56585 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
56586 +
56587 +ifneq ($(kernrel3),2.6.20)
56588 +EXTRA_CFLAGS += $(CPPFLAGS)
56589 +endif
56590 +
56591 +else
56592 +
56593 +PWD := $(shell pwd)
56594 +PORTLIB := $(PWD)/../dwc_common_port
56595 +
56596 +# Command paths
56597 +CTAGS := $(CTAGS)
56598 +DOXYGEN := $(DOXYGEN)
56599 +
56600 +default: portlib
56601 + $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
56602 +
56603 +install: default
56604 + $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
56605 + $(MAKE) -C$(KDIR) M=$(PWD) modules_install
56606 +
56607 +portlib:
56608 + $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
56609 + cp $(PORTLIB)/Module.symvers $(PWD)/
56610 +
56611 +docs: $(wildcard *.[hc]) doc/doxygen.cfg
56612 + $(DOXYGEN) doc/doxygen.cfg
56613 +
56614 +tags: $(wildcard *.[hc])
56615 + $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
56616 +
56617 +
56618 +clean:
56619 + rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
56620 +
56621 +endif
56622 diff -urN linux-3.10/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56623 --- linux-3.10/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100
56624 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2013-07-06 15:25:50.000000000 +0100
56625 @@ -0,0 +1,337 @@
56626 +package dwc_otg_test;
56627 +
56628 +use strict;
56629 +use Exporter ();
56630 +
56631 +use vars qw(@ISA @EXPORT
56632 +$sysfsdir $paramdir $errors $params
56633 +);
56634 +
56635 +@ISA = qw(Exporter);
56636 +
56637 +#
56638 +# Globals
56639 +#
56640 +$sysfsdir = "/sys/devices/lm0";
56641 +$paramdir = "/sys/module/dwc_otg";
56642 +$errors = 0;
56643 +
56644 +$params = [
56645 + {
56646 + NAME => "otg_cap",
56647 + DEFAULT => 0,
56648 + ENUM => [],
56649 + LOW => 0,
56650 + HIGH => 2
56651 + },
56652 + {
56653 + NAME => "dma_enable",
56654 + DEFAULT => 0,
56655 + ENUM => [],
56656 + LOW => 0,
56657 + HIGH => 1
56658 + },
56659 + {
56660 + NAME => "dma_burst_size",
56661 + DEFAULT => 32,
56662 + ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
56663 + LOW => 1,
56664 + HIGH => 256
56665 + },
56666 + {
56667 + NAME => "host_speed",
56668 + DEFAULT => 0,
56669 + ENUM => [],
56670 + LOW => 0,
56671 + HIGH => 1
56672 + },
56673 + {
56674 + NAME => "host_support_fs_ls_low_power",
56675 + DEFAULT => 0,
56676 + ENUM => [],
56677 + LOW => 0,
56678 + HIGH => 1
56679 + },
56680 + {
56681 + NAME => "host_ls_low_power_phy_clk",
56682 + DEFAULT => 0,
56683 + ENUM => [],
56684 + LOW => 0,
56685 + HIGH => 1
56686 + },
56687 + {
56688 + NAME => "dev_speed",
56689 + DEFAULT => 0,
56690 + ENUM => [],
56691 + LOW => 0,
56692 + HIGH => 1
56693 + },
56694 + {
56695 + NAME => "enable_dynamic_fifo",
56696 + DEFAULT => 1,
56697 + ENUM => [],
56698 + LOW => 0,
56699 + HIGH => 1
56700 + },
56701 + {
56702 + NAME => "data_fifo_size",
56703 + DEFAULT => 8192,
56704 + ENUM => [],
56705 + LOW => 32,
56706 + HIGH => 32768
56707 + },
56708 + {
56709 + NAME => "dev_rx_fifo_size",
56710 + DEFAULT => 1064,
56711 + ENUM => [],
56712 + LOW => 16,
56713 + HIGH => 32768
56714 + },
56715 + {
56716 + NAME => "dev_nperio_tx_fifo_size",
56717 + DEFAULT => 1024,
56718 + ENUM => [],
56719 + LOW => 16,
56720 + HIGH => 32768
56721 + },
56722 + {
56723 + NAME => "dev_perio_tx_fifo_size_1",
56724 + DEFAULT => 256,
56725 + ENUM => [],
56726 + LOW => 4,
56727 + HIGH => 768
56728 + },
56729 + {
56730 + NAME => "dev_perio_tx_fifo_size_2",
56731 + DEFAULT => 256,
56732 + ENUM => [],
56733 + LOW => 4,
56734 + HIGH => 768
56735 + },
56736 + {
56737 + NAME => "dev_perio_tx_fifo_size_3",
56738 + DEFAULT => 256,
56739 + ENUM => [],
56740 + LOW => 4,
56741 + HIGH => 768
56742 + },
56743 + {
56744 + NAME => "dev_perio_tx_fifo_size_4",
56745 + DEFAULT => 256,
56746 + ENUM => [],
56747 + LOW => 4,
56748 + HIGH => 768
56749 + },
56750 + {
56751 + NAME => "dev_perio_tx_fifo_size_5",
56752 + DEFAULT => 256,
56753 + ENUM => [],
56754 + LOW => 4,
56755 + HIGH => 768
56756 + },
56757 + {
56758 + NAME => "dev_perio_tx_fifo_size_6",
56759 + DEFAULT => 256,
56760 + ENUM => [],
56761 + LOW => 4,
56762 + HIGH => 768
56763 + },
56764 + {
56765 + NAME => "dev_perio_tx_fifo_size_7",
56766 + DEFAULT => 256,
56767 + ENUM => [],
56768 + LOW => 4,
56769 + HIGH => 768
56770 + },
56771 + {
56772 + NAME => "dev_perio_tx_fifo_size_8",
56773 + DEFAULT => 256,
56774 + ENUM => [],
56775 + LOW => 4,
56776 + HIGH => 768
56777 + },
56778 + {
56779 + NAME => "dev_perio_tx_fifo_size_9",
56780 + DEFAULT => 256,
56781 + ENUM => [],
56782 + LOW => 4,
56783 + HIGH => 768
56784 + },
56785 + {
56786 + NAME => "dev_perio_tx_fifo_size_10",
56787 + DEFAULT => 256,
56788 + ENUM => [],
56789 + LOW => 4,
56790 + HIGH => 768
56791 + },
56792 + {
56793 + NAME => "dev_perio_tx_fifo_size_11",
56794 + DEFAULT => 256,
56795 + ENUM => [],
56796 + LOW => 4,
56797 + HIGH => 768
56798 + },
56799 + {
56800 + NAME => "dev_perio_tx_fifo_size_12",
56801 + DEFAULT => 256,
56802 + ENUM => [],
56803 + LOW => 4,
56804 + HIGH => 768
56805 + },
56806 + {
56807 + NAME => "dev_perio_tx_fifo_size_13",
56808 + DEFAULT => 256,
56809 + ENUM => [],
56810 + LOW => 4,
56811 + HIGH => 768
56812 + },
56813 + {
56814 + NAME => "dev_perio_tx_fifo_size_14",
56815 + DEFAULT => 256,
56816 + ENUM => [],
56817 + LOW => 4,
56818 + HIGH => 768
56819 + },
56820 + {
56821 + NAME => "dev_perio_tx_fifo_size_15",
56822 + DEFAULT => 256,
56823 + ENUM => [],
56824 + LOW => 4,
56825 + HIGH => 768
56826 + },
56827 + {
56828 + NAME => "host_rx_fifo_size",
56829 + DEFAULT => 1024,
56830 + ENUM => [],
56831 + LOW => 16,
56832 + HIGH => 32768
56833 + },
56834 + {
56835 + NAME => "host_nperio_tx_fifo_size",
56836 + DEFAULT => 1024,
56837 + ENUM => [],
56838 + LOW => 16,
56839 + HIGH => 32768
56840 + },
56841 + {
56842 + NAME => "host_perio_tx_fifo_size",
56843 + DEFAULT => 1024,
56844 + ENUM => [],
56845 + LOW => 16,
56846 + HIGH => 32768
56847 + },
56848 + {
56849 + NAME => "max_transfer_size",
56850 + DEFAULT => 65535,
56851 + ENUM => [],
56852 + LOW => 2047,
56853 + HIGH => 65535
56854 + },
56855 + {
56856 + NAME => "max_packet_count",
56857 + DEFAULT => 511,
56858 + ENUM => [],
56859 + LOW => 15,
56860 + HIGH => 511
56861 + },
56862 + {
56863 + NAME => "host_channels",
56864 + DEFAULT => 12,
56865 + ENUM => [],
56866 + LOW => 1,
56867 + HIGH => 16
56868 + },
56869 + {
56870 + NAME => "dev_endpoints",
56871 + DEFAULT => 6,
56872 + ENUM => [],
56873 + LOW => 1,
56874 + HIGH => 15
56875 + },
56876 + {
56877 + NAME => "phy_type",
56878 + DEFAULT => 1,
56879 + ENUM => [],
56880 + LOW => 0,
56881 + HIGH => 2
56882 + },
56883 + {
56884 + NAME => "phy_utmi_width",
56885 + DEFAULT => 16,
56886 + ENUM => [8, 16],
56887 + LOW => 8,
56888 + HIGH => 16
56889 + },
56890 + {
56891 + NAME => "phy_ulpi_ddr",
56892 + DEFAULT => 0,
56893 + ENUM => [],
56894 + LOW => 0,
56895 + HIGH => 1
56896 + },
56897 + ];
56898 +
56899 +
56900 +#
56901 +#
56902 +sub check_arch {
56903 + $_ = `uname -m`;
56904 + chomp;
56905 + unless (m/armv4tl/) {
56906 + warn "# \n# Can't execute on $_. Run on integrator platform.\n# \n";
56907 + return 0;
56908 + }
56909 + return 1;
56910 +}
56911 +
56912 +#
56913 +#
56914 +sub load_module {
56915 + my $params = shift;
56916 + print "\nRemoving Module\n";
56917 + system "rmmod dwc_otg";
56918 + print "Loading Module\n";
56919 + if ($params ne "") {
56920 + print "Module Parameters: $params\n";
56921 + }
56922 + if (system("modprobe dwc_otg $params")) {
56923 + warn "Unable to load module\n";
56924 + return 0;
56925 + }
56926 + return 1;
56927 +}
56928 +
56929 +#
56930 +#
56931 +sub test_status {
56932 + my $arg = shift;
56933 +
56934 + print "\n";
56935 +
56936 + if (defined $arg) {
56937 + warn "WARNING: $arg\n";
56938 + }
56939 +
56940 + if ($errors > 0) {
56941 + warn "TEST FAILED with $errors errors\n";
56942 + return 0;
56943 + } else {
56944 + print "TEST PASSED\n";
56945 + return 0 if (defined $arg);
56946 + }
56947 + return 1;
56948 +}
56949 +
56950 +#
56951 +#
56952 +@EXPORT = qw(
56953 +$sysfsdir
56954 +$paramdir
56955 +$params
56956 +$errors
56957 +check_arch
56958 +load_module
56959 +test_status
56960 +);
56961 +
56962 +1;
56963 diff -urN linux-3.10/drivers/usb/host/dwc_otg/test/Makefile linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/Makefile
56964 --- linux-3.10/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100
56965 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/Makefile 2013-07-06 15:25:50.000000000 +0100
56966 @@ -0,0 +1,16 @@
56967 +
56968 +PERL=/usr/bin/perl
56969 +PL_TESTS=test_sysfs.pl test_mod_param.pl
56970 +
56971 +.PHONY : test
56972 +test : perl_tests
56973 +
56974 +perl_tests :
56975 + @echo
56976 + @echo Running perl tests
56977 + @for test in $(PL_TESTS); do \
56978 + if $(PERL) ./$$test ; then \
56979 + echo "=======> $$test, PASSED" ; \
56980 + else echo "=======> $$test, FAILED" ; \
56981 + fi \
56982 + done
56983 diff -urN linux-3.10/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56984 --- linux-3.10/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100
56985 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2013-07-06 15:25:50.000000000 +0100
56986 @@ -0,0 +1,133 @@
56987 +#!/usr/bin/perl -w
56988 +#
56989 +# Run this program on the integrator.
56990 +#
56991 +# - Tests module parameter default values.
56992 +# - Tests setting of valid module parameter values via modprobe.
56993 +# - Tests invalid module parameter values.
56994 +# -----------------------------------------------------------------------------
56995 +use strict;
56996 +use dwc_otg_test;
56997 +
56998 +check_arch() or die;
56999 +
57000 +#
57001 +#
57002 +sub test {
57003 + my ($param,$expected) = @_;
57004 + my $value = get($param);
57005 +
57006 + if ($value == $expected) {
57007 + print "$param = $value, okay\n";
57008 + }
57009 +
57010 + else {
57011 + warn "ERROR: value of $param != $expected, $value\n";
57012 + $errors ++;
57013 + }
57014 +}
57015 +
57016 +#
57017 +#
57018 +sub get {
57019 + my $param = shift;
57020 + my $tmp = `cat $paramdir/$param`;
57021 + chomp $tmp;
57022 + return $tmp;
57023 +}
57024 +
57025 +#
57026 +#
57027 +sub test_main {
57028 +
57029 + print "\nTesting Module Parameters\n";
57030 +
57031 + load_module("") or die;
57032 +
57033 + # Test initial values
57034 + print "\nTesting Default Values\n";
57035 + foreach (@{$params}) {
57036 + test ($_->{NAME}, $_->{DEFAULT});
57037 + }
57038 +
57039 + # Test low value
57040 + print "\nTesting Low Value\n";
57041 + my $cmd_params = "";
57042 + foreach (@{$params}) {
57043 + $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
57044 + }
57045 + load_module($cmd_params) or die;
57046 +
57047 + foreach (@{$params}) {
57048 + test ($_->{NAME}, $_->{LOW});
57049 + }
57050 +
57051 + # Test high value
57052 + print "\nTesting High Value\n";
57053 + $cmd_params = "";
57054 + foreach (@{$params}) {
57055 + $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
57056 + }
57057 + load_module($cmd_params) or die;
57058 +
57059 + foreach (@{$params}) {
57060 + test ($_->{NAME}, $_->{HIGH});
57061 + }
57062 +
57063 + # Test Enum
57064 + print "\nTesting Enumerated\n";
57065 + foreach (@{$params}) {
57066 + if (defined $_->{ENUM}) {
57067 + my $value;
57068 + foreach $value (@{$_->{ENUM}}) {
57069 + $cmd_params = "$_->{NAME}=$value";
57070 + load_module($cmd_params) or die;
57071 + test ($_->{NAME}, $value);
57072 + }
57073 + }
57074 + }
57075 +
57076 + # Test Invalid Values
57077 + print "\nTesting Invalid Values\n";
57078 + $cmd_params = "";
57079 + foreach (@{$params}) {
57080 + $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
57081 + }
57082 + load_module($cmd_params) or die;
57083 +
57084 + foreach (@{$params}) {
57085 + test ($_->{NAME}, $_->{DEFAULT});
57086 + }
57087 +
57088 + $cmd_params = "";
57089 + foreach (@{$params}) {
57090 + $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
57091 + }
57092 + load_module($cmd_params) or die;
57093 +
57094 + foreach (@{$params}) {
57095 + test ($_->{NAME}, $_->{DEFAULT});
57096 + }
57097 +
57098 + print "\nTesting Enumerated\n";
57099 + foreach (@{$params}) {
57100 + if (defined $_->{ENUM}) {
57101 + my $value;
57102 + foreach $value (@{$_->{ENUM}}) {
57103 + $value = $value + 1;
57104 + $cmd_params = "$_->{NAME}=$value";
57105 + load_module($cmd_params) or die;
57106 + test ($_->{NAME}, $_->{DEFAULT});
57107 + $value = $value - 2;
57108 + $cmd_params = "$_->{NAME}=$value";
57109 + load_module($cmd_params) or die;
57110 + test ($_->{NAME}, $_->{DEFAULT});
57111 + }
57112 + }
57113 + }
57114 +
57115 + test_status() or die;
57116 +}
57117 +
57118 +test_main();
57119 +0;
57120 diff -urN linux-3.10/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/test_sysfs.pl
57121 --- linux-3.10/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100
57122 +++ linux-rpi-3.10.y/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2013-07-06 15:25:50.000000000 +0100
57123 @@ -0,0 +1,193 @@
57124 +#!/usr/bin/perl -w
57125 +#
57126 +# Run this program on the integrator
57127 +# - Tests select sysfs attributes.
57128 +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
57129 +# -----------------------------------------------------------------------------
57130 +use strict;
57131 +use dwc_otg_test;
57132 +
57133 +check_arch() or die;
57134 +
57135 +#
57136 +#
57137 +sub test {
57138 + my ($attr,$expected) = @_;
57139 + my $string = get($attr);
57140 +
57141 + if ($string eq $expected) {
57142 + printf("$attr = $string, okay\n");
57143 + }
57144 + else {
57145 + warn "ERROR: value of $attr != $expected, $string\n";
57146 + $errors ++;
57147 + }
57148 +}
57149 +
57150 +#
57151 +#
57152 +sub set {
57153 + my ($reg, $value) = @_;
57154 + system "echo $value > $sysfsdir/$reg";
57155 +}
57156 +
57157 +#
57158 +#
57159 +sub get {
57160 + my $attr = shift;
57161 + my $string = `cat $sysfsdir/$attr`;
57162 + chomp $string;
57163 + if ($string =~ m/\s\=\s/) {
57164 + my $tmp;
57165 + ($tmp, $string) = split /\s=\s/, $string;
57166 + }
57167 + return $string;
57168 +}
57169 +
57170 +#
57171 +#
57172 +sub test_main {
57173 + print("\nTesting Sysfs Attributes\n");
57174 +
57175 + load_module("") or die;
57176 +
57177 + # Test initial values of regoffset/regvalue/guid/gsnpsid
57178 + print("\nTesting Default Values\n");
57179 +
57180 + test("regoffset", "0xffffffff");
57181 + test("regvalue", "invalid offset");
57182 + test("guid", "0x12345678"); # this will fail if it has been changed
57183 + test("gsnpsid", "0x4f54200a");
57184 +
57185 + # Test operation of regoffset/regvalue
57186 + print("\nTesting regoffset\n");
57187 + set('regoffset', '5a5a5a5a');
57188 + test("regoffset", "0xffffffff");
57189 +
57190 + set('regoffset', '0');
57191 + test("regoffset", "0x00000000");
57192 +
57193 + set('regoffset', '40000');
57194 + test("regoffset", "0x00000000");
57195 +
57196 + set('regoffset', '3ffff');
57197 + test("regoffset", "0x0003ffff");
57198 +
57199 + set('regoffset', '1');
57200 + test("regoffset", "0x00000001");
57201 +
57202 + print("\nTesting regvalue\n");
57203 + set('regoffset', '3c');
57204 + test("regvalue", "0x12345678");
57205 + set('regvalue', '5a5a5a5a');
57206 + test("regvalue", "0x5a5a5a5a");
57207 + set('regvalue','a5a5a5a5');
57208 + test("regvalue", "0xa5a5a5a5");
57209 + set('guid','12345678');
57210 +
57211 + # Test HNP Capable
57212 + print("\nTesting HNP Capable bit\n");
57213 + set('hnpcapable', '1');
57214 + test("hnpcapable", "0x1");
57215 + set('hnpcapable','0');
57216 + test("hnpcapable", "0x0");
57217 +
57218 + set('regoffset','0c');
57219 +
57220 + my $old = get('gusbcfg');
57221 + print("setting hnpcapable\n");
57222 + set('hnpcapable', '1');
57223 + test("hnpcapable", "0x1");
57224 + test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
57225 + test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
57226 +
57227 + $old = get('gusbcfg');
57228 + print("clearing hnpcapable\n");
57229 + set('hnpcapable', '0');
57230 + test("hnpcapable", "0x0");
57231 + test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
57232 + test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
57233 +
57234 + # Test SRP Capable
57235 + print("\nTesting SRP Capable bit\n");
57236 + set('srpcapable', '1');
57237 + test("srpcapable", "0x1");
57238 + set('srpcapable','0');
57239 + test("srpcapable", "0x0");
57240 +
57241 + set('regoffset','0c');
57242 +
57243 + $old = get('gusbcfg');
57244 + print("setting srpcapable\n");
57245 + set('srpcapable', '1');
57246 + test("srpcapable", "0x1");
57247 + test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
57248 + test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
57249 +
57250 + $old = get('gusbcfg');
57251 + print("clearing srpcapable\n");
57252 + set('srpcapable', '0');
57253 + test("srpcapable", "0x0");
57254 + test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
57255 + test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
57256 +
57257 + # Test GGPIO
57258 + print("\nTesting GGPIO\n");
57259 + set('ggpio','5a5a5a5a');
57260 + test('ggpio','0x5a5a0000');
57261 + set('ggpio','a5a5a5a5');
57262 + test('ggpio','0xa5a50000');
57263 + set('ggpio','11110000');
57264 + test('ggpio','0x11110000');
57265 + set('ggpio','00001111');
57266 + test('ggpio','0x00000000');
57267 +
57268 + # Test DEVSPEED
57269 + print("\nTesting DEVSPEED\n");
57270 + set('regoffset','800');
57271 + $old = get('regvalue');
57272 + set('devspeed','0');
57273 + test('devspeed','0x0');
57274 + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
57275 + set('devspeed','1');
57276 + test('devspeed','0x1');
57277 + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
57278 + set('devspeed','2');
57279 + test('devspeed','0x2');
57280 + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
57281 + set('devspeed','3');
57282 + test('devspeed','0x3');
57283 + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
57284 + set('devspeed','4');
57285 + test('devspeed','0x0');
57286 + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
57287 + set('devspeed','5');
57288 + test('devspeed','0x1');
57289 + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
57290 +
57291 +
57292 + # mode Returns the current mode:0 for device mode1 for host mode Read
57293 + # hnp Initiate the Host Negotiation Protocol. Read returns the status. Read/Write
57294 + # srp Initiate the Session Request Protocol. Read returns the status. Read/Write
57295 + # buspower Get or Set the Power State of the bus (0 - Off or 1 - On) Read/Write
57296 + # bussuspend Suspend the USB bus. Read/Write
57297 + # busconnected Get the connection status of the bus Read
57298 +
57299 + # gotgctl Get or set the Core Control Status Register. Read/Write
57300 + ## gusbcfg Get or set the Core USB Configuration Register Read/Write
57301 + # grxfsiz Get or set the Receive FIFO Size Register Read/Write
57302 + # gnptxfsiz Get or set the non-periodic Transmit Size Register Read/Write
57303 + # gpvndctl Get or set the PHY Vendor Control Register Read/Write
57304 + ## ggpio Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
57305 + ## guid Get or set the value of the User ID Register Read/Write
57306 + ## gsnpsid Get the value of the Synopsys ID Regester Read
57307 + ## devspeed Get or set the device speed setting in the DCFG register Read/Write
57308 + # enumspeed Gets the device enumeration Speed. Read
57309 + # hptxfsiz Get the value of the Host Periodic Transmit FIFO Read
57310 + # hprt0 Get or Set the value in the Host Port Control and Status Register Read/Write
57311 +
57312 + test_status("TEST NYI") or die;
57313 +}
57314 +
57315 +test_main();
57316 +0;
57317 diff -urN linux-3.10/drivers/usb/host/Kconfig linux-rpi-3.10.y/drivers/usb/host/Kconfig
57318 --- linux-3.10/drivers/usb/host/Kconfig 2013-06-30 23:13:29.000000000 +0100
57319 +++ linux-rpi-3.10.y/drivers/usb/host/Kconfig 2013-07-06 15:25:50.000000000 +0100
57320 @@ -663,6 +663,19 @@
57321 To compile this driver a module, choose M here: the module
57322 will be called "hwa-hc".
57323
57324 +config USB_DWCOTG
57325 + tristate "Synopsis DWC host support"
57326 + depends on USB
57327 + help
57328 + The Synopsis DWC controller is a dual-role
57329 + host/peripheral/OTG ("On The Go") USB controllers.
57330 +
57331 + Enable this option to support this IP in host controller mode.
57332 + If unsure, say N.
57333 +
57334 + To compile this driver as a module, choose M here: the
57335 + modules built will be called dwc_otg and dwc_common_port.
57336 +
57337 config USB_IMX21_HCD
57338 tristate "i.MX21 HCD support"
57339 depends on ARM && ARCH_MXC
57340 diff -urN linux-3.10/drivers/usb/host/Makefile linux-rpi-3.10.y/drivers/usb/host/Makefile
57341 --- linux-3.10/drivers/usb/host/Makefile 2013-06-30 23:13:29.000000000 +0100
57342 +++ linux-rpi-3.10.y/drivers/usb/host/Makefile 2013-07-06 15:25:50.000000000 +0100
57343 @@ -47,6 +47,8 @@
57344 obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
57345 obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
57346 obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o
57347 +
57348 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/
57349 obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
57350 obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
57351 obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
57352 diff -urN linux-3.10/drivers/usb/Makefile linux-rpi-3.10.y/drivers/usb/Makefile
57353 --- linux-3.10/drivers/usb/Makefile 2013-06-30 23:13:29.000000000 +0100
57354 +++ linux-rpi-3.10.y/drivers/usb/Makefile 2013-07-06 15:25:50.000000000 +0100
57355 @@ -23,6 +23,7 @@
57356 obj-$(CONFIG_USB_R8A66597_HCD) += host/
57357 obj-$(CONFIG_USB_HWA_HCD) += host/
57358 obj-$(CONFIG_USB_ISP1760_HCD) += host/
57359 +obj-$(CONFIG_USB_DWCOTG) += host/
57360 obj-$(CONFIG_USB_IMX21_HCD) += host/
57361 obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
57362